mirror of
https://github.com/alexgo-io/gaze-brc20-indexer.git
synced 2026-01-12 14:34:54 +08:00
feat: add base code for brc20 dgs and repos
This commit is contained in:
@@ -35,7 +35,7 @@ CREATE TABLE IF NOT EXISTS "brc20_tickers" (
|
|||||||
"limit_per_mint" DECIMAL NOT NULL,
|
"limit_per_mint" DECIMAL NOT NULL,
|
||||||
"is_self_mint" BOOLEAN NOT NULL,
|
"is_self_mint" BOOLEAN NOT NULL,
|
||||||
"deploy_inscription_id" TEXT NOT NULL,
|
"deploy_inscription_id" TEXT NOT NULL,
|
||||||
"created_at" TIMESTAMP NOT NULL
|
"created_at" TIMESTAMP NOT NULL,
|
||||||
"created_at_height" INT NOT NULL
|
"created_at_height" INT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ CREATE INDEX IF NOT EXISTS brc20_deploy_events_block_height_idx ON "brc20_deploy
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "brc20_mint_events" (
|
CREATE TABLE IF NOT EXISTS "brc20_mint_events" (
|
||||||
"id" BIGSERIAL PRIMARY KEY,
|
"id" BIGSERIAL PRIMARY KEY,
|
||||||
"inscription_id" TEXT NOT NULL,,
|
"inscription_id" TEXT NOT NULL,
|
||||||
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
||||||
"original_tick" TEXT NOT NULL,
|
"original_tick" TEXT NOT NULL,
|
||||||
"tx_hash" TEXT NOT NULL,
|
"tx_hash" TEXT NOT NULL,
|
||||||
@@ -79,13 +79,13 @@ CREATE TABLE IF NOT EXISTS "brc20_mint_events" (
|
|||||||
|
|
||||||
"pkscript" TEXT NOT NULL,
|
"pkscript" TEXT NOT NULL,
|
||||||
"amount" DECIMAL NOT NULL,
|
"amount" DECIMAL NOT NULL,
|
||||||
"parent_id" TEXT, -- requires parent deploy inscription id if minting a self-mint ticker
|
"parent_id" TEXT -- requires parent deploy inscription id if minting a self-mint ticker
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS brc20_mint_events_block_height_idx ON "brc20_mint_events" USING BTREE ("block_height");
|
CREATE INDEX IF NOT EXISTS brc20_mint_events_block_height_idx ON "brc20_mint_events" USING BTREE ("block_height");
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "brc20_transfer_events" (
|
CREATE TABLE IF NOT EXISTS "brc20_transfer_events" (
|
||||||
"id" BIGSERIAL PRIMARY KEY,
|
"id" BIGSERIAL PRIMARY KEY,
|
||||||
"inscription_id" TEXT NOT NULL,,
|
"inscription_id" TEXT NOT NULL,
|
||||||
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
||||||
"original_tick" TEXT NOT NULL,
|
"original_tick" TEXT NOT NULL,
|
||||||
"tx_hash" TEXT NOT NULL,
|
"tx_hash" TEXT NOT NULL,
|
||||||
@@ -95,7 +95,7 @@ CREATE TABLE IF NOT EXISTS "brc20_transfer_events" (
|
|||||||
|
|
||||||
"from_pkscript" TEXT, -- if null, it's inscribe transfer. Otherwise, it's transfer transfer
|
"from_pkscript" TEXT, -- if null, it's inscribe transfer. Otherwise, it's transfer transfer
|
||||||
"to_pkscript" TEXT NOT NULL,
|
"to_pkscript" TEXT NOT NULL,
|
||||||
"amount" DECIMAL NOT NULL,
|
"amount" DECIMAL NOT NULL
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS brc20_transfer_events_block_height_idx ON "brc20_transfer_events" USING BTREE ("block_height");
|
CREATE INDEX IF NOT EXISTS brc20_transfer_events_block_height_idx ON "brc20_transfer_events" USING BTREE ("block_height");
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS "brc20_inscription_locations" (
|
|||||||
"block_height" INT NOT NULL,
|
"block_height" INT NOT NULL,
|
||||||
"tx_hash" TEXT NOT NULL,
|
"tx_hash" TEXT NOT NULL,
|
||||||
"tx_idx" INT NOT NULL, -- output index
|
"tx_idx" INT NOT NULL, -- output index
|
||||||
"sat_offset" BIGINT NOT NULL
|
"sat_offset" BIGINT NOT NULL,
|
||||||
PRIMARY KEY ("inscription_id", "block_height")
|
PRIMARY KEY ("inscription_id", "block_height")
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS brc20_inscription_locations_tx_hash_tx_idx_idx ON "brc20_inscription_locations" USING BTREE ("tx_hash", "tx_idx");
|
CREATE INDEX IF NOT EXISTS brc20_inscription_locations_tx_hash_tx_idx_idx ON "brc20_inscription_locations" USING BTREE ("tx_hash", "tx_idx");
|
||||||
|
|||||||
11
modules/brc20/database/postgresql/queries/info.sql
Normal file
11
modules/brc20/database/postgresql/queries/info.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-- name: GetLatestIndexerState :one
|
||||||
|
SELECT * FROM brc20_indexer_state ORDER BY created_at DESC LIMIT 1;
|
||||||
|
|
||||||
|
-- name: SetIndexerState :exec
|
||||||
|
INSERT INTO brc20_indexer_state (db_version, event_hash_version) VALUES ($1, $2);
|
||||||
|
|
||||||
|
-- name: GetLatestIndexerStats :one
|
||||||
|
SELECT "client_version", "network" FROM brc20_indexer_stats ORDER BY id DESC LIMIT 1;
|
||||||
|
|
||||||
|
-- name: UpdateIndexerStats :exec
|
||||||
|
INSERT INTO brc20_indexer_stats (client_version, network) VALUES ($1, $2);
|
||||||
26
modules/brc20/internal/datagateway/brc20.go
Normal file
26
modules/brc20/internal/datagateway/brc20.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package datagateway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BRC20DataGateway interface {
|
||||||
|
BRC20ReaderDataGateway
|
||||||
|
BRC20WriterDataGateway
|
||||||
|
|
||||||
|
// BeginBRC20Tx returns a new BRC20DataGateway with transaction enabled. All write operations performed in this datagateway must be committed to persist changes.
|
||||||
|
BeginBRC20Tx(ctx context.Context) (BRC20DataGatewayWithTx, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BRC20DataGatewayWithTx interface {
|
||||||
|
BRC20DataGateway
|
||||||
|
Tx
|
||||||
|
}
|
||||||
|
|
||||||
|
type BRC20ReaderDataGateway interface {
|
||||||
|
// TODO: add methods
|
||||||
|
}
|
||||||
|
|
||||||
|
type BRC20WriterDataGateway interface {
|
||||||
|
// TODO: add methods
|
||||||
|
}
|
||||||
12
modules/brc20/internal/datagateway/tx.go
Normal file
12
modules/brc20/internal/datagateway/tx.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package datagateway
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type Tx interface {
|
||||||
|
// Commit commits the DB transaction. All changes made after Begin() will be persisted. Calling Commit() will close the current transaction.
|
||||||
|
// If Commit() is called without a prior Begin(), it must be a no-op.
|
||||||
|
Commit(ctx context.Context) error
|
||||||
|
// Rollback rolls back the DB transaction. All changes made after Begin() will be discarded.
|
||||||
|
// 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
|
||||||
|
}
|
||||||
32
modules/brc20/internal/repository/postgres/gen/db.go
Normal file
32
modules/brc20/internal/repository/postgres/gen/db.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.26.0
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DBTX interface {
|
||||||
|
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||||
|
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||||
|
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(db DBTX) *Queries {
|
||||||
|
return &Queries{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Queries struct {
|
||||||
|
db DBTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||||
|
return &Queries{
|
||||||
|
db: tx,
|
||||||
|
}
|
||||||
|
}
|
||||||
70
modules/brc20/internal/repository/postgres/gen/info.sql.go
Normal file
70
modules/brc20/internal/repository/postgres/gen/info.sql.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.26.0
|
||||||
|
// source: info.sql
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
const getLatestIndexerState = `-- name: GetLatestIndexerState :one
|
||||||
|
SELECT id, db_version, event_hash_version, created_at FROM brc20_indexer_state ORDER BY created_at DESC LIMIT 1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetLatestIndexerState(ctx context.Context) (Brc20IndexerState, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getLatestIndexerState)
|
||||||
|
var i Brc20IndexerState
|
||||||
|
err := row.Scan(
|
||||||
|
&i.Id,
|
||||||
|
&i.DbVersion,
|
||||||
|
&i.EventHashVersion,
|
||||||
|
&i.CreatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLatestIndexerStats = `-- name: GetLatestIndexerStats :one
|
||||||
|
SELECT "client_version", "network" FROM brc20_indexer_stats ORDER BY id DESC LIMIT 1
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetLatestIndexerStatsRow struct {
|
||||||
|
ClientVersion string
|
||||||
|
Network string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetLatestIndexerStats(ctx context.Context) (GetLatestIndexerStatsRow, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getLatestIndexerStats)
|
||||||
|
var i GetLatestIndexerStatsRow
|
||||||
|
err := row.Scan(&i.ClientVersion, &i.Network)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const setIndexerState = `-- name: SetIndexerState :exec
|
||||||
|
INSERT INTO brc20_indexer_state (db_version, event_hash_version) VALUES ($1, $2)
|
||||||
|
`
|
||||||
|
|
||||||
|
type SetIndexerStateParams struct {
|
||||||
|
DbVersion int32
|
||||||
|
EventHashVersion int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SetIndexerState(ctx context.Context, arg SetIndexerStateParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, setIndexerState, arg.DbVersion, arg.EventHashVersion)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateIndexerStats = `-- name: UpdateIndexerStats :exec
|
||||||
|
INSERT INTO brc20_indexer_stats (client_version, network) VALUES ($1, $2)
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateIndexerStatsParams struct {
|
||||||
|
ClientVersion string
|
||||||
|
Network string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateIndexerStats(ctx context.Context, arg UpdateIndexerStatsParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, updateIndexerStats, arg.ClientVersion, arg.Network)
|
||||||
|
return err
|
||||||
|
}
|
||||||
128
modules/brc20/internal/repository/postgres/gen/models.go
Normal file
128
modules/brc20/internal/repository/postgres/gen/models.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.26.0
|
||||||
|
|
||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Brc20Balance struct {
|
||||||
|
Pkscript string
|
||||||
|
BlockHeight int32
|
||||||
|
Ticker string
|
||||||
|
OverallBalance pgtype.Numeric
|
||||||
|
AvailableBalance pgtype.Numeric
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20DeployEvent struct {
|
||||||
|
Id int64
|
||||||
|
InscriptionID string
|
||||||
|
Tick string
|
||||||
|
OriginalTick string
|
||||||
|
TxHash string
|
||||||
|
BlockHeight int32
|
||||||
|
TxIndex int32
|
||||||
|
Timestamp pgtype.Timestamp
|
||||||
|
Pkscript string
|
||||||
|
TotalSupply pgtype.Numeric
|
||||||
|
Decimals int16
|
||||||
|
LimitPerMint pgtype.Numeric
|
||||||
|
IsSelfMint bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20IndexedBlock struct {
|
||||||
|
Height int32
|
||||||
|
Hash string
|
||||||
|
PrevHash string
|
||||||
|
EventHash string
|
||||||
|
CumulativeEventHash string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20IndexerStat struct {
|
||||||
|
Id int64
|
||||||
|
ClientVersion string
|
||||||
|
Network string
|
||||||
|
CreatedAt pgtype.Timestamptz
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20IndexerState struct {
|
||||||
|
Id int64
|
||||||
|
DbVersion int32
|
||||||
|
EventHashVersion int32
|
||||||
|
CreatedAt pgtype.Timestamptz
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20Inscription struct {
|
||||||
|
Id string
|
||||||
|
Number int64
|
||||||
|
SequenceNumber int64
|
||||||
|
Delegate pgtype.Text
|
||||||
|
Metadata []byte
|
||||||
|
Metaprotocol pgtype.Text
|
||||||
|
Parent pgtype.Text
|
||||||
|
Pointer pgtype.Int8
|
||||||
|
Content []byte
|
||||||
|
ContentType string
|
||||||
|
TransferCount int32
|
||||||
|
CreatedAt pgtype.Timestamp
|
||||||
|
CreatedAtHeight int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20InscriptionLocation struct {
|
||||||
|
InscriptionID string
|
||||||
|
BlockHeight int32
|
||||||
|
TxHash string
|
||||||
|
TxIdx int32
|
||||||
|
SatOffset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20MintEvent struct {
|
||||||
|
Id int64
|
||||||
|
InscriptionID string
|
||||||
|
Tick string
|
||||||
|
OriginalTick string
|
||||||
|
TxHash string
|
||||||
|
BlockHeight int32
|
||||||
|
TxIndex int32
|
||||||
|
Timestamp pgtype.Timestamp
|
||||||
|
Pkscript string
|
||||||
|
Amount pgtype.Numeric
|
||||||
|
ParentID pgtype.Text
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20Ticker struct {
|
||||||
|
Tick string
|
||||||
|
OriginalTick string
|
||||||
|
TotalSupply pgtype.Numeric
|
||||||
|
Decimals int16
|
||||||
|
LimitPerMint pgtype.Numeric
|
||||||
|
IsSelfMint bool
|
||||||
|
DeployInscriptionID string
|
||||||
|
CreatedAt pgtype.Timestamp
|
||||||
|
CreatedAtHeight int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20TickerState struct {
|
||||||
|
Tick string
|
||||||
|
BlockHeight int32
|
||||||
|
MintedAmount pgtype.Numeric
|
||||||
|
BurnedAmount pgtype.Numeric
|
||||||
|
CompletedAt pgtype.Timestamp
|
||||||
|
CompletedAtHeight pgtype.Int4
|
||||||
|
}
|
||||||
|
|
||||||
|
type Brc20TransferEvent struct {
|
||||||
|
Id int64
|
||||||
|
InscriptionID string
|
||||||
|
Tick string
|
||||||
|
OriginalTick string
|
||||||
|
TxHash string
|
||||||
|
BlockHeight int32
|
||||||
|
TxIndex int32
|
||||||
|
Timestamp pgtype.Timestamp
|
||||||
|
FromPkscript pgtype.Text
|
||||||
|
ToPkscript string
|
||||||
|
Amount pgtype.Numeric
|
||||||
|
}
|
||||||
20
modules/brc20/internal/repository/postgres/postgres.go
Normal file
20
modules/brc20/internal/repository/postgres/postgres.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gaze-network/indexer-network/internal/postgres"
|
||||||
|
"github.com/gaze-network/indexer-network/modules/brc20/internal/repository/postgres/gen"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Repository struct {
|
||||||
|
db postgres.DB
|
||||||
|
queries *gen.Queries
|
||||||
|
tx pgx.Tx
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRepository(db postgres.DB) *Repository {
|
||||||
|
return &Repository{
|
||||||
|
db: db,
|
||||||
|
queries: gen.New(db),
|
||||||
|
}
|
||||||
|
}
|
||||||
62
modules/brc20/internal/repository/postgres/tx.go
Normal file
62
modules/brc20/internal/repository/postgres/tx.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/cockroachdb/errors"
|
||||||
|
"github.com/gaze-network/indexer-network/modules/brc20/internal/datagateway"
|
||||||
|
"github.com/gaze-network/indexer-network/pkg/logger"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrTxAlreadyExists = errors.New("Transaction already exists. Call Commit() or Rollback() first.")
|
||||||
|
|
||||||
|
func (r *Repository) begin(ctx context.Context) (*Repository, error) {
|
||||||
|
if r.tx != nil {
|
||||||
|
return nil, errors.WithStack(ErrTxAlreadyExists)
|
||||||
|
}
|
||||||
|
tx, err := r.db.Begin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to begin transaction")
|
||||||
|
}
|
||||||
|
return &Repository{
|
||||||
|
db: r.db,
|
||||||
|
queries: r.queries.WithTx(tx),
|
||||||
|
tx: tx,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) BeginBRC20Tx(ctx context.Context) (datagateway.BRC20DataGatewayWithTx, error) {
|
||||||
|
repo, err := r.begin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) Commit(ctx context.Context) error {
|
||||||
|
if r.tx == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := r.tx.Commit(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to commit transaction")
|
||||||
|
}
|
||||||
|
r.tx = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) Rollback(ctx context.Context) error {
|
||||||
|
if r.tx == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := r.tx.Rollback(ctx)
|
||||||
|
if err != nil && !errors.Is(err, pgx.ErrTxClosed) {
|
||||||
|
return errors.Wrap(err, "failed to rollback transaction")
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
logger.DebugContext(ctx, "rolled back transaction")
|
||||||
|
}
|
||||||
|
r.tx = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
10
sqlc.yaml
10
sqlc.yaml
@@ -17,3 +17,13 @@ sql:
|
|||||||
sql_package: "pgx/v5"
|
sql_package: "pgx/v5"
|
||||||
rename:
|
rename:
|
||||||
id: "Id"
|
id: "Id"
|
||||||
|
- schema: "./modules/brc20/database/postgresql/migrations"
|
||||||
|
queries: "./modules/brc20/database/postgresql/queries"
|
||||||
|
engine: "postgresql"
|
||||||
|
gen:
|
||||||
|
go:
|
||||||
|
package: "gen"
|
||||||
|
out: "./modules/brc20/internal/repository/postgres/gen"
|
||||||
|
sql_package: "pgx/v5"
|
||||||
|
rename:
|
||||||
|
id: "Id"
|
||||||
|
|||||||
Reference in New Issue
Block a user