feat: implement get indexed block

This commit is contained in:
Gaze
2024-04-12 00:39:08 +07:00
parent a712c18bb3
commit 7616f9c4b0
8 changed files with 115 additions and 0 deletions

View File

@@ -32,6 +32,9 @@ SELECT * FROM runes_processor_state;
-- name: UpdateLatestBlock :exec
UPDATE runes_processor_state SET latest_block_height = $1, latest_block_hash = $2, latest_prev_block_hash = $3;
-- name: GetIndexedBlockByHeight :one
SELECT * FROM runes_indexed_blocks WHERE height = $1;
-- name: CreateIndexedBlock :exec
INSERT INTO runes_indexed_blocks (hash, height, event_hash, cumulative_event_hash) VALUES ($1, $2, $3, $4);

View File

@@ -3,6 +3,7 @@ package datagateway
import (
"context"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/gaze-network/indexer-network/core/types"
"github.com/gaze-network/indexer-network/modules/runes/internal/entity"
@@ -17,6 +18,7 @@ type RunesDataGateway interface {
type RunesReaderDataGateway interface {
GetLatestBlock(ctx context.Context) (types.BlockHeader, error)
GetIndexedBlockByHeight(ctx context.Context, height int64) (*entity.IndexedBlock, 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.
@@ -47,6 +49,9 @@ type RunesWriterDataGateway interface {
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
CreateIndexedBlock(ctx context.Context, block *entity.IndexedBlock) error
DeleteIndexedBlockByHash(ctx context.Context, hash chainhash.Hash) error
}
type CreateRuneBalancesAtBlockParams struct {

View File

@@ -0,0 +1,10 @@
package entity
import "github.com/btcsuite/btcd/chaincfg/chainhash"
type IndexedBlock struct {
Height int64
Hash chainhash.Hash
EventHash chainhash.Hash
CumulativeEventHash chainhash.Hash
}

View File

@@ -109,6 +109,22 @@ func (q *Queries) GetBalancesByRuneId(ctx context.Context, arg GetBalancesByRune
return items, nil
}
const getIndexedBlockByHeight = `-- name: GetIndexedBlockByHeight :one
SELECT hash, height, event_hash, cumulative_event_hash FROM runes_indexed_blocks WHERE height = $1
`
func (q *Queries) GetIndexedBlockByHeight(ctx context.Context, height int32) (RunesIndexedBlock, error) {
row := q.db.QueryRow(ctx, getIndexedBlockByHeight, height)
var i RunesIndexedBlock
err := row.Scan(
&i.Hash,
&i.Height,
&i.EventHash,
&i.CumulativeEventHash,
)
return i, err
}
const getOutPointBalances = `-- name: GetOutPointBalances :many
SELECT rune_id, tx_hash, tx_idx, amount, block_height, spent_height FROM runes_outpoint_balances WHERE tx_hash = $1 AND tx_idx = $2
`

View File

@@ -4,6 +4,7 @@ import (
"encoding/hex"
"time"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/cockroachdb/errors"
"github.com/gaze-network/indexer-network/modules/runes/internal/entity"
"github.com/gaze-network/indexer-network/modules/runes/internal/repository/postgres/gen"
@@ -217,3 +218,33 @@ func mapBalanceModelToType(src gen.RunesBalance) (*entity.Balance, error) {
BlockHeight: uint64(src.BlockHeight),
}, nil
}
func mapIndexedBlockModelToType(src gen.RunesIndexedBlock) (*entity.IndexedBlock, error) {
hash, err := chainhash.NewHashFromStr(src.Hash)
if err != nil {
return nil, errors.Wrap(err, "failed to parse block hash")
}
eventHash, err := chainhash.NewHashFromStr(src.EventHash)
if err != nil {
return nil, errors.Wrap(err, "failed to parse event hash")
}
cumulativeEventHash, err := chainhash.NewHashFromStr(src.CumulativeEventHash)
if err != nil {
return nil, errors.Wrap(err, "failed to parse cumulative event hash")
}
return &entity.IndexedBlock{
Height: int64(src.Height),
Hash: *hash,
EventHash: *eventHash,
CumulativeEventHash: *cumulativeEventHash,
}, nil
}
func mapIndexedBlockTypeToParams(src entity.IndexedBlock) (gen.CreateIndexedBlockParams, error) {
return gen.CreateIndexedBlockParams{
Height: int32(src.Height),
Hash: src.Hash.String(),
EventHash: src.EventHash.String(),
CumulativeEventHash: src.CumulativeEventHash.String(),
}, nil
}

View File

@@ -20,6 +20,8 @@ import (
var _ datagateway.RunesDataGateway = (*Repository)(nil)
// warning: GetLatestBlock currently returns a types.BlockHeader with only Height, Hash, and PrevBlock fields populated.
// This is because it is known that all usage of this function only requires these fields. In the future, we may want to populate all fields for type safety.
func (r *Repository) GetLatestBlock(ctx context.Context) (types.BlockHeader, error) {
state, err := r.queries.GetRunesProcessorState(ctx)
if err != nil {
@@ -40,6 +42,19 @@ func (r *Repository) GetLatestBlock(ctx context.Context) (types.BlockHeader, err
}, nil
}
func (r *Repository) GetIndexedBlockByHeight(ctx context.Context, height int64) (*entity.IndexedBlock, error) {
indexedBlockModel, err := r.queries.GetIndexedBlockByHeight(ctx, int32(height))
if err != nil {
return nil, errors.Wrap(err, "error during query")
}
indexedBlock, err := mapIndexedBlockModelToType(indexedBlockModel)
if err != nil {
return nil, errors.Wrap(err, "failed to parse indexed block model")
}
return indexedBlock, 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(),
@@ -241,3 +256,24 @@ func (r *Repository) GetBalancesByRuneId(ctx context.Context, runeId runes.RuneI
}
return result, nil
}
func (r *Repository) CreateIndexedBlock(ctx context.Context, block *entity.IndexedBlock) error {
if block == nil {
return nil
}
params, err := mapIndexedBlockTypeToParams(*block)
if err != nil {
return errors.Wrap(err, "failed to map indexed block to params")
}
if err = r.queries.CreateIndexedBlock(ctx, params); err != nil {
return errors.Wrap(err, "error during exec")
}
return nil
}
func (r *Repository) DeleteIndexedBlockByHash(ctx context.Context, hash chainhash.Hash) error {
if err := r.queries.DeleteIndexedBlockByHash(ctx, hash.String()); err != nil {
return errors.Wrap(err, "error during exec")
}
return nil
}

View File

@@ -45,6 +45,19 @@ func (p *Processor) CurrentBlock(ctx context.Context) (types.BlockHeader, error)
return blockHeader, nil
}
// warning: GetIndexedBlock currently returns a types.BlockHeader with only Height, Hash fields populated.
// This is because it is known that all usage of this function only requires these fields. In the future, we may want to populate all fields for type safety.
func (p *Processor) GetIndexedBlock(ctx context.Context, height int64) (types.BlockHeader, error) {
block, err := p.runesDg.GetIndexedBlockByHeight(ctx, height)
if err != nil {
return types.BlockHeader{}, errors.Wrap(err, "failed to get indexed block")
}
return types.BlockHeader{
Height: block.Height,
Hash: block.Hash,
}, nil
}
func (p *Processor) PrepareData(ctx context.Context, from, to int64) ([]*types.Block, error) {
panic("implement me")
}

View File

@@ -33,6 +33,7 @@ func (p *Processor) Process(ctx context.Context, blocks []*types.Block) error {
return errors.Wrap(err, "failed to process tx")
}
}
// TODO: create indexed block in db
}
if err := p.runesDg.Commit(ctx); err != nil {
return errors.Wrap(err, "failed to commit transaction")