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,
|
||||
"is_self_mint" BOOLEAN NOT NULL,
|
||||
"deploy_inscription_id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP NOT NULL
|
||||
"created_at" TIMESTAMP 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" (
|
||||
"id" BIGSERIAL PRIMARY KEY,
|
||||
"inscription_id" TEXT NOT NULL,,
|
||||
"inscription_id" TEXT NOT NULL,
|
||||
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
||||
"original_tick" TEXT NOT NULL,
|
||||
"tx_hash" TEXT NOT NULL,
|
||||
@@ -79,13 +79,13 @@ CREATE TABLE IF NOT EXISTS "brc20_mint_events" (
|
||||
|
||||
"pkscript" TEXT 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 TABLE IF NOT EXISTS "brc20_transfer_events" (
|
||||
"id" BIGSERIAL PRIMARY KEY,
|
||||
"inscription_id" TEXT NOT NULL,,
|
||||
"inscription_id" TEXT NOT NULL,
|
||||
"tick" TEXT NOT NULL, -- lowercase of original_tick
|
||||
"original_tick" 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
|
||||
"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");
|
||||
|
||||
@@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS "brc20_inscription_locations" (
|
||||
"block_height" INT NOT NULL,
|
||||
"tx_hash" TEXT NOT NULL,
|
||||
"tx_idx" INT NOT NULL, -- output index
|
||||
"sat_offset" BIGINT NOT NULL
|
||||
"sat_offset" BIGINT NOT NULL,
|
||||
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");
|
||||
|
||||
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"
|
||||
rename:
|
||||
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