Files
blockbook/api/types.go
Jiří Musil ae0172dddf Add longTermFeeRate websocket endpoint (#1262)
* feat: add longTermFeeRate websocket endpoint

* chore: regenerate blockbook-api.ts with longTermFeeRate
2025-06-09 14:09:15 +02:00

628 lines
37 KiB
Go

package api
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"sort"
"strings"
"time"
"github.com/trezor/blockbook/bchain"
"github.com/trezor/blockbook/bchain/coins/eth"
"github.com/trezor/blockbook/common"
"github.com/trezor/blockbook/db"
)
const maxUint32 = ^uint32(0)
const maxInt = int(^uint(0) >> 1)
const maxInt64 = int64(^uint64(0) >> 1)
// AccountDetails specifies what data returns GetAddress and GetXpub calls
type AccountDetails int
const (
// AccountDetailsBasic - only that address is indexed and some basic info
AccountDetailsBasic AccountDetails = iota
// AccountDetailsTokens - basic info + tokens
AccountDetailsTokens
// AccountDetailsTokenBalances - basic info + token with balance
AccountDetailsTokenBalances
// AccountDetailsTxidHistory - basic + token balances + txids, subject to paging
AccountDetailsTxidHistory
// AccountDetailsTxHistoryLight - basic + tokens + easily obtained tx data (not requiring requests to backend), subject to paging
AccountDetailsTxHistoryLight
// AccountDetailsTxHistory - basic + tokens + full tx data, subject to paging
AccountDetailsTxHistory
)
// ErrUnsupportedXpub is returned when coin type does not support xpub address derivation or provided string is not an xpub
var ErrUnsupportedXpub = errors.New("XPUB not supported")
// APIError extends error by information if the error details should be returned to the end user
type APIError struct {
Text string `ts_doc:"Human-readable error message describing the issue."`
Public bool `ts_doc:"Whether the error message can safely be shown to the end user."`
}
func (e *APIError) Error() string {
return e.Text
}
// NewAPIError creates ApiError
func NewAPIError(s string, public bool) error {
return &APIError{
Text: s,
Public: public,
}
}
// Amount is a datatype holding amounts
type Amount big.Int
// IsZeroBigInt checks if big int has zero value
func IsZeroBigInt(b *big.Int) bool {
return len(b.Bits()) == 0
}
// Compare returns an integer comparing two Amounts. The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
// Nil Amount is always less then non-nil amount, two nil Amounts are equal
func (a *Amount) Compare(b *Amount) int {
if b == nil {
if a == nil {
return 0
}
return 1
}
if a == nil {
return -1
}
return (*big.Int)(a).Cmp((*big.Int)(b))
}
// MarshalJSON Amount serialization
func (a *Amount) MarshalJSON() (out []byte, err error) {
if a == nil {
return []byte(`"0"`), nil
}
return []byte(`"` + (*big.Int)(a).String() + `"`), nil
}
func (a *Amount) UnmarshalJSON(data []byte) error {
s := strings.Trim(string(data), "\"")
if len(s) > 0 {
bigValue, parsed := new(big.Int).SetString(s, 10)
if !parsed {
return fmt.Errorf("couldn't parse number: %s", s)
}
*a = Amount(*bigValue)
} else {
// assuming empty string means zero
*a = Amount{}
}
return nil
}
func (a *Amount) String() string {
if a == nil {
return ""
}
return (*big.Int)(a).String()
}
// DecimalString returns amount with decimal point placed according to parameter d
func (a *Amount) DecimalString(d int) string {
return bchain.AmountToDecimalString((*big.Int)(a), d)
}
// AsBigInt returns big.Int type for the Amount (empty if Amount is nil)
func (a *Amount) AsBigInt() big.Int {
if a == nil {
return *new(big.Int)
}
return big.Int(*a)
}
// AsInt64 returns Amount as int64 (0 if Amount is nil).
// It is used only for legacy interfaces (socket.io)
// and generally not recommended to use for possible loss of precision.
func (a *Amount) AsInt64() int64 {
if a == nil {
return 0
}
return (*big.Int)(a).Int64()
}
// Vin contains information about single transaction input
type Vin struct {
Txid string `json:"txid,omitempty" ts_doc:"ID/hash of the originating transaction (where the UTXO comes from)."`
Vout uint32 `json:"vout,omitempty" ts_doc:"Index of the output in the referenced transaction."`
Sequence int64 `json:"sequence,omitempty" ts_doc:"Sequence number for this input (e.g. 4294967293)."`
N int `json:"n" ts_doc:"Relative index of this input within the transaction."`
AddrDesc bchain.AddressDescriptor `json:"-" ts_doc:"Internal address descriptor for backend usage (not exposed via JSON)."`
Addresses []string `json:"addresses,omitempty" ts_doc:"List of addresses associated with this input."`
IsAddress bool `json:"isAddress" ts_doc:"Indicates if this input is from a known address."`
IsOwn bool `json:"isOwn,omitempty" ts_doc:"Indicates if this input belongs to the wallet in context."`
ValueSat *Amount `json:"value,omitempty" ts_doc:"Amount (in satoshi or base units) of the input."`
Hex string `json:"hex,omitempty" ts_doc:"Raw script hex data for this input."`
Asm string `json:"asm,omitempty" ts_doc:"Disassembled script for this input."`
Coinbase string `json:"coinbase,omitempty" ts_doc:"Data for coinbase inputs (when mining)."`
}
// Vout contains information about single transaction output
type Vout struct {
ValueSat *Amount `json:"value,omitempty" ts_doc:"Amount (in satoshi or base units) of the output."`
N int `json:"n" ts_doc:"Relative index of this output within the transaction."`
Spent bool `json:"spent,omitempty" ts_doc:"Indicates whether this output has been spent."`
SpentTxID string `json:"spentTxId,omitempty" ts_doc:"Transaction ID in which this output was spent."`
SpentIndex int `json:"spentIndex,omitempty" ts_doc:"Index of the input that spent this output."`
SpentHeight int `json:"spentHeight,omitempty" ts_doc:"Block height at which this output was spent."`
Hex string `json:"hex,omitempty" ts_doc:"Raw script hex data for this output - aka ScriptPubKey."`
Asm string `json:"asm,omitempty" ts_doc:"Disassembled script for this output."`
AddrDesc bchain.AddressDescriptor `json:"-" ts_doc:"Internal address descriptor for backend usage (not exposed via JSON)."`
Addresses []string `json:"addresses" ts_doc:"List of addresses associated with this output."`
IsAddress bool `json:"isAddress" ts_doc:"Indicates whether this output is owned by valid address."`
IsOwn bool `json:"isOwn,omitempty" ts_doc:"Indicates if this output belongs to the wallet in context."`
Type string `json:"type,omitempty" ts_doc:"Output script type (e.g., 'P2PKH', 'P2SH')."`
}
// MultiTokenValue contains values for contracts with multiple token IDs
type MultiTokenValue struct {
Id *Amount `json:"id,omitempty" ts_doc:"Token ID (for ERC1155)."`
Value *Amount `json:"value,omitempty" ts_doc:"Amount of that specific token ID."`
}
// Token contains info about tokens held by an address
type Token struct {
// Deprecated: Use Standard instead.
Type bchain.TokenStandardName `json:"type" ts_type:"'' | 'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155' | 'BEP20' | 'BEP721' | 'BEP1155'" ts_doc:"@deprecated: Use standard instead."`
Standard bchain.TokenStandardName `json:"standard" ts_type:"'' | 'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155' | 'BEP20' | 'BEP721' | 'BEP1155'"`
Name string `json:"name" ts_doc:"Readable name of the token."`
Path string `json:"path,omitempty" ts_doc:"Derivation path if this token is derived from an XPUB-based address."`
Contract string `json:"contract,omitempty" ts_doc:"Contract address on-chain."`
Transfers int `json:"transfers" ts_doc:"Total number of token transfers for this address."`
Symbol string `json:"symbol,omitempty" ts_doc:"Symbol for the token (e.g., 'ETH', 'USDT')."`
Decimals int `json:"decimals,omitempty" ts_doc:"Number of decimals for this token."`
BalanceSat *Amount `json:"balance,omitempty" ts_doc:"Current token balance (in minimal base units)."`
BaseValue float64 `json:"baseValue,omitempty" ts_doc:"Value in the base currency (e.g. ETH for ERC20 tokens)."`
SecondaryValue float64 `json:"secondaryValue,omitempty" ts_doc:"Value in a secondary currency (e.g. fiat), if available."`
Ids []Amount `json:"ids,omitempty" ts_doc:"List of token IDs (for ERC721, each ID is a unique collectible)."`
MultiTokenValues []MultiTokenValue `json:"multiTokenValues,omitempty" ts_doc:"Multiple ERC1155 token balances (id + value)."`
TotalReceivedSat *Amount `json:"totalReceived,omitempty" ts_doc:"Total amount of tokens received."`
TotalSentSat *Amount `json:"totalSent,omitempty" ts_doc:"Total amount of tokens sent."`
ContractIndex string `json:"-"`
}
// Tokens is array of Token
type Tokens []Token
func (a Tokens) Len() int { return len(a) }
func (a Tokens) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a Tokens) Less(i, j int) bool {
ti := &a[i]
tj := &a[j]
// sort by BaseValue descending and then Name and then by Contract
if ti.BaseValue < tj.BaseValue {
return false
} else if ti.BaseValue > tj.BaseValue {
return true
}
if ti.Name == "" {
if tj.Name != "" {
return false
}
} else {
if tj.Name == "" {
return true
}
return ti.Name < tj.Name
}
return ti.Contract < tj.Contract
}
// TokenTransfer contains info about a token transfer done in a transaction
type TokenTransfer struct {
// Deprecated: Use Standard instead.
Type bchain.TokenStandardName `json:"type" ts_type:"'' | 'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155' | 'BEP20' | 'BEP721' | 'BEP1155'" ts_doc:"@deprecated: Use standard instead."`
Standard bchain.TokenStandardName `json:"standard" ts_type:"'' | 'XPUBAddress' | 'ERC20' | 'ERC721' | 'ERC1155' | 'BEP20' | 'BEP721' | 'BEP1155'"`
From string `json:"from" ts_doc:"Source address of the token transfer."`
To string `json:"to" ts_doc:"Destination address of the token transfer."`
Contract string `json:"contract" ts_doc:"Contract address of the token."`
Name string `json:"name,omitempty" ts_doc:"Token name."`
Symbol string `json:"symbol,omitempty" ts_doc:"Token symbol."`
Decimals int `json:"decimals,omitempty" ts_doc:"Number of decimals for this token (if applicable)."`
Value *Amount `json:"value,omitempty" ts_doc:"Amount (in base units) of tokens transferred."`
MultiTokenValues []MultiTokenValue `json:"multiTokenValues,omitempty" ts_doc:"List of multiple ID-value pairs for ERC1155 transfers."`
}
// EthereumInternalTransfer represents internal transaction data in Ethereum-like blockchains
type EthereumInternalTransfer struct {
Type bchain.EthereumInternalTransactionType `json:"type" ts_doc:"Type of internal transfer (CALL, CREATE, etc.)."`
From string `json:"from" ts_doc:"Address from which the transfer originated."`
To string `json:"to" ts_doc:"Address to which the transfer was sent."`
Value *Amount `json:"value" ts_doc:"Value transferred internally (in Wei or base units)."`
}
// EthereumSpecific contains ethereum-specific transaction data
type EthereumSpecific struct {
Type bchain.EthereumInternalTransactionType `json:"type,omitempty" ts_doc:"High-level type of the Ethereum tx (e.g., 'call', 'create')."`
CreatedContract string `json:"createdContract,omitempty" ts_doc:"Address of contract created by this transaction, if any."`
Status eth.TxStatus `json:"status" ts_doc:"Execution status of the transaction (1: success, 0: fail, -1: pending)."`
Error string `json:"error,omitempty" ts_doc:"Error encountered during execution, if any."`
Nonce uint64 `json:"nonce" ts_doc:"Transaction nonce (sequential number from the sender)."`
GasLimit *big.Int `json:"gasLimit" ts_doc:"Maximum gas allowed by the sender for this transaction."`
GasUsed *big.Int `json:"gasUsed,omitempty" ts_doc:"Actual gas consumed by the transaction execution."`
GasPrice *Amount `json:"gasPrice,omitempty" ts_doc:"Price (in Wei or base units) per gas unit."`
MaxPriorityFeePerGas *Amount `json:"maxPriorityFeePerGas,omitempty"`
MaxFeePerGas *Amount `json:"maxFeePerGas,omitempty"`
BaseFeePerGas *Amount `json:"baseFeePerGas,omitempty"`
L1Fee *big.Int `json:"l1Fee,omitempty" ts_doc:"Fee used for L1 part in rollups (e.g. Optimism)."`
L1FeeScalar string `json:"l1FeeScalar,omitempty" ts_doc:"Scaling factor for L1 fees in certain Layer 2 solutions."`
L1GasPrice *Amount `json:"l1GasPrice,omitempty" ts_doc:"Gas price for L1 component, if applicable."`
L1GasUsed *big.Int `json:"l1GasUsed,omitempty" ts_doc:"Amount of gas used in L1 for this tx, if applicable."`
Data string `json:"data,omitempty" ts_doc:"Hex-encoded input data for the transaction."`
ParsedData *bchain.EthereumParsedInputData `json:"parsedData,omitempty" ts_doc:"Decoded transaction data (function name, params, etc.)."`
InternalTransfers []EthereumInternalTransfer `json:"internalTransfers,omitempty" ts_doc:"List of internal (sub-call) transfers."`
}
// AddressAlias holds a specialized alias for an address
type AddressAlias struct {
Type string `ts_doc:"Type of alias, e.g., user-defined name or contract name."`
Alias string `ts_doc:"Alias string for the address."`
}
// AddressAliasesMap is a map of address strings to their alias definitions
type AddressAliasesMap map[string]AddressAlias
// Tx holds information about a transaction
type Tx struct {
Txid string `json:"txid" ts_doc:"Transaction ID (hash)."`
Version int32 `json:"version,omitempty" ts_doc:"Version of the transaction (if applicable)."`
Locktime uint32 `json:"lockTime,omitempty" ts_doc:"Locktime indicating earliest time/height transaction can be mined."`
Vin []Vin `json:"vin" ts_doc:"Array of inputs for this transaction."`
Vout []Vout `json:"vout" ts_doc:"Array of outputs for this transaction."`
Blockhash string `json:"blockHash,omitempty" ts_doc:"Hash of the block containing this transaction."`
Blockheight int `json:"blockHeight" ts_doc:"Block height in which this transaction was included."`
Confirmations uint32 `json:"confirmations" ts_doc:"Number of confirmations (blocks mined after this tx's block)."`
ConfirmationETABlocks uint32 `json:"confirmationETABlocks,omitempty" ts_doc:"Estimated blocks remaining until confirmation (if unconfirmed)."`
ConfirmationETASeconds int64 `json:"confirmationETASeconds,omitempty" ts_doc:"Estimated seconds remaining until confirmation (if unconfirmed)."`
Blocktime int64 `json:"blockTime" ts_doc:"Unix timestamp of the block in which this transaction was included. 0 if unconfirmed."`
Size int `json:"size,omitempty" ts_doc:"Transaction size in bytes."`
VSize int `json:"vsize,omitempty" ts_doc:"Virtual size in bytes, for SegWit-enabled chains."`
ValueOutSat *Amount `json:"value" ts_doc:"Total value of all outputs (in satoshi or base units)."`
ValueInSat *Amount `json:"valueIn,omitempty" ts_doc:"Total value of all inputs (in satoshi or base units)."`
FeesSat *Amount `json:"fees,omitempty" ts_doc:"Transaction fee (inputs - outputs)."`
Hex string `json:"hex,omitempty" ts_doc:"Raw hex-encoded transaction data."`
Rbf bool `json:"rbf,omitempty" ts_doc:"Indicates if this transaction is replace-by-fee (RBF) enabled."`
CoinSpecificData json.RawMessage `json:"coinSpecificData,omitempty" ts_type:"any" ts_doc:"Blockchain-specific extended data."`
TokenTransfers []TokenTransfer `json:"tokenTransfers,omitempty" ts_doc:"List of token transfers that occurred in this transaction."`
EthereumSpecific *EthereumSpecific `json:"ethereumSpecific,omitempty" ts_doc:"Ethereum-like blockchain specific data (if applicable)."`
AddressAliases AddressAliasesMap `json:"addressAliases,omitempty" ts_doc:"Aliases for addresses involved in this transaction."`
}
// FeeStats contains detailed block fee statistics
type FeeStats struct {
TxCount int `json:"txCount" ts_doc:"Number of transactions in the given block."`
TotalFeesSat *Amount `json:"totalFeesSat" ts_doc:"Sum of all fees in satoshi or base units."`
AverageFeePerKb int64 `json:"averageFeePerKb" ts_doc:"Average fee per kilobyte in satoshi or base units."`
DecilesFeePerKb [11]int64 `json:"decilesFeePerKb" ts_doc:"Fee distribution deciles (0%..100%) in satoshi or base units per kB."`
}
// Paging contains information about paging for address, blocks and block
type Paging struct {
Page int `json:"page,omitempty" ts_doc:"Current page index."`
TotalPages int `json:"totalPages,omitempty" ts_doc:"Total number of pages available."`
ItemsOnPage int `json:"itemsOnPage,omitempty" ts_doc:"Number of items returned on this page."`
}
// TokensToReturn specifies what tokens are returned by GetAddress and GetXpubAddress
type TokensToReturn int
const (
// AddressFilterVoutOff disables filtering of transactions by vout
AddressFilterVoutOff = -1
// AddressFilterVoutInputs specifies that only txs where the address is as input are returned
AddressFilterVoutInputs = -2
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
AddressFilterVoutOutputs = -3
// AddressFilterVoutQueryNotNecessary signals that query for transactions is not necessary as there are no transactions for specified contract filter
AddressFilterVoutQueryNotNecessary = -4
// TokensToReturnNonzeroBalance - return only tokens with nonzero balance
TokensToReturnNonzeroBalance TokensToReturn = 0
// TokensToReturnUsed - return tokens with some transfers (even if they have zero balance now)
TokensToReturnUsed TokensToReturn = 1
// TokensToReturnDerived - return all derived tokens
TokensToReturnDerived TokensToReturn = 2
)
// AddressFilter is used to filter data returned from GetAddress api method
type AddressFilter struct {
Vout int `ts_doc:"Specifies which output index we are interested in filtering (or use the special constants)."`
Contract string `ts_doc:"Contract address to filter by, if applicable."`
FromHeight uint32 `ts_doc:"Starting block height for filtering transactions."`
ToHeight uint32 `ts_doc:"Ending block height for filtering transactions."`
TokensToReturn TokensToReturn `ts_doc:"Which tokens to include in the result set."`
// OnlyConfirmed set to true will ignore mempool transactions; mempool is also ignored if FromHeight/ToHeight filter is specified
OnlyConfirmed bool `ts_doc:"If true, ignores mempool (unconfirmed) transactions."`
}
// StakingPool holds data about address participation in a staking pool contract
type StakingPool struct {
Contract string `json:"contract" ts_doc:"Staking pool contract address on-chain."`
Name string `json:"name" ts_doc:"Name of the staking pool contract."`
PendingBalance *Amount `json:"pendingBalance" ts_doc:"Balance pending deposit or withdrawal, if any."`
PendingDepositedBalance *Amount `json:"pendingDepositedBalance" ts_doc:"Any pending deposit that is not yet finalized."`
DepositedBalance *Amount `json:"depositedBalance" ts_doc:"Currently deposited/staked balance."`
WithdrawTotalAmount *Amount `json:"withdrawTotalAmount" ts_doc:"Total amount withdrawn from this pool by the address."`
ClaimableAmount *Amount `json:"claimableAmount" ts_doc:"Rewards or principal currently claimable by the address."`
RestakedReward *Amount `json:"restakedReward" ts_doc:"Total rewards that have been restaked automatically."`
AutocompoundBalance *Amount `json:"autocompoundBalance" ts_doc:"Any balance automatically reinvested into the pool."`
}
// Address holds information about an address and its transactions
type Address struct {
Paging
AddrStr string `json:"address" ts_doc:"The address string in standard format."`
BalanceSat *Amount `json:"balance" ts_doc:"Current confirmed balance (in satoshi or base units)."`
TotalReceivedSat *Amount `json:"totalReceived,omitempty" ts_doc:"Total amount ever received by this address."`
TotalSentSat *Amount `json:"totalSent,omitempty" ts_doc:"Total amount ever sent by this address."`
UnconfirmedBalanceSat *Amount `json:"unconfirmedBalance" ts_doc:"Unconfirmed balance for this address."`
UnconfirmedTxs int `json:"unconfirmedTxs" ts_doc:"Number of unconfirmed transactions for this address."`
UnconfirmedSending *Amount `json:"unconfirmedSending,omitempty" ts_doc:"Unconfirmed outgoing balance for this address."`
UnconfirmedReceiving *Amount `json:"unconfirmedReceiving,omitempty" ts_doc:"Unconfirmed incoming balance for this address."`
Txs int `json:"txs" ts_doc:"Number of transactions for this address (including confirmed)."`
AddrTxCount int `json:"addrTxCount,omitempty" ts_doc:"Historical total count of transactions, if known."`
NonTokenTxs int `json:"nonTokenTxs,omitempty" ts_doc:"Number of transactions not involving tokens (pure coin transfers)."`
InternalTxs int `json:"internalTxs,omitempty" ts_doc:"Number of internal transactions (e.g., Ethereum calls)."`
Transactions []*Tx `json:"transactions,omitempty" ts_doc:"List of transaction details (if requested)."`
Txids []string `json:"txids,omitempty" ts_doc:"List of transaction IDs (if detailed data is not requested)."`
Nonce string `json:"nonce,omitempty" ts_doc:"Current transaction nonce for Ethereum-like addresses."`
UsedTokens int `json:"usedTokens,omitempty" ts_doc:"Number of tokens with any historical usage at this address."`
Tokens Tokens `json:"tokens,omitempty" ts_doc:"List of tokens associated with this address."`
SecondaryValue float64 `json:"secondaryValue,omitempty" ts_doc:"Total value of the address in secondary currency (e.g. fiat)."`
TokensBaseValue float64 `json:"tokensBaseValue,omitempty" ts_doc:"Sum of token values in base currency."`
TokensSecondaryValue float64 `json:"tokensSecondaryValue,omitempty" ts_doc:"Sum of token values in secondary currency (fiat)."`
TotalBaseValue float64 `json:"totalBaseValue,omitempty" ts_doc:"Address's entire value in base currency, including tokens."`
TotalSecondaryValue float64 `json:"totalSecondaryValue,omitempty" ts_doc:"Address's entire value in secondary currency, including tokens."`
ContractInfo *bchain.ContractInfo `json:"contractInfo,omitempty" ts_doc:"Extra info if the address is a contract (ABI, type)."`
// Deprecated: replaced by ContractInfo
Erc20Contract *bchain.ContractInfo `json:"erc20Contract,omitempty" ts_doc:"@deprecated: replaced by contractInfo"`
AddressAliases AddressAliasesMap `json:"addressAliases,omitempty" ts_doc:"Aliases assigned to this address."`
StakingPools []StakingPool `json:"stakingPools,omitempty" ts_doc:"List of staking pool data if address interacts with staking."`
// helpers for explorer
Filter string `json:"-" ts_doc:"Filter used internally for data retrieval."`
XPubAddresses map[string]struct{} `json:"-" ts_doc:"Set of derived XPUB addresses (internal usage)."`
}
// Utxo is one unspent transaction output
type Utxo struct {
Txid string `json:"txid" ts_doc:"Transaction ID in which this UTXO was created."`
Vout int32 `json:"vout" ts_doc:"Index of the output in that transaction."`
AmountSat *Amount `json:"value" ts_doc:"Value of this UTXO (in satoshi or base units)."`
Height int `json:"height,omitempty" ts_doc:"Block height in which the UTXO was confirmed."`
Confirmations int `json:"confirmations" ts_doc:"Number of confirmations for this UTXO."`
Address string `json:"address,omitempty" ts_doc:"Address to which this UTXO belongs."`
Path string `json:"path,omitempty" ts_doc:"Derivation path for XPUB-based wallets, if applicable."`
Locktime uint32 `json:"lockTime,omitempty" ts_doc:"If non-zero, locktime required before spending this UTXO."`
Coinbase bool `json:"coinbase,omitempty" ts_doc:"Indicates if this UTXO originated from a coinbase transaction."`
}
// Utxos is array of Utxo
type Utxos []Utxo
func (a Utxos) Len() int { return len(a) }
func (a Utxos) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a Utxos) Less(i, j int) bool {
// sort in reverse order, unconfirmed (height==0) utxos on top
hi := a[i].Height
hj := a[j].Height
if hi == 0 {
hi = maxInt
}
if hj == 0 {
hj = maxInt
}
return hi >= hj
}
// BalanceHistory contains info about one point in time of balance history
type BalanceHistory struct {
Time uint32 `json:"time" ts_doc:"Unix timestamp for this point in the balance history."`
Txs uint32 `json:"txs" ts_doc:"Number of transactions in this interval."`
ReceivedSat *Amount `json:"received" ts_doc:"Amount received in this interval (in satoshi or base units)."`
SentSat *Amount `json:"sent" ts_doc:"Amount sent in this interval (in satoshi or base units)."`
SentToSelfSat *Amount `json:"sentToSelf" ts_doc:"Amount sent to the same address (self-transfer)."`
FiatRates map[string]float32 `json:"rates,omitempty" ts_doc:"Exchange rates at this point in time, if available."`
Txid string `json:"txid,omitempty" ts_doc:"Transaction ID if the time corresponds to a specific tx."`
}
// BalanceHistories is array of BalanceHistory
type BalanceHistories []BalanceHistory
func (a BalanceHistories) Len() int { return len(a) }
func (a BalanceHistories) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a BalanceHistories) Less(i, j int) bool {
ti := a[i].Time
tj := a[j].Time
if ti == tj {
return a[i].Txid < a[j].Txid
}
return ti < tj
}
// SortAndAggregate sums BalanceHistories to groups defined by parameter groupByTime
func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories {
bhs := make(BalanceHistories, 0)
if len(a) > 0 {
bha := BalanceHistory{
ReceivedSat: &Amount{},
SentSat: &Amount{},
SentToSelfSat: &Amount{},
}
sort.Sort(a)
for i := range a {
bh := &a[i]
time := bh.Time - bh.Time%groupByTime
if bha.Time != time {
if bha.Time != 0 {
// in aggregate, do not return txid as it could multiple of them
bha.Txid = ""
bhs = append(bhs, bha)
}
bha = BalanceHistory{
Time: time,
ReceivedSat: &Amount{},
SentSat: &Amount{},
SentToSelfSat: &Amount{},
}
}
if bha.Txid != bh.Txid {
bha.Txs += bh.Txs
bha.Txid = bh.Txid
}
(*big.Int)(bha.ReceivedSat).Add((*big.Int)(bha.ReceivedSat), (*big.Int)(bh.ReceivedSat))
(*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat))
(*big.Int)(bha.SentToSelfSat).Add((*big.Int)(bha.SentToSelfSat), (*big.Int)(bh.SentToSelfSat))
}
if bha.Txs > 0 {
bha.Txid = ""
bhs = append(bhs, bha)
}
}
return bhs
}
// Blocks is list of blocks with paging information
type Blocks struct {
Paging
Blocks []db.BlockInfo `json:"blocks" ts_doc:"List of blocks."`
}
// BlockInfo contains extended block header data and a list of block txids
type BlockInfo struct {
Hash string `json:"hash" ts_doc:"Block hash."`
Prev string `json:"previousBlockHash,omitempty" ts_doc:"Hash of the previous block in the chain."`
Next string `json:"nextBlockHash,omitempty" ts_doc:"Hash of the next block, if known."`
Height uint32 `json:"height" ts_doc:"Block height (0-based index in the chain)."`
Confirmations int `json:"confirmations" ts_doc:"Number of confirmations of this block (distance from best chain tip)."`
Size int `json:"size" ts_doc:"Size of the block in bytes."`
Time int64 `json:"time,omitempty" ts_doc:"Timestamp of when this block was mined."`
Version common.JSONNumber `json:"version" ts_doc:"Block version (chain-specific meaning)."`
MerkleRoot string `json:"merkleRoot" ts_doc:"Merkle root of the block's transactions."`
Nonce string `json:"nonce" ts_doc:"Nonce used in the mining process."`
Bits string `json:"bits" ts_doc:"Compact representation of the target threshold."`
Difficulty string `json:"difficulty" ts_doc:"Difficulty target for mining this block."`
Txids []string `json:"tx,omitempty" ts_doc:"List of transaction IDs included in this block."`
}
// Block contains information about block
type Block struct {
Paging
BlockInfo
TxCount int `json:"txCount" ts_doc:"Total count of transactions in this block."`
Transactions []*Tx `json:"txs,omitempty" ts_doc:"List of full transaction details (if requested)."`
AddressAliases AddressAliasesMap `json:"addressAliases,omitempty" ts_doc:"Optional aliases for addresses found in this block."`
}
// BlockRaw contains raw block in hex
type BlockRaw struct {
Hex string `json:"hex" ts_doc:"Hex-encoded block data."`
}
// BlockbookInfo contains information about the running blockbook instance
type BlockbookInfo struct {
Coin string `json:"coin" ts_doc:"Coin name, e.g. 'Bitcoin'."`
Network string `json:"network" ts_doc:"Network shortcut, e.g. 'BTC'."`
Host string `json:"host" ts_doc:"Hostname of the blockbook instance, e.g. 'backend5'."`
Version string `json:"version" ts_doc:"Running blockbook version, e.g. '0.4.0'."`
GitCommit string `json:"gitCommit" ts_doc:"Git commit hash of the running blockbook, e.g. 'a0960c8e'."`
BuildTime string `json:"buildTime" ts_doc:"Build time of running blockbook, e.g. '2024-08-08T12:32:50+00:00'."`
SyncMode bool `json:"syncMode" ts_doc:"If true, blockbook is syncing from scratch or in a special sync mode."`
InitialSync bool `json:"initialSync" ts_doc:"Indicates if blockbook is in its initial sync phase."`
InSync bool `json:"inSync" ts_doc:"Indicates if the backend is fully synced with the blockchain."`
BestHeight uint32 `json:"bestHeight" ts_doc:"Best (latest) block height according to this instance."`
LastBlockTime time.Time `json:"lastBlockTime" ts_doc:"Timestamp of the latest block in the chain."`
InSyncMempool bool `json:"inSyncMempool" ts_doc:"Indicates if mempool info is synced as well."`
LastMempoolTime time.Time `json:"lastMempoolTime" ts_doc:"Timestamp of the last mempool update."`
MempoolSize int `json:"mempoolSize" ts_doc:"Number of unconfirmed transactions in the mempool."`
Decimals int `json:"decimals" ts_doc:"Number of decimals for this coin's base unit."`
DbSize int64 `json:"dbSize" ts_doc:"Size of the underlying database in bytes."`
HasFiatRates bool `json:"hasFiatRates,omitempty" ts_doc:"Whether this instance provides fiat exchange rates."`
HasTokenFiatRates bool `json:"hasTokenFiatRates,omitempty" ts_doc:"Whether this instance provides fiat exchange rates for tokens."`
CurrentFiatRatesTime *time.Time `json:"currentFiatRatesTime,omitempty" ts_doc:"Timestamp of the latest fiat rates update."`
HistoricalFiatRatesTime *time.Time `json:"historicalFiatRatesTime,omitempty" ts_doc:"Timestamp of the latest historical fiat rates update."`
HistoricalTokenFiatRatesTime *time.Time `json:"historicalTokenFiatRatesTime,omitempty" ts_doc:"Timestamp of the latest historical token fiat rates update."`
SupportedStakingPools []string `json:"supportedStakingPools,omitempty" ts_doc:"List of contract addresses supported for staking."`
DbSizeFromColumns int64 `json:"dbSizeFromColumns,omitempty" ts_doc:"Optional calculated DB size from columns."`
DbColumns []common.InternalStateColumn `json:"dbColumns,omitempty" ts_doc:"List of columns/tables in the DB for internal state."`
About string `json:"about" ts_doc:"Additional human-readable info about this blockbook instance."`
}
// SystemInfo contains information about the running blockbook and backend instance
type SystemInfo struct {
Blockbook *BlockbookInfo `json:"blockbook" ts_doc:"Blockbook instance information."`
Backend *common.BackendInfo `json:"backend" ts_doc:"Information about the connected backend node."`
}
// MempoolTxid contains information about a transaction in mempool
type MempoolTxid struct {
Time int64 `json:"time" ts_doc:"Timestamp when the transaction was received in the mempool."`
Txid string `json:"txid" ts_doc:"Transaction hash for this mempool entry."`
}
// MempoolTxids contains a list of mempool txids with paging information
type MempoolTxids struct {
Paging
Mempool []MempoolTxid `json:"mempool" ts_doc:"List of transactions currently in the mempool."`
MempoolSize int `json:"mempoolSize" ts_doc:"Number of unconfirmed transactions in the mempool."`
}
// FiatTicker contains formatted CurrencyRatesTicker data
type FiatTicker struct {
Timestamp int64 `json:"ts,omitempty" ts_doc:"Unix timestamp for these fiat rates."`
Rates map[string]float32 `json:"rates" ts_doc:"Map of currency codes to their exchange rate."`
Error string `json:"error,omitempty" ts_doc:"Any error message encountered while fetching rates."`
}
// FiatTickers contains a formatted CurrencyRatesTicker list
type FiatTickers struct {
Tickers []FiatTicker `json:"tickers" ts_doc:"List of fiat tickers with timestamps and rates."`
}
// AvailableVsCurrencies contains formatted data about available versus currencies for exchange rates
type AvailableVsCurrencies struct {
Timestamp int64 `json:"ts,omitempty" ts_doc:"Timestamp for the available currency list."`
Tickers []string `json:"available_currencies" ts_doc:"List of currency codes (e.g., USD, EUR) supported by the rates."`
Error string `json:"error,omitempty" ts_doc:"Error message, if any, when fetching the available currencies."`
}
// Eip1559Fee
type Eip1559Fee struct {
MaxFeePerGas *Amount `json:"maxFeePerGas"`
MaxPriorityFeePerGas *Amount `json:"maxPriorityFeePerGas"`
MinWaitTimeEstimate int `json:"minWaitTimeEstimate,omitempty"`
MaxWaitTimeEstimate int `json:"maxWaitTimeEstimate,omitempty"`
}
// Eip1559Fees
type Eip1559Fees struct {
BaseFeePerGas *Amount `json:"baseFeePerGas,omitempty"`
Low *Eip1559Fee `json:"low,omitempty"`
Medium *Eip1559Fee `json:"medium,omitempty"`
High *Eip1559Fee `json:"high,omitempty"`
Instant *Eip1559Fee `json:"instant,omitempty"`
NetworkCongestion float64 `json:"networkCongestion,omitempty"`
LatestPriorityFeeRange []*Amount `json:"latestPriorityFeeRange,omitempty"`
HistoricalPriorityFeeRange []*Amount `json:"historicalPriorityFeeRange,omitempty"`
HistoricalBaseFeeRange []*Amount `json:"historicalBaseFeeRange,omitempty"`
PriorityFeeTrend string `json:"priorityFeeTrend,omitempty" ts_type:"'up' | 'down'"`
BaseFeeTrend string `json:"baseFeeTrend,omitempty" ts_type:"'up' | 'down'"`
}
type LongTermFeeRate struct {
FeePerUnit string `json:"feePerUnit" ts_doc:"Long term fee rate (in sat/kByte)."`
Blocks uint64 `json:"blocks" ts_doc:"Amount of blocks used for the long term fee rate estimation."`
}