mirror of
https://github.com/alexgo-io/gaze-indexer.git
synced 2026-04-29 04:05:12 +08:00
* fix: don't remove first block * fix: make etching_terms nullable * fix: fix panic if empty pkscript * chore: change testnet starting block * feat: more logs * fix: extract tapscript bug * feat: more logs * fix: switch pk to block height * chore: remove redundant log * fix: repo * fix: not found error * fix: golangci-lint * feat: add etching tx hash to rune entries * feat: stop main if indexer failed * fix: check balance after populating current balance * fix: sql ambiguous column * feat: add tx hash and out index in tx output * fix: actually use transactions to write db * fix: create rune entry states only during flushes * fix: mint cap reached off by one * fix: debug log unsafe * feat: prevent processing of txs before activation height * feat: add rune number to rune entry * feat: include new rune entries in event hash and flushing * refactor(config): separate init and get config func Co-authored-by: Gaze <dev@gaze.network> * feat: remove annoying log Co-authored-by: Gaze <dev@gaze.network> * feat: mod tidy Co-authored-by: Gaze <dev@gaze.network> * refactor: move main to root Co-authored-by: Gaze <dev@gaze.network> * feat(cli): create cli commands Co-authored-by: Gaze <dev@gaze.network> * refactor: move main logic to command Co-authored-by: Gaze <dev@gaze.network> * doc: remove unused desc Co-authored-by: Gaze <dev@gaze.network> * refactor: test structure in runestone_test.go * fix: edict flaws were ignored * feat: more tests * refactor(cli): add local flag Co-authored-by: Gaze <dev@gaze.network> * feat: set symbol limit to utf8.MaxRune * refactor(cli): flags for each module Co-authored-by: Gaze <dev@gaze.network> * feat(cli): support db selection Co-authored-by: Gaze <dev@gaze.network> * fix: remove temp code Co-authored-by: Gaze <dev@gaze.network> * fix: get data from cache in processor first, then dg * feat(cli): add version command Co-authored-by: Gaze <dev@gaze.network> * doc(cli): add refactor plan Co-authored-by: Gaze <dev@gaze.network> * refactor(cli): rename files Co-authored-by: Gaze <dev@gaze.network> * feat: add main.go Co-authored-by: Gaze <dev@gaze.network> * feat: more tests * feat: add overflow err * feat: finish runestone tests * refactor(cli): separate protocol config and cli flag Co-authored-by: Gaze <dev@gaze.network> * chore(btc): update example config Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add get block header to datasource interface Co-authored-by: Gaze <dev@gaze.network> * feat(btc): reorg handling Co-authored-by: Gaze <dev@gaze.network> * fix: interface Co-authored-by: Gaze <dev@gaze.network> * fix: rename postgres config key * fix: migrated runes indexer integration to new cli * fix: commit every block * feat(btc): add revert data query Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add revert data to processor Co-authored-by: Gaze <dev@gaze.network> * feat: implement public errors * fix: use errs in api * refactor: move api and usecase outside of internal * feat: add custom opcode check for datapush * fix: break if input utxo is not P2TR * fix: zero len destination case * fix: get the rest of transaction data in GetTransaction * refactor: create subscription utils tools Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add btc_database from datasource Co-authored-by: Gaze <dev@gaze.network> * doc(btc): add note Co-authored-by: Gaze <dev@gaze.network> * wip(btc): imple prepare range func Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add pg queries for datasource Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update queries Co-authored-by: Gaze <dev@gaze.network> * feat(btc): implement repo for get blocks Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update dg Co-authored-by: Gaze <dev@gaze.network> * fix(btc): return nil if errors Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update fetch async for db datasource Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add get block header from db for reorg handling Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add todo notes Co-authored-by: Gaze <dev@gaze.network> * feat: implement get tx by hash * fix: rename func * fix: rename func * fix: rename func * fix: fix get transaction by hash * feat: integrate bitcoin client db to main * fix: reduce chunk size * fix: stop main if bitcoin indexer failed * fix: stop main if runes indexer failed * fix: move stop() inside goroutine * chore: add log * fix: duplicate rune entry number * feat(btc): add witness utils Co-authored-by: Gaze <dev@gaze.network> * feat(btc): witness datamodel parsing Co-authored-by: Gaze <dev@gaze.network> * fix(btc): invalid table name Co-authored-by: Gaze <dev@gaze.network> * fix(btc): remove uniqte index for hash Co-authored-by: Gaze <dev@gaze.network> * doc: add todo Co-authored-by: Gaze <dev@gaze.network> * feat(logger): remove error verbose Co-authored-by: Gaze <dev@gaze.network> * feat: support postgresql db Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add err notfound Co-authored-by: Gaze <dev@gaze.network> * fix: invalid pgx version Co-authored-by: Gaze <dev@gaze.network> * fix: invalid indexer flow Co-authored-by: Gaze <dev@gaze.network> * feat: refactor runes api * feat: implement http server * fix: mount runes api * fix: error handler * fix: first empty state error Co-authored-by: Gaze <dev@gaze.network> * fix: off by one confirmation * ci: ignore RollBack error * fix: change WithPublicMessage to be prefix * feat: bump cstream version Co-authored-by: Gaze <dev@gaze.network> * feat(btc): nullable pkscript Co-authored-by: Gaze <dev@gaze.network> * feat(btc): change rollback style Co-authored-by: Gaze <dev@gaze.network> * refactor: move runes out of internal * feat: rename id field to runeId in rune transaction * feat(btc): update index Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add default current block Co-authored-by: Gaze <dev@gaze.network> * doc: add note Co-authored-by: Gaze <dev@gaze.network> * fix(btc): use int64 to store sequence Co-authored-by: Gaze <dev@gaze.network> * fix(btc): upgrade data type for numbers Co-authored-by: Gaze <dev@gaze.network> * feat(btc): upgrade data type for idx Co-authored-by: Gaze <dev@gaze.network> * feat(btc): get indexed block impl Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add common.ZeroHash Co-authored-by: Gaze <dev@gaze.network> * feat: add chainparam * feat: implement get transactions * fix: wrong condition for non-OP_RETURN output * feat(btc): add verify indexer states Co-authored-by: Gaze <dev@gaze.network> * refactor: sorting code Co-authored-by: Gaze <dev@gaze.network> * feat: fix interface * feat(btc): update chuunk size Co-authored-by: Gaze <dev@gaze.network> * feat: add rune_etched column in rune transaction * fix: missing field in create * feat: add runeEtched in get transactions * feat: implement get token info * feat: add holders count in token info * feat: implement get holders * fix: return a new repository when beginning a new tx * fix: rename type * feat: add pkscript to outpoint balance * feat: implement get utxos by address api * fix: spend outpoint bug * feat: implement get balances by address batch * feat: sort balances result by amount * ci: create Dockerfile Co-authored-by: Gaze <dev@gaze.network> * ci: add arg run Co-authored-by: Gaze <dev@gaze.network> * perf: add automaxprocs Co-authored-by: Gaze <dev@gaze.network> * chore: add performance logging Co-authored-by: Gaze <dev@gaze.network> * chore: add performance logger for debyug Co-authored-by: Gaze <dev@gaze.network> * fix: empty etched at * fix: revert data sequentially * fix: remove unused funcs * fix: main.go * feat: add flag --api-only to run cmd * fix: create index * fix: don't add zero mint to unallocated * fix: ignore zero burn amount * feat(reorg): add reorg detail Co-authored-by: Gaze <dev@gaze.network> * fix: wrong index type * feat: implement reporting client to report runes blocks * feat: implement report node * feat(runes): add latest block api Co-authored-by: Gaze <dev@gaze.network> * feat(btc): use logger warn Co-authored-by: Gaze <dev@gaze.network> * fix(btc): txout aren't revert if it's have to revert spent Co-authored-by: Gaze <dev@gaze.network> * fix: annoying error when unsubscribe fetcher Co-authored-by: Gaze <dev@gaze.network> * refactor(btc): readable code Co-authored-by: Gaze <dev@gaze.network> * fix(indexer): fix subscription closed before process when success fetch Co-authored-by: Gaze <dev@gaze.network> * fix: remove module enum * fix: increase max reorg limit * feat: add starting height for runes mainnet * fix(btc): fix `with` modified same row twice Co-authored-by: Gaze <dev@gaze.network> * fix(runes): handling latest block not found Co-authored-by: Gaze <dev@gaze.network> * feat: add decimals in get transactions * fix: wrong condition * feat: add more index * feat: implement get transactions by pkscript * feat: allow query by rune id too * feat: more comments * perf(btc): bitcoin indexer performance optimization (#4) * feat(btc): not null to witness Co-authored-by: Gaze <dev@gaze.network> * perf(btc): add batch insert txin Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert txout Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert transaction Co-authored-by: Gaze <dev@gaze.network> * feat(btc): remove old queries Co-authored-by: Gaze <dev@gaze.network> * fix(btc): typo Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert blocks (#5) Co-authored-by: Gaze <gazenw@users.noreply.github.com> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat(btc): Duplicate coinbase transaction handling (#7) * feat(btc): tx_hash can duplicated in block v1 Co-authored-by: Gaze <dev@gaze.network> * feat(btc): duplicate tx will use same txin/txout from previous tx Co-authored-by: Gaze <dev@gaze.network> * feat(btc): prevent revert block v1 data if you really want to revert the data before the block version 2, you should reset the database and reindex the data instead. Co-authored-by: Gaze <dev@gaze.network> * doc(btc): update list duplicate tx hash Co-authored-by: Gaze <dev@gaze.network> * doc(btc): update docs Co-authored-by: Gaze <dev@gaze.network> * fix(btc): use last v1 block instead Co-authored-by: Gaze <dev@gaze.network> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat: add ping handler * fix: type Co-authored-by: Gaze <dev@gaze.network> * doc: add refactor note Co-authored-by: Gaze <dev@gaze.network> * ci: add golang linter and test runner gh action * ci: use go-test-action@v0 * ci: annotate test result * ci: update running flag * fix: try to fix malformed import path * feat: add mock test * ci: remove annotation ci * ci: add annotate test result * chore: remove unused * feat: try testify * feat: remove test * ci: add go test on macos, windows and go latest version * ci: test building * feat: remove mock code * ci: add sqlc diff checker action (#10) * feat: Graceful shutdown (#8) * feat: add shutdown function for indexer Co-authored-by: Gaze <dev@gaze.network> * feat: add force shutdown Co-authored-by: Gaze <dev@gaze.network> * revert Co-authored-by: Gaze <dev@gaze.network> * feat(btc): remove unused Co-authored-by: Gaze <dev@gaze.network> * style: go fmt Co-authored-by: Gaze <dev@gaze.network> * feat: separate context for worker and application * feat: increase force shutdown timeout Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update logging Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update shutdown function Co-authored-by: Gaze <dev@gaze.network> * feat: remove wg for shutdown Co-authored-by: Gaze <dev@gaze.network> * feat: refactor shutdown flow Co-authored-by: Gaze <dev@gaze.network> * feat: update shutdown flow Co-authored-by: Gaze <dev@gaze.network> * feat: update maming Co-authored-by: Gaze <dev@gaze.network> * feat: update force shutdown logic Co-authored-by: Gaze <dev@gaze.network> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat: check reporting config name * fix: use db config in bitcoin module for runes datasource * Add migrate commands (#2) * feat: add migrate up * feat: add down migration * fix: example * feat: change description * fix: hardcode migration source directory * Update README.md for public release. (#11) * feat: initial draft for README.md * fix: remove some sections * feat: add block reporting to first description * fix: reduce redundancy * feat: update README.md * Update README.md * feat: update README.md * fix: update config.yaml in README * fix: remove redundant words * fix: change default datasource * fix: config.yaml comments * feat: update README.md * refactor(logger): format logging (#12) * feat(logger): format main logger * feat(logger): use duration ms for gcp output * refactor(logger): bitcoin node logger * refactor(logger): indexer logger * refactor(logger): fix cmd logger * refactor(logger): logger in config pacakge * refactor(logger): set pgx error log level debug * refactor(logger): btcclient datasource * refactor: processor name * refactor(logger): runese logger * refactor(logger): update logger * fix(runes): wrong btc db datasource * refactor(logger): remove unnecessary debug log * refactor: update logger in indexer * fix(logger): deadlock in load() * fix: remove unused --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat(btc): remove unused func * fix: fix golangci-lint error * fix(pg): update logger level * doc: update config example * feat: go mod tidy * doc: update readme * fix: panic cause didn't handle error * doc: update example config * doc: update example config in readme * feat(logger): only log error stacktrace when debug mode is on * feat(reporting): handling invalid config error * feat(pg): handling invalid config error * fix: panic in get_token_info --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> Co-authored-by: Planxnx <thanee@cleverse.com> Co-authored-by: Thanee Charattrakool <37617738+Planxnx@users.noreply.github.com>
409 lines
11 KiB
Go
409 lines
11 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.26.0
|
|
// source: data.sql
|
|
|
|
package gen
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const batchInsertBlocks = `-- name: BatchInsertBlocks :exec
|
|
INSERT INTO bitcoin_blocks ("block_height","block_hash","version","merkle_root","prev_block_hash","timestamp","bits","nonce")
|
|
VALUES (
|
|
unnest($1::INT[]),
|
|
unnest($2::TEXT[]),
|
|
unnest($3::INT[]),
|
|
unnest($4::TEXT[]),
|
|
unnest($5::TEXT[]),
|
|
unnest($6::TIMESTAMP WITH TIME ZONE[]), -- or use TIMESTAMPTZ
|
|
unnest($7::BIGINT[]),
|
|
unnest($8::BIGINT[])
|
|
)
|
|
`
|
|
|
|
type BatchInsertBlocksParams struct {
|
|
BlockHeightArr []int32
|
|
BlockHashArr []string
|
|
VersionArr []int32
|
|
MerkleRootArr []string
|
|
PrevBlockHashArr []string
|
|
TimestampArr []pgtype.Timestamptz
|
|
BitsArr []int64
|
|
NonceArr []int64
|
|
}
|
|
|
|
func (q *Queries) BatchInsertBlocks(ctx context.Context, arg BatchInsertBlocksParams) error {
|
|
_, err := q.db.Exec(ctx, batchInsertBlocks,
|
|
arg.BlockHeightArr,
|
|
arg.BlockHashArr,
|
|
arg.VersionArr,
|
|
arg.MerkleRootArr,
|
|
arg.PrevBlockHashArr,
|
|
arg.TimestampArr,
|
|
arg.BitsArr,
|
|
arg.NonceArr,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const batchInsertTransactionTxIns = `-- name: BatchInsertTransactionTxIns :exec
|
|
WITH update_txout AS (
|
|
UPDATE "bitcoin_transaction_txouts"
|
|
SET "is_spent" = true
|
|
FROM (SELECT unnest($1::TEXT[]) as tx_hash, unnest($2::INT[]) as tx_idx) as txin
|
|
WHERE "bitcoin_transaction_txouts"."tx_hash" = txin.tx_hash AND "bitcoin_transaction_txouts"."tx_idx" = txin.tx_idx AND "is_spent" = false
|
|
RETURNING "bitcoin_transaction_txouts"."tx_hash", "bitcoin_transaction_txouts"."tx_idx", "pkscript"
|
|
), prepare_insert AS (
|
|
SELECT input.tx_hash, input.tx_idx, prevout_tx_hash, prevout_tx_idx, update_txout.pkscript as prevout_pkscript, scriptsig, witness, sequence
|
|
FROM (
|
|
SELECT
|
|
unnest($3::TEXT[]) as tx_hash,
|
|
unnest($4::INT[]) as tx_idx,
|
|
unnest($1::TEXT[]) as prevout_tx_hash,
|
|
unnest($2::INT[]) as prevout_tx_idx,
|
|
unnest($5::TEXT[]) as scriptsig,
|
|
unnest($6::TEXT[]) as witness,
|
|
unnest($7::INT[]) as sequence
|
|
) input LEFT JOIN update_txout ON "update_txout"."tx_hash" = "input"."prevout_tx_hash" AND "update_txout"."tx_idx" = "input"."prevout_tx_idx"
|
|
)
|
|
INSERT INTO bitcoin_transaction_txins ("tx_hash","tx_idx","prevout_tx_hash","prevout_tx_idx", "prevout_pkscript","scriptsig","witness","sequence")
|
|
SELECT "tx_hash", "tx_idx", "prevout_tx_hash", "prevout_tx_idx", "prevout_pkscript", "scriptsig", "witness", "sequence" FROM prepare_insert
|
|
`
|
|
|
|
type BatchInsertTransactionTxInsParams struct {
|
|
PrevoutTxHashArr []string
|
|
PrevoutTxIdxArr []int32
|
|
TxHashArr []string
|
|
TxIdxArr []int32
|
|
ScriptsigArr []string
|
|
WitnessArr []string
|
|
SequenceArr []int32
|
|
}
|
|
|
|
func (q *Queries) BatchInsertTransactionTxIns(ctx context.Context, arg BatchInsertTransactionTxInsParams) error {
|
|
_, err := q.db.Exec(ctx, batchInsertTransactionTxIns,
|
|
arg.PrevoutTxHashArr,
|
|
arg.PrevoutTxIdxArr,
|
|
arg.TxHashArr,
|
|
arg.TxIdxArr,
|
|
arg.ScriptsigArr,
|
|
arg.WitnessArr,
|
|
arg.SequenceArr,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const batchInsertTransactionTxOuts = `-- name: BatchInsertTransactionTxOuts :exec
|
|
INSERT INTO bitcoin_transaction_txouts ("tx_hash","tx_idx","pkscript","value")
|
|
VALUES (
|
|
unnest($1::TEXT[]),
|
|
unnest($2::INT[]),
|
|
unnest($3::TEXT[]),
|
|
unnest($4::BIGINT[])
|
|
)
|
|
`
|
|
|
|
type BatchInsertTransactionTxOutsParams struct {
|
|
TxHashArr []string
|
|
TxIdxArr []int32
|
|
PkscriptArr []string
|
|
ValueArr []int64
|
|
}
|
|
|
|
func (q *Queries) BatchInsertTransactionTxOuts(ctx context.Context, arg BatchInsertTransactionTxOutsParams) error {
|
|
_, err := q.db.Exec(ctx, batchInsertTransactionTxOuts,
|
|
arg.TxHashArr,
|
|
arg.TxIdxArr,
|
|
arg.PkscriptArr,
|
|
arg.ValueArr,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const batchInsertTransactions = `-- name: BatchInsertTransactions :exec
|
|
INSERT INTO bitcoin_transactions ("tx_hash","version","locktime","block_height","block_hash","idx")
|
|
VALUES (
|
|
unnest($1::TEXT[]),
|
|
unnest($2::INT[]),
|
|
unnest($3::BIGINT[]),
|
|
unnest($4::INT[]),
|
|
unnest($5::TEXT[]),
|
|
unnest($6::INT[])
|
|
)
|
|
`
|
|
|
|
type BatchInsertTransactionsParams struct {
|
|
TxHashArr []string
|
|
VersionArr []int32
|
|
LocktimeArr []int64
|
|
BlockHeightArr []int32
|
|
BlockHashArr []string
|
|
IdxArr []int32
|
|
}
|
|
|
|
func (q *Queries) BatchInsertTransactions(ctx context.Context, arg BatchInsertTransactionsParams) error {
|
|
_, err := q.db.Exec(ctx, batchInsertTransactions,
|
|
arg.TxHashArr,
|
|
arg.VersionArr,
|
|
arg.LocktimeArr,
|
|
arg.BlockHeightArr,
|
|
arg.BlockHashArr,
|
|
arg.IdxArr,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const getBlockByHeight = `-- name: GetBlockByHeight :one
|
|
SELECT block_height, block_hash, version, merkle_root, prev_block_hash, timestamp, bits, nonce FROM bitcoin_blocks WHERE block_height = $1
|
|
`
|
|
|
|
func (q *Queries) GetBlockByHeight(ctx context.Context, blockHeight int32) (BitcoinBlock, error) {
|
|
row := q.db.QueryRow(ctx, getBlockByHeight, blockHeight)
|
|
var i BitcoinBlock
|
|
err := row.Scan(
|
|
&i.BlockHeight,
|
|
&i.BlockHash,
|
|
&i.Version,
|
|
&i.MerkleRoot,
|
|
&i.PrevBlockHash,
|
|
&i.Timestamp,
|
|
&i.Bits,
|
|
&i.Nonce,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getBlocksByHeightRange = `-- name: GetBlocksByHeightRange :many
|
|
SELECT block_height, block_hash, version, merkle_root, prev_block_hash, timestamp, bits, nonce FROM bitcoin_blocks WHERE block_height >= $1 AND block_height <= $2 ORDER BY block_height ASC
|
|
`
|
|
|
|
type GetBlocksByHeightRangeParams struct {
|
|
FromHeight int32
|
|
ToHeight int32
|
|
}
|
|
|
|
func (q *Queries) GetBlocksByHeightRange(ctx context.Context, arg GetBlocksByHeightRangeParams) ([]BitcoinBlock, error) {
|
|
rows, err := q.db.Query(ctx, getBlocksByHeightRange, arg.FromHeight, arg.ToHeight)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []BitcoinBlock
|
|
for rows.Next() {
|
|
var i BitcoinBlock
|
|
if err := rows.Scan(
|
|
&i.BlockHeight,
|
|
&i.BlockHash,
|
|
&i.Version,
|
|
&i.MerkleRoot,
|
|
&i.PrevBlockHash,
|
|
&i.Timestamp,
|
|
&i.Bits,
|
|
&i.Nonce,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getLatestBlockHeader = `-- name: GetLatestBlockHeader :one
|
|
SELECT block_height, block_hash, version, merkle_root, prev_block_hash, timestamp, bits, nonce FROM bitcoin_blocks ORDER BY block_height DESC LIMIT 1
|
|
`
|
|
|
|
func (q *Queries) GetLatestBlockHeader(ctx context.Context) (BitcoinBlock, error) {
|
|
row := q.db.QueryRow(ctx, getLatestBlockHeader)
|
|
var i BitcoinBlock
|
|
err := row.Scan(
|
|
&i.BlockHeight,
|
|
&i.BlockHash,
|
|
&i.Version,
|
|
&i.MerkleRoot,
|
|
&i.PrevBlockHash,
|
|
&i.Timestamp,
|
|
&i.Bits,
|
|
&i.Nonce,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTransactionByHash = `-- name: GetTransactionByHash :one
|
|
SELECT tx_hash, version, locktime, block_height, block_hash, idx FROM bitcoin_transactions WHERE tx_hash = $1
|
|
`
|
|
|
|
func (q *Queries) GetTransactionByHash(ctx context.Context, txHash string) (BitcoinTransaction, error) {
|
|
row := q.db.QueryRow(ctx, getTransactionByHash, txHash)
|
|
var i BitcoinTransaction
|
|
err := row.Scan(
|
|
&i.TxHash,
|
|
&i.Version,
|
|
&i.Locktime,
|
|
&i.BlockHeight,
|
|
&i.BlockHash,
|
|
&i.Idx,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTransactionTxInsByTxHashes = `-- name: GetTransactionTxInsByTxHashes :many
|
|
SELECT tx_hash, tx_idx, prevout_tx_hash, prevout_tx_idx, prevout_pkscript, scriptsig, witness, sequence FROM bitcoin_transaction_txins WHERE tx_hash = ANY($1::TEXT[])
|
|
`
|
|
|
|
func (q *Queries) GetTransactionTxInsByTxHashes(ctx context.Context, txHashes []string) ([]BitcoinTransactionTxin, error) {
|
|
rows, err := q.db.Query(ctx, getTransactionTxInsByTxHashes, txHashes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []BitcoinTransactionTxin
|
|
for rows.Next() {
|
|
var i BitcoinTransactionTxin
|
|
if err := rows.Scan(
|
|
&i.TxHash,
|
|
&i.TxIdx,
|
|
&i.PrevoutTxHash,
|
|
&i.PrevoutTxIdx,
|
|
&i.PrevoutPkscript,
|
|
&i.Scriptsig,
|
|
&i.Witness,
|
|
&i.Sequence,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getTransactionTxOutsByTxHashes = `-- name: GetTransactionTxOutsByTxHashes :many
|
|
SELECT tx_hash, tx_idx, pkscript, value, is_spent FROM bitcoin_transaction_txouts WHERE tx_hash = ANY($1::TEXT[])
|
|
`
|
|
|
|
func (q *Queries) GetTransactionTxOutsByTxHashes(ctx context.Context, txHashes []string) ([]BitcoinTransactionTxout, error) {
|
|
rows, err := q.db.Query(ctx, getTransactionTxOutsByTxHashes, txHashes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []BitcoinTransactionTxout
|
|
for rows.Next() {
|
|
var i BitcoinTransactionTxout
|
|
if err := rows.Scan(
|
|
&i.TxHash,
|
|
&i.TxIdx,
|
|
&i.Pkscript,
|
|
&i.Value,
|
|
&i.IsSpent,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getTransactionsByHeightRange = `-- name: GetTransactionsByHeightRange :many
|
|
SELECT tx_hash, version, locktime, block_height, block_hash, idx FROM bitcoin_transactions WHERE block_height >= $1 AND block_height <= $2
|
|
`
|
|
|
|
type GetTransactionsByHeightRangeParams struct {
|
|
FromHeight int32
|
|
ToHeight int32
|
|
}
|
|
|
|
func (q *Queries) GetTransactionsByHeightRange(ctx context.Context, arg GetTransactionsByHeightRangeParams) ([]BitcoinTransaction, error) {
|
|
rows, err := q.db.Query(ctx, getTransactionsByHeightRange, arg.FromHeight, arg.ToHeight)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []BitcoinTransaction
|
|
for rows.Next() {
|
|
var i BitcoinTransaction
|
|
if err := rows.Scan(
|
|
&i.TxHash,
|
|
&i.Version,
|
|
&i.Locktime,
|
|
&i.BlockHeight,
|
|
&i.BlockHash,
|
|
&i.Idx,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const insertBlock = `-- name: InsertBlock :exec
|
|
INSERT INTO bitcoin_blocks ("block_height","block_hash","version","merkle_root","prev_block_hash","timestamp","bits","nonce") VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
`
|
|
|
|
type InsertBlockParams struct {
|
|
BlockHeight int32
|
|
BlockHash string
|
|
Version int32
|
|
MerkleRoot string
|
|
PrevBlockHash string
|
|
Timestamp pgtype.Timestamptz
|
|
Bits int64
|
|
Nonce int64
|
|
}
|
|
|
|
func (q *Queries) InsertBlock(ctx context.Context, arg InsertBlockParams) error {
|
|
_, err := q.db.Exec(ctx, insertBlock,
|
|
arg.BlockHeight,
|
|
arg.BlockHash,
|
|
arg.Version,
|
|
arg.MerkleRoot,
|
|
arg.PrevBlockHash,
|
|
arg.Timestamp,
|
|
arg.Bits,
|
|
arg.Nonce,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const revertData = `-- name: RevertData :exec
|
|
WITH delete_tx AS (
|
|
DELETE FROM "bitcoin_transactions" WHERE "block_height" >= $1
|
|
RETURNING "tx_hash"
|
|
), delete_txin AS (
|
|
DELETE FROM "bitcoin_transaction_txins" WHERE "tx_hash" = ANY(SELECT "tx_hash" FROM delete_tx)
|
|
RETURNING "prevout_tx_hash", "prevout_tx_idx"
|
|
), delete_txout AS (
|
|
DELETE FROM "bitcoin_transaction_txouts" WHERE "tx_hash" = ANY(SELECT "tx_hash" FROM delete_tx)
|
|
RETURNING "tx_hash", "tx_idx"
|
|
), revert_txout_spent AS (
|
|
UPDATE "bitcoin_transaction_txouts"
|
|
SET "is_spent" = false
|
|
WHERE
|
|
("tx_hash", "tx_idx") IN (SELECT "prevout_tx_hash", "prevout_tx_idx" FROM delete_txin) AND
|
|
("tx_hash", "tx_idx") NOT IN (SELECT "tx_hash", "tx_idx" FROM delete_txout) -- avoid to modified same row twice (modified the same row twice in a single statement is not supported)
|
|
RETURNING NULL
|
|
)
|
|
DELETE FROM "bitcoin_blocks" WHERE "bitcoin_blocks"."block_height" >= $1
|
|
`
|
|
|
|
func (q *Queries) RevertData(ctx context.Context, fromHeight int32) error {
|
|
_, err := q.db.Exec(ctx, revertData, fromHeight)
|
|
return err
|
|
}
|