diff --git a/backfill/config/env.go b/backfill/config/env.go index 6a996a2c..47e3d866 100644 --- a/backfill/config/env.go +++ b/backfill/config/env.go @@ -75,3 +75,58 @@ func getEnvAsInt(key string) int { } return value } + +func GetMinHeights(network string) map[int]int { + minHeights := make(map[int]int) + if network == "mainnet01" { + minHeights = map[int]int{ + 0: 0, + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 852054, + 11: 852054, + 12: 852054, + 13: 852054, + 14: 852054, + 15: 852054, + 16: 852054, + 17: 852054, + 18: 852054, + 19: 852054, + } + } + + if network == "testnet04" { + minHeights = map[int]int{ + 0: 0, + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 0, + 7: 0, + 8: 0, + 9: 0, + 10: 332604, + 11: 332604, + 12: 332604, + 13: 332604, + 14: 332604, + 15: 332604, + 16: 332604, + 17: 332604, + 18: 332604, + 19: 332604, + } + } + + return minHeights +} diff --git a/backfill/main.go b/backfill/main.go index 84aed365..6e43dab9 100644 --- a/backfill/main.go +++ b/backfill/main.go @@ -19,6 +19,7 @@ func main() { go config.StartMemoryMonitoring() cut := fetch.FetchCut() ChainId := env.ChainId - SyncMinHeight := env.SyncMinHeight + minHeights := config.GetMinHeights(env.Network) + SyncMinHeight := minHeights[ChainId] process.StartBackfill(cut.Height, cut.Hash, ChainId, SyncMinHeight, pool) } diff --git a/backfill/middle-backfill/middle-backfill.go b/backfill/middle-backfill/middle-backfill.go index ca60d768..8df44f29 100644 --- a/backfill/middle-backfill/middle-backfill.go +++ b/backfill/middle-backfill/middle-backfill.go @@ -69,15 +69,5 @@ func FetchMaxHeightByChain(pool *pgxpool.Pool) ([]BlockHeight, error) { return nil, fmt.Errorf("error occurred during row iteration: %w", err) } - // const maxHeight = 5444446 - // var blockHeights = []BlockHeight{} - - // for i := 0; i < 20; i++ { - // blockHeights = append(blockHeights, BlockHeight{ - // ChainID: int64(i), - // MaxHeight: maxHeight, - // }) - // } - return results, nil } diff --git a/backfill/process/coinbase.go b/backfill/process/coinbase.go new file mode 100644 index 00000000..f019b489 --- /dev/null +++ b/backfill/process/coinbase.go @@ -0,0 +1,65 @@ +package process + +import ( + "encoding/json" + "fmt" + "go-backfill/fetch" + "go-backfill/repository" + "strconv" +) + +type Coinbase struct { + ReqKey string `json:"reqKey"` + TxID int `json:"txId"` + Events []fetch.Event `json:"events"` + Result json.RawMessage `json:"result"` + Logs string `json:"logs"` +} + +func decodeCoinbase(jsonStr string) (*Coinbase, error) { + var coinbase Coinbase + err := json.Unmarshal([]byte(jsonStr), &coinbase) + if err != nil { + return nil, err + } + return &coinbase, nil +} + +func processCoinbaseTransaction(coinbase string, blockId int64, creationTime int64, chainId int64) (repository.TransactionAttributes, error) { + + coinbaseDecoded, err := decodeCoinbase(coinbase) + if err != nil { + return repository.TransactionAttributes{}, fmt.Errorf("decoding Coinbase JSON of block %d: %w", blockId, err) + } + + emptyJSON, _ := json.Marshal(map[string]interface{}{}) + emptyArray, _ := json.Marshal([]interface{}{}) + + txAttribute := repository.TransactionAttributes{ + BlockId: blockId, + Code: emptyJSON, + Data: emptyJSON, + ChainId: int(chainId), + CreationTime: strconv.FormatInt(creationTime, 10), + GasLimit: "0", + GasPrice: "0", + Hash: coinbaseDecoded.ReqKey, + Nonce: "", + PactId: nil, + Continuation: emptyJSON, + Gas: "0", + Result: coinbaseDecoded.Result, + Logs: coinbaseDecoded.Logs, + NumEvents: len(coinbaseDecoded.Events), + RequestKey: coinbaseDecoded.ReqKey, + Rollback: false, + Sender: "coinbase", + Sigs: emptyArray, + Step: 0, + Proof: nil, + TTL: "0", + TxId: fmt.Sprintf("%d", coinbaseDecoded.TxID), + } + + return txAttribute, nil +} diff --git a/backfill/process/process_blocks.go b/backfill/process/process_blocks.go index c344b926..3b92a812 100644 --- a/backfill/process/process_blocks.go +++ b/backfill/process/process_blocks.go @@ -29,7 +29,7 @@ func PrepareBlocks(network string, chainId int, payloads []fetch.ProcessedPayloa TransactionsHash: payload.TransactionsHash, OutputsHash: payload.OutputsHash, Coinbase: string(payload.Coinbase), - TransactionsCount: len(payload.Transactions), + TransactionsCount: len(payload.Transactions) + 1, // txs + coinbase tx } blocks = append(blocks, block) diff --git a/backfill/process/process_events.go b/backfill/process/process_events.go index 257327bf..4bf8c84b 100644 --- a/backfill/process/process_events.go +++ b/backfill/process/process_events.go @@ -10,10 +10,6 @@ import ( func PrepareEvents(network string, payload fetch.ProcessedPayload, transactionsId []int64) ([]repository.EventAttributes, error) { transactions := payload.Transactions - if len(transactions) == 0 { - return []repository.EventAttributes{}, nil - } - const avgEventsPerTransaction = 80 events := make([]repository.EventAttributes, 0, len(transactions)*avgEventsPerTransaction) @@ -42,7 +38,34 @@ func PrepareEvents(network string, payload fetch.ProcessedPayload, transactionsI } events = append(events, eventRecord) } + } + + coinbaseDecoded, err := decodeCoinbase(string(payload.Coinbase)) + if err != nil { + return nil, fmt.Errorf("decoding Coinbase JSON of block: %w", err) + } + var coinbaseTxId = transactionsId[len(transactionsId)-1] + for eventIndex, event := range coinbaseDecoded.Events { + + module := buildModuleName(event.Module.Namespace, event.Module.Name) + qualName := buildModuleName(event.Module.Namespace, event.Module.Name) + paramsJSON, err := json.Marshal(event.Params) + if err != nil { + return []repository.EventAttributes{}, fmt.Errorf("marshaling params for event %s: %w", event.Name, err) + } + + eventRecord := repository.EventAttributes{ + TransactionId: coinbaseTxId, + ChainId: payload.Header.ChainId, + Module: module, + Name: event.Name, + Params: paramsJSON, + QualName: qualName, + RequestKey: coinbaseDecoded.ReqKey, + OrderIndex: eventIndex, + } + events = append(events, eventRecord) } return events, nil diff --git a/backfill/process/process_transactions.go b/backfill/process/process_transactions.go index 3bf6cfd8..352f8b5d 100644 --- a/backfill/process/process_transactions.go +++ b/backfill/process/process_transactions.go @@ -31,13 +31,9 @@ type CmdData struct { } `json:"payload"` } -func PrepareTransactions(network string, blockId int64, payload fetch.ProcessedPayload) ([]repository.TransactionAttributes, error) { +func PrepareTransactions(network string, blockId int64, payload fetch.ProcessedPayload, block repository.BlockAttributes) ([]repository.TransactionAttributes, error) { transactions := payload.Transactions - if len(transactions) == 0 { - return []repository.TransactionAttributes{}, nil - } - transactionRecords := make([]repository.TransactionAttributes, 0, len(transactions)) var cmdData CmdData @@ -91,9 +87,14 @@ func PrepareTransactions(network string, blockId int64, payload fetch.ProcessedP } } - chainId, err := strconv.Atoi(cmdData.Meta.ChainId) - if err != nil { - return nil, fmt.Errorf("converting ChainId for transaction %s: %w", t.Hash, err) + var chainId int + if cmdData.Meta.ChainId != "" { + chainId, err = strconv.Atoi(cmdData.Meta.ChainId) + if err != nil { + return nil, fmt.Errorf("converting ChainId for transaction %s: %w", t.Hash, err) + } + } else { + chainId = block.ChainId } txId := strconv.Itoa(t.TxId) @@ -137,6 +138,14 @@ func PrepareTransactions(network string, blockId int64, payload fetch.ProcessedP transactionRecords = append(transactionRecords, transactionRecord) } + coinbaseTx, err := processCoinbaseTransaction(string(payload.Coinbase), blockId, block.CreationTime, int64(block.ChainId)) + + if err != nil { + return nil, fmt.Errorf("processing coinbase transaction %d: %w", blockId, err) + } + + transactionRecords = append(transactionRecords, coinbaseTx) + return transactionRecords, nil } diff --git a/backfill/process/process_transfers.go b/backfill/process/process_transfers.go index 0d249011..6cfc55b7 100644 --- a/backfill/process/process_transfers.go +++ b/backfill/process/process_transfers.go @@ -1,17 +1,14 @@ package process import ( + "fmt" "go-backfill/fetch" "go-backfill/repository" ) -func PrepareTransfers(network string, payload fetch.ProcessedPayload, transactionsId []int64) []repository.TransferAttributes { +func PrepareTransfers(network string, payload fetch.ProcessedPayload, transactionsId []int64) ([]repository.TransferAttributes, error) { transactions := payload.Transactions - if len(transactions) == 0 { - return []repository.TransferAttributes{} - } - const avgTransfersPerTransaction = 80 transfers := make([]repository.TransferAttributes, 0, len(transactions)*avgTransfersPerTransaction) @@ -23,5 +20,14 @@ func PrepareTransfers(network string, payload fetch.ProcessedPayload, transactio transfers = append(transfers, nftTransfers...) } - return transfers + coinbaseDecoded, err := decodeCoinbase(string(payload.Coinbase)) + if err != nil { + return nil, fmt.Errorf("decoding Coinbase JSON of block: %w", err) + } + + var coinbaseTxId = transactionsId[len(transactionsId)-1] + coinTransfers := GetCoinTransfers(coinbaseDecoded.Events, payload.Header.ChainId, coinbaseDecoded.ReqKey, coinbaseTxId) + transfers = append(transfers, coinTransfers...) + + return transfers, nil } diff --git a/backfill/process/save_payloads.go b/backfill/process/save_payloads.go index b4686c8d..84889792 100644 --- a/backfill/process/save_payloads.go +++ b/backfill/process/save_payloads.go @@ -68,7 +68,9 @@ func savePayloads(network string, chainId int, processedPayloads []fetch.Process var transactionIdsToSave [][]int64 for index, processedPayload := range processedPayloads { - txs, err := PrepareTransactions(network, blockIds[index], processedPayload) + var blockId = blockIds[index] + var currBlock = blocks[index] + txs, err := PrepareTransactions(network, blockId, processedPayload, currBlock) if err != nil { return Counters{}, DataSizeTracker{}, fmt.Errorf("saving transactions -> %w", err) } @@ -98,7 +100,10 @@ func savePayloads(network string, chainId int, processedPayloads []fetch.Process } for index, processedPayload := range processedPayloads { - transfers := PrepareTransfers(network, processedPayload, transactionIdsToSave[index]) + transfers, err := PrepareTransfers(network, processedPayload, transactionIdsToSave[index]) + if err != nil { + return Counters{}, DataSizeTracker{}, fmt.Errorf("preparing transfers -> %w", err) + } if err := repository.SaveTransfersToDatabase(transfers, tx); err != nil { return Counters{}, DataSizeTracker{}, fmt.Errorf("saving transfers: %w", err) } diff --git a/backfill/process/utils.go b/backfill/process/utils.go index afb8c356..4a90db0c 100644 --- a/backfill/process/utils.go +++ b/backfill/process/utils.go @@ -86,6 +86,13 @@ func (g *GasLimit) UnmarshalJSON(data []byte) error { return nil } + // Attempt to unmarshal the data as a float + var floatValue float64 + if err := json.Unmarshal(data, &floatValue); err == nil { + *g = GasLimit(fmt.Sprintf("%.0f", floatValue)) // Convert float to int-like string + return nil + } + // Attempt to unmarshal the data as a string var stringValue string if err := json.Unmarshal(data, &stringValue); err == nil { @@ -93,8 +100,16 @@ func (g *GasLimit) UnmarshalJSON(data []byte) error { return nil } + var tempStruct struct { + Int int `json:"int"` + } + if err := json.Unmarshal(data, &tempStruct); err == nil { + *g = GasLimit(strconv.Itoa(tempStruct.Int)) // Convert int to string and assign + return nil + } + // If neither, return an error - return fmt.Errorf("data is neither int nor string: %s", string(data)) + return fmt.Errorf("data is neither int nor string nor float not { int: }: %s", string(data)) } func convertToFloat64(event fetch.Event, index int) (float64, bool) { diff --git a/backfill/recreate-indexes/recreate-indexes.go b/backfill/recreate-indexes/recreate-indexes.go index 72b40831..6b22b586 100644 --- a/backfill/recreate-indexes/recreate-indexes.go +++ b/backfill/recreate-indexes/recreate-indexes.go @@ -27,69 +27,91 @@ func main() { log.Println("Connected to database") + tx, err := db.Begin() + if err != nil { + log.Fatalf("Failed to begin transaction: %v", err) + } + // SQL commands grouped by table commands := []struct { description string query string }{ - // // CREATE INDEX commands for Balances - // {"Create unique index on Balances", `CREATE UNIQUE INDEX "balances_unique_constraint" ON "Balances" (network, "chainId", account, qualname, "tokenId");`}, - // {"Create account index on Balances", `CREATE INDEX "balances_account_index" ON "Balances" (account);`}, - // {"Create tokenId index on Balances", `CREATE INDEX "balances_tokenid_index" ON "Balances" ("tokenId");`}, - // {"Create contractId index on Balances", `CREATE INDEX "balances_contractid_index" ON "Balances" ("contractId");`}, - // {"Create search index on Balances", `CREATE INDEX "balances_search_idx" ON "Balances" (LOWER(account));`}, - - // // CREATE INDEX commands for Blocks - // {"Create height index on Blocks", `CREATE INDEX "blocks_height_idx" ON "Blocks" (height);`}, - // {"Create chainId height index on Blocks", `CREATE INDEX "blocks_chainid_height_idx" ON "Blocks" ("chainId", height);`}, - // {"Create chainId index on Blocks", `CREATE INDEX "blocks_chainid_idx" ON "Blocks" ("chainId");`}, - // {"Create canonical index on Blocks", `CREATE INDEX "blocks_canonical_idx" ON "Blocks" (canonical);`}, - // {"Create GIN trgm parent index on Blocks", `CREATE INDEX "blocks_trgm_parent_idx" ON "Blocks" USING gin (LOWER(parent) gin_trgm_ops);`}, - - // // CREATE INDEX commands for Contracts - // {"Create unique index on Contracts", `CREATE UNIQUE INDEX "contract_unique_constraint" ON "Contracts" (network, "chainId", module, "tokenId");`}, - // {"Create search index on Contracts", `CREATE INDEX "contracts_search_idx" ON "Contracts" (LOWER(module));`}, - - // // CREATE INDEX commands for Events - // {"Create transactionId index on Events", `CREATE INDEX "events_transactionid_idx" ON "Events" ("transactionId");`}, - - // CREATE INDEX commands for Signers - {"Create publicKey transactionId index on Signers", `CREATE INDEX "signers_pubkey_transactionid_idx" ON "Signers" (pubkey, "transactionId");`}, - - // CREATE INDEX commands for Transactions - {"Create requestkey index on Transactions", `CREATE INDEX "transactions_requestkey_idx" ON "Transactions" (requestkey);`}, - {"Create sender index on Transactions", `CREATE INDEX "transactions_sender_idx" ON "Transactions" (sender);`}, - {"Create chainId blockId index on Transactions", `CREATE INDEX "transactions_chainid_blockid_idx" ON "Transactions" ("chainId", "blockId");`}, - {"Create hash index on Transactions", `CREATE INDEX "transactions_hash_idx" ON "Transactions" (hash);`}, - {"Create canonical index on Transactions", `CREATE INDEX "transactions_canonical_idx" ON "Transactions" (canonical);`}, - {"Create GIN trgm requestkey index on Transactions", `CREATE INDEX "transactions_trgm_requestkey_idx" ON "Transactions" USING gin (LOWER(requestkey) gin_trgm_ops);`}, - {"Create GIN trgm hash index on Transactions", `CREATE INDEX "transactions_trgm_hash_idx" ON "Transactions" USING gin (LOWER(hash) gin_trgm_ops);`}, - {"Create GIN trgm txid index on Transactions", `CREATE INDEX "transactions_trgm_txid_idx" ON "Transactions" USING gin (LOWER(txid) gin_trgm_ops);`}, - {"Create GIN trgm pactid index on Transactions", `CREATE INDEX "transactions_trgm_pactid_idx" ON "Transactions" USING gin (LOWER(pactid) gin_trgm_ops);`}, - {"Create GIN trgm sender index on Transactions", `CREATE INDEX "transactions_trgm_sender_idx" ON "Transactions" USING gin (LOWER(sender) gin_trgm_ops);`}, - - // CREATE INDEX commands for Transfers - {"Create contractId index on Transfers", `CREATE INDEX "transfers_contractid_idx" ON "Transfers" ("contractId");`}, - {"Create type index on Transfers", `CREATE INDEX "transfers_type_idx" ON "Transfers" (type);`}, - {"Create transactionId index on Transfers", `CREATE INDEX "transfers_transactionid_idx" ON "Transfers" ("transactionId");`}, - {"Create modulename index on Transfers", `CREATE INDEX "transfers_modulename_idx" ON "Transfers" (modulename);`}, - {"Create from_acct modulename index on Transfers", `CREATE INDEX "transfers_from_acct_modulename_idx" ON "Transfers" (from_acct, modulename);`}, + {"Create unique index on Balances", `CREATE UNIQUE INDEX "Balances_pkey" ON public."Balances" USING btree (id);`}, + {"Create index on account column of Balances", `CREATE INDEX balances_account_index ON public."Balances" USING btree (account);`}, + {"Create index on contractId column of Balances", `CREATE INDEX balances_contractid_index ON public."Balances" USING btree ("contractId");`}, + {"Create index on lower(account) column of Balances", `CREATE INDEX balances_search_idx ON public."Balances" USING btree (lower((account)::text));`}, + {"Create index on tokenId column of Balances", `CREATE INDEX balances_tokenid_index ON public."Balances" USING btree ("tokenId");`}, + {"Create unique constraint on Balances", `CREATE UNIQUE INDEX balances_unique_constraint ON public."Balances" USING btree ("chainId", account, module, "tokenId");`}, + {"Create unique index on Blocks", `CREATE UNIQUE INDEX "Blocks_pkey" ON public."Blocks" USING btree (id);`}, + {"Create index on canonical column of Blocks", `CREATE INDEX blocks_canonical_idx ON public."Blocks" USING btree (canonical);`}, + {"Create index on chainId, height columns of Blocks", `CREATE INDEX blocks_chainid_height_idx ON public."Blocks" USING btree ("chainId", height);`}, + {"Create index on chainId column of Blocks", `CREATE INDEX blocks_chainid_idx ON public."Blocks" USING btree ("chainId");`}, + {"Create unique index on Blocks chainwebVersion, chainId, hash", `CREATE UNIQUE INDEX "blocks_chainwebVersion_chainid_hash_unique_idx" ON public."Blocks" USING btree ("chainwebVersion", "chainId", hash);`}, + {"Create index on hash column of Blocks", `CREATE INDEX blocks_hash_idx ON public."Blocks" USING btree (hash);`}, + {"Create index on height, id columns of Blocks", `CREATE INDEX blocks_height_id_idx ON public."Blocks" USING btree (height, id);`}, + {"Create index on height column of Blocks", `CREATE INDEX blocks_height_idx ON public."Blocks" USING btree (height);`}, + {"Create GIN index on parent column of Blocks", `CREATE INDEX blocks_trgm_parent_idx ON public."Blocks" USING gin (lower((parent)::text));`}, + {"Create unique index on Contracts", `CREATE UNIQUE INDEX "Contracts_pkey" ON public."Contracts" USING btree (id);`}, + {"Create unique constraint on Contracts", `CREATE UNIQUE INDEX contract_unique_constraint ON public."Contracts" USING btree ("chainId", module, "tokenId");`}, + {"Create index on Contracts module", `CREATE INDEX contracts_search_idx ON public."Contracts" USING btree (lower((module)::text));`}, + {"Create unique index on Events", `CREATE UNIQUE INDEX "Events_pkey" ON public."Events" USING btree (id);`}, + {"Create index on Events module, name", `CREATE INDEX events_module_name_idx ON public."Events" USING btree (module, name);`}, + {"Create index on transactionId column of Events", `CREATE INDEX events_transactionid_idx ON public."Events" USING btree ("transactionId");`}, + {"Create unique index on Guards", `CREATE UNIQUE INDEX "Guards_pkey" ON public."Guards" USING btree (id);`}, + {"Create unique index on Guards publicKey, predicate, balanceId", `CREATE UNIQUE INDEX guards_publickey_predicate_balanceid_idx ON public."Guards" USING btree ("publicKey", predicate, "balanceId");`}, + {"Create unique index on Signers", `CREATE UNIQUE INDEX "Signers_pkey" ON public."Signers" USING btree (id);`}, + {"Create index on pubkey column of Signers", `CREATE INDEX signers_pubkey_idx ON public."Signers" USING btree (pubkey);`}, + {"Create index on pubkey, transactionId columns of Signers", `CREATE INDEX signers_pubkey_transactionid_idx ON public."Signers" USING btree (pubkey, "transactionId");`}, + {"Create index on transactionId column of Signers", `CREATE INDEX signers_transaction_id_idx ON public."Signers" USING btree ("transactionId");`}, + {"Create unique index on Transactions", `CREATE UNIQUE INDEX "Transactions_pkey" ON public."Transactions" USING btree (id);`}, + {"Create index on blockId column of Transactions", `CREATE INDEX "transactions_blockId_idx" ON public."Transactions" USING btree ("blockId");`}, + {"Create index on canonical column of Transactions", `CREATE INDEX transactions_canonical_idx ON public."Transactions" USING btree (canonical);`}, + {"Create index on chainId column of Transactions", `CREATE INDEX "transactions_chainId_idx" ON public."Transactions" USING btree ("chainId");`}, + {"Create index on chainId, blockId columns of Transactions", `CREATE INDEX transactions_chainid_blockid_idx ON public."Transactions" USING btree ("chainId", "blockId");`}, + {"Create index on hash column of Transactions", `CREATE INDEX transactions_hash_idx ON public."Transactions" USING btree (hash);`}, + {"Create index on requestkey column of Transactions", `CREATE INDEX transactions_requestkey_idx ON public."Transactions" USING btree (requestkey);`}, + {"Create index on sender, id columns of Transactions", `CREATE INDEX transactions_sender_id_idx ON public."Transactions" USING btree (sender, id);`}, + {"Create index on sender column of Transactions", `CREATE INDEX transactions_sender_idx ON public."Transactions" USING btree (sender);`}, + {"Create GIN index on hash column of Transactions", `CREATE INDEX transactions_trgm_hash_idx ON public."Transactions" USING gin (lower((hash)::text));`}, + {"Create GIN index on pactid column of Transactions", `CREATE INDEX transactions_trgm_pactid_idx ON public."Transactions" USING gin (lower((pactid)::text));`}, + {"Create GIN index on requestkey column of Transactions", `CREATE INDEX transactions_trgm_requestkey_idx ON public."Transactions" USING gin (lower((requestkey)::text));`}, + {"Create GIN index on sender column of Transactions", `CREATE INDEX transactions_trgm_sender_idx ON public."Transactions" USING gin (lower((sender)::text));`}, + {"Create GIN index on txid column of Transactions", `CREATE INDEX transactions_trgm_txid_idx ON public."Transactions" USING gin (lower((txid)::text));`}, + {"Create unique index on Transfers", `CREATE UNIQUE INDEX "Transfers_pkey" ON public."Transfers" USING btree (id);`}, + {"Create index on from_acct column of Transfers", `CREATE INDEX from_acct_idx ON public."Transfers" USING btree (from_acct);`}, + {"Create index on to_acct column of Transfers", `CREATE INDEX to_acct_idx ON public."Transfers" USING btree (to_acct);`}, + {"Create index on chainId, from_acct, modulename columns of Transfers", `CREATE INDEX transfers_chainid_from_acct_modulename_idx ON public."Transfers" USING btree ("chainId", from_acct, modulename);`}, + {"Create index on chainId, to_acct, modulename columns of Transfers", `CREATE INDEX transfers_chainid_to_acct_modulename_idx ON public."Transfers" USING btree ("chainId", to_acct, modulename);`}, + {"Create index on contractId column of Transfers", `CREATE INDEX transfers_contractid_idx ON public."Transfers" USING btree ("contractId");`}, + {"Create index on from_acct, modulename columns of Transfers", `CREATE INDEX transfers_from_acct_modulename_idx ON public."Transfers" USING btree (from_acct, modulename);`}, + {"Create index on hasTokenId column of Transfers", `CREATE INDEX "transfers_hasTokenId_idx" ON public."Transfers" USING btree ("hasTokenId");`}, + {"Create index on modulename column of Transfers", `CREATE INDEX transfers_modulename_idx ON public."Transfers" USING btree (modulename);`}, + {"Create index on transactionId column of Transfers", `CREATE INDEX transfers_transactionid_idx ON public."Transfers" USING btree ("transactionId");`}, + {"Create index on type column of Transfers", `CREATE INDEX transfers_type_idx ON public."Transfers" USING btree (type);`}, } for i, cmd := range commands { log.Printf("Executing (%d/%d): %s", i+1, len(commands), cmd.description) start := time.Now() - _, err := db.Exec(cmd.query) + _, err := tx.Exec(cmd.query) elapsed := time.Since(start) if err != nil { log.Printf("Error executing (%d): %s - %v", i+1, cmd.description, err) - break // Optionally exit on error or log and continue + tx.Rollback() + log.Println("Transaction rolled back due to error") + return } else { log.Printf("Successfully executed (%d): %s in %v", i+1, cmd.description, elapsed) } } + // Commit transaction + if err := tx.Commit(); err != nil { + log.Fatalf("Failed to commit transaction: %v", err) + } + log.Println("All commands executed") } diff --git a/backfill/repository/transaction_repository.go b/backfill/repository/transaction_repository.go index 0ef606fa..bd98f261 100644 --- a/backfill/repository/transaction_repository.go +++ b/backfill/repository/transaction_repository.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "time" "github.com/jackc/pgx/v5" @@ -54,11 +55,23 @@ func SaveTransactions(db pgx.Tx, transactions []TransactionAttributes) ([]int64, batch := &pgx.Batch{} for _, t := range transactions { - code, err := json.Marshal(t.Code) + var codeStr string + json.Unmarshal(t.Code, &codeStr) + codeStrCleaned := strings.ReplaceAll(codeStr, "\u0000", "") + if codeStrCleaned != codeStr { + fmt.Printf("Code cleaned: %s\n", t.RequestKey) + } + + codeCleaned, err := json.Marshal(codeStrCleaned) if err != nil { return nil, fmt.Errorf("failed to marshal code: %v", err) } + code := t.Code + if codeStrCleaned != "" { + code = codeCleaned + } + data, err := json.Marshal(t.Data) if err != nil { return nil, fmt.Errorf("failed to marshal data: %v", err) diff --git a/backfill/sqls/before-backfill.sql b/backfill/sqls/before-backfill.sql index 61a5ad88..34f1a680 100644 --- a/backfill/sqls/before-backfill.sql +++ b/backfill/sqls/before-backfill.sql @@ -1,73 +1,71 @@ --- Drop indexes from the Balances table -DROP INDEX IF EXISTS "balances_unique_constraint"; -DROP INDEX IF EXISTS "balances_account_index"; -DROP INDEX IF EXISTS "balances_tokenid_index"; -DROP INDEX IF EXISTS "balances_contractid_index"; -DROP INDEX IF EXISTS "balances_search_idx"; +BEGIN; --- Drop indexes from the Blocks table -DROP INDEX IF EXISTS "blocks_chainwebVersion_chainid_hash_unique_idx"; -DROP INDEX IF EXISTS "blocks_height_idx"; -DROP INDEX IF EXISTS "blocks_chainid_height_idx"; -DROP INDEX IF EXISTS "blocks_chainid_idx"; -DROP INDEX IF EXISTS "blocks_canonical_idx"; -DROP INDEX IF EXISTS "blocks_trgm_parent_idx"; +ALTER TABLE "Guards" DROP CONSTRAINT IF EXISTS "Guards_pkey"; +DROP INDEX IF EXISTS "Guards_pkey"; +DROP INDEX IF EXISTS guards_publickey_predicate_balanceid_idx; --- Drop indexes from the Contracts table -DROP INDEX IF EXISTS "contract_unique_constraint"; -DROP INDEX IF EXISTS "contracts_search_idx"; +ALTER TABLE "Balances" DROP CONSTRAINT IF EXISTS "Balances_pkey" CASCADE; +DROP INDEX IF EXISTS "Balances_pkey"; +DROP INDEX IF EXISTS balances_account_index; +DROP INDEX IF EXISTS balances_contractid_index; +DROP INDEX IF EXISTS balances_search_idx; +DROP INDEX IF EXISTS balances_tokenid_index; +DROP INDEX IF EXISTS balances_unique_constraint; --- Drop indexes from the Events table -DROP INDEX IF EXISTS "events_transactionid_idx"; +ALTER TABLE "Contracts" DROP CONSTRAINT IF EXISTS "Contracts_pkey" CASCADE; +DROP INDEX IF EXISTS "Contracts_pkey"; +DROP INDEX IF EXISTS contract_unique_constraint; +DROP INDEX IF EXISTS contracts_search_idx; --- Drop indexes from the Guards table -DROP INDEX IF EXISTS "signers_pubkey_transactionid_idx"; +ALTER TABLE "Events" DROP CONSTRAINT IF EXISTS "Events_pkey"; +DROP INDEX IF EXISTS "Events_pkey"; +DROP INDEX IF EXISTS events_module_name_idx; +DROP INDEX IF EXISTS events_transactionid_idx; --- Drop indexes from the Signers table -DROP INDEX IF EXISTS "signers_pubkey_transactionid_idx"; +ALTER TABLE "Signers" DROP CONSTRAINT IF EXISTS "Signers_pkey"; +DROP INDEX IF EXISTS "Signers_pkey"; +DROP INDEX IF EXISTS signers_pubkey_idx; +DROP INDEX IF EXISTS signers_pubkey_transactionid_idx; +DROP INDEX IF EXISTS signers_transaction_id_idx; --- Drop indexes from the Transactions table -DROP INDEX IF EXISTS "transactions_requestkey_idx"; +ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_pkey" CASCADE; +DROP INDEX IF EXISTS "Transactions_pkey"; DROP INDEX IF EXISTS "transactions_blockId_idx"; -DROP INDEX IF EXISTS "transactions_sender_idx"; +DROP INDEX IF EXISTS transactions_canonical_idx; DROP INDEX IF EXISTS "transactions_chainId_idx"; -DROP INDEX IF EXISTS "transactions_chainid_blockid_idx"; -DROP INDEX IF EXISTS "transactions_hash_idx"; -DROP INDEX IF EXISTS "transactions_canonical_idx"; -DROP INDEX IF EXISTS "transactions_trgm_requestkey_idx"; -DROP INDEX IF EXISTS "transactions_trgm_hash_idx"; -DROP INDEX IF EXISTS "transactions_trgm_txid_idx"; -DROP INDEX IF EXISTS "transactions_trgm_pactid_idx"; -DROP INDEX IF EXISTS "transactions_trgm_sender_idx"; +DROP INDEX IF EXISTS transactions_chainid_blockid_idx; +DROP INDEX IF EXISTS transactions_hash_idx; +DROP INDEX IF EXISTS transactions_requestkey_idx; +DROP INDEX IF EXISTS transactions_sender_id_idx; +DROP INDEX IF EXISTS transactions_sender_idx; +DROP INDEX IF EXISTS transactions_trgm_hash_idx; +DROP INDEX IF EXISTS transactions_trgm_pactid_idx; +DROP INDEX IF EXISTS transactions_trgm_requestkey_idx; +DROP INDEX IF EXISTS transactions_trgm_sender_idx; +DROP INDEX IF EXISTS transactions_trgm_txid_idx; --- Drop indexes from the Transfers table -DROP INDEX IF EXISTS "transfers_type_idx"; -DROP INDEX IF EXISTS "transfers_transactionid_idx"; +ALTER TABLE "Transfers" DROP CONSTRAINT IF EXISTS "Transfers_pkey"; +DROP INDEX IF EXISTS "Transfers_pkey"; +DROP INDEX IF EXISTS from_acct_idx; +DROP INDEX IF EXISTS to_acct_idx; +DROP INDEX IF EXISTS transfers_chainid_from_acct_modulename_idx; +DROP INDEX IF EXISTS transfers_chainid_to_acct_modulename_idx; +DROP INDEX IF EXISTS transfers_contractid_idx; +DROP INDEX IF EXISTS transfers_from_acct_modulename_idx; DROP INDEX IF EXISTS "transfers_hasTokenId_idx"; -DROP INDEX IF EXISTS "transfers_contractid_idx"; -DROP INDEX IF EXISTS "transfers_modulename_idx"; -DROP INDEX IF EXISTS "transfers_from_acct_modulename_idx"; - --- Drop constraints from the Balances table -ALTER TABLE "Balances" DROP CONSTRAINT IF EXISTS "Balances_pkey"; - --- Drop constraints from the Blocks table -ALTER TABLE "Blocks" DROP CONSTRAINT IF EXISTS "Blocks_pkey"; - --- Drop constraints from the Contracts table -ALTER TABLE "Contracts" DROP CONSTRAINT IF EXISTS "Contracts_pkey"; +DROP INDEX IF EXISTS transfers_modulename_idx; +DROP INDEX IF EXISTS transfers_transactionid_idx; +DROP INDEX IF EXISTS transfers_type_idx; --- Drop constraints from the Events table -ALTER TABLE "Events" DROP CONSTRAINT IF EXISTS "Events_pkey"; - --- Drop constraints from the Guards table -ALTER TABLE "Guards" DROP CONSTRAINT IF EXISTS "Guards_pkey"; - --- Drop constraints from the Signers table -ALTER TABLE "Signers" DROP CONSTRAINT IF EXISTS "Signers_pkey"; - --- Drop constraints from the Transactions table -ALTER TABLE "Transactions" DROP CONSTRAINT IF EXISTS "Transactions_pkey"; +ALTER TABLE "Blocks" DROP CONSTRAINT IF EXISTS "Blocks_pkey" CASCADE; +DROP INDEX IF EXISTS "Blocks_pkey"; +DROP INDEX IF EXISTS blocks_canonical_idx; +DROP INDEX IF EXISTS blocks_chainid_height_idx; +DROP INDEX IF EXISTS blocks_chainid_idx; +DROP INDEX IF EXISTS "blocks_chainwebVersion_chainid_hash_unique_idx"; +DROP INDEX IF EXISTS blocks_hash_idx; +DROP INDEX IF EXISTS blocks_height_id_idx; +DROP INDEX IF EXISTS blocks_height_idx; +DROP INDEX IF EXISTS blocks_trgm_parent_idx; --- Drop constraints from the Transfers table -ALTER TABLE "Transfers" DROP CONSTRAINT IF EXISTS "Transfers_pkey"; +COMMIT; diff --git a/indexer/migrations/20250226201907-transaction-nonce-type-change.js b/indexer/migrations/20250226201907-transaction-nonce-type-change.js new file mode 100644 index 00000000..988633c6 --- /dev/null +++ b/indexer/migrations/20250226201907-transaction-nonce-type-change.js @@ -0,0 +1,16 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.changeColumn('Transactions', 'nonce', { + type: Sequelize.TEXT, // Equivalent to TEXT in SQL when using Sequelize + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.changeColumn('Transactions', 'nonce', { + type: Sequelize.STRING, // Equivalent to VARCHAR(255) in SQL when using Sequelize + }); + }, +}; diff --git a/indexer/package.json b/indexer/package.json index 4b597c5a..b154aacf 100644 --- a/indexer/package.json +++ b/indexer/package.json @@ -65,8 +65,10 @@ "typescript": "^5.3.3" }, "scripts": { + "build": "tsc", "create:database": "ts-node src/index.ts --database && yarn migrate:up", "dev": "docker-compose -f docker-compose.yml up && docker-compose logs -f indexer", + "dev:guards": "ts-node src/index.ts --guards", "dev:database": "ts-node src/index.ts --database", "dev:streaming": "ts-node src/index.ts --streaming", "dev:graphql": "ts-node src/index.ts --graphql", diff --git a/indexer/src/circulating-coins/token_payments.csv b/indexer/src/circulating-coins/token_payments.csv index 11fb7dc4..30e594c1 100644 --- a/indexer/src/circulating-coins/token_payments.csv +++ b/indexer/src/circulating-coins/token_payments.csv @@ -831,11 +831,6 @@ PS_C1_829,2021-02-01T00:00:00Z,PS_C1,400000,1 PS_C2_830,2021-02-01T00:00:00Z,PS_C2,400000,2 PS_C3_831,2021-02-01T00:00:00Z,PS_C3,400000,3 PS_C4_832,2021-02-01T00:00:00Z,PS_C4,400000,4 -PS_C5_833,2021-02-01T00:00:00Z,PS_C5,400000,5 -PS_C6_834,2021-02-01T00:00:00Z,PS_C6,400000,6 -PS_C7_835,2021-02-01T00:00:00Z,PS_C7,400000,7 -PS_C8_836,2021-02-01T00:00:00Z,PS_C8,400000,8 -PS_C9_837,2021-02-01T00:00:00Z,PS_C9,184000,9 EB_C9_838,2021-02-01T00:00:00Z,EB_C9,216000,9 CS1_C2_839,2021-02-01T00:00:00Z,CS1_C2,666667,2 PS_C0_840,2021-03-01T00:00:00Z,PS_C0,400000,0 @@ -843,11 +838,6 @@ PS_C1_841,2021-03-01T00:00:00Z,PS_C1,400000,1 PS_C2_842,2021-03-01T00:00:00Z,PS_C2,400000,2 PS_C3_843,2021-03-01T00:00:00Z,PS_C3,400000,3 PS_C4_844,2021-03-01T00:00:00Z,PS_C4,400000,4 -PS_C5_845,2021-03-01T00:00:00Z,PS_C5,400000,5 -PS_C6_846,2021-03-01T00:00:00Z,PS_C6,400000,6 -PS_C7_847,2021-03-01T00:00:00Z,PS_C7,400000,7 -PS_C8_848,2021-03-01T00:00:00Z,PS_C8,400000,8 -PS_C9_849,2021-03-01T00:00:00Z,PS_C9,184000,9 EB_C9_850,2021-03-01T00:00:00Z,EB_C9,216000,9 CS1_C2_851,2021-03-01T00:00:00Z,CS1_C2,666667,2 PS_C0_852,2021-04-01T00:00:00Z,PS_C0,400000,0 @@ -855,11 +845,6 @@ PS_C1_853,2021-04-01T00:00:00Z,PS_C1,400000,1 PS_C2_854,2021-04-01T00:00:00Z,PS_C2,400000,2 PS_C3_855,2021-04-01T00:00:00Z,PS_C3,400000,3 PS_C4_856,2021-04-01T00:00:00Z,PS_C4,400000,4 -PS_C5_857,2021-04-01T00:00:00Z,PS_C5,400000,5 -PS_C6_858,2021-04-01T00:00:00Z,PS_C6,400000,6 -PS_C7_859,2021-04-01T00:00:00Z,PS_C7,400000,7 -PS_C8_860,2021-04-01T00:00:00Z,PS_C8,400000,8 -PS_C9_861,2021-04-01T00:00:00Z,PS_C9,184000,9 EB_C9_862,2021-04-01T00:00:00Z,EB_C9,216000,9 CS1_C2_863,2021-04-01T00:00:00Z,CS1_C2,666667,2 ST_C1_864,2021-04-01T00:00:00Z,ST_C1,1666667,1 @@ -868,33 +853,18 @@ PS_C1_866,2021-05-01T00:00:00Z,PS_C1,400000,1 PS_C2_867,2021-05-01T00:00:00Z,PS_C2,400000,2 PS_C3_868,2021-05-01T00:00:00Z,PS_C3,400000,3 PS_C4_869,2021-05-01T00:00:00Z,PS_C4,400000,4 -PS_C5_870,2021-05-01T00:00:00Z,PS_C5,400000,5 -PS_C6_871,2021-05-01T00:00:00Z,PS_C6,400000,6 -PS_C7_872,2021-05-01T00:00:00Z,PS_C7,400000,7 -PS_C8_873,2021-05-01T00:00:00Z,PS_C8,400000,8 -PS_C9_874,2021-05-01T00:00:00Z,PS_C9,184000,9 EB_C9_875,2021-05-01T00:00:00Z,EB_C9,216000,9 PS_C0_876,2021-06-01T00:00:00Z,PS_C0,400000,0 PS_C1_877,2021-06-01T00:00:00Z,PS_C1,400000,1 PS_C2_878,2021-06-01T00:00:00Z,PS_C2,400000,2 PS_C3_879,2021-06-01T00:00:00Z,PS_C3,400000,3 PS_C4_880,2021-06-01T00:00:00Z,PS_C4,400000,4 -PS_C5_881,2021-06-01T00:00:00Z,PS_C5,400000,5 -PS_C6_882,2021-06-01T00:00:00Z,PS_C6,400000,6 -PS_C7_883,2021-06-01T00:00:00Z,PS_C7,400000,7 -PS_C8_884,2021-06-01T00:00:00Z,PS_C8,400000,8 -PS_C9_885,2021-06-01T00:00:00Z,PS_C9,184000,9 EB_C9_886,2021-06-01T00:00:00Z,EB_C9,216000,9 PS_C0_887,2021-07-01T00:00:00Z,PS_C0,400000,0 PS_C1_888,2021-07-01T00:00:00Z,PS_C1,400000,1 PS_C2_889,2021-07-01T00:00:00Z,PS_C2,400000,2 PS_C3_890,2021-07-01T00:00:00Z,PS_C3,400000,3 PS_C4_891,2021-07-01T00:00:00Z,PS_C4,400000,4 -PS_C5_892,2021-07-01T00:00:00Z,PS_C5,400000,5 -PS_C6_893,2021-07-01T00:00:00Z,PS_C6,400000,6 -PS_C7_894,2021-07-01T00:00:00Z,PS_C7,400000,7 -PS_C8_895,2021-07-01T00:00:00Z,PS_C8,400000,8 -PS_C9_896,2021-07-01T00:00:00Z,PS_C9,184000,9 EB_C9_897,2021-07-01T00:00:00Z,EB_C9,216000,9 ST_C1_898,2021-07-01T00:00:00Z,ST_C1,1666667,1 PS_C0_899,2021-08-01T00:00:00Z,PS_C0,400000,0 @@ -902,33 +872,18 @@ PS_C1_900,2021-08-01T00:00:00Z,PS_C1,400000,1 PS_C2_901,2021-08-01T00:00:00Z,PS_C2,400000,2 PS_C3_902,2021-08-01T00:00:00Z,PS_C3,400000,3 PS_C4_903,2021-08-01T00:00:00Z,PS_C4,400000,4 -PS_C5_904,2021-08-01T00:00:00Z,PS_C5,400000,5 -PS_C6_905,2021-08-01T00:00:00Z,PS_C6,400000,6 -PS_C7_906,2021-08-01T00:00:00Z,PS_C7,400000,7 -PS_C8_907,2021-08-01T00:00:00Z,PS_C8,400000,8 -PS_C9_908,2021-08-01T00:00:00Z,PS_C9,184000,9 EB_C9_909,2021-08-01T00:00:00Z,EB_C9,216000,9 PS_C0_910,2021-09-01T00:00:00Z,PS_C0,400000,0 PS_C1_911,2021-09-01T00:00:00Z,PS_C1,400000,1 PS_C2_912,2021-09-01T00:00:00Z,PS_C2,400000,2 PS_C3_913,2021-09-01T00:00:00Z,PS_C3,400000,3 PS_C4_914,2021-09-01T00:00:00Z,PS_C4,400000,4 -PS_C5_915,2021-09-01T00:00:00Z,PS_C5,400000,5 -PS_C6_916,2021-09-01T00:00:00Z,PS_C6,400000,6 -PS_C7_917,2021-09-01T00:00:00Z,PS_C7,400000,7 -PS_C8_918,2021-09-01T00:00:00Z,PS_C8,400000,8 -PS_C9_919,2021-09-01T00:00:00Z,PS_C9,184000,9 EB_C9_920,2021-09-01T00:00:00Z,EB_C9,216000,9 PS_C0_921,2021-10-01T00:00:00Z,PS_C0,400000,0 PS_C1_922,2021-10-01T00:00:00Z,PS_C1,400000,1 PS_C2_923,2021-10-01T00:00:00Z,PS_C2,400000,2 PS_C3_924,2021-10-01T00:00:00Z,PS_C3,400000,3 PS_C4_925,2021-10-01T00:00:00Z,PS_C4,400000,4 -PS_C5_926,2021-10-01T00:00:00Z,PS_C5,400000,5 -PS_C6_927,2021-10-01T00:00:00Z,PS_C6,400000,6 -PS_C7_928,2021-10-01T00:00:00Z,PS_C7,400000,7 -PS_C8_929,2021-10-01T00:00:00Z,PS_C8,400000,8 -PS_C9_930,2021-10-01T00:00:00Z,PS_C9,184000,9 EB_C9_931,2021-10-01T00:00:00Z,EB_C9,216000,9 ST_C1_932,2021-10-01T00:00:00Z,ST_C1,1666667,1 PS_C0_933,2021-11-01T00:00:00Z,PS_C0,400000,0 @@ -936,384 +891,429 @@ PS_C1_934,2021-11-01T00:00:00Z,PS_C1,400000,1 PS_C2_935,2021-11-01T00:00:00Z,PS_C2,400000,2 PS_C3_936,2021-11-01T00:00:00Z,PS_C3,400000,3 PS_C4_937,2021-11-01T00:00:00Z,PS_C4,400000,4 -PS_C5_938,2021-11-01T00:00:00Z,PS_C5,400000,5 -PS_C6_939,2021-11-01T00:00:00Z,PS_C6,400000,6 -PS_C7_940,2021-11-01T00:00:00Z,PS_C7,400000,7 -PS_C8_941,2021-11-01T00:00:00Z,PS_C8,400000,8 -PS_C9_942,2021-11-01T00:00:00Z,PS_C9,184000,9 EB_C9_943,2021-11-01T00:00:00Z,EB_C9,216000,9 PS_C0_944,2021-12-01T00:00:00Z,PS_C0,400000,0 PS_C1_945,2021-12-01T00:00:00Z,PS_C1,400000,1 PS_C2_946,2021-12-01T00:00:00Z,PS_C2,400000,2 PS_C3_947,2021-12-01T00:00:00Z,PS_C3,400000,3 PS_C4_948,2021-12-01T00:00:00Z,PS_C4,400000,4 -PS_C5_949,2021-12-01T00:00:00Z,PS_C5,400000,5 -PS_C6_950,2021-12-01T00:00:00Z,PS_C6,400000,6 -PS_C7_951,2021-12-01T00:00:00Z,PS_C7,400000,7 -PS_C8_952,2021-12-01T00:00:00Z,PS_C8,400000,8 -PS_C9_953,2021-12-01T00:00:00Z,PS_C9,176000,9 EB_C9_954,2021-12-01T00:00:00Z,EB_C9,224000,9 PS_C0_955,2022-01-01T00:00:00Z,PS_C0,400000,0 PS_C1_956,2022-01-01T00:00:00Z,PS_C1,400000,1 PS_C2_957,2022-01-01T00:00:00Z,PS_C2,400000,2 PS_C3_958,2022-01-01T00:00:00Z,PS_C3,400000,3 PS_C4_959,2022-01-01T00:00:00Z,PS_C4,400000,4 -PS_C5_960,2022-01-01T00:00:00Z,PS_C5,400000,5 -PS_C6_961,2022-01-01T00:00:00Z,PS_C6,400000,6 -PS_C7_962,2022-01-01T00:00:00Z,PS_C7,400000,7 -PS_C8_963,2022-01-01T00:00:00Z,PS_C8,400000,8 -PS_C9_964,2022-01-01T00:00:00Z,PS_C9,400000,9 ST_C1_965,2022-01-01T00:00:00Z,ST_C1,1666667,1 PS_C0_966,2022-02-01T00:00:00Z,PS_C0,400000,0 PS_C1_967,2022-02-01T00:00:00Z,PS_C1,400000,1 PS_C2_968,2022-02-01T00:00:00Z,PS_C2,400000,2 PS_C3_969,2022-02-01T00:00:00Z,PS_C3,400000,3 PS_C4_970,2022-02-01T00:00:00Z,PS_C4,400000,4 -PS_C5_971,2022-02-01T00:00:00Z,PS_C5,400000,5 -PS_C6_972,2022-02-01T00:00:00Z,PS_C6,400000,6 -PS_C7_973,2022-02-01T00:00:00Z,PS_C7,400000,7 -PS_C8_974,2022-02-01T00:00:00Z,PS_C8,400000,8 -PS_C9_975,2022-02-01T00:00:00Z,PS_C9,400000,9 PS_C0_976,2022-03-01T00:00:00Z,PS_C0,400000,0 PS_C1_977,2022-03-01T00:00:00Z,PS_C1,400000,1 PS_C2_978,2022-03-01T00:00:00Z,PS_C2,400000,2 PS_C3_979,2022-03-01T00:00:00Z,PS_C3,400000,3 PS_C4_980,2022-03-01T00:00:00Z,PS_C4,400000,4 -PS_C5_981,2022-03-01T00:00:00Z,PS_C5,400000,5 -PS_C6_982,2022-03-01T00:00:00Z,PS_C6,400000,6 -PS_C7_983,2022-03-01T00:00:00Z,PS_C7,400000,7 -PS_C8_984,2022-03-01T00:00:00Z,PS_C8,400000,8 -PS_C9_985,2022-03-01T00:00:00Z,PS_C9,400000,9 PS_C0_986,2022-04-01T00:00:00Z,PS_C0,400000,0 PS_C1_987,2022-04-01T00:00:00Z,PS_C1,400000,1 PS_C2_988,2022-04-01T00:00:00Z,PS_C2,400000,2 PS_C3_989,2022-04-01T00:00:00Z,PS_C3,400000,3 PS_C4_990,2022-04-01T00:00:00Z,PS_C4,400000,4 -PS_C5_991,2022-04-01T00:00:00Z,PS_C5,400000,5 -PS_C6_992,2022-04-01T00:00:00Z,PS_C6,400000,6 -PS_C7_993,2022-04-01T00:00:00Z,PS_C7,400000,7 -PS_C8_994,2022-04-01T00:00:00Z,PS_C8,400000,8 -PS_C9_995,2022-04-01T00:00:00Z,PS_C9,400000,9 ST_C1_996,2022-04-01T00:00:00Z,ST_C1,1666667,1 PS_C0_997,2022-05-01T00:00:00Z,PS_C0,400000,0 PS_C1_998,2022-05-01T00:00:00Z,PS_C1,400000,1 PS_C2_999,2022-05-01T00:00:00Z,PS_C2,400000,2 PS_C3_1000,2022-05-01T00:00:00Z,PS_C3,400000,3 PS_C4_1001,2022-05-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1002,2022-05-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1003,2022-05-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1004,2022-05-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1005,2022-05-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1006,2022-05-01T00:00:00Z,PS_C9,400000,9 PS_C0_1007,2022-06-01T00:00:00Z,PS_C0,400000,0 PS_C1_1008,2022-06-01T00:00:00Z,PS_C1,400000,1 PS_C2_1009,2022-06-01T00:00:00Z,PS_C2,400000,2 PS_C3_1010,2022-06-01T00:00:00Z,PS_C3,400000,3 PS_C4_1011,2022-06-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1012,2022-06-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1013,2022-06-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1014,2022-06-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1015,2022-06-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1016,2022-06-01T00:00:00Z,PS_C9,400000,9 PS_C0_1017,2022-07-01T00:00:00Z,PS_C0,400000,0 PS_C1_1018,2022-07-01T00:00:00Z,PS_C1,400000,1 PS_C2_1019,2022-07-01T00:00:00Z,PS_C2,400000,2 PS_C3_1020,2022-07-01T00:00:00Z,PS_C3,400000,3 PS_C4_1021,2022-07-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1022,2022-07-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1023,2022-07-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1024,2022-07-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1025,2022-07-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1026,2022-07-01T00:00:00Z,PS_C9,400000,9 ST_C1_1027,2022-07-01T00:00:00Z,ST_C1,1666667,1 PS_C0_1028,2022-08-01T00:00:00Z,PS_C0,400000,0 PS_C1_1029,2022-08-01T00:00:00Z,PS_C1,400000,1 PS_C2_1030,2022-08-01T00:00:00Z,PS_C2,400000,2 PS_C3_1031,2022-08-01T00:00:00Z,PS_C3,400000,3 PS_C4_1032,2022-08-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1033,2022-08-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1034,2022-08-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1035,2022-08-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1036,2022-08-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1037,2022-08-01T00:00:00Z,PS_C9,400000,9 PS_C0_1038,2022-09-01T00:00:00Z,PS_C0,400000,0 PS_C1_1039,2022-09-01T00:00:00Z,PS_C1,400000,1 PS_C2_1040,2022-09-01T00:00:00Z,PS_C2,400000,2 PS_C3_1041,2022-09-01T00:00:00Z,PS_C3,400000,3 PS_C4_1042,2022-09-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1043,2022-09-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1044,2022-09-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1045,2022-09-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1046,2022-09-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1047,2022-09-01T00:00:00Z,PS_C9,400000,9 PS_C0_1048,2022-10-01T00:00:00Z,PS_C0,400000,0 PS_C1_1049,2022-10-01T00:00:00Z,PS_C1,400000,1 PS_C2_1050,2022-10-01T00:00:00Z,PS_C2,400000,2 PS_C3_1051,2022-10-01T00:00:00Z,PS_C3,400000,3 PS_C4_1052,2022-10-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1053,2022-10-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1054,2022-10-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1055,2022-10-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1056,2022-10-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1057,2022-10-01T00:00:00Z,PS_C9,400000,9 ST_C1_1058,2022-10-01T00:00:00Z,ST_C1,1666667,1 PS_C0_1059,2022-11-01T00:00:00Z,PS_C0,400000,0 PS_C1_1060,2022-11-01T00:00:00Z,PS_C1,400000,1 PS_C2_1061,2022-11-01T00:00:00Z,PS_C2,400000,2 PS_C3_1062,2022-11-01T00:00:00Z,PS_C3,400000,3 PS_C4_1063,2022-11-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1064,2022-11-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1065,2022-11-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1066,2022-11-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1067,2022-11-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1068,2022-11-01T00:00:00Z,PS_C9,400000,9 -PS_C0_1069,2022-12-01T00:00:00Z,PS_C0,400000,0 -PS_C1_1070,2022-12-01T00:00:00Z,PS_C1,400000,1 -PS_C2_1071,2022-12-01T00:00:00Z,PS_C2,400000,2 -PS_C3_1072,2022-12-01T00:00:00Z,PS_C3,400000,3 -PS_C4_1073,2022-12-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1074,2022-12-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1075,2022-12-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1076,2022-12-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1077,2022-12-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1078,2022-12-01T00:00:00Z,PS_C9,400000,9 PS_C0_1079,2023-01-01T00:00:00Z,PS_C0,400000,0 PS_C1_1080,2023-01-01T00:00:00Z,PS_C1,400000,1 PS_C2_1081,2023-01-01T00:00:00Z,PS_C2,400000,2 PS_C3_1082,2023-01-01T00:00:00Z,PS_C3,400000,3 PS_C4_1083,2023-01-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1084,2023-01-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1085,2023-01-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1086,2023-01-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1087,2023-01-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1088,2023-01-01T00:00:00Z,PS_C9,400000,9 PS_C0_1089,2023-02-01T00:00:00Z,PS_C0,400000,0 PS_C1_1090,2023-02-01T00:00:00Z,PS_C1,400000,1 PS_C2_1091,2023-02-01T00:00:00Z,PS_C2,400000,2 PS_C3_1092,2023-02-01T00:00:00Z,PS_C3,400000,3 PS_C4_1093,2023-02-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1094,2023-02-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1095,2023-02-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1096,2023-02-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1097,2023-02-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1098,2023-02-01T00:00:00Z,PS_C9,400000,9 PS_C0_1099,2023-03-01T00:00:00Z,PS_C0,400000,0 PS_C1_1100,2023-03-01T00:00:00Z,PS_C1,400000,1 PS_C2_1101,2023-03-01T00:00:00Z,PS_C2,400000,2 PS_C3_1102,2023-03-01T00:00:00Z,PS_C3,400000,3 PS_C4_1103,2023-03-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1104,2023-03-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1105,2023-03-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1106,2023-03-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1107,2023-03-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1108,2023-03-01T00:00:00Z,PS_C9,400000,9 PS_C0_1109,2023-04-01T00:00:00Z,PS_C0,400000,0 PS_C1_1110,2023-04-01T00:00:00Z,PS_C1,400000,1 PS_C2_1111,2023-04-01T00:00:00Z,PS_C2,400000,2 PS_C3_1112,2023-04-01T00:00:00Z,PS_C3,400000,3 PS_C4_1113,2023-04-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1114,2023-04-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1115,2023-04-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1116,2023-04-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1117,2023-04-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1118,2023-04-01T00:00:00Z,PS_C9,400000,9 PS_C0_1119,2023-05-01T00:00:00Z,PS_C0,400000,0 PS_C1_1120,2023-05-01T00:00:00Z,PS_C1,400000,1 PS_C2_1121,2023-05-01T00:00:00Z,PS_C2,400000,2 PS_C3_1122,2023-05-01T00:00:00Z,PS_C3,400000,3 PS_C4_1123,2023-05-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1124,2023-05-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1125,2023-05-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1126,2023-05-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1127,2023-05-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1128,2023-05-01T00:00:00Z,PS_C9,400000,9 PS_C0_1129,2023-06-01T00:00:00Z,PS_C0,400000,0 PS_C1_1130,2023-06-01T00:00:00Z,PS_C1,400000,1 PS_C2_1131,2023-06-01T00:00:00Z,PS_C2,400000,2 PS_C3_1132,2023-06-01T00:00:00Z,PS_C3,400000,3 PS_C4_1133,2023-06-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1134,2023-06-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1135,2023-06-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1136,2023-06-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1137,2023-06-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1138,2023-06-01T00:00:00Z,PS_C9,400000,9 PS_C0_1139,2023-07-01T00:00:00Z,PS_C0,400000,0 PS_C1_1140,2023-07-01T00:00:00Z,PS_C1,400000,1 PS_C2_1141,2023-07-01T00:00:00Z,PS_C2,400000,2 PS_C3_1142,2023-07-01T00:00:00Z,PS_C3,400000,3 PS_C4_1143,2023-07-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1144,2023-07-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1145,2023-07-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1146,2023-07-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1147,2023-07-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1148,2023-07-01T00:00:00Z,PS_C9,400000,9 PS_C0_1149,2023-08-01T00:00:00Z,PS_C0,400000,0 PS_C1_1150,2023-08-01T00:00:00Z,PS_C1,400000,1 PS_C2_1151,2023-08-01T00:00:00Z,PS_C2,400000,2 PS_C3_1152,2023-08-01T00:00:00Z,PS_C3,400000,3 PS_C4_1153,2023-08-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1154,2023-08-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1155,2023-08-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1156,2023-08-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1157,2023-08-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1158,2023-08-01T00:00:00Z,PS_C9,400000,9 PS_C0_1159,2023-09-01T00:00:00Z,PS_C0,400000,0 PS_C1_1160,2023-09-01T00:00:00Z,PS_C1,400000,1 PS_C2_1161,2023-09-01T00:00:00Z,PS_C2,400000,2 PS_C3_1162,2023-09-01T00:00:00Z,PS_C3,400000,3 PS_C4_1163,2023-09-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1164,2023-09-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1165,2023-09-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1166,2023-09-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1167,2023-09-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1168,2023-09-01T00:00:00Z,PS_C9,400000,9 PS_C0_1169,2023-10-01T00:00:00Z,PS_C0,400000,0 PS_C1_1170,2023-10-01T00:00:00Z,PS_C1,400000,1 PS_C2_1171,2023-10-01T00:00:00Z,PS_C2,400000,2 PS_C3_1172,2023-10-01T00:00:00Z,PS_C3,400000,3 PS_C4_1173,2023-10-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1174,2023-10-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1175,2023-10-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1176,2023-10-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1177,2023-10-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1178,2023-10-01T00:00:00Z,PS_C9,400000,9 PS_C0_1179,2023-11-01T00:00:00Z,PS_C0,400000,0 PS_C1_1180,2023-11-01T00:00:00Z,PS_C1,400000,1 PS_C2_1181,2023-11-01T00:00:00Z,PS_C2,400000,2 PS_C3_1182,2023-11-01T00:00:00Z,PS_C3,400000,3 PS_C4_1183,2023-11-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1184,2023-11-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1185,2023-11-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1186,2023-11-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1187,2023-11-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1188,2023-11-01T00:00:00Z,PS_C9,400000,9 -PS_C0_1189,2023-12-01T00:00:00Z,PS_C0,400000,0 -PS_C1_1190,2023-12-01T00:00:00Z,PS_C1,400000,1 -PS_C2_1191,2023-12-01T00:00:00Z,PS_C2,400000,2 -PS_C3_1192,2023-12-01T00:00:00Z,PS_C3,400000,3 -PS_C4_1193,2023-12-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1194,2023-12-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1195,2023-12-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1196,2023-12-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1197,2023-12-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1198,2023-12-01T00:00:00Z,PS_C9,400000,9 PS_C0_1199,2024-01-01T00:00:00Z,PS_C0,400000,0 PS_C1_1200,2024-01-01T00:00:00Z,PS_C1,400000,1 PS_C2_1201,2024-01-01T00:00:00Z,PS_C2,400000,2 PS_C3_1202,2024-01-01T00:00:00Z,PS_C3,400000,3 PS_C4_1203,2024-01-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1204,2024-01-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1205,2024-01-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1206,2024-01-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1207,2024-01-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1208,2024-01-01T00:00:00Z,PS_C9,400000,9 PS_C0_1209,2024-02-01T00:00:00Z,PS_C0,400000,0 PS_C1_1210,2024-02-01T00:00:00Z,PS_C1,400000,1 PS_C2_1211,2024-02-01T00:00:00Z,PS_C2,400000,2 PS_C3_1212,2024-02-01T00:00:00Z,PS_C3,400000,3 PS_C4_1213,2024-02-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1214,2024-02-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1215,2024-02-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1216,2024-02-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1217,2024-02-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1218,2024-02-01T00:00:00Z,PS_C9,400000,9 PS_C0_1219,2024-03-01T00:00:00Z,PS_C0,400000,0 PS_C1_1220,2024-03-01T00:00:00Z,PS_C1,400000,1 PS_C2_1221,2024-03-01T00:00:00Z,PS_C2,400000,2 PS_C3_1222,2024-03-01T00:00:00Z,PS_C3,400000,3 PS_C4_1223,2024-03-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1224,2024-03-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1225,2024-03-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1226,2024-03-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1227,2024-03-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1228,2024-03-01T00:00:00Z,PS_C9,400000,9 PS_C0_1229,2024-04-01T00:00:00Z,PS_C0,400000,0 PS_C1_1230,2024-04-01T00:00:00Z,PS_C1,400000,1 PS_C2_1231,2024-04-01T00:00:00Z,PS_C2,400000,2 PS_C3_1232,2024-04-01T00:00:00Z,PS_C3,400000,3 PS_C4_1233,2024-04-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1234,2024-04-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1235,2024-04-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1236,2024-04-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1237,2024-04-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1238,2024-04-01T00:00:00Z,PS_C9,400000,9 PS_C0_1239,2024-05-01T00:00:00Z,PS_C0,400000,0 PS_C1_1240,2024-05-01T00:00:00Z,PS_C1,400000,1 PS_C2_1241,2024-05-01T00:00:00Z,PS_C2,400000,2 PS_C3_1242,2024-05-01T00:00:00Z,PS_C3,400000,3 PS_C4_1243,2024-05-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1244,2024-05-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1245,2024-05-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1246,2024-05-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1247,2024-05-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1248,2024-05-01T00:00:00Z,PS_C9,400000,9 PS_C0_1249,2024-06-01T00:00:00Z,PS_C0,400000,0 PS_C1_1250,2024-06-01T00:00:00Z,PS_C1,400000,1 PS_C2_1251,2024-06-01T00:00:00Z,PS_C2,400000,2 PS_C3_1252,2024-06-01T00:00:00Z,PS_C3,400000,3 PS_C4_1253,2024-06-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1254,2024-06-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1255,2024-06-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1256,2024-06-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1257,2024-06-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1258,2024-06-01T00:00:00Z,PS_C9,400000,9 PS_C0_1259,2024-07-01T00:00:00Z,PS_C0,400000,0 PS_C1_1260,2024-07-01T00:00:00Z,PS_C1,400000,1 PS_C2_1261,2024-07-01T00:00:00Z,PS_C2,400000,2 PS_C3_1262,2024-07-01T00:00:00Z,PS_C3,400000,3 PS_C4_1263,2024-07-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1264,2024-07-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1265,2024-07-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1266,2024-07-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1267,2024-07-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1268,2024-07-01T00:00:00Z,PS_C9,400000,9 PS_C0_1269,2024-08-01T00:00:00Z,PS_C0,400000,0 PS_C1_1270,2024-08-01T00:00:00Z,PS_C1,400000,1 PS_C2_1271,2024-08-01T00:00:00Z,PS_C2,400000,2 PS_C3_1272,2024-08-01T00:00:00Z,PS_C3,400000,3 PS_C4_1273,2024-08-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1274,2024-08-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1275,2024-08-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1276,2024-08-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1277,2024-08-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1278,2024-08-01T00:00:00Z,PS_C9,400000,9 PS_C0_1279,2024-09-01T00:00:00Z,PS_C0,400000,0 PS_C1_1280,2024-09-01T00:00:00Z,PS_C1,400000,1 PS_C2_1281,2024-09-01T00:00:00Z,PS_C2,400000,2 PS_C3_1282,2024-09-01T00:00:00Z,PS_C3,400000,3 PS_C4_1283,2024-09-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1284,2024-09-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1285,2024-09-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1286,2024-09-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1287,2024-09-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1288,2024-09-01T00:00:00Z,PS_C9,400000,9 PS_C0_1289,2024-10-01T00:00:00Z,PS_C0,400000,0 PS_C1_1290,2024-10-01T00:00:00Z,PS_C1,400000,1 PS_C2_1291,2024-10-01T00:00:00Z,PS_C2,400000,2 PS_C3_1292,2024-10-01T00:00:00Z,PS_C3,400000,3 PS_C4_1293,2024-10-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1294,2024-10-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1295,2024-10-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1296,2024-10-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1297,2024-10-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1298,2024-10-01T00:00:00Z,PS_C9,400000,9 PS_C0_1299,2024-11-01T00:00:00Z,PS_C0,400000,0 PS_C1_1300,2024-11-01T00:00:00Z,PS_C1,400000,1 PS_C2_1301,2024-11-01T00:00:00Z,PS_C2,400000,2 PS_C3_1302,2024-11-01T00:00:00Z,PS_C3,400000,3 PS_C4_1303,2024-11-01T00:00:00Z,PS_C4,400000,4 -PS_C5_1304,2024-11-01T00:00:00Z,PS_C5,400000,5 -PS_C6_1305,2024-11-01T00:00:00Z,PS_C6,400000,6 -PS_C7_1306,2024-11-01T00:00:00Z,PS_C7,400000,7 -PS_C8_1307,2024-11-01T00:00:00Z,PS_C8,400000,8 -PS_C9_1308,2024-11-01T00:00:00Z,PS_C9,400000,9 -PS_C0_1309,2024-12-01T00:00:00Z,PS_C0,1200000,0 -PS_C1_1310,2024-12-01T00:00:00Z,PS_C1,1200000,1 -PS_C2_1311,2024-12-01T00:00:00Z,PS_C2,1200000,2 -PS_C3_1312,2024-12-01T00:00:00Z,PS_C3,1200000,3 -PS_C4_1313,2024-12-01T00:00:00Z,PS_C4,1200000,4 -PS_C5_1314,2024-12-01T00:00:00Z,PS_C5,1200000,5 -PS_C6_1315,2024-12-01T00:00:00Z,PS_C6,1200000,6 -PS_C7_1316,2024-12-01T00:00:00Z,PS_C7,1200000,7 -PS_C8_1317,2024-12-01T00:00:00Z,PS_C8,1200000,8 -PS_C9_1318,2024-12-01T00:00:00Z,PS_C9,1200000,9 +PS_C0_1069,2025-01-01T00:00:00Z,PS_C0,400000,0 +PS_C1_1070,2025-01-01T00:00:00Z,PS_C1,400000,1 +PS_C2_1071,2025-01-01T00:00:00Z,PS_C2,400000,2 +PS_C3_1072,2025-01-01T00:00:00Z,PS_C3,400000,3 +PS_C4_1073,2025-01-01T00:00:00Z,PS_C4,400000,4 +PS_C5_833,2025-02-01T00:00:00Z,PS_C5,400000,5 +PS_C6_834,2025-02-01T00:00:00Z,PS_C6,400000,6 +PS_C7_835,2025-02-01T00:00:00Z,PS_C7,400000,7 +PS_C8_836,2025-02-01T00:00:00Z,PS_C8,400000,8 +PS_C0_1189,2025-02-01T00:00:00Z,PS_C0,400000,0 +PS_C5_845,2025-03-01T00:00:00Z,PS_C5,400000,5 +PS_C6_846,2025-03-01T00:00:00Z,PS_C6,400000,6 +PS_C7_847,2025-03-01T00:00:00Z,PS_C7,400000,7 +PS_C8_848,2025-03-01T00:00:00Z,PS_C8,400000,8 +PS_C1_1190,2025-03-01T00:00:00Z,PS_C1,400000,1 +PS_C5_857,2025-04-01T00:00:00Z,PS_C5,400000,5 +PS_C6_858,2025-04-01T00:00:00Z,PS_C6,400000,6 +PS_C7_859,2025-04-01T00:00:00Z,PS_C7,400000,7 +PS_C8_860,2025-04-01T00:00:00Z,PS_C8,400000,8 +PS_C2_1191,2025-04-01T00:00:00Z,PS_C2,400000,2 +PS_C5_870,2025-05-01T00:00:00Z,PS_C5,400000,5 +PS_C6_871,2025-05-01T00:00:00Z,PS_C6,400000,6 +PS_C7_872,2025-05-01T00:00:00Z,PS_C7,400000,7 +PS_C8_873,2025-05-01T00:00:00Z,PS_C8,400000,8 +PS_C3_1192,2025-05-01T00:00:00Z,PS_C3,400000,3 +PS_C5_881,2025-06-01T00:00:00Z,PS_C5,400000,5 +PS_C6_882,2025-06-01T00:00:00Z,PS_C6,400000,6 +PS_C7_883,2025-06-01T00:00:00Z,PS_C7,400000,7 +PS_C8_884,2025-06-01T00:00:00Z,PS_C8,400000,8 +PS_C4_1193,2025-06-01T00:00:00Z,PS_C4,400000,4 +PS_C5_892,2025-07-01T00:00:00Z,PS_C5,400000,5 +PS_C6_893,2025-07-01T00:00:00Z,PS_C6,400000,6 +PS_C7_894,2025-07-01T00:00:00Z,PS_C7,400000,7 +PS_C8_895,2025-07-01T00:00:00Z,PS_C8,400000,8 +PS_C9_896,2025-07-01T00:00:00Z,PS_C9,184000,9 +PS_C9_837,2025-07-01T00:00:00Z,PS_C9,184000,9 +PS_C5_904,2025-08-01T00:00:00Z,PS_C5,400000,5 +PS_C6_905,2025-08-01T00:00:00Z,PS_C6,400000,6 +PS_C7_906,2025-08-01T00:00:00Z,PS_C7,400000,7 +PS_C8_907,2025-08-01T00:00:00Z,PS_C8,400000,8 +PS_C9_908,2025-08-01T00:00:00Z,PS_C9,184000,9 +PS_C9_849,2025-08-01T00:00:00Z,PS_C9,184000,9 +PS_C5_915,2025-09-01T00:00:00Z,PS_C5,400000,5 +PS_C6_916,2025-09-01T00:00:00Z,PS_C6,400000,6 +PS_C7_917,2025-09-01T00:00:00Z,PS_C7,400000,7 +PS_C8_918,2025-09-01T00:00:00Z,PS_C8,400000,8 +PS_C9_919,2025-09-01T00:00:00Z,PS_C9,184000,9 +PS_C9_861,2025-09-01T00:00:00Z,PS_C9,184000,9 +PS_C5_926,2025-10-01T00:00:00Z,PS_C5,400000,5 +PS_C6_927,2025-10-01T00:00:00Z,PS_C6,400000,6 +PS_C7_928,2025-10-01T00:00:00Z,PS_C7,400000,7 +PS_C8_929,2025-10-01T00:00:00Z,PS_C8,400000,8 +PS_C9_930,2025-10-01T00:00:00Z,PS_C9,184000,9 +PS_C9_874,2025-10-01T00:00:00Z,PS_C9,184000,9 +PS_C5_938,2025-11-01T00:00:00Z,PS_C5,400000,5 +PS_C6_939,2025-11-01T00:00:00Z,PS_C6,400000,6 +PS_C7_940,2025-11-01T00:00:00Z,PS_C7,400000,7 +PS_C8_941,2025-11-01T00:00:00Z,PS_C8,400000,8 +PS_C9_942,2025-11-01T00:00:00Z,PS_C9,184000,9 +PS_C9_885,2025-11-01T00:00:00Z,PS_C9,184000,9 +PS_C5_960,2026-01-01T00:00:00Z,PS_C5,400000,5 +PS_C6_961,2026-01-01T00:00:00Z,PS_C6,400000,6 +PS_C7_962,2026-01-01T00:00:00Z,PS_C7,400000,7 +PS_C8_963,2026-01-01T00:00:00Z,PS_C8,400000,8 +PS_C9_964,2026-01-01T00:00:00Z,PS_C9,400000,9 +PS_C5_971,2026-02-01T00:00:00Z,PS_C5,400000,5 +PS_C6_972,2026-02-01T00:00:00Z,PS_C6,400000,6 +PS_C7_973,2026-02-01T00:00:00Z,PS_C7,400000,7 +PS_C8_974,2026-02-01T00:00:00Z,PS_C8,400000,8 +PS_C9_975,2026-02-01T00:00:00Z,PS_C9,400000,9 +PS_C5_981,2026-03-01T00:00:00Z,PS_C5,400000,5 +PS_C6_982,2026-03-01T00:00:00Z,PS_C6,400000,6 +PS_C7_983,2026-03-01T00:00:00Z,PS_C7,400000,7 +PS_C8_984,2026-03-01T00:00:00Z,PS_C8,400000,8 +PS_C9_985,2026-03-01T00:00:00Z,PS_C9,400000,9 +PS_C5_991,2026-04-01T00:00:00Z,PS_C5,400000,5 +PS_C6_992,2026-04-01T00:00:00Z,PS_C6,400000,6 +PS_C7_993,2026-04-01T00:00:00Z,PS_C7,400000,7 +PS_C8_994,2026-04-01T00:00:00Z,PS_C8,400000,8 +PS_C9_995,2026-04-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1002,2026-05-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1003,2026-05-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1004,2026-05-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1005,2026-05-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1006,2026-05-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1012,2026-06-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1013,2026-06-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1014,2026-06-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1015,2026-06-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1016,2026-06-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1022,2026-07-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1023,2026-07-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1024,2026-07-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1025,2026-07-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1026,2026-07-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1033,2026-08-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1034,2026-08-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1035,2026-08-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1036,2026-08-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1037,2026-08-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1043,2026-09-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1044,2026-09-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1045,2026-09-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1046,2026-09-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1047,2026-09-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1053,2026-10-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1054,2026-10-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1055,2026-10-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1056,2026-10-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1057,2026-10-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1064,2026-11-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1065,2026-11-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1066,2026-11-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1067,2026-11-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1068,2026-11-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1084,2027-01-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1085,2027-01-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1086,2027-01-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1087,2027-01-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1088,2027-01-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1094,2027-02-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1095,2027-02-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1096,2027-02-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1097,2027-02-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1098,2027-02-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1104,2027-03-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1105,2027-03-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1106,2027-03-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1107,2027-03-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1108,2027-03-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1114,2027-04-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1115,2027-04-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1116,2027-04-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1117,2027-04-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1118,2027-04-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1124,2027-05-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1125,2027-05-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1126,2027-05-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1127,2027-05-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1128,2027-05-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1134,2027-06-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1135,2027-06-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1136,2027-06-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1137,2027-06-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1138,2027-06-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1144,2027-07-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1145,2027-07-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1146,2027-07-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1147,2027-07-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1148,2027-07-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1154,2027-08-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1155,2027-08-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1156,2027-08-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1157,2027-08-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1158,2027-08-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1164,2027-09-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1165,2027-09-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1166,2027-09-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1167,2027-09-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1168,2027-09-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1174,2027-10-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1175,2027-10-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1176,2027-10-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1177,2027-10-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1178,2027-10-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1184,2027-11-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1185,2027-11-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1186,2027-11-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1187,2027-11-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1188,2027-11-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1204,2028-01-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1205,2028-01-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1206,2028-01-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1207,2028-01-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1208,2028-01-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1214,2028-02-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1215,2028-02-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1216,2028-02-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1217,2028-02-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1218,2028-02-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1224,2028-03-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1225,2028-03-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1226,2028-03-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1227,2028-03-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1228,2028-03-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1234,2028-04-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1235,2028-04-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1236,2028-04-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1237,2028-04-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1238,2028-04-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1244,2028-05-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1245,2028-05-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1246,2028-05-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1247,2028-05-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1248,2028-05-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1254,2028-06-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1255,2028-06-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1256,2028-06-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1257,2028-06-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1258,2028-06-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1264,2028-07-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1265,2028-07-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1266,2028-07-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1267,2028-07-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1268,2028-07-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1274,2028-08-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1275,2028-08-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1276,2028-08-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1277,2028-08-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1278,2028-08-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1284,2028-09-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1285,2028-09-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1286,2028-09-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1287,2028-09-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1288,2028-09-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1294,2028-10-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1295,2028-10-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1296,2028-10-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1297,2028-10-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1298,2028-10-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1304,2028-11-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1305,2028-11-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1306,2028-11-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1307,2028-11-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1308,2028-11-01T00:00:00Z,PS_C9,400000,9 +PS_C0_1309,2029-01-01T00:00:00Z,PS_C0,1200000,0 +PS_C5_949,2029-01-01T00:00:00Z,PS_C5,400000,5 +PS_C1_1310,2029-02-01T00:00:00Z,PS_C1,1200000,1 +PS_C6_950,2029-02-01T00:00:00Z,PS_C6,400000,6 +PS_C2_1311,2029-03-01T00:00:00Z,PS_C2,1200000,2 +PS_C7_951,2029-03-01T00:00:00Z,PS_C7,400000,7 +PS_C3_1312,2029-04-01T00:00:00Z,PS_C3,1200000,3 +PS_C8_952,2029-04-01T00:00:00Z,PS_C8,400000,8 +PS_C4_1313,2029-05-01T00:00:00Z,PS_C4,1200000,4 +PS_C9_953,2029-05-01T00:00:00Z,PS_C9,176000,9 +PS_C5_1314,2029-06-01T00:00:00Z,PS_C5,1200000,5 +PS_C5_1074,2029-06-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1315,2029-07-01T00:00:00Z,PS_C6,1200000,6 +PS_C6_1075,2029-07-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1316,2029-08-01T00:00:00Z,PS_C7,1200000,7 +PS_C7_1076,2029-08-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1317,2029-09-01T00:00:00Z,PS_C8,1200000,8 +PS_C8_1077,2029-09-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1318,2029-10-01T00:00:00Z,PS_C9,1200000,9 +PS_C9_1078,2029-10-01T00:00:00Z,PS_C9,400000,9 +PS_C5_1194,2029-11-01T00:00:00Z,PS_C5,400000,5 +PS_C6_1195,2029-11-01T00:00:00Z,PS_C6,400000,6 +PS_C7_1196,2029-11-01T00:00:00Z,PS_C7,400000,7 +PS_C8_1197,2029-11-01T00:00:00Z,PS_C8,400000,8 +PS_C9_1198,2029-11-01T00:00:00Z,PS_C9,400000,9 diff --git a/indexer/src/config/database.ts b/indexer/src/config/database.ts index 5b5b6ec1..7eab0642 100644 --- a/indexer/src/config/database.ts +++ b/indexer/src/config/database.ts @@ -9,7 +9,7 @@ const DB_PASSWORD = getRequiredEnvString('DB_PASSWORD'); const DB_NAME = getRequiredEnvString('DB_NAME'); const DB_HOST = getRequiredEnvString('DB_HOST'); const DB_SSL_ENABLED = getRequiredEnvString('DB_SSL_ENABLED'); -const DB_CONNECTION = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`; +const DB_CONNECTION = `postgres://${DB_USERNAME}:${encodeURIComponent(DB_PASSWORD)}@${DB_HOST}/${DB_NAME}`; const isSslEnabled = DB_SSL_ENABLED === 'true'; diff --git a/indexer/src/index.ts b/indexer/src/index.ts index 3fb47e26..7bf84417 100644 --- a/indexer/src/index.ts +++ b/indexer/src/index.ts @@ -8,8 +8,8 @@ import { usePostgraphile } from './server/metrics'; import { useKadenaGraphqlServer } from './kadena-server/server'; import { closeDatabase } from './config/database'; import { initializeDatabase } from './config/init'; -import { startGuardsBackfill } from './services/sync/guards'; import { startBackfillCoinbaseTransactions } from './services/sync/coinbase'; +import { backfillBalances } from './services/sync/balances'; program .option('-s, --streaming', 'Start streaming blockchain data') @@ -39,7 +39,9 @@ async function main() { if (options.streaming) { await startStreaming(); } else if (options.guards) { - await startGuardsBackfill(); + await backfillBalances(); + await closeDatabase(); + process.exit(0); } else if (options.coinbase) { await startBackfillCoinbaseTransactions(); } else if (options.oldGraphql) { diff --git a/indexer/src/kadena-server/utils/coin-circulation.ts b/indexer/src/kadena-server/utils/coin-circulation.ts index c2475086..652dcaf4 100644 --- a/indexer/src/kadena-server/utils/coin-circulation.ts +++ b/indexer/src/kadena-server/utils/coin-circulation.ts @@ -15,23 +15,21 @@ function calculateReward(csvContent: string, cutHeight: number): number { const averageHeight = cutHeight / 20; // number of chains let totalReward = 0; - let previousRow: RewardRow | null = null; - for (const row of parsed.data) { + for (let i = 0; i < parsed.data.length; i += 1) { + const row = parsed.data[i]; + const previousHeight = i === 0 ? 0 : parsed.data[i - 1][0]; const height = row[0]; const reward = row[1]; if (averageHeight < height) { - if (previousRow) { - const remainingHeight = height - averageHeight; - const proportionedReward = remainingHeight * reward; - totalReward += proportionedReward; - } + const remainingHeight = averageHeight - previousHeight; + const proportionedReward = remainingHeight * reward; + totalReward += proportionedReward; break; } - totalReward += reward; - previousRow = row; + totalReward = totalReward + reward * (height - previousHeight); } return totalReward; @@ -54,18 +52,13 @@ function calculateTokenPayments(csvContent: string, targetTimestamp: number): nu let totalSum = 0; let previousRow: CsvRow | null = null; + const targetDate = new Date(targetTimestamp / 1000); for (const row of parsed.data) { const creationTimeISO = row[1]; const amount = row[3]; - const creationTimestamp = new Date(creationTimeISO).getTime(); - - if (targetTimestamp < creationTimestamp) { - if (previousRow) { - const remainingTime = creationTimestamp - targetTimestamp; - const proportionedPayment = remainingTime * amount; - totalSum += proportionedPayment; - } + const creationDate = new Date(creationTimeISO); + if (targetDate < creationDate) { break; } diff --git a/indexer/src/services/sync/balances.ts b/indexer/src/services/sync/balances.ts new file mode 100644 index 00000000..45292533 --- /dev/null +++ b/indexer/src/services/sync/balances.ts @@ -0,0 +1,25 @@ +import { rootPgPool } from '../../config/database'; + +export async function backfillBalances() { + await rootPgPool.query( + ` + BEGIN; + SET enable_seqscan = OFF; + WITH combined AS ( + SELECT "chainId", "from_acct" AS "account", "modulename" AS "module" + FROM "Transfers" + UNION ALL + SELECT "chainId", "to_acct" AS "account", "modulename" AS "module" + FROM "Transfers" + ) + INSERT INTO "Balances" ("chainId", "account", "module", "createdAt", "updatedAt", "tokenId") + SELECT "chainId", "account", "module", NOW() AS "createdAt", NOW() AS "updatedAt", '' AS "tokenId" + FROM combined + GROUP BY "chainId", "account", "module" + ON CONFLICT ("chainId", "account", "module", "tokenId") DO NOTHING; + COMMIT; + `, + ); + + console.log('Balances backfilled successfully.'); +} diff --git a/indexer/src/services/sync/guards.ts b/indexer/src/services/sync/guards.ts index a3aea876..3f696b86 100644 --- a/indexer/src/services/sync/guards.ts +++ b/indexer/src/services/sync/guards.ts @@ -6,36 +6,17 @@ import Guard from '../../models/guard'; const CONCURRENCY_LIMIT = 4; // Number of concurrent fetches allowed const limitFetch = pLimit(CONCURRENCY_LIMIT); -export async function startGuardsBackfill() { - await sequelize.authenticate(); - console.log('Connected to the database.'); +export async function backfillGuards() { + console.log('Starting guards backfill ...'); - await rootPgPool.query( - ` - BEGIN; - SET enable_seqscan = OFF; - WITH combined AS ( - SELECT "chainId", "from_acct" AS "account", "modulename" AS "module" - FROM "Transfers" - UNION ALL - SELECT "chainId", "to_acct" AS "account", "modulename" AS "module" - FROM "Transfers" - ) - INSERT INTO "Balances" ("chainId", "account", "module", "createdAt", "updatedAt", "tokenId") - SELECT "chainId", "account", "module", NOW() AS "createdAt", NOW() AS "updatedAt", '' AS "tokenId" - FROM combined - GROUP BY "chainId", "account", "module" - ON CONFLICT ("chainId", "account", "module", "tokenId") DO NOTHING; - DELETE FROM "Guards"; - ALTER SEQUENCE "Guards_id_seq" RESTART WITH 1; - COMMIT; - `, - ); + const deleteGuardsQuery = ` + DELETE FROM "Guards"; + ALTER SEQUENCE "Guards_id_seq" RESTART WITH 1; + `; - console.log('Balances backfilled successfully.'); - console.log('Starting guards backfill ...'); + await rootPgPool.query(deleteGuardsQuery); - const limit = 10000; // Number of rows to process in one batch + const limit = 1000; // Number of rows to process in one batch let offset = 0; while (true) { @@ -86,6 +67,5 @@ export async function startGuardsBackfill() { } } - await closeDatabase(); - process.exit(0); + console.log('Guards backfilled successfully.'); } diff --git a/indexer/src/services/sync/payload.ts b/indexer/src/services/sync/payload.ts index 3454a1a3..31b52c85 100644 --- a/indexer/src/services/sync/payload.ts +++ b/indexer/src/services/sync/payload.ts @@ -3,7 +3,7 @@ import TransactionModel, { TransactionAttributes } from '../../models/transactio import Event, { EventAttributes } from '../../models/event'; import Transfer, { TransferAttributes } from '../../models/transfer'; import { getNftTransfers, getCoinTransfers } from './transfers'; -import { QueryTypes, Transaction } from 'sequelize'; +import { Transaction } from 'sequelize'; import Signer from '../../models/signer'; import Guard from '../../models/guard'; import { handleSingleQuery } from '../../kadena-server/utils/raw-query'; @@ -171,20 +171,16 @@ export async function processTransaction( ) .join(', '); - const query = ` + const newBalancesQuery = ` INSERT INTO "Balances" ("chainId", account, module, "tokenId", "hasTokenId", "createdAt", "updatedAt") VALUES ${values} ON CONFLICT ("chainId", account, module, "tokenId") DO NOTHING - RETURNING id, "chainId", account, module; `; - const insertedBalances = await sequelize.query(query, { - type: QueryTypes.SELECT, // Use SELECT to retrieve rows with RETURNING + await sequelize.query(newBalancesQuery, { transaction: tx, }); - await saveGuards(insertedBalances ?? [], tx); - return eventsAttributes; } catch (error) { console.error(`Error saving transaction to the database: ${error}`); @@ -228,11 +224,3 @@ export async function getGuardsFromBalances(balances: BalanceInsertResult[]) { return filteredGuards; } - -async function saveGuards(balances: BalanceInsertResult[], tx?: Transaction) { - const filteredGuards = await getGuardsFromBalances(balances); - await Guard.bulkCreate(filteredGuards, { - transaction: tx, - ignoreDuplicates: true, - }); -} diff --git a/indexer/src/services/sync/streaming.ts b/indexer/src/services/sync/streaming.ts index b9f12ad8..67e8ecaa 100644 --- a/indexer/src/services/sync/streaming.ts +++ b/indexer/src/services/sync/streaming.ts @@ -6,6 +6,7 @@ import { uint64ToInt64 } from '../../utils/int-uint-64'; import Block, { BlockAttributes } from '../../models/block'; import { sequelize } from '../../config/database'; import StreamingError from '../../models/streaming-error'; +import { backfillGuards } from './guards'; const SYNC_BASE_URL = getRequiredEnvString('SYNC_BASE_URL'); const SYNC_NETWORK = getRequiredEnvString('SYNC_NETWORK'); @@ -49,6 +50,9 @@ export async function startStreaming() { }, 1000 * 60 * 10, ); + + backfillGuards(); // run when initialize + setInterval(backfillGuards, 1000 * 60 * 60); // every one hour } function processPayload(payload: any) {