blk/internal/entities/entities.go
2024-08-11 04:52:08 +03:00

196 lines
5.8 KiB
Go

package entities
import (
"encoding/json"
"fmt"
"math/big"
"sort"
"time"
)
// Wallet represents an on-chain wallet with address in hex format and
// delta of its balance
type Wallet struct {
Address string
Delta *big.Int
}
// []*Wallet type alias
type Wallets []*Wallet
// Sort sorts wallets by delta
func (w Wallets) Sort() {
sort.Slice(w, func(r, l int) bool {
if r := w[r].Delta.Cmp(w[l].Delta); r < 0 {
return true
}
return false
})
}
// BlockNumber is an alias for hex block number
type BlockNumber string
// ToInt converts string hex block number into its big.Int representation
func (n BlockNumber) ToInt() (*big.Int, error) {
return hexToInt((string)(n))
}
// Block object
type Block struct {
Difficulty *big.Int `json:"difficulty"`
BaseFeePerGas *big.Int `json:"baseFeePerGas"`
ExtraData string `json:"extraData"`
GasLimit *big.Int `json:"gasLimit"`
GasUsed *big.Int `json:"gasUsed"`
Hash string `json:"hash"`
LogsBloom string `json:"logsBloom"`
Miner string `json:"miner"`
MixHash string `json:"mixHash"`
Nonce string `json:"nonce"`
Number *big.Int `json:"number"`
ParentHash string `json:"parentHash"`
ReceiptsRoot string `json:"receiptsRoot"`
Sha3Uncles string `json:"sha3Uncles"`
Size *big.Int `json:"size"`
StateRoot string `json:"stateRoot"`
Timestamp time.Time `json:"timestamp"`
TotalDifficulty *big.Int `json:"totalDifficulty"`
Transactions []*Transaction `json:"transactions"`
TransactionsRoot string `json:"transactionsRoot"`
}
// helper alias for proper unmarshal of a block object
type blockAlias Block
// blockRaw is an intermediate object needed for unmarshalling
type blockRaw struct {
*blockAlias
BaseFeePerGas string `json:"baseFeePerGas"`
Difficulty string `json:"difficulty"`
GasLimit string `json:"gasLimit"`
GasUsed string `json:"gasUsed"`
Number string `json:"number"`
Size string `json:"size"`
Timestamp string `json:"timestamp"`
TotalDifficulty string `json:"totalDifficulty"`
}
func (b *Block) UnmarshalJSON(data []byte) error {
raw := &blockRaw{
blockAlias: (*blockAlias)(b),
}
if err := json.Unmarshal(data, raw); err != nil {
return fmt.Errorf("error unmarshal base block data. %w", err)
}
b.Difficulty = hexToIntMust(raw.Difficulty)
b.TotalDifficulty = hexToIntMust(raw.TotalDifficulty)
b.BaseFeePerGas = hexToIntMust(raw.BaseFeePerGas)
b.GasLimit = hexToIntMust(raw.GasLimit)
b.GasUsed = hexToIntMust(raw.GasUsed)
b.Number = hexToIntMust(raw.Number)
b.Size = hexToIntMust(raw.Size)
b.Timestamp = time.Unix(hexToIntMust(raw.Timestamp).Int64(), 0)
return nil
}
// Transaction object
type Transaction struct {
BlockHash string `json:"blockHash"`
BlockNumber *big.Int `json:"blockNumber"`
From string `json:"from"`
Gas *big.Int `json:"gas"`
GasPrice *big.Int `json:"gasPrice"`
Hash string `json:"hash"`
Input string `json:"input"`
Nonce *big.Int `json:"nonce"`
To string `json:"to"`
TransactionIndex *big.Int `json:"transactionIndex"`
Value *big.Int `json:"value"`
Type *big.Int `json:"type"`
V *big.Int `json:"v"`
R string `json:"r"`
S string `json:"s"`
MaxFeePerGas *big.Int `json:"maxFeePerGas"`
MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"`
AccessList []interface{} `json:"accessList"`
ChainID *big.Int `json:"chainId"`
}
// helper alias for proper unmarshal of a transaction object
type transactionAlias Transaction
// transactionRaw is an intermediate object needed for unmarshalling
type transactionRaw struct {
*transactionAlias
BlockNumber string `json:"blockNumber"`
Gas string `json:"gas"`
GasPrice string `json:"gasPrice"`
Nonce string `json:"nonce"`
TransactionIndex string `json:"transactionIndex"`
Value string `json:"value"`
Type string `json:"type"`
V string `json:"v"`
MaxFeePerGas string `json:"maxFeePerGas"`
MaxPriorityFeePerGas string `json:"maxPriorityFeePerGas"`
ChainID string `json:"chainId"`
}
func (t *Transaction) UnmarshalJSON(data []byte) error {
txRaw := &transactionRaw{
transactionAlias: (*transactionAlias)(t),
}
if err := json.Unmarshal(data, txRaw); err != nil {
return fmt.Errorf("error unmarshal base tx data. %w", err)
}
t.BlockNumber = hexToIntMust(txRaw.BlockNumber)
t.Gas = hexToIntMust(txRaw.Gas)
t.GasPrice = hexToIntMust(txRaw.GasPrice)
t.Nonce = hexToIntMust(txRaw.Nonce)
t.TransactionIndex = hexToIntMust(txRaw.TransactionIndex)
t.Value = hexToIntMust(txRaw.Value)
t.Type = hexToIntMust(txRaw.Type)
t.V = hexToIntMust(txRaw.V)
t.MaxFeePerGas = hexToIntMust(txRaw.MaxFeePerGas)
t.MaxPriorityFeePerGas = hexToIntMust(txRaw.MaxPriorityFeePerGas)
t.ChainID = hexToIntMust(txRaw.ChainID)
return nil
}
// hexToIntMust is a shortcur for
//
// i, err := hexToInt(s)
// if err != nil {
// panic(err)
// }
func hexToIntMust(s string) *big.Int {
i, err := hexToInt(s)
if err != nil {
panic(err)
}
return i
}
// hexToInt converts string hex value into a big.Int
func hexToInt(s string) (*big.Int, error) {
bi := new(big.Int)
if len(s) < 2 {
return bi, nil
}
if _, ok := bi.SetString(s[2:], 16); !ok {
return nil, fmt.Errorf("error invalid hex number")
}
return bi, nil
}