196 lines
5.8 KiB
Go
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
|
|
}
|