feat: add base code for brc20 dgs and repos

This commit is contained in:
Gaze
2024-05-21 11:43:52 +07:00
parent eb65b8dcbc
commit bb3c24b472
10 changed files with 377 additions and 6 deletions

View File

@@ -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");

View 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);

View 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
}

View 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
}

View 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,
}
}

View 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
}

View 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
}

View 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),
}
}

View 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
}

View File

@@ -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"