mirror of
https://github.com/alexgo-io/gaze-indexer.git
synced 2026-04-29 12:15:13 +08:00
feat: implement runes data reader funcs
This commit is contained in:
@@ -27,15 +27,17 @@ CREATE TABLE IF NOT EXISTS "runes_entries" (
|
||||
"mints" DECIMAL NOT NULL,
|
||||
"premine" DECIMAL NOT NULL,
|
||||
"symbol" INT NOT NULL,
|
||||
"term_amount" DECIMAL,
|
||||
"term_cap" DECIMAL,
|
||||
"term_height_start" DECIMAL, -- using DECIMAL because it is uint64 but postgres only supports up to int64
|
||||
"term_height_end" DECIMAL,
|
||||
"term_offset_start" DECIMAL,
|
||||
"term_offset_end" DECIMAL,
|
||||
"divisibility" SMALLINT NOT NULL,
|
||||
"terms" BOOLEAN NOT NULL, -- if true, then minting term exists for this entry
|
||||
"terms_amount" DECIMAL,
|
||||
"terms_cap" DECIMAL,
|
||||
"terms_height_start" DECIMAL, -- using DECIMAL because it is uint64 but postgres only supports up to int64
|
||||
"terms_height_end" DECIMAL,
|
||||
"terms_offset_start" DECIMAL,
|
||||
"terms_offset_end" DECIMAL,
|
||||
"completion_time" TIMESTAMP NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS runes_entries_rune_idx ON "runes_entries" USING HASH ("rune");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS runes_entries_rune_idx ON "runes_entries" USING BTREE ("rune");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "runes_outpoint_balances" (
|
||||
"rune_id" TEXT NOT NULL,
|
||||
|
||||
@@ -5,10 +5,10 @@ SELECT DISTINCT ON (rune_id) * FROM runes_balances WHERE pkscript = $1 AND block
|
||||
SELECT DISTINCT ON (pkscript) * FROM runes_balances WHERE rune_id = $1 AND block_height <= $2 ORDER BY pkscript, block_height DESC;
|
||||
|
||||
-- name: GetOutPointBalances :many
|
||||
SELECT * FROM runes_outpoint_balances WHERE rune_id = $1 AND tx_hash = $2 AND tx_idx = $3;
|
||||
SELECT * FROM runes_outpoint_balances WHERE tx_hash = $1 AND tx_idx = $2;
|
||||
|
||||
-- name: GetRuneEntriesByRuneIds :many
|
||||
SELECT * FROM runes_entries WHERE rune_id = ANY(@rune_ids::text[]);
|
||||
-- name: GetRuneEntryByRuneId :one
|
||||
SELECT * FROM runes_entries WHERE rune_id = $1;
|
||||
|
||||
-- name: GetRuneEntriesByRunes :many
|
||||
SELECT * FROM runes_entries WHERE rune = ANY(@rune_ids::text[]);
|
||||
-- name: GetRuneEntryByRune :one
|
||||
SELECT * FROM runes_entries WHERE rune = $1;
|
||||
|
||||
@@ -78,17 +78,16 @@ func (q *Queries) GetBalancesByRuneId(ctx context.Context, arg GetBalancesByRune
|
||||
}
|
||||
|
||||
const getOutPointBalances = `-- name: GetOutPointBalances :many
|
||||
SELECT rune_id, tx_hash, tx_idx, value FROM runes_outpoint_balances WHERE rune_id = $1 AND tx_hash = $2 AND tx_idx = $3
|
||||
SELECT rune_id, tx_hash, tx_idx, value FROM runes_outpoint_balances WHERE tx_hash = $1 AND tx_idx = $2
|
||||
`
|
||||
|
||||
type GetOutPointBalancesParams struct {
|
||||
RuneID string
|
||||
TxHash string
|
||||
TxIdx int32
|
||||
}
|
||||
|
||||
func (q *Queries) GetOutPointBalances(ctx context.Context, arg GetOutPointBalancesParams) ([]RunesOutpointBalance, error) {
|
||||
rows, err := q.db.Query(ctx, getOutPointBalances, arg.RuneID, arg.TxHash, arg.TxIdx)
|
||||
rows, err := q.db.Query(ctx, getOutPointBalances, arg.TxHash, arg.TxIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -112,80 +111,58 @@ func (q *Queries) GetOutPointBalances(ctx context.Context, arg GetOutPointBalanc
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getRuneEntriesByRuneIds = `-- name: GetRuneEntriesByRuneIds :many
|
||||
SELECT rune_id, rune, spacers, burned_amount, mints, premine, symbol, term_amount, term_cap, term_height_start, term_height_end, term_offset_start, term_offset_end, completion_time FROM runes_entries WHERE rune_id = ANY($1::text[])
|
||||
const getRuneEntryByRune = `-- name: GetRuneEntryByRune :one
|
||||
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 = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRuneEntriesByRuneIds(ctx context.Context, runeIds []string) ([]RunesEntry, error) {
|
||||
rows, err := q.db.Query(ctx, getRuneEntriesByRuneIds, runeIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RunesEntry
|
||||
for rows.Next() {
|
||||
var i RunesEntry
|
||||
if err := rows.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.TermAmount,
|
||||
&i.TermCap,
|
||||
&i.TermHeightStart,
|
||||
&i.TermHeightEnd,
|
||||
&i.TermOffsetStart,
|
||||
&i.TermOffsetEnd,
|
||||
&i.CompletionTime,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
func (q *Queries) GetRuneEntryByRune(ctx context.Context, rune string) (RunesEntry, error) {
|
||||
row := q.db.QueryRow(ctx, getRuneEntryByRune, rune)
|
||||
var i RunesEntry
|
||||
err := row.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.Divisibility,
|
||||
&i.Terms,
|
||||
&i.TermsAmount,
|
||||
&i.TermsCap,
|
||||
&i.TermsHeightStart,
|
||||
&i.TermsHeightEnd,
|
||||
&i.TermsOffsetStart,
|
||||
&i.TermsOffsetEnd,
|
||||
&i.CompletionTime,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getRuneEntriesByRunes = `-- name: GetRuneEntriesByRunes :many
|
||||
SELECT rune_id, rune, spacers, burned_amount, mints, premine, symbol, term_amount, term_cap, term_height_start, term_height_end, term_offset_start, term_offset_end, completion_time FROM runes_entries WHERE rune = ANY($1::text[])
|
||||
const getRuneEntryByRuneId = `-- name: GetRuneEntryByRuneId :one
|
||||
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 = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetRuneEntriesByRunes(ctx context.Context, runeIds []string) ([]RunesEntry, error) {
|
||||
rows, err := q.db.Query(ctx, getRuneEntriesByRunes, runeIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []RunesEntry
|
||||
for rows.Next() {
|
||||
var i RunesEntry
|
||||
if err := rows.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.TermAmount,
|
||||
&i.TermCap,
|
||||
&i.TermHeightStart,
|
||||
&i.TermHeightEnd,
|
||||
&i.TermOffsetStart,
|
||||
&i.TermOffsetEnd,
|
||||
&i.CompletionTime,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
func (q *Queries) GetRuneEntryByRuneId(ctx context.Context, runeID string) (RunesEntry, error) {
|
||||
row := q.db.QueryRow(ctx, getRuneEntryByRuneId, runeID)
|
||||
var i RunesEntry
|
||||
err := row.Scan(
|
||||
&i.RuneID,
|
||||
&i.Rune,
|
||||
&i.Spacers,
|
||||
&i.BurnedAmount,
|
||||
&i.Mints,
|
||||
&i.Premine,
|
||||
&i.Symbol,
|
||||
&i.Divisibility,
|
||||
&i.Terms,
|
||||
&i.TermsAmount,
|
||||
&i.TermsCap,
|
||||
&i.TermsHeightStart,
|
||||
&i.TermsHeightEnd,
|
||||
&i.TermsOffsetStart,
|
||||
&i.TermsOffsetEnd,
|
||||
&i.CompletionTime,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -16,20 +16,22 @@ type RunesBalance struct {
|
||||
}
|
||||
|
||||
type RunesEntry struct {
|
||||
RuneID string
|
||||
Rune string
|
||||
Spacers int32
|
||||
BurnedAmount pgtype.Numeric
|
||||
Mints pgtype.Numeric
|
||||
Premine pgtype.Numeric
|
||||
Symbol int32
|
||||
TermAmount pgtype.Numeric
|
||||
TermCap pgtype.Numeric
|
||||
TermHeightStart pgtype.Numeric
|
||||
TermHeightEnd pgtype.Numeric
|
||||
TermOffsetStart pgtype.Numeric
|
||||
TermOffsetEnd pgtype.Numeric
|
||||
CompletionTime pgtype.Timestamp
|
||||
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.Numeric
|
||||
TermsHeightEnd pgtype.Numeric
|
||||
TermsOffsetStart pgtype.Numeric
|
||||
TermsOffsetEnd pgtype.Numeric
|
||||
CompletionTime pgtype.Timestamp
|
||||
}
|
||||
|
||||
type RunesIndexerDbVersion struct {
|
||||
@@ -39,10 +41,11 @@ type RunesIndexerDbVersion struct {
|
||||
}
|
||||
|
||||
type RunesIndexerStat struct {
|
||||
Id int64
|
||||
ClientVersion string
|
||||
Network string
|
||||
CreatedAt pgtype.Timestamptz
|
||||
Id int64
|
||||
ClientVersion string
|
||||
Network string
|
||||
LatestBlockHeight int32
|
||||
CreatedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type RunesOutpointBalance struct {
|
||||
|
||||
108
modules/runes/internal/repository/postgres/mapper.go
Normal file
108
modules/runes/internal/repository/postgres/mapper.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/repository/postgres/gen"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/runes"
|
||||
"github.com/gaze-network/uint128"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func uint128FromNumeric(src pgtype.Numeric) (uint128.Uint128, error) {
|
||||
bytes, err := src.MarshalJSON()
|
||||
if err != nil {
|
||||
return uint128.Uint128{}, errors.WithStack(err)
|
||||
}
|
||||
result, err := uint128.FromString(string(bytes))
|
||||
if err != nil {
|
||||
return uint128.Uint128{}, errors.WithStack(err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func mapRuneEntryModelToType(src gen.RunesEntry) (*runes.RuneEntry, error) {
|
||||
runeId, err := runes.NewRuneIdFromString(src.RuneID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse rune id")
|
||||
}
|
||||
burnedAmount, err := uint128FromNumeric(src.BurnedAmount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse burned amount")
|
||||
}
|
||||
rune, err := runes.NewRuneFromString(src.Rune)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse rune")
|
||||
}
|
||||
mints, err := uint128FromNumeric(src.Mints)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse mints")
|
||||
}
|
||||
premine, err := uint128FromNumeric(src.Premine)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse premine")
|
||||
}
|
||||
var completionTime time.Time
|
||||
if src.CompletionTime.Valid {
|
||||
completionTime = src.CompletionTime.Time
|
||||
}
|
||||
var terms *runes.Terms
|
||||
if src.Terms {
|
||||
terms = &runes.Terms{}
|
||||
if src.TermsAmount.Valid {
|
||||
amount, err := uint128FromNumeric(src.TermsAmount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms amount")
|
||||
}
|
||||
terms.Amount = &amount
|
||||
}
|
||||
if src.TermsCap.Valid {
|
||||
cap, err := uint128FromNumeric(src.TermsCap)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms cap")
|
||||
}
|
||||
terms.Cap = &cap
|
||||
}
|
||||
if src.TermsHeightStart.Valid {
|
||||
heightStart, err := uint128FromNumeric(src.TermsHeightStart)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms height start")
|
||||
}
|
||||
terms.HeightStart = lo.ToPtr((heightStart.Uint64()))
|
||||
}
|
||||
if src.TermsHeightEnd.Valid {
|
||||
heightEnd, err := uint128FromNumeric(src.TermsHeightEnd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms height end")
|
||||
}
|
||||
terms.HeightEnd = lo.ToPtr((heightEnd.Uint64()))
|
||||
}
|
||||
if src.TermsOffsetStart.Valid {
|
||||
offsetStart, err := uint128FromNumeric(src.TermsOffsetStart)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms offset start")
|
||||
}
|
||||
terms.OffsetStart = lo.ToPtr((offsetStart.Uint64()))
|
||||
}
|
||||
if src.TermsOffsetEnd.Valid {
|
||||
offsetEnd, err := uint128FromNumeric(src.TermsOffsetEnd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse terms offset end")
|
||||
}
|
||||
terms.OffsetEnd = lo.ToPtr((offsetEnd.Uint64()))
|
||||
}
|
||||
}
|
||||
return &runes.RuneEntry{
|
||||
RuneId: runeId,
|
||||
SpacedRune: runes.NewSpacedRune(rune, uint32(src.Spacers)),
|
||||
Mints: mints,
|
||||
BurnedAmount: burnedAmount,
|
||||
Premine: premine,
|
||||
Symbol: src.Symbol,
|
||||
Divisibility: uint8(src.Divisibility),
|
||||
CompletionTime: completionTime,
|
||||
Terms: terms,
|
||||
}, nil
|
||||
}
|
||||
21
modules/runes/internal/repository/postgres/mapper_test.go
Normal file
21
modules/runes/internal/repository/postgres/mapper_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gaze-network/uint128"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUint128FromNumeric(t *testing.T) {
|
||||
numeric := pgtype.Numeric{}
|
||||
numeric.ScanInt64(pgtype.Int8{
|
||||
Int64: 1000,
|
||||
Valid: true,
|
||||
})
|
||||
|
||||
result, err := uint128FromNumeric(numeric)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, uint128.From64(1000), result)
|
||||
}
|
||||
61
modules/runes/internal/repository/postgres/postgres.go
Normal file
61
modules/runes/internal/repository/postgres/postgres.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/gaze-network/indexer-network/common/errs"
|
||||
"github.com/gaze-network/indexer-network/internal/postgres"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/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),
|
||||
}
|
||||
}
|
||||
|
||||
var ErrTxAlreadyExists = errs.ErrorKind("Transaction already exists. Call Commit() or Rollback() first.")
|
||||
|
||||
func (r *Repository) Begin(ctx context.Context) (err error) {
|
||||
if r.tx != nil {
|
||||
return errors.WithStack(ErrTxAlreadyExists)
|
||||
}
|
||||
r.tx, err = r.db.Begin(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to begin transaction")
|
||||
}
|
||||
return 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 {
|
||||
return errors.Wrap(err, "failed to rollback transaction")
|
||||
}
|
||||
r.tx = nil
|
||||
return nil
|
||||
}
|
||||
88
modules/runes/internal/repository/postgres/runes.go
Normal file
88
modules/runes/internal/repository/postgres/runes.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/gaze-network/indexer-network/common/errs"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/datagateway"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/repository/postgres/gen"
|
||||
"github.com/gaze-network/indexer-network/modules/runes/internal/runes"
|
||||
"github.com/gaze-network/uint128"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
var _ datagateway.RunesDataGateway = (*Repository)(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(),
|
||||
TxIdx: int32(outPoint.Index),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during query")
|
||||
}
|
||||
|
||||
result := make(map[runes.RuneId]uint128.Uint128, len(balances))
|
||||
for _, balance := range balances {
|
||||
runeId, err := runes.NewRuneIdFromString(balance.RuneID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse RuneId")
|
||||
}
|
||||
value, err := uint128FromNumeric(balance.Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse balance")
|
||||
}
|
||||
result[runeId] = value
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRuneIdByRune(ctx context.Context, rune runes.Rune) (runes.RuneId, error) {
|
||||
runeEntryModel, err := r.queries.GetRuneEntryByRune(ctx, rune.String())
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return runes.RuneId{}, errors.WithStack(errs.NotFound)
|
||||
}
|
||||
return runes.RuneId{}, errors.Wrap(err, "error during query")
|
||||
}
|
||||
|
||||
runeId, err := runes.NewRuneIdFromString(runeEntryModel.RuneID)
|
||||
if err != nil {
|
||||
return runes.RuneId{}, errors.Wrap(err, "failed to parse rune id")
|
||||
}
|
||||
return runeId, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetRuneEntryByRuneId(ctx context.Context, runeId runes.RuneId) (*runes.RuneEntry, error) {
|
||||
runeEntryModel, err := r.queries.GetRuneEntryByRuneId(ctx, runeId.String())
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errors.WithStack(errs.NotFound)
|
||||
}
|
||||
return nil, errors.Wrap(err, "error during query")
|
||||
}
|
||||
|
||||
runeEntry, err := mapRuneEntryModelToType(runeEntryModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse rune entry model")
|
||||
}
|
||||
return runeEntry, nil
|
||||
}
|
||||
|
||||
func (r *Repository) SetRuneEntry(ctx context.Context, entry *runes.RuneEntry) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r *Repository) CreateRunesBalanceAtOutPoint(ctx context.Context, outPoint wire.OutPoint, balances map[runes.RuneId]uint128.Uint128) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r *Repository) CreateRuneBalance(ctx context.Context, pkScript string, runeId runes.RuneId, blockHeight uint64, balance uint128.Uint128) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r *Repository) UpdateLatestBlockHeight(ctx context.Context, blockHeight uint64) error {
|
||||
panic("implement me")
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package runes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -51,6 +52,10 @@ func NewRuneIdFromString(str string) (RuneId, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r RuneId) String() string {
|
||||
return fmt.Sprintf("%d:%d", r.BlockHeight, r.TxIndex)
|
||||
}
|
||||
|
||||
// Delta calculates the delta encoding between two RuneIds. If the two RuneIds are in the same block, then the block delta is 0 and the tx index delta is the difference between the two tx indices.
|
||||
// If the two RuneIds are in different blocks, then the block delta is the difference between the two block indices and the tx index delta is the tx index in the other block.
|
||||
func (r RuneId) Delta(next RuneId) (uint64, uint32) {
|
||||
|
||||
Reference in New Issue
Block a user