mirror of
https://github.com/alexgo-io/gaze-indexer.git
synced 2026-04-29 20:25:24 +08:00
feat: implement more tables
This commit is contained in:
2
go.mod
2
go.mod
@@ -9,7 +9,7 @@ require (
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
|
||||
github.com/cockroachdb/errors v1.11.1
|
||||
github.com/gaze-network/uint128 v1.2.0
|
||||
github.com/gaze-network/uint128 v1.3.0
|
||||
github.com/gofiber/fiber/v2 v2.52.4
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/mcosta74/pgx-slog v0.3.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -51,8 +51,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gaze-network/uint128 v1.2.0 h1:LRruR+EvzNv/eJg8nk0hztMJ4tOpYKolFYlQZqNvWmo=
|
||||
github.com/gaze-network/uint128 v1.2.0/go.mod h1:zAwwcnoRUNiiQj0vjLmHgNgJ+w2RUgzMAJgl8d7tRug=
|
||||
github.com/gaze-network/uint128 v1.3.0 h1:25qtRiDKQXa+mD5rN0nbUkbvY26/uzfSF97eWvhIr0I=
|
||||
github.com/gaze-network/uint128 v1.3.0/go.mod h1:zAwwcnoRUNiiQj0vjLmHgNgJ+w2RUgzMAJgl8d7tRug=
|
||||
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
|
||||
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
|
||||
@@ -2,9 +2,13 @@ BEGIN;
|
||||
|
||||
DROP TABLE IF EXISTS "runes_indexer_stats";
|
||||
DROP TABLE IF EXISTS "runes_indexer_db_version";
|
||||
DROP TABLE IF EXISTS "runes_processor_state";
|
||||
DROP TABLE IF EXISTS "runes_indexed_blocks";
|
||||
DROP TABLE IF EXISTS "runes_entries";
|
||||
DROP TABLE IF EXISTS "runes_entry_states";
|
||||
DROP TABLE IF EXISTS "runes_transactions";
|
||||
DROP TABLE IF EXISTS "runes_runestones";
|
||||
DROP TABLE IF EXISTS "runes_outpoint_balances";
|
||||
DROP TABLE IF EXISTS "runes_balances";
|
||||
DROP TABLE IF EXISTS "runes_balances";
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -39,8 +39,6 @@ CREATE TABLE IF NOT EXISTS "runes_entries" (
|
||||
"rune_id" TEXT NOT NULL PRIMARY KEY,
|
||||
"rune" TEXT NOT NULL,
|
||||
"spacers" INT NOT NULL,
|
||||
"burned_amount" DECIMAL NOT NULL,
|
||||
"mints" DECIMAL NOT NULL,
|
||||
"premine" DECIMAL NOT NULL,
|
||||
"symbol" INT NOT NULL,
|
||||
"divisibility" SMALLINT NOT NULL,
|
||||
@@ -51,10 +49,52 @@ CREATE TABLE IF NOT EXISTS "runes_entries" (
|
||||
"terms_height_end" INT,
|
||||
"terms_offset_start" INT,
|
||||
"terms_offset_end" INT,
|
||||
"completion_time" TIMESTAMP NOT NULL
|
||||
"created_at_block" INT NOT NULL
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS runes_entries_rune_idx ON "runes_entries" USING BTREE ("rune");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "runes_entry_states" (
|
||||
"rune_id" TEXT NOT NULL,
|
||||
"block_height" INT NOT NULL,
|
||||
"mints" DECIMAL NOT NULL,
|
||||
"burned_amount" DECIMAL NOT NULL,
|
||||
"completion_time" TIMESTAMP,
|
||||
PRIMARY KEY ("rune_id", "block_height")
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "runes_transactions" (
|
||||
"hash" TEXT NOT NULL PRIMARY KEY,
|
||||
"block_height" INT NOT NULL,
|
||||
"timestamp" TIMESTAMP NOT NULL,
|
||||
"inputs" JSONB NOT NULL,
|
||||
"outputs" JSONB NOT NULL,
|
||||
"mints" JSONB NOT NULL,
|
||||
"burns" JSONB NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "runes_runestones" (
|
||||
"tx_hash" TEXT NOT NULL PRIMARY KEY,
|
||||
"block_height" INT NOT NULL,
|
||||
"etching" BOOLEAN NOT NULL,
|
||||
"etching_divisibility" SMALLINT,
|
||||
"etching_premine" DECIMAL,
|
||||
"etching_rune" TEXT,
|
||||
"etching_spacers" INT,
|
||||
"etching_symbol" INT,
|
||||
"etching_terms" BOOLEAN NOT NULL,
|
||||
"etching_terms_amount" DECIMAL,
|
||||
"etching_terms_cap" DECIMAL,
|
||||
"etching_terms_height_start" INT,
|
||||
"etching_terms_height_end" INT,
|
||||
"etching_terms_offset_start" INT,
|
||||
"etching_terms_offset_end" INT,
|
||||
"edicts" JSONB NOT NULL DEFAULT '[]',
|
||||
"mint" TEXT,
|
||||
"pointer" INT,
|
||||
"cenotaph" BOOLEAN NOT NULL,
|
||||
"flaws" INT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "runes_outpoint_balances" (
|
||||
"rune_id" TEXT NOT NULL,
|
||||
"tx_hash" TEXT NOT NULL,
|
||||
|
||||
@@ -7,18 +7,36 @@ SELECT DISTINCT ON (pkscript) * FROM runes_balances WHERE rune_id = $1 AND block
|
||||
-- name: GetOutPointBalances :many
|
||||
SELECT * FROM runes_outpoint_balances WHERE tx_hash = $1 AND tx_idx = $2;
|
||||
|
||||
-- using FOR UPDATE to prevent other connections for updating the same rune entries if they are being accessed by Processor
|
||||
-- name: GetRuneEntriesByRuneIds :many
|
||||
SELECT * FROM runes_entries WHERE rune_id = ANY(@rune_ids::text[]) FOR UPDATE;
|
||||
WITH states AS (
|
||||
-- select latest state
|
||||
SELECT DISTINCT ON (rune_id) * FROM runes_entry_states WHERE rune_id = ANY(@rune_ids::text[]) ORDER BY rune_id, block_height DESC
|
||||
)
|
||||
SELECT * FROM runes_entries
|
||||
LEFT JOIN states ON runes_entries.rune_id = states.rune_id
|
||||
WHERE rune_id = ANY(@rune_ids::text[]);
|
||||
|
||||
-- using FOR UPDATE to prevent other connections for updating the same rune entries if they are being accessed by Processor
|
||||
-- name: GetRuneEntriesByRunes :many
|
||||
SELECT * FROM runes_entries WHERE rune = ANY(@runes::text[]) FOR UPDATE;
|
||||
-- name: GetRuneIdFromRune :one
|
||||
SELECT rune_id FROM runes_entries WHERE rune = $1;
|
||||
|
||||
-- name: SetRuneEntry :exec
|
||||
INSERT INTO runes_entries (rune_id, rune, spacers, burned_amount, mints, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end, completion_time)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
ON CONFLICT (rune_id) DO UPDATE SET (burned_amount, mints, completion_time) = (excluded.burned_amount, excluded.mints, excluded.completion_time);
|
||||
-- name: GetRuneTransactionsByHeight :many
|
||||
SELECT * FROM runes_transactions
|
||||
LEFT JOIN runes_runestones ON runes_transactions.hash = runes_runestones.tx_hash
|
||||
WHERE runes_transactions.block_height = $1;
|
||||
|
||||
-- name: CreateRuneEntry :exec
|
||||
INSERT INTO runes_entries (rune_id, rune, spacers, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);
|
||||
|
||||
-- name: CreateRuneEntryState :exec
|
||||
INSERT INTO runes_entry_states (rune_id, block_height, mints, burned_amount, completion_time) VALUES ($1, $2, $3, $4, $5);
|
||||
|
||||
-- name: CreateRuneTransaction :exec
|
||||
INSERT INTO runes_transactions (hash, block_height, timestamp, inputs, outputs, mints, burns) VALUES ($1, $2, $3, $4, $5, $6, $7);
|
||||
|
||||
-- name: CreateRunestone :exec
|
||||
INSERT INTO runes_runestones (tx_hash, block_height, etching, etching_divisibility, etching_premine, etching_rune, etching_spacers, etching_symbol, etching_terms, etching_terms_amount, etching_terms_cap, etching_terms_height_start, etching_terms_height_end, etching_terms_offset_start, etching_terms_offset_end, edicts, mint, pointer, cenotaph, flaws)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20);
|
||||
|
||||
-- name: CreateRuneBalancesAtOutPoint :batchexec
|
||||
INSERT INTO runes_outpoint_balances (rune_id, tx_hash, tx_idx, amount) VALUES ($1, $2, $3, $4);
|
||||
|
||||
@@ -76,11 +76,11 @@ func (h *HttpHandler) resolveRuneId(ctx context.Context, id string) (runes.RuneI
|
||||
// attempt to parse as rune
|
||||
rune, err := runes.NewRuneFromString(id)
|
||||
if err == nil {
|
||||
runeEntry, err := h.usecase.GetRuneEntryByRune(ctx, rune)
|
||||
runeId, err := h.usecase.GetRuneIdFromRune(ctx, rune)
|
||||
if err != nil {
|
||||
return runes.RuneId{}, false
|
||||
}
|
||||
return runeEntry.RuneId, true
|
||||
return runeId, true
|
||||
}
|
||||
|
||||
return runes.RuneId{}, false
|
||||
|
||||
@@ -19,10 +19,11 @@ type RunesDataGateway interface {
|
||||
type RunesReaderDataGateway interface {
|
||||
GetLatestBlock(ctx context.Context) (types.BlockHeader, error)
|
||||
GetIndexedBlockByHeight(ctx context.Context, height int64) (*entity.IndexedBlock, error)
|
||||
GetRuneTransactionsByHeight(ctx context.Context, height uint64) ([]*entity.RuneTransaction, error)
|
||||
|
||||
GetRunesBalancesAtOutPoint(ctx context.Context, outPoint wire.OutPoint) (map[runes.RuneId]uint128.Uint128, error)
|
||||
// GetRuneEntryByRune returns the RuneEntry for the given rune. Returns errs.NotFound if the rune entry is not found.
|
||||
GetRuneEntryByRune(ctx context.Context, rune runes.Rune) (*runes.RuneEntry, error)
|
||||
// GetRuneIdFromRune returns the RuneId for the given rune. Returns errs.NotFound if the rune entry is not found.
|
||||
GetRuneIdFromRune(ctx context.Context, rune runes.Rune) (runes.RuneId, error)
|
||||
// GetRuneEntryByRuneId returns the RuneEntry for the given runeId. Returns errs.NotFound if the rune entry is not found.
|
||||
GetRuneEntryByRuneId(ctx context.Context, runeId runes.RuneId) (*runes.RuneEntry, error)
|
||||
// GetRuneEntryByRuneId returns the RuneEntry for the given runeId. Returns errs.NotFound if the rune entry is not found.
|
||||
@@ -45,11 +46,13 @@ type RunesWriterDataGateway interface {
|
||||
// Rollback() must be safe to call even if no transaction is active. Hence, a defer Rollback() is safe, even if Commit() was called prior with non-error conditions.
|
||||
Rollback(ctx context.Context) error
|
||||
|
||||
SetRuneEntry(ctx context.Context, entry *runes.RuneEntry) error
|
||||
CreateRuneEntry(ctx context.Context, entry *runes.RuneEntry) error
|
||||
CreateRuneBalancesAtOutPoint(ctx context.Context, outPoint wire.OutPoint, balances map[runes.RuneId]uint128.Uint128) error
|
||||
CreateRuneBalancesAtBlock(ctx context.Context, params []CreateRuneBalancesAtBlockParams) error
|
||||
UpdateLatestBlock(ctx context.Context, blockHeader types.BlockHeader) error
|
||||
|
||||
CreateRuneTransaction(ctx context.Context, tx *entity.RuneTransaction) error
|
||||
|
||||
CreateIndexedBlock(ctx context.Context, block *entity.IndexedBlock) error
|
||||
DeleteIndexedBlockByHash(ctx context.Context, hash chainhash.Hash) error
|
||||
}
|
||||
|
||||
27
modules/runes/internal/entity/rune_transaction.go
Normal file
27
modules/runes/internal/entity/rune_transaction.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/runes"
|
||||
"github.com/gaze-network/uint128"
|
||||
)
|
||||
|
||||
type OutPointBalance struct {
|
||||
PkScript []byte
|
||||
Id runes.RuneId
|
||||
Value uint128.Uint128
|
||||
Index uint32
|
||||
}
|
||||
|
||||
type RuneTransaction struct {
|
||||
Hash chainhash.Hash
|
||||
BlockHeight uint64
|
||||
Timestamp time.Time
|
||||
Inputs []*OutPointBalance
|
||||
Outputs []*OutPointBalance
|
||||
Mints []*OutPointBalance
|
||||
Burns map[runes.RuneId]uint128.Uint128
|
||||
Runestone *runes.Runestone
|
||||
}
|
||||
@@ -32,6 +32,150 @@ func (q *Queries) CreateIndexedBlock(ctx context.Context, arg CreateIndexedBlock
|
||||
return err
|
||||
}
|
||||
|
||||
const createRuneEntry = `-- name: CreateRuneEntry :exec
|
||||
INSERT INTO runes_entries (rune_id, rune, spacers, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
|
||||
`
|
||||
|
||||
type CreateRuneEntryParams struct {
|
||||
RuneID string
|
||||
Rune string
|
||||
Spacers int32
|
||||
Premine pgtype.Numeric
|
||||
Symbol int32
|
||||
Divisibility int16
|
||||
Terms bool
|
||||
TermsAmount pgtype.Numeric
|
||||
TermsCap pgtype.Numeric
|
||||
TermsHeightStart pgtype.Int4
|
||||
TermsHeightEnd pgtype.Int4
|
||||
TermsOffsetStart pgtype.Int4
|
||||
TermsOffsetEnd pgtype.Int4
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRuneEntry(ctx context.Context, arg CreateRuneEntryParams) error {
|
||||
_, err := q.db.Exec(ctx, createRuneEntry,
|
||||
arg.RuneID,
|
||||
arg.Rune,
|
||||
arg.Spacers,
|
||||
arg.Premine,
|
||||
arg.Symbol,
|
||||
arg.Divisibility,
|
||||
arg.Terms,
|
||||
arg.TermsAmount,
|
||||
arg.TermsCap,
|
||||
arg.TermsHeightStart,
|
||||
arg.TermsHeightEnd,
|
||||
arg.TermsOffsetStart,
|
||||
arg.TermsOffsetEnd,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const createRuneEntryState = `-- name: CreateRuneEntryState :exec
|
||||
INSERT INTO runes_entry_states (rune_id, block_height, mints, burned_amount, completion_time) VALUES ($1, $2, $3, $4, $5)
|
||||
`
|
||||
|
||||
type CreateRuneEntryStateParams struct {
|
||||
RuneID string
|
||||
BlockHeight int32
|
||||
Mints pgtype.Numeric
|
||||
BurnedAmount pgtype.Numeric
|
||||
CompletionTime pgtype.Timestamp
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRuneEntryState(ctx context.Context, arg CreateRuneEntryStateParams) error {
|
||||
_, err := q.db.Exec(ctx, createRuneEntryState,
|
||||
arg.RuneID,
|
||||
arg.BlockHeight,
|
||||
arg.Mints,
|
||||
arg.BurnedAmount,
|
||||
arg.CompletionTime,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const createRuneTransaction = `-- name: CreateRuneTransaction :exec
|
||||
INSERT INTO runes_transactions (hash, block_height, timestamp, inputs, outputs, mints, burns) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`
|
||||
|
||||
type CreateRuneTransactionParams struct {
|
||||
Hash string
|
||||
BlockHeight int32
|
||||
Timestamp pgtype.Timestamp
|
||||
Inputs []byte
|
||||
Outputs []byte
|
||||
Mints []byte
|
||||
Burns []byte
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRuneTransaction(ctx context.Context, arg CreateRuneTransactionParams) error {
|
||||
_, err := q.db.Exec(ctx, createRuneTransaction,
|
||||
arg.Hash,
|
||||
arg.BlockHeight,
|
||||
arg.Timestamp,
|
||||
arg.Inputs,
|
||||
arg.Outputs,
|
||||
arg.Mints,
|
||||
arg.Burns,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const createRunestone = `-- name: CreateRunestone :exec
|
||||
INSERT INTO runes_runestones (tx_hash, block_height, etching, etching_divisibility, etching_premine, etching_rune, etching_spacers, etching_symbol, etching_terms, etching_terms_amount, etching_terms_cap, etching_terms_height_start, etching_terms_height_end, etching_terms_offset_start, etching_terms_offset_end, edicts, mint, pointer, cenotaph, flaws)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
|
||||
`
|
||||
|
||||
type CreateRunestoneParams struct {
|
||||
TxHash string
|
||||
BlockHeight int32
|
||||
Etching bool
|
||||
EtchingDivisibility pgtype.Int2
|
||||
EtchingPremine pgtype.Numeric
|
||||
EtchingRune pgtype.Text
|
||||
EtchingSpacers pgtype.Int4
|
||||
EtchingSymbol pgtype.Int4
|
||||
EtchingTerms bool
|
||||
EtchingTermsAmount pgtype.Numeric
|
||||
EtchingTermsCap pgtype.Numeric
|
||||
EtchingTermsHeightStart pgtype.Int4
|
||||
EtchingTermsHeightEnd pgtype.Int4
|
||||
EtchingTermsOffsetStart pgtype.Int4
|
||||
EtchingTermsOffsetEnd pgtype.Int4
|
||||
Edicts []byte
|
||||
Mint pgtype.Text
|
||||
Pointer pgtype.Int4
|
||||
Cenotaph bool
|
||||
Flaws int32
|
||||
}
|
||||
|
||||
func (q *Queries) CreateRunestone(ctx context.Context, arg CreateRunestoneParams) error {
|
||||
_, err := q.db.Exec(ctx, createRunestone,
|
||||
arg.TxHash,
|
||||
arg.BlockHeight,
|
||||
arg.Etching,
|
||||
arg.EtchingDivisibility,
|
||||
arg.EtchingPremine,
|
||||
arg.EtchingRune,
|
||||
arg.EtchingSpacers,
|
||||
arg.EtchingSymbol,
|
||||
arg.EtchingTerms,
|
||||
arg.EtchingTermsAmount,
|
||||
arg.EtchingTermsCap,
|
||||
arg.EtchingTermsHeightStart,
|
||||
arg.EtchingTermsHeightEnd,
|
||||
arg.EtchingTermsOffsetStart,
|
||||
arg.EtchingTermsOffsetEnd,
|
||||
arg.Edicts,
|
||||
arg.Mint,
|
||||
arg.Pointer,
|
||||
arg.Cenotaph,
|
||||
arg.Flaws,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteIndexedBlockByHash = `-- name: DeleteIndexedBlockByHash :exec
|
||||
DELETE FROM runes_indexed_blocks WHERE hash = $1
|
||||
`
|
||||
@@ -162,25 +306,50 @@ func (q *Queries) GetOutPointBalances(ctx context.Context, arg GetOutPointBalanc
|
||||
}
|
||||
|
||||
const getRuneEntriesByRuneIds = `-- name: GetRuneEntriesByRuneIds :many
|
||||
SELECT rune_id, rune, spacers, burned_amount, mints, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end, completion_time FROM runes_entries WHERE rune_id = ANY($1::text[]) FOR UPDATE
|
||||
WITH states AS (
|
||||
-- select latest state
|
||||
SELECT DISTINCT ON (rune_id) rune_id, block_height, mints, burned_amount, completion_time FROM runes_entry_states WHERE rune_id = ANY($1::text[]) ORDER BY rune_id, block_height DESC
|
||||
)
|
||||
SELECT runes_entries.rune_id, rune, spacers, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end, created_at_block, states.rune_id, block_height, mints, burned_amount, completion_time FROM runes_entries
|
||||
LEFT JOIN states ON runes_entries.rune_id = states.rune_id
|
||||
WHERE rune_id = ANY($1::text[])
|
||||
`
|
||||
|
||||
// using FOR UPDATE to prevent other connections for updating the same rune entries if they are being accessed by Processor
|
||||
func (q *Queries) GetRuneEntriesByRuneIds(ctx context.Context, runeIds []string) ([]RunesEntry, error) {
|
||||
type GetRuneEntriesByRuneIdsRow struct {
|
||||
RuneID string
|
||||
Rune string
|
||||
Spacers int32
|
||||
Premine pgtype.Numeric
|
||||
Symbol int32
|
||||
Divisibility int16
|
||||
Terms bool
|
||||
TermsAmount pgtype.Numeric
|
||||
TermsCap pgtype.Numeric
|
||||
TermsHeightStart pgtype.Int4
|
||||
TermsHeightEnd pgtype.Int4
|
||||
TermsOffsetStart pgtype.Int4
|
||||
TermsOffsetEnd pgtype.Int4
|
||||
CreatedAtBlock int32
|
||||
RuneID_2 pgtype.Text
|
||||
BlockHeight pgtype.Int4
|
||||
Mints pgtype.Numeric
|
||||
BurnedAmount pgtype.Numeric
|
||||
CompletionTime pgtype.Timestamp
|
||||
}
|
||||
|
||||
func (q *Queries) GetRuneEntriesByRuneIds(ctx context.Context, runeIds []string) ([]GetRuneEntriesByRuneIdsRow, error) {
|
||||
rows, err := q.db.Query(ctx, getRuneEntriesByRuneIds, runeIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RunesEntry
|
||||
var items []GetRuneEntriesByRuneIdsRow
|
||||
for rows.Next() {
|
||||
var i RunesEntry
|
||||
var i GetRuneEntriesByRuneIdsRow
|
||||
if err := rows.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.Divisibility,
|
||||
@@ -191,6 +360,11 @@ func (q *Queries) GetRuneEntriesByRuneIds(ctx context.Context, runeIds []string)
|
||||
&i.TermsHeightEnd,
|
||||
&i.TermsOffsetStart,
|
||||
&i.TermsOffsetEnd,
|
||||
&i.CreatedAtBlock,
|
||||
&i.RuneID_2,
|
||||
&i.BlockHeight,
|
||||
&i.Mints,
|
||||
&i.BurnedAmount,
|
||||
&i.CompletionTime,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -203,37 +377,90 @@ func (q *Queries) GetRuneEntriesByRuneIds(ctx context.Context, runeIds []string)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getRuneEntriesByRunes = `-- name: GetRuneEntriesByRunes :many
|
||||
SELECT rune_id, rune, spacers, burned_amount, mints, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end, completion_time FROM runes_entries WHERE rune = ANY($1::text[]) FOR UPDATE
|
||||
const getRuneIdFromRune = `-- name: GetRuneIdFromRune :one
|
||||
SELECT rune_id FROM runes_entries WHERE rune = $1
|
||||
`
|
||||
|
||||
// using FOR UPDATE to prevent other connections for updating the same rune entries if they are being accessed by Processor
|
||||
func (q *Queries) GetRuneEntriesByRunes(ctx context.Context, runes []string) ([]RunesEntry, error) {
|
||||
rows, err := q.db.Query(ctx, getRuneEntriesByRunes, runes)
|
||||
func (q *Queries) GetRuneIdFromRune(ctx context.Context, rune string) (string, error) {
|
||||
row := q.db.QueryRow(ctx, getRuneIdFromRune, rune)
|
||||
var rune_id string
|
||||
err := row.Scan(&rune_id)
|
||||
return rune_id, err
|
||||
}
|
||||
|
||||
const getRuneTransactionsByHeight = `-- name: GetRuneTransactionsByHeight :many
|
||||
SELECT hash, runes_transactions.block_height, timestamp, inputs, outputs, mints, burns, tx_hash, runes_runestones.block_height, etching, etching_divisibility, etching_premine, etching_rune, etching_spacers, etching_symbol, etching_terms, etching_terms_amount, etching_terms_cap, etching_terms_height_start, etching_terms_height_end, etching_terms_offset_start, etching_terms_offset_end, edicts, mint, pointer, cenotaph, flaws FROM runes_transactions
|
||||
LEFT JOIN runes_runestones ON runes_transactions.hash = runes_runestones.tx_hash
|
||||
WHERE runes_transactions.block_height = $1
|
||||
`
|
||||
|
||||
type GetRuneTransactionsByHeightRow struct {
|
||||
Hash string
|
||||
BlockHeight int32
|
||||
Timestamp pgtype.Timestamp
|
||||
Inputs []byte
|
||||
Outputs []byte
|
||||
Mints []byte
|
||||
Burns []byte
|
||||
TxHash pgtype.Text
|
||||
BlockHeight_2 pgtype.Int4
|
||||
Etching pgtype.Bool
|
||||
EtchingDivisibility pgtype.Int2
|
||||
EtchingPremine pgtype.Numeric
|
||||
EtchingRune pgtype.Text
|
||||
EtchingSpacers pgtype.Int4
|
||||
EtchingSymbol pgtype.Int4
|
||||
EtchingTerms pgtype.Bool
|
||||
EtchingTermsAmount pgtype.Numeric
|
||||
EtchingTermsCap pgtype.Numeric
|
||||
EtchingTermsHeightStart pgtype.Int4
|
||||
EtchingTermsHeightEnd pgtype.Int4
|
||||
EtchingTermsOffsetStart pgtype.Int4
|
||||
EtchingTermsOffsetEnd pgtype.Int4
|
||||
Edicts []byte
|
||||
Mint pgtype.Text
|
||||
Pointer pgtype.Int4
|
||||
Cenotaph pgtype.Bool
|
||||
Flaws pgtype.Int4
|
||||
}
|
||||
|
||||
func (q *Queries) GetRuneTransactionsByHeight(ctx context.Context, blockHeight int32) ([]GetRuneTransactionsByHeightRow, error) {
|
||||
rows, err := q.db.Query(ctx, getRuneTransactionsByHeight, blockHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RunesEntry
|
||||
var items []GetRuneTransactionsByHeightRow
|
||||
for rows.Next() {
|
||||
var i RunesEntry
|
||||
var i GetRuneTransactionsByHeightRow
|
||||
if err := rows.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Hash,
|
||||
&i.BlockHeight,
|
||||
&i.Timestamp,
|
||||
&i.Inputs,
|
||||
&i.Outputs,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.Divisibility,
|
||||
&i.Terms,
|
||||
&i.TermsAmount,
|
||||
&i.TermsCap,
|
||||
&i.TermsHeightStart,
|
||||
&i.TermsHeightEnd,
|
||||
&i.TermsOffsetStart,
|
||||
&i.TermsOffsetEnd,
|
||||
&i.CompletionTime,
|
||||
&i.Burns,
|
||||
&i.TxHash,
|
||||
&i.BlockHeight_2,
|
||||
&i.Etching,
|
||||
&i.EtchingDivisibility,
|
||||
&i.EtchingPremine,
|
||||
&i.EtchingRune,
|
||||
&i.EtchingSpacers,
|
||||
&i.EtchingSymbol,
|
||||
&i.EtchingTerms,
|
||||
&i.EtchingTermsAmount,
|
||||
&i.EtchingTermsCap,
|
||||
&i.EtchingTermsHeightStart,
|
||||
&i.EtchingTermsHeightEnd,
|
||||
&i.EtchingTermsOffsetStart,
|
||||
&i.EtchingTermsOffsetEnd,
|
||||
&i.Edicts,
|
||||
&i.Mint,
|
||||
&i.Pointer,
|
||||
&i.Cenotaph,
|
||||
&i.Flaws,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -261,53 +488,6 @@ func (q *Queries) GetRunesProcessorState(ctx context.Context) (RunesProcessorSta
|
||||
return i, err
|
||||
}
|
||||
|
||||
const setRuneEntry = `-- name: SetRuneEntry :exec
|
||||
INSERT INTO runes_entries (rune_id, rune, spacers, burned_amount, mints, premine, symbol, divisibility, terms, terms_amount, terms_cap, terms_height_start, terms_height_end, terms_offset_start, terms_offset_end, completion_time)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
ON CONFLICT (rune_id) DO UPDATE SET (burned_amount, mints, completion_time) = (excluded.burned_amount, excluded.mints, excluded.completion_time)
|
||||
`
|
||||
|
||||
type SetRuneEntryParams struct {
|
||||
RuneID string
|
||||
Rune string
|
||||
Spacers int32
|
||||
BurnedAmount pgtype.Numeric
|
||||
Mints pgtype.Numeric
|
||||
Premine pgtype.Numeric
|
||||
Symbol int32
|
||||
Divisibility int16
|
||||
Terms bool
|
||||
TermsAmount pgtype.Numeric
|
||||
TermsCap pgtype.Numeric
|
||||
TermsHeightStart pgtype.Int4
|
||||
TermsHeightEnd pgtype.Int4
|
||||
TermsOffsetStart pgtype.Int4
|
||||
TermsOffsetEnd pgtype.Int4
|
||||
CompletionTime pgtype.Timestamp
|
||||
}
|
||||
|
||||
func (q *Queries) SetRuneEntry(ctx context.Context, arg SetRuneEntryParams) error {
|
||||
_, err := q.db.Exec(ctx, setRuneEntry,
|
||||
arg.RuneID,
|
||||
arg.Rune,
|
||||
arg.Spacers,
|
||||
arg.BurnedAmount,
|
||||
arg.Mints,
|
||||
arg.Premine,
|
||||
arg.Symbol,
|
||||
arg.Divisibility,
|
||||
arg.Terms,
|
||||
arg.TermsAmount,
|
||||
arg.TermsCap,
|
||||
arg.TermsHeightStart,
|
||||
arg.TermsHeightEnd,
|
||||
arg.TermsOffsetStart,
|
||||
arg.TermsOffsetEnd,
|
||||
arg.CompletionTime,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateLatestBlock = `-- name: UpdateLatestBlock :exec
|
||||
UPDATE runes_processor_state SET latest_block_height = $1, latest_block_hash = $2, latest_prev_block_hash = $3
|
||||
`
|
||||
|
||||
@@ -19,8 +19,6 @@ type RunesEntry struct {
|
||||
RuneID string
|
||||
Rune string
|
||||
Spacers int32
|
||||
BurnedAmount pgtype.Numeric
|
||||
Mints pgtype.Numeric
|
||||
Premine pgtype.Numeric
|
||||
Symbol int32
|
||||
Divisibility int16
|
||||
@@ -31,7 +29,15 @@ type RunesEntry struct {
|
||||
TermsHeightEnd pgtype.Int4
|
||||
TermsOffsetStart pgtype.Int4
|
||||
TermsOffsetEnd pgtype.Int4
|
||||
CompletionTime pgtype.Timestamp
|
||||
CreatedAtBlock int32
|
||||
}
|
||||
|
||||
type RunesEntryState struct {
|
||||
RuneID string
|
||||
BlockHeight int32
|
||||
Mints pgtype.Numeric
|
||||
BurnedAmount pgtype.Numeric
|
||||
CompletionTime pgtype.Timestamp
|
||||
}
|
||||
|
||||
type RunesIndexedBlock struct {
|
||||
@@ -71,3 +77,36 @@ type RunesProcessorState struct {
|
||||
LatestPrevBlockHash string
|
||||
UpdatedAt pgtype.Timestamp
|
||||
}
|
||||
|
||||
type RunesRunestone struct {
|
||||
TxHash string
|
||||
BlockHeight int32
|
||||
Etching bool
|
||||
EtchingDivisibility pgtype.Int2
|
||||
EtchingPremine pgtype.Numeric
|
||||
EtchingRune pgtype.Text
|
||||
EtchingSpacers pgtype.Int4
|
||||
EtchingSymbol pgtype.Int4
|
||||
EtchingTerms bool
|
||||
EtchingTermsAmount pgtype.Numeric
|
||||
EtchingTermsCap pgtype.Numeric
|
||||
EtchingTermsHeightStart pgtype.Int4
|
||||
EtchingTermsHeightEnd pgtype.Int4
|
||||
EtchingTermsOffsetStart pgtype.Int4
|
||||
EtchingTermsOffsetEnd pgtype.Int4
|
||||
Edicts []byte
|
||||
Mint pgtype.Text
|
||||
Pointer pgtype.Int4
|
||||
Cenotaph bool
|
||||
Flaws int32
|
||||
}
|
||||
|
||||
type RunesTransaction struct {
|
||||
Hash string
|
||||
BlockHeight int32
|
||||
Timestamp pgtype.Timestamp
|
||||
Inputs []byte
|
||||
Outputs []byte
|
||||
Mints []byte
|
||||
Burns []byte
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package postgres
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
@@ -42,7 +43,7 @@ func numericFromUint128(src *uint128.Uint128) (pgtype.Numeric, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func mapRuneEntryModelToType(src gen.RunesEntry) (runes.RuneEntry, error) {
|
||||
func mapRuneEntryModelToType(src gen.GetRuneEntriesByRuneIdsRow) (runes.RuneEntry, error) {
|
||||
runeId, err := runes.NewRuneIdFromString(src.RuneID)
|
||||
if err != nil {
|
||||
return runes.RuneEntry{}, errors.Wrap(err, "failed to parse rune id")
|
||||
@@ -114,21 +115,21 @@ func mapRuneEntryModelToType(src gen.RunesEntry) (runes.RuneEntry, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func mapRuneEntryTypeToParams(src runes.RuneEntry) (gen.SetRuneEntryParams, error) {
|
||||
func mapRuneEntryTypeToParams(src runes.RuneEntry) (gen.CreateRuneEntryParams, gen.CreateRuneEntryStateParams, error) {
|
||||
runeId := src.RuneId.String()
|
||||
rune := src.SpacedRune.Rune.String()
|
||||
spacers := int32(src.SpacedRune.Spacers)
|
||||
burnedAmount, err := numericFromUint128(&src.BurnedAmount)
|
||||
if err != nil {
|
||||
return gen.SetRuneEntryParams{}, errors.Wrap(err, "failed to parse burned amount")
|
||||
}
|
||||
mints, err := numericFromUint128(&src.Mints)
|
||||
if err != nil {
|
||||
return gen.SetRuneEntryParams{}, errors.Wrap(err, "failed to parse mints")
|
||||
return gen.CreateRuneEntryParams{}, gen.CreateRuneEntryStateParams{}, errors.Wrap(err, "failed to parse mints")
|
||||
}
|
||||
burnedAmount, err := numericFromUint128(&src.BurnedAmount)
|
||||
if err != nil {
|
||||
return gen.CreateRuneEntryParams{}, gen.CreateRuneEntryStateParams{}, errors.Wrap(err, "failed to parse burned amount")
|
||||
}
|
||||
premine, err := numericFromUint128(&src.Premine)
|
||||
if err != nil {
|
||||
return gen.SetRuneEntryParams{}, errors.Wrap(err, "failed to parse premine")
|
||||
return gen.CreateRuneEntryParams{}, gen.CreateRuneEntryStateParams{}, errors.Wrap(err, "failed to parse premine")
|
||||
}
|
||||
var completionTime pgtype.Timestamp
|
||||
if !src.CompletionTime.IsZero() {
|
||||
@@ -143,13 +144,13 @@ func mapRuneEntryTypeToParams(src runes.RuneEntry) (gen.SetRuneEntryParams, erro
|
||||
if src.Terms.Amount != nil {
|
||||
termsAmount, err = numericFromUint128(src.Terms.Amount)
|
||||
if err != nil {
|
||||
return gen.SetRuneEntryParams{}, errors.Wrap(err, "failed to parse terms amount")
|
||||
return gen.CreateRuneEntryParams{}, gen.CreateRuneEntryStateParams{}, errors.Wrap(err, "failed to parse terms amount")
|
||||
}
|
||||
}
|
||||
if src.Terms.Cap != nil {
|
||||
termsCap, err = numericFromUint128(src.Terms.Cap)
|
||||
if err != nil {
|
||||
return gen.SetRuneEntryParams{}, errors.Wrap(err, "failed to parse terms cap")
|
||||
return gen.CreateRuneEntryParams{}, gen.CreateRuneEntryStateParams{}, errors.Wrap(err, "failed to parse terms cap")
|
||||
}
|
||||
}
|
||||
if src.Terms.HeightStart != nil {
|
||||
@@ -178,26 +179,353 @@ func mapRuneEntryTypeToParams(src runes.RuneEntry) (gen.SetRuneEntryParams, erro
|
||||
}
|
||||
}
|
||||
|
||||
return gen.SetRuneEntryParams{
|
||||
RuneID: runeId,
|
||||
Rune: rune,
|
||||
Spacers: spacers,
|
||||
BurnedAmount: burnedAmount,
|
||||
Mints: mints,
|
||||
Premine: premine,
|
||||
Symbol: src.Symbol,
|
||||
Divisibility: int16(src.Divisibility),
|
||||
Terms: terms,
|
||||
TermsAmount: termsAmount,
|
||||
TermsCap: termsCap,
|
||||
TermsHeightStart: termsHeightStart,
|
||||
TermsHeightEnd: termsHeightEnd,
|
||||
TermsOffsetStart: termsOffsetStart,
|
||||
TermsOffsetEnd: termsOffsetEnd,
|
||||
CompletionTime: completionTime,
|
||||
return gen.CreateRuneEntryParams{
|
||||
RuneID: runeId,
|
||||
Rune: rune,
|
||||
Spacers: spacers,
|
||||
Premine: premine,
|
||||
Symbol: src.Symbol,
|
||||
Divisibility: int16(src.Divisibility),
|
||||
Terms: terms,
|
||||
TermsAmount: termsAmount,
|
||||
TermsCap: termsCap,
|
||||
TermsHeightStart: termsHeightStart,
|
||||
TermsHeightEnd: termsHeightEnd,
|
||||
TermsOffsetStart: termsOffsetStart,
|
||||
TermsOffsetEnd: termsOffsetEnd,
|
||||
}, gen.CreateRuneEntryStateParams{
|
||||
RuneID: runeId,
|
||||
Mints: mints,
|
||||
BurnedAmount: burnedAmount,
|
||||
CompletionTime: completionTime,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type outpointBalanceModel struct {
|
||||
PkScript string
|
||||
Id runes.RuneId
|
||||
Value uint128.Uint128
|
||||
Index uint32
|
||||
}
|
||||
|
||||
func mapOutPointBalanceTypeToModel(src entity.OutPointBalance) outpointBalanceModel {
|
||||
return outpointBalanceModel{
|
||||
PkScript: hex.EncodeToString(src.PkScript),
|
||||
Id: src.Id,
|
||||
Value: src.Value,
|
||||
Index: src.Index,
|
||||
}
|
||||
}
|
||||
|
||||
// mapRuneTransactionModelToType returns params for creating a new rune transaction and (optionally) a runestone.
|
||||
func mapRuneTransactionTypeToParams(src entity.RuneTransaction) (gen.CreateRuneTransactionParams, *gen.CreateRunestoneParams, error) {
|
||||
var timestamp pgtype.Timestamp
|
||||
if !src.Timestamp.IsZero() {
|
||||
timestamp.Time = src.Timestamp
|
||||
timestamp.Valid = true
|
||||
}
|
||||
inputs := lo.Map(src.Inputs, func(input *entity.OutPointBalance, _ int) outpointBalanceModel {
|
||||
return mapOutPointBalanceTypeToModel(*input)
|
||||
})
|
||||
outputs := lo.Map(src.Outputs, func(output *entity.OutPointBalance, _ int) outpointBalanceModel {
|
||||
return mapOutPointBalanceTypeToModel(*output)
|
||||
})
|
||||
mints := lo.Map(src.Mints, func(mint *entity.OutPointBalance, _ int) outpointBalanceModel {
|
||||
return mapOutPointBalanceTypeToModel(*mint)
|
||||
})
|
||||
inputsBytes, err := json.Marshal(inputs)
|
||||
if err != nil {
|
||||
return gen.CreateRuneTransactionParams{}, nil, errors.Wrap(err, "failed to marshal inputs")
|
||||
}
|
||||
outputsBytes, err := json.Marshal(outputs)
|
||||
if err != nil {
|
||||
return gen.CreateRuneTransactionParams{}, nil, errors.Wrap(err, "failed to marshal outputs")
|
||||
}
|
||||
mintsBytes, err := json.Marshal(mints)
|
||||
if err != nil {
|
||||
return gen.CreateRuneTransactionParams{}, nil, errors.Wrap(err, "failed to marshal mints")
|
||||
}
|
||||
burnsBytes, err := json.Marshal(src.Burns)
|
||||
if err != nil {
|
||||
return gen.CreateRuneTransactionParams{}, nil, errors.Wrap(err, "failed to marshal burns")
|
||||
}
|
||||
|
||||
var runestoneParams *gen.CreateRunestoneParams
|
||||
if src.Runestone != nil {
|
||||
params, err := mapRunestoneTypeToParams(*src.Runestone, src.Hash, src.BlockHeight)
|
||||
if err != nil {
|
||||
return gen.CreateRuneTransactionParams{}, nil, errors.Wrap(err, "failed to map runestone to params")
|
||||
}
|
||||
runestoneParams = ¶ms
|
||||
}
|
||||
|
||||
return gen.CreateRuneTransactionParams{
|
||||
Hash: src.Hash.String(),
|
||||
BlockHeight: int32(src.BlockHeight),
|
||||
Timestamp: timestamp,
|
||||
Inputs: inputsBytes,
|
||||
Outputs: outputsBytes,
|
||||
Mints: mintsBytes,
|
||||
Burns: burnsBytes,
|
||||
}, runestoneParams, nil
|
||||
}
|
||||
|
||||
func extractModelRuneTxAndRunestone(src gen.GetRuneTransactionsByHeightRow) (gen.RunesTransaction, *gen.RunesRunestone, error) {
|
||||
var runestone *gen.RunesRunestone
|
||||
if src.TxHash.Valid {
|
||||
// these fields should never be null
|
||||
if !src.Etching.Valid {
|
||||
return gen.RunesTransaction{}, nil, errors.New("runestone etching bool is null")
|
||||
}
|
||||
if !src.EtchingTerms.Valid {
|
||||
return gen.RunesTransaction{}, nil, errors.New("runestone etching terms bool is null")
|
||||
}
|
||||
if !src.Cenotaph.Valid {
|
||||
return gen.RunesTransaction{}, nil, errors.New("runestone cenotaph is null")
|
||||
}
|
||||
if !src.Flaws.Valid {
|
||||
return gen.RunesTransaction{}, nil, errors.New("runestone flaws is null")
|
||||
}
|
||||
runestone = &gen.RunesRunestone{
|
||||
TxHash: src.TxHash.String,
|
||||
BlockHeight: src.BlockHeight,
|
||||
Etching: src.Etching.Bool,
|
||||
EtchingDivisibility: src.EtchingDivisibility,
|
||||
EtchingPremine: src.EtchingPremine,
|
||||
EtchingRune: src.EtchingRune,
|
||||
EtchingSpacers: src.EtchingSpacers,
|
||||
EtchingSymbol: src.EtchingSymbol,
|
||||
EtchingTerms: src.EtchingTerms.Bool,
|
||||
EtchingTermsAmount: src.EtchingTermsAmount,
|
||||
EtchingTermsCap: src.EtchingTermsCap,
|
||||
EtchingTermsHeightStart: src.EtchingTermsHeightStart,
|
||||
EtchingTermsHeightEnd: src.EtchingTermsHeightEnd,
|
||||
EtchingTermsOffsetStart: src.EtchingTermsOffsetStart,
|
||||
EtchingTermsOffsetEnd: src.EtchingTermsOffsetEnd,
|
||||
Edicts: src.Edicts,
|
||||
Mint: src.Mint,
|
||||
Pointer: src.Pointer,
|
||||
Cenotaph: src.Cenotaph.Bool,
|
||||
Flaws: src.Flaws.Int32,
|
||||
}
|
||||
}
|
||||
return gen.RunesTransaction{
|
||||
Hash: src.Hash,
|
||||
BlockHeight: src.BlockHeight,
|
||||
Timestamp: src.Timestamp,
|
||||
Inputs: src.Inputs,
|
||||
Outputs: src.Outputs,
|
||||
Mints: src.Mints,
|
||||
Burns: src.Burns,
|
||||
}, runestone, nil
|
||||
}
|
||||
|
||||
func mapRuneTransactionModelToType(src gen.RunesTransaction) (entity.RuneTransaction, error) {
|
||||
hash, err := chainhash.NewHashFromStr(src.Hash)
|
||||
if err != nil {
|
||||
return entity.RuneTransaction{}, errors.Wrap(err, "failed to parse transaction hash")
|
||||
}
|
||||
var timestamp time.Time
|
||||
if src.Timestamp.Valid {
|
||||
timestamp = src.Timestamp.Time
|
||||
}
|
||||
inputs := make([]*entity.OutPointBalance, 0)
|
||||
if err := json.Unmarshal(src.Inputs, &inputs); err != nil {
|
||||
return entity.RuneTransaction{}, errors.Wrap(err, "failed to unmarshal inputs")
|
||||
}
|
||||
outputs := make([]*entity.OutPointBalance, 0)
|
||||
if err := json.Unmarshal(src.Outputs, &outputs); err != nil {
|
||||
return entity.RuneTransaction{}, errors.Wrap(err, "failed to unmarshal outputs")
|
||||
}
|
||||
mints := make([]*entity.OutPointBalance, 0)
|
||||
if err := json.Unmarshal(src.Mints, &mints); err != nil {
|
||||
return entity.RuneTransaction{}, errors.Wrap(err, "failed to unmarshal mints")
|
||||
}
|
||||
burns := make(map[runes.RuneId]uint128.Uint128)
|
||||
if err := json.Unmarshal(src.Burns, &burns); err != nil {
|
||||
return entity.RuneTransaction{}, errors.Wrap(err, "failed to unmarshal burns")
|
||||
}
|
||||
|
||||
return entity.RuneTransaction{
|
||||
Hash: *hash,
|
||||
BlockHeight: uint64(src.BlockHeight),
|
||||
Timestamp: timestamp,
|
||||
Inputs: inputs,
|
||||
Outputs: outputs,
|
||||
Mints: mints,
|
||||
Burns: burns,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func mapRunestoneTypeToParams(src runes.Runestone, txHash chainhash.Hash, blockHeight uint64) (gen.CreateRunestoneParams, error) {
|
||||
var runestoneParams gen.CreateRunestoneParams
|
||||
|
||||
edictsBytes, err := json.Marshal(src.Edicts)
|
||||
if err != nil {
|
||||
return gen.CreateRunestoneParams{}, errors.Wrap(err, "failed to marshal runestone edicts")
|
||||
}
|
||||
runestoneParams = gen.CreateRunestoneParams{
|
||||
TxHash: txHash.String(),
|
||||
BlockHeight: int32(blockHeight),
|
||||
Edicts: edictsBytes,
|
||||
Cenotaph: src.Cenotaph,
|
||||
Flaws: int32(src.Flaws),
|
||||
}
|
||||
if src.Etching != nil {
|
||||
runestoneParams.Etching = true
|
||||
etching := *src.Etching
|
||||
if etching.Divisibility != nil {
|
||||
runestoneParams.EtchingDivisibility = pgtype.Int2{Int16: int16(*etching.Divisibility), Valid: true}
|
||||
}
|
||||
if etching.Premine != nil {
|
||||
premine, err := numericFromUint128(etching.Premine)
|
||||
if err != nil {
|
||||
return gen.CreateRunestoneParams{}, errors.Wrap(err, "failed to parse etching premine")
|
||||
}
|
||||
runestoneParams.EtchingPremine = premine
|
||||
}
|
||||
if etching.Rune != nil {
|
||||
runestoneParams.EtchingRune = pgtype.Text{String: etching.Rune.String(), Valid: true}
|
||||
}
|
||||
if etching.Spacers != nil {
|
||||
runestoneParams.EtchingSpacers = pgtype.Int4{Int32: int32(*etching.Spacers), Valid: true}
|
||||
}
|
||||
if etching.Symbol != nil {
|
||||
runestoneParams.EtchingSymbol = pgtype.Int4{Int32: int32(*etching.Symbol), Valid: true}
|
||||
}
|
||||
if etching.Terms != nil {
|
||||
runestoneParams.EtchingTerms = true
|
||||
terms := *etching.Terms
|
||||
if terms.Amount != nil {
|
||||
amount, err := numericFromUint128(terms.Amount)
|
||||
if err != nil {
|
||||
return gen.CreateRunestoneParams{}, errors.Wrap(err, "failed to parse etching terms amount")
|
||||
}
|
||||
runestoneParams.EtchingTermsAmount = amount
|
||||
}
|
||||
if terms.Cap != nil {
|
||||
cap, err := numericFromUint128(terms.Cap)
|
||||
if err != nil {
|
||||
return gen.CreateRunestoneParams{}, errors.Wrap(err, "failed to parse etching terms cap")
|
||||
}
|
||||
runestoneParams.EtchingTermsCap = cap
|
||||
}
|
||||
if terms.HeightStart != nil {
|
||||
runestoneParams.EtchingTermsHeightStart = pgtype.Int4{Int32: int32(*terms.HeightStart), Valid: true}
|
||||
}
|
||||
if terms.HeightEnd != nil {
|
||||
runestoneParams.EtchingTermsHeightEnd = pgtype.Int4{Int32: int32(*terms.HeightEnd), Valid: true}
|
||||
}
|
||||
if terms.OffsetStart != nil {
|
||||
runestoneParams.EtchingTermsOffsetStart = pgtype.Int4{Int32: int32(*terms.OffsetStart), Valid: true}
|
||||
}
|
||||
if terms.OffsetEnd != nil {
|
||||
runestoneParams.EtchingTermsOffsetEnd = pgtype.Int4{Int32: int32(*terms.OffsetEnd), Valid: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
if src.Mint != nil {
|
||||
runestoneParams.Mint = pgtype.Text{String: src.Mint.String(), Valid: true}
|
||||
}
|
||||
if src.Pointer != nil {
|
||||
runestoneParams.Pointer = pgtype.Int4{Int32: int32(*src.Pointer), Valid: true}
|
||||
}
|
||||
|
||||
return runestoneParams, nil
|
||||
}
|
||||
|
||||
func mapRunestoneModelToType(src gen.RunesRunestone) (runes.Runestone, error) {
|
||||
runestone := runes.Runestone{
|
||||
Cenotaph: src.Cenotaph,
|
||||
Flaws: runes.Flaws(src.Flaws),
|
||||
}
|
||||
if src.Etching {
|
||||
etching := runes.Etching{}
|
||||
if src.EtchingDivisibility.Valid {
|
||||
divisibility := uint8(src.EtchingDivisibility.Int16)
|
||||
etching.Divisibility = &divisibility
|
||||
}
|
||||
if src.EtchingPremine.Valid {
|
||||
premine, err := uint128FromNumeric(src.EtchingPremine)
|
||||
if err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to parse etching premine")
|
||||
}
|
||||
etching.Premine = premine
|
||||
}
|
||||
if src.EtchingRune.Valid {
|
||||
rune, err := runes.NewRuneFromString(src.EtchingRune.String)
|
||||
if err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to parse etching rune")
|
||||
}
|
||||
etching.Rune = &rune
|
||||
}
|
||||
if src.EtchingSpacers.Valid {
|
||||
spacers := uint32(src.EtchingSpacers.Int32)
|
||||
etching.Spacers = &spacers
|
||||
}
|
||||
if src.EtchingSymbol.Valid {
|
||||
symbol := rune(src.EtchingSymbol.Int32)
|
||||
etching.Symbol = &symbol
|
||||
}
|
||||
if src.EtchingTerms {
|
||||
terms := runes.Terms{}
|
||||
if src.EtchingTermsAmount.Valid {
|
||||
amount, err := uint128FromNumeric(src.EtchingTermsAmount)
|
||||
if err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to parse etching terms amount")
|
||||
}
|
||||
terms.Amount = amount
|
||||
}
|
||||
if src.EtchingTermsCap.Valid {
|
||||
cap, err := uint128FromNumeric(src.EtchingTermsCap)
|
||||
if err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to parse etching terms cap")
|
||||
}
|
||||
terms.Cap = cap
|
||||
}
|
||||
if src.EtchingTermsHeightStart.Valid {
|
||||
heightStart := uint64(src.EtchingTermsHeightStart.Int32)
|
||||
terms.HeightStart = &heightStart
|
||||
}
|
||||
if src.EtchingTermsHeightEnd.Valid {
|
||||
heightEnd := uint64(src.EtchingTermsHeightEnd.Int32)
|
||||
terms.HeightEnd = &heightEnd
|
||||
}
|
||||
if src.EtchingTermsOffsetStart.Valid {
|
||||
offsetStart := uint64(src.EtchingTermsOffsetStart.Int32)
|
||||
terms.OffsetStart = &offsetStart
|
||||
}
|
||||
if src.EtchingTermsOffsetEnd.Valid {
|
||||
offsetEnd := uint64(src.EtchingTermsOffsetEnd.Int32)
|
||||
terms.OffsetEnd = &offsetEnd
|
||||
}
|
||||
etching.Terms = &terms
|
||||
}
|
||||
runestone.Etching = &etching
|
||||
}
|
||||
if src.Mint.Valid {
|
||||
mint, err := runes.NewRuneIdFromString(src.Mint.String)
|
||||
if err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to parse mint")
|
||||
}
|
||||
runestone.Mint = &mint
|
||||
}
|
||||
if src.Pointer.Valid {
|
||||
pointer := uint64(src.Pointer.Int32)
|
||||
runestone.Pointer = &pointer
|
||||
}
|
||||
// Edicts
|
||||
{
|
||||
if err := json.Unmarshal(src.Edicts, &runestone.Edicts); err != nil {
|
||||
return runes.Runestone{}, errors.Wrap(err, "failed to unmarshal edicts")
|
||||
}
|
||||
if len(runestone.Edicts) == 0 {
|
||||
runestone.Edicts = nil
|
||||
}
|
||||
}
|
||||
return runestone, nil
|
||||
}
|
||||
|
||||
func mapBalanceModelToType(src gen.RunesBalance) (*entity.Balance, error) {
|
||||
runeId, err := runes.NewRuneIdFromString(src.RuneID)
|
||||
if err != nil {
|
||||
|
||||
@@ -55,6 +55,35 @@ func (r *Repository) GetIndexedBlockByHeight(ctx context.Context, height int64)
|
||||
return indexedBlock, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRuneTransactionsByHeight(ctx context.Context, height uint64) ([]*entity.RuneTransaction, error) {
|
||||
rows, err := r.queries.GetRuneTransactionsByHeight(ctx, int32(height))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during query")
|
||||
}
|
||||
|
||||
runeTxs := make([]*entity.RuneTransaction, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
runeTxModel, runestoneModel, err := extractModelRuneTxAndRunestone(row)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to extract rune transaction and runestone from row")
|
||||
}
|
||||
|
||||
runeTx, err := mapRuneTransactionModelToType(runeTxModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse rune transaction model")
|
||||
}
|
||||
if runestoneModel != nil {
|
||||
runestone, err := mapRunestoneModelToType(*runestoneModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse runestone model")
|
||||
}
|
||||
runeTx.Runestone = &runestone
|
||||
}
|
||||
runeTxs = append(runeTxs, &runeTx)
|
||||
}
|
||||
return runeTxs, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRunesBalancesAtOutPoint(ctx context.Context, outPoint wire.OutPoint) (map[runes.RuneId]uint128.Uint128, error) {
|
||||
balances, err := r.queries.GetOutPointBalances(ctx, gen.GetOutPointBalancesParams{
|
||||
TxHash: outPoint.Hash.String(),
|
||||
@@ -79,20 +108,16 @@ func (r *Repository) GetRunesBalancesAtOutPoint(ctx context.Context, outPoint wi
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRuneEntryByRune(ctx context.Context, rune runes.Rune) (*runes.RuneEntry, error) {
|
||||
runeEntryModels, err := r.queries.GetRuneEntriesByRunes(ctx, []string{rune.String()})
|
||||
func (r *Repository) GetRuneIdFromRune(ctx context.Context, rune runes.Rune) (runes.RuneId, error) {
|
||||
runeIdStr, err := r.queries.GetRuneIdFromRune(ctx, rune.String())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during query")
|
||||
return runes.RuneId{}, errors.Wrap(err, "error during query")
|
||||
}
|
||||
if len(runeEntryModels) == 0 {
|
||||
return nil, errors.WithStack(errs.NotFound)
|
||||
}
|
||||
|
||||
runeEntry, err := mapRuneEntryModelToType(runeEntryModels[0])
|
||||
runeId, err := runes.NewRuneIdFromString(runeIdStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse rune entry model")
|
||||
return runes.RuneId{}, errors.Wrap(err, "failed to parse RuneId")
|
||||
}
|
||||
return &runeEntry, nil
|
||||
return runeId, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRuneEntryByRuneId(ctx context.Context, runeId runes.RuneId) (*runes.RuneEntry, error) {
|
||||
@@ -135,16 +160,52 @@ func (r *Repository) GetRuneEntryByRuneIdBatch(ctx context.Context, runeIds []ru
|
||||
return runeEntries, nil
|
||||
}
|
||||
|
||||
func (r *Repository) SetRuneEntry(ctx context.Context, entry *runes.RuneEntry) error {
|
||||
func (r *Repository) CreateRuneTransaction(ctx context.Context, tx *entity.RuneTransaction) error {
|
||||
if tx == nil {
|
||||
return nil
|
||||
}
|
||||
txParams, runestoneParams, err := mapRuneTransactionTypeToParams(*tx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to map rune transaction to params")
|
||||
}
|
||||
if err = r.queries.CreateRuneTransaction(ctx, txParams); err != nil {
|
||||
return errors.Wrap(err, "error during exec CreateRuneTransaction")
|
||||
}
|
||||
if runestoneParams != nil {
|
||||
if err = r.queries.CreateRunestone(ctx, *runestoneParams); err != nil {
|
||||
return errors.Wrap(err, "error during exec CreateRunestone")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) CreateRuneEntry(ctx context.Context, entry *runes.RuneEntry) error {
|
||||
if entry == nil {
|
||||
return nil
|
||||
}
|
||||
params, err := mapRuneEntryTypeToParams(*entry)
|
||||
createParams, createStateParams, err := mapRuneEntryTypeToParams(*entry)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to map rune entry to params")
|
||||
}
|
||||
if err = r.queries.SetRuneEntry(ctx, params); err != nil {
|
||||
return errors.Wrap(err, "error during exec")
|
||||
if err = r.queries.CreateRuneEntry(ctx, createParams); err != nil {
|
||||
return errors.Wrap(err, "error during exec CreateRuneEntry")
|
||||
}
|
||||
if err = r.queries.CreateRuneEntryState(ctx, createStateParams); err != nil {
|
||||
return errors.Wrap(err, "error during exec CreateRuneEntryState")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) CreateRuneEntryState(ctx context.Context, entry *runes.RuneEntry) error {
|
||||
if entry == nil {
|
||||
return nil
|
||||
}
|
||||
_, createStateParams, err := mapRuneEntryTypeToParams(*entry)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to map rune entry to params")
|
||||
}
|
||||
if err = r.queries.CreateRuneEntryState(ctx, createStateParams); err != nil {
|
||||
return errors.Wrap(err, "error during exec CreateRuneEntryState")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -153,3 +153,23 @@ func GetReservedRune(blockHeight uint64, txIndex uint32) Rune {
|
||||
delta := uint128.From64(blockHeight).Lsh(32).Or64(uint64(txIndex))
|
||||
return Rune(firstReservedRune.Uint128().Add(delta))
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (r Rune) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + r.String() + `"`), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (r *Rune) UnmarshalJSON(data []byte) error {
|
||||
// data must be quoted
|
||||
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
|
||||
return errors.New("must be string")
|
||||
}
|
||||
data = data[1 : len(data)-1]
|
||||
parsed, err := NewRuneFromString(string(data))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
*r = parsed
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -80,3 +80,23 @@ func (r RuneId) Next(blockDelta uint64, txIndexDelta uint32) (RuneId, error) {
|
||||
txIndexDelta,
|
||||
)
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (r RuneId) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + r.String() + `"`), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (r *RuneId) UnmarshalJSON(data []byte) error {
|
||||
// data must be quoted
|
||||
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
|
||||
return errors.New("must be string")
|
||||
}
|
||||
data = data[1 : len(data)-1]
|
||||
parsed, err := NewRuneIdFromString(string(data))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
*r = parsed
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -81,3 +81,28 @@ func TestNewRuneIdFromString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuneIdMarshal(t *testing.T) {
|
||||
runeId := RuneId{
|
||||
BlockHeight: 1,
|
||||
TxIndex: 2,
|
||||
}
|
||||
bytes, err := runeId.MarshalJSON()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(`"1:2"`), bytes)
|
||||
}
|
||||
|
||||
func TestRuneIdUnmarshal(t *testing.T) {
|
||||
str := `"1:2"`
|
||||
var runeId RuneId
|
||||
err := runeId.UnmarshalJSON([]byte(str))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, RuneId{
|
||||
BlockHeight: 1,
|
||||
TxIndex: 2,
|
||||
}, runeId)
|
||||
|
||||
str = `1`
|
||||
err = runeId.UnmarshalJSON([]byte(str))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -251,3 +251,22 @@ func TestCommitment(t *testing.T) {
|
||||
test(NewRune(65535), []byte{255, 255})
|
||||
test(NewRune(65536), []byte{0, 0, 1})
|
||||
}
|
||||
|
||||
func TestRuneMarshal(t *testing.T) {
|
||||
rune := NewRune(5)
|
||||
bytes, err := rune.MarshalJSON()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(`"F"`), bytes)
|
||||
}
|
||||
|
||||
func TestRuneUnmarshal(t *testing.T) {
|
||||
str := `"F"`
|
||||
var rune Rune
|
||||
err := rune.UnmarshalJSON([]byte(str))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, NewRune(5), rune)
|
||||
|
||||
str = `1`
|
||||
err = rune.UnmarshalJSON([]byte(str))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/runes"
|
||||
)
|
||||
|
||||
func (u *Usecase) GetRuneEntryByRune(ctx context.Context, rune runes.Rune) (*runes.RuneEntry, error) {
|
||||
runeEntry, err := u.runesDg.GetRuneEntryByRune(ctx, rune)
|
||||
func (u *Usecase) GetRuneIdFromRune(ctx context.Context, rune runes.Rune) (runes.RuneId, error) {
|
||||
runeId, err := u.runesDg.GetRuneIdFromRune(ctx, rune)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get rune entry by rune")
|
||||
return runes.RuneId{}, errors.Wrap(err, "failed to get rune entry by rune")
|
||||
}
|
||||
return runeEntry, nil
|
||||
return runeId, nil
|
||||
}
|
||||
|
||||
func (u *Usecase) GetRuneEntryByRuneId(ctx context.Context, runeId runes.RuneId) (*runes.RuneEntry, error) {
|
||||
|
||||
@@ -14,22 +14,25 @@ import (
|
||||
var _ indexers.BitcoinProcessor = (*Processor)(nil)
|
||||
|
||||
type Processor struct {
|
||||
runesDg datagateway.RunesDataGateway
|
||||
bitcoinClient btcclient.Contract
|
||||
network common.Network
|
||||
runesDg datagateway.RunesDataGateway
|
||||
bitcoinClient btcclient.Contract
|
||||
bitcoinDataSource indexers.BitcoinDatasource
|
||||
network common.Network
|
||||
}
|
||||
|
||||
type NewProcessorParams struct {
|
||||
RunesDg datagateway.RunesDataGateway
|
||||
BitcoinClient btcclient.Contract
|
||||
Network common.Network
|
||||
RunesDg datagateway.RunesDataGateway
|
||||
BitcoinClient btcclient.Contract
|
||||
BitcoinDataSource indexers.BitcoinDatasource
|
||||
Network common.Network
|
||||
}
|
||||
|
||||
func NewProcessor(params NewProcessorParams) *Processor {
|
||||
return &Processor{
|
||||
runesDg: params.RunesDg,
|
||||
bitcoinClient: params.BitcoinClient,
|
||||
network: params.Network,
|
||||
runesDg: params.RunesDg,
|
||||
bitcoinClient: params.BitcoinClient,
|
||||
bitcoinDataSource: params.BitcoinDataSource,
|
||||
network: params.Network,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +61,6 @@ func (p *Processor) GetIndexedBlock(ctx context.Context, height int64) (types.Bl
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Processor) PrepareData(ctx context.Context, from, to int64) ([]*types.Block, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (p *Processor) RevertData(ctx context.Context, from int64) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -270,8 +270,8 @@ func (p *Processor) getEtchedRune(ctx context.Context, tx *types.Transaction, ru
|
||||
return nil, runes.RuneId{}, runes.Rune{}, nil
|
||||
}
|
||||
|
||||
_, err := p.runesDg.GetRuneEntryByRune(ctx, *rune)
|
||||
if err != nil && errors.Is(err, errs.NotFound) {
|
||||
_, err := p.runesDg.GetRuneIdFromRune(ctx, *rune)
|
||||
if err != nil && !errors.Is(err, errs.NotFound) {
|
||||
return nil, runes.RuneId{}, runes.Rune{}, errors.Wrap(err, "error during get rune entry by rune")
|
||||
}
|
||||
// if found, then this is duplicate
|
||||
|
||||
Reference in New Issue
Block a user