github.com/theQRL/go-zond@v0.1.1/zondclient/zondclient.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package zondclient provides a client for the Ethereum RPC API. 18 package zondclient 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "math/big" 26 27 "github.com/theQRL/go-zond" 28 "github.com/theQRL/go-zond/common" 29 "github.com/theQRL/go-zond/common/hexutil" 30 "github.com/theQRL/go-zond/core/types" 31 "github.com/theQRL/go-zond/rpc" 32 ) 33 34 // Client defines typed wrappers for the Ethereum RPC API. 35 type Client struct { 36 c *rpc.Client 37 } 38 39 // Dial connects a client to the given URL. 40 func Dial(rawurl string) (*Client, error) { 41 return DialContext(context.Background(), rawurl) 42 } 43 44 // DialContext connects a client to the given URL with context. 45 func DialContext(ctx context.Context, rawurl string) (*Client, error) { 46 c, err := rpc.DialContext(ctx, rawurl) 47 if err != nil { 48 return nil, err 49 } 50 return NewClient(c), nil 51 } 52 53 // NewClient creates a client that uses the given RPC client. 54 func NewClient(c *rpc.Client) *Client { 55 return &Client{c} 56 } 57 58 // Close closes the underlying RPC connection. 59 func (ec *Client) Close() { 60 ec.c.Close() 61 } 62 63 // Client gets the underlying RPC client. 64 func (ec *Client) Client() *rpc.Client { 65 return ec.c 66 } 67 68 // Blockchain Access 69 70 // ChainID retrieves the current chain ID for transaction replay protection. 71 func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { 72 var result hexutil.Big 73 err := ec.c.CallContext(ctx, &result, "zond_chainId") 74 if err != nil { 75 return nil, err 76 } 77 return (*big.Int)(&result), err 78 } 79 80 // BlockByHash returns the given full block. 81 // 82 // Note that loading full blocks requires two requests. Use HeaderByHash 83 // if you don't need all transactions or uncle headers. 84 func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 85 return ec.getBlock(ctx, "zond_getBlockByHash", hash, true) 86 } 87 88 // BlockByNumber returns a block from the current canonical chain. If number is nil, the 89 // latest known block is returned. 90 // 91 // Note that loading full blocks requires two requests. Use HeaderByNumber 92 // if you don't need all transactions or uncle headers. 93 func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 94 return ec.getBlock(ctx, "zond_getBlockByNumber", toBlockNumArg(number), true) 95 } 96 97 // BlockNumber returns the most recent block number 98 func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) { 99 var result hexutil.Uint64 100 err := ec.c.CallContext(ctx, &result, "zond_blockNumber") 101 return uint64(result), err 102 } 103 104 // PeerCount returns the number of p2p peers as reported by the net_peerCount method. 105 func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { 106 var result hexutil.Uint64 107 err := ec.c.CallContext(ctx, &result, "net_peerCount") 108 return uint64(result), err 109 } 110 111 // BlockReceipts returns the receipts of a given block number or hash 112 func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { 113 var r []*types.Receipt 114 err := ec.c.CallContext(ctx, &r, "zond_getBlockReceipts", blockNrOrHash) 115 if err == nil && r == nil { 116 return nil, zond.NotFound 117 } 118 return r, err 119 } 120 121 type rpcBlock struct { 122 Hash common.Hash `json:"hash"` 123 Transactions []rpcTransaction `json:"transactions"` 124 UncleHashes []common.Hash `json:"uncles"` 125 Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` 126 } 127 128 func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { 129 var raw json.RawMessage 130 err := ec.c.CallContext(ctx, &raw, method, args...) 131 if err != nil { 132 return nil, err 133 } 134 135 // Decode header and transactions. 136 var head *types.Header 137 if err := json.Unmarshal(raw, &head); err != nil { 138 return nil, err 139 } 140 // When the block is not found, the API returns JSON null. 141 if head == nil { 142 return nil, zond.NotFound 143 } 144 145 var body rpcBlock 146 if err := json.Unmarshal(raw, &body); err != nil { 147 return nil, err 148 } 149 // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. 150 if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { 151 return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles") 152 } 153 if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { 154 return nil, errors.New("server returned empty uncle list but block header indicates uncles") 155 } 156 if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 { 157 return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions") 158 } 159 if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 { 160 return nil, errors.New("server returned empty transaction list but block header indicates transactions") 161 } 162 // Load uncles because they are not included in the block response. 163 var uncles []*types.Header 164 if len(body.UncleHashes) > 0 { 165 uncles = make([]*types.Header, len(body.UncleHashes)) 166 reqs := make([]rpc.BatchElem, len(body.UncleHashes)) 167 for i := range reqs { 168 reqs[i] = rpc.BatchElem{ 169 Method: "zond_getUncleByBlockHashAndIndex", 170 Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))}, 171 Result: &uncles[i], 172 } 173 } 174 if err := ec.c.BatchCallContext(ctx, reqs); err != nil { 175 return nil, err 176 } 177 for i := range reqs { 178 if reqs[i].Error != nil { 179 return nil, reqs[i].Error 180 } 181 if uncles[i] == nil { 182 return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:]) 183 } 184 } 185 } 186 // Fill the sender cache of transactions in the block. 187 txs := make([]*types.Transaction, len(body.Transactions)) 188 for i, tx := range body.Transactions { 189 if tx.From != nil { 190 setSenderFromServer(tx.tx, *tx.From, body.Hash) 191 } 192 txs[i] = tx.tx 193 } 194 return types.NewBlockWithHeader(head).WithBody(txs, uncles).WithWithdrawals(body.Withdrawals), nil 195 } 196 197 // HeaderByHash returns the block header with the given hash. 198 func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 199 var head *types.Header 200 err := ec.c.CallContext(ctx, &head, "zond_getBlockByHash", hash, false) 201 if err == nil && head == nil { 202 err = zond.NotFound 203 } 204 return head, err 205 } 206 207 // HeaderByNumber returns a block header from the current canonical chain. If number is 208 // nil, the latest known header is returned. 209 func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 210 var head *types.Header 211 err := ec.c.CallContext(ctx, &head, "zond_getBlockByNumber", toBlockNumArg(number), false) 212 if err == nil && head == nil { 213 err = zond.NotFound 214 } 215 return head, err 216 } 217 218 type rpcTransaction struct { 219 tx *types.Transaction 220 txExtraInfo 221 } 222 223 type txExtraInfo struct { 224 BlockNumber *string `json:"blockNumber,omitempty"` 225 BlockHash *common.Hash `json:"blockHash,omitempty"` 226 From *common.Address `json:"from,omitempty"` 227 } 228 229 func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { 230 if err := json.Unmarshal(msg, &tx.tx); err != nil { 231 return err 232 } 233 return json.Unmarshal(msg, &tx.txExtraInfo) 234 } 235 236 // TransactionByHash returns the transaction with the given hash. 237 func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { 238 var json *rpcTransaction 239 err = ec.c.CallContext(ctx, &json, "zond_getTransactionByHash", hash) 240 if err != nil { 241 return nil, false, err 242 } else if json == nil { 243 return nil, false, zond.NotFound 244 } else if r := json.tx.RawSignatureValue(); r == nil { 245 return nil, false, errors.New("server returned transaction without signature") 246 } 247 if json.From != nil && json.BlockHash != nil { 248 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 249 } 250 return json.tx, json.BlockNumber == nil, nil 251 } 252 253 // TransactionSender returns the sender address of the given transaction. The transaction 254 // must be known to the remote node and included in the blockchain at the given block and 255 // index. The sender is the one derived by the protocol at the time of inclusion. 256 // 257 // There is a fast-path for transactions retrieved by TransactionByHash and 258 // TransactionInBlock. Getting their sender address can be done without an RPC interaction. 259 func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { 260 // Try to load the address from the cache. 261 sender, err := types.Sender(&senderFromServer{blockhash: block}, tx) 262 if err == nil { 263 return sender, nil 264 } 265 266 // It was not found in cache, ask the server. 267 var meta struct { 268 Hash common.Hash 269 From common.Address 270 } 271 if err = ec.c.CallContext(ctx, &meta, "zond_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil { 272 return common.Address{}, err 273 } 274 if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() { 275 return common.Address{}, errors.New("wrong inclusion block/index") 276 } 277 return meta.From, nil 278 } 279 280 // TransactionCount returns the total number of transactions in the given block. 281 func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { 282 var num hexutil.Uint 283 err := ec.c.CallContext(ctx, &num, "zond_getBlockTransactionCountByHash", blockHash) 284 return uint(num), err 285 } 286 287 // TransactionInBlock returns a single transaction at index in the given block. 288 func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { 289 var json *rpcTransaction 290 err := ec.c.CallContext(ctx, &json, "zond_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) 291 if err != nil { 292 return nil, err 293 } 294 if json == nil { 295 return nil, zond.NotFound 296 } else if r := json.tx.RawSignatureValue(); r == nil { 297 return nil, errors.New("server returned transaction without signature") 298 } 299 if json.From != nil && json.BlockHash != nil { 300 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 301 } 302 return json.tx, err 303 } 304 305 // TransactionReceipt returns the receipt of a transaction by transaction hash. 306 // Note that the receipt is not available for pending transactions. 307 func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 308 var r *types.Receipt 309 err := ec.c.CallContext(ctx, &r, "zond_getTransactionReceipt", txHash) 310 if err == nil { 311 if r == nil { 312 return nil, zond.NotFound 313 } 314 } 315 return r, err 316 } 317 318 // SyncProgress retrieves the current progress of the sync algorithm. If there's 319 // no sync currently running, it returns nil. 320 func (ec *Client) SyncProgress(ctx context.Context) (*zond.SyncProgress, error) { 321 var raw json.RawMessage 322 if err := ec.c.CallContext(ctx, &raw, "zond_syncing"); err != nil { 323 return nil, err 324 } 325 // Handle the possible response types 326 var syncing bool 327 if err := json.Unmarshal(raw, &syncing); err == nil { 328 return nil, nil // Not syncing (always false) 329 } 330 var p *rpcProgress 331 if err := json.Unmarshal(raw, &p); err != nil { 332 return nil, err 333 } 334 return p.toSyncProgress(), nil 335 } 336 337 // SubscribeNewHead subscribes to notifications about the current blockchain head 338 // on the given channel. 339 func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (zond.Subscription, error) { 340 sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads") 341 if err != nil { 342 // Defensively prefer returning nil interface explicitly on error-path, instead 343 // of letting default golang behavior wrap it with non-nil interface that stores 344 // nil concrete type value. 345 return nil, err 346 } 347 return sub, nil 348 } 349 350 // State Access 351 352 // NetworkID returns the network ID for this client. 353 func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) { 354 version := new(big.Int) 355 var ver string 356 if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil { 357 return nil, err 358 } 359 if _, ok := version.SetString(ver, 10); !ok { 360 return nil, fmt.Errorf("invalid net_version result %q", ver) 361 } 362 return version, nil 363 } 364 365 // BalanceAt returns the wei balance of the given account. 366 // The block number can be nil, in which case the balance is taken from the latest known block. 367 func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { 368 var result hexutil.Big 369 err := ec.c.CallContext(ctx, &result, "zond_getBalance", account, toBlockNumArg(blockNumber)) 370 return (*big.Int)(&result), err 371 } 372 373 // StorageAt returns the value of key in the contract storage of the given account. 374 // The block number can be nil, in which case the value is taken from the latest known block. 375 func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { 376 var result hexutil.Bytes 377 err := ec.c.CallContext(ctx, &result, "zond_getStorageAt", account, key, toBlockNumArg(blockNumber)) 378 return result, err 379 } 380 381 // CodeAt returns the contract code of the given account. 382 // The block number can be nil, in which case the code is taken from the latest known block. 383 func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { 384 var result hexutil.Bytes 385 err := ec.c.CallContext(ctx, &result, "zond_getCode", account, toBlockNumArg(blockNumber)) 386 return result, err 387 } 388 389 // NonceAt returns the account nonce of the given account. 390 // The block number can be nil, in which case the nonce is taken from the latest known block. 391 func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { 392 var result hexutil.Uint64 393 err := ec.c.CallContext(ctx, &result, "zond_getTransactionCount", account, toBlockNumArg(blockNumber)) 394 return uint64(result), err 395 } 396 397 // Filters 398 399 // FilterLogs executes a filter query. 400 func (ec *Client) FilterLogs(ctx context.Context, q zond.FilterQuery) ([]types.Log, error) { 401 var result []types.Log 402 arg, err := toFilterArg(q) 403 if err != nil { 404 return nil, err 405 } 406 err = ec.c.CallContext(ctx, &result, "zond_getLogs", arg) 407 return result, err 408 } 409 410 // SubscribeFilterLogs subscribes to the results of a streaming filter query. 411 func (ec *Client) SubscribeFilterLogs(ctx context.Context, q zond.FilterQuery, ch chan<- types.Log) (zond.Subscription, error) { 412 arg, err := toFilterArg(q) 413 if err != nil { 414 return nil, err 415 } 416 sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg) 417 if err != nil { 418 // Defensively prefer returning nil interface explicitly on error-path, instead 419 // of letting default golang behavior wrap it with non-nil interface that stores 420 // nil concrete type value. 421 return nil, err 422 } 423 return sub, nil 424 } 425 426 func toFilterArg(q zond.FilterQuery) (interface{}, error) { 427 arg := map[string]interface{}{ 428 "address": q.Addresses, 429 "topics": q.Topics, 430 } 431 if q.BlockHash != nil { 432 arg["blockHash"] = *q.BlockHash 433 if q.FromBlock != nil || q.ToBlock != nil { 434 return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock") 435 } 436 } else { 437 if q.FromBlock == nil { 438 arg["fromBlock"] = "0x0" 439 } else { 440 arg["fromBlock"] = toBlockNumArg(q.FromBlock) 441 } 442 arg["toBlock"] = toBlockNumArg(q.ToBlock) 443 } 444 return arg, nil 445 } 446 447 // Pending State 448 449 // PendingBalanceAt returns the wei balance of the given account in the pending state. 450 func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { 451 var result hexutil.Big 452 err := ec.c.CallContext(ctx, &result, "zond_getBalance", account, "pending") 453 return (*big.Int)(&result), err 454 } 455 456 // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. 457 func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { 458 var result hexutil.Bytes 459 err := ec.c.CallContext(ctx, &result, "zond_getStorageAt", account, key, "pending") 460 return result, err 461 } 462 463 // PendingCodeAt returns the contract code of the given account in the pending state. 464 func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 465 var result hexutil.Bytes 466 err := ec.c.CallContext(ctx, &result, "zond_getCode", account, "pending") 467 return result, err 468 } 469 470 // PendingNonceAt returns the account nonce of the given account in the pending state. 471 // This is the nonce that should be used for the next transaction. 472 func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { 473 var result hexutil.Uint64 474 err := ec.c.CallContext(ctx, &result, "zond_getTransactionCount", account, "pending") 475 return uint64(result), err 476 } 477 478 // PendingTransactionCount returns the total number of transactions in the pending state. 479 func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) { 480 var num hexutil.Uint 481 err := ec.c.CallContext(ctx, &num, "zond_getBlockTransactionCountByNumber", "pending") 482 return uint(num), err 483 } 484 485 // Contract Calling 486 487 // CallContract executes a message call transaction, which is directly executed in the VM 488 // of the node, but never mined into the blockchain. 489 // 490 // blockNumber selects the block height at which the call runs. It can be nil, in which 491 // case the code is taken from the latest known block. Note that state from very old 492 // blocks might not be available. 493 func (ec *Client) CallContract(ctx context.Context, msg zond.CallMsg, blockNumber *big.Int) ([]byte, error) { 494 var hex hexutil.Bytes 495 err := ec.c.CallContext(ctx, &hex, "zond_call", toCallArg(msg), toBlockNumArg(blockNumber)) 496 if err != nil { 497 return nil, err 498 } 499 return hex, nil 500 } 501 502 // CallContractAtHash is almost the same as CallContract except that it selects 503 // the block by block hash instead of block height. 504 func (ec *Client) CallContractAtHash(ctx context.Context, msg zond.CallMsg, blockHash common.Hash) ([]byte, error) { 505 var hex hexutil.Bytes 506 err := ec.c.CallContext(ctx, &hex, "zond_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) 507 if err != nil { 508 return nil, err 509 } 510 return hex, nil 511 } 512 513 // PendingCallContract executes a message call transaction using the EVM. 514 // The state seen by the contract call is the pending state. 515 func (ec *Client) PendingCallContract(ctx context.Context, msg zond.CallMsg) ([]byte, error) { 516 var hex hexutil.Bytes 517 err := ec.c.CallContext(ctx, &hex, "zond_call", toCallArg(msg), "pending") 518 if err != nil { 519 return nil, err 520 } 521 return hex, nil 522 } 523 524 // SuggestGasPrice retrieves the currently suggested gas price to allow a timely 525 // execution of a transaction. 526 func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 527 var hex hexutil.Big 528 if err := ec.c.CallContext(ctx, &hex, "zond_gasPrice"); err != nil { 529 return nil, err 530 } 531 return (*big.Int)(&hex), nil 532 } 533 534 // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to 535 // allow a timely execution of a transaction. 536 func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 537 var hex hexutil.Big 538 if err := ec.c.CallContext(ctx, &hex, "zond_maxPriorityFeePerGas"); err != nil { 539 return nil, err 540 } 541 return (*big.Int)(&hex), nil 542 } 543 544 type feeHistoryResultMarshaling struct { 545 OldestBlock *hexutil.Big `json:"oldestBlock"` 546 Reward [][]*hexutil.Big `json:"reward,omitempty"` 547 BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` 548 GasUsedRatio []float64 `json:"gasUsedRatio"` 549 } 550 551 // FeeHistory retrieves the fee market history. 552 func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*zond.FeeHistory, error) { 553 var res feeHistoryResultMarshaling 554 if err := ec.c.CallContext(ctx, &res, "zond_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil { 555 return nil, err 556 } 557 reward := make([][]*big.Int, len(res.Reward)) 558 for i, r := range res.Reward { 559 reward[i] = make([]*big.Int, len(r)) 560 for j, r := range r { 561 reward[i][j] = (*big.Int)(r) 562 } 563 } 564 baseFee := make([]*big.Int, len(res.BaseFee)) 565 for i, b := range res.BaseFee { 566 baseFee[i] = (*big.Int)(b) 567 } 568 return &zond.FeeHistory{ 569 OldestBlock: (*big.Int)(res.OldestBlock), 570 Reward: reward, 571 BaseFee: baseFee, 572 GasUsedRatio: res.GasUsedRatio, 573 }, nil 574 } 575 576 // EstimateGas tries to estimate the gas needed to execute a specific transaction based on 577 // the current pending state of the backend blockchain. There is no guarantee that this is 578 // the true gas limit requirement as other transactions may be added or removed by miners, 579 // but it should provide a basis for setting a reasonable default. 580 func (ec *Client) EstimateGas(ctx context.Context, msg zond.CallMsg) (uint64, error) { 581 var hex hexutil.Uint64 582 err := ec.c.CallContext(ctx, &hex, "zond_estimateGas", toCallArg(msg)) 583 if err != nil { 584 return 0, err 585 } 586 return uint64(hex), nil 587 } 588 589 // SendTransaction injects a signed transaction into the pending pool for execution. 590 // 591 // If the transaction was a contract creation use the TransactionReceipt method to get the 592 // contract address after the transaction has been mined. 593 func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { 594 data, err := tx.MarshalBinary() 595 if err != nil { 596 return err 597 } 598 return ec.c.CallContext(ctx, nil, "zond_sendRawTransaction", hexutil.Encode(data)) 599 } 600 601 func toBlockNumArg(number *big.Int) string { 602 if number == nil { 603 return "latest" 604 } 605 if number.Sign() >= 0 { 606 return hexutil.EncodeBig(number) 607 } 608 // It's negative. 609 if number.IsInt64() { 610 return rpc.BlockNumber(number.Int64()).String() 611 } 612 // It's negative and large, which is invalid. 613 return fmt.Sprintf("<invalid %d>", number) 614 } 615 616 func toCallArg(msg zond.CallMsg) interface{} { 617 arg := map[string]interface{}{ 618 "from": msg.From, 619 "to": msg.To, 620 } 621 if len(msg.Data) > 0 { 622 arg["input"] = hexutil.Bytes(msg.Data) 623 } 624 if msg.Value != nil { 625 arg["value"] = (*hexutil.Big)(msg.Value) 626 } 627 if msg.Gas != 0 { 628 arg["gas"] = hexutil.Uint64(msg.Gas) 629 } 630 if msg.GasPrice != nil { 631 arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) 632 } 633 return arg 634 } 635 636 // rpcProgress is a copy of SyncProgress with hex-encoded fields. 637 type rpcProgress struct { 638 StartingBlock hexutil.Uint64 639 CurrentBlock hexutil.Uint64 640 HighestBlock hexutil.Uint64 641 642 PulledStates hexutil.Uint64 643 KnownStates hexutil.Uint64 644 645 SyncedAccounts hexutil.Uint64 646 SyncedAccountBytes hexutil.Uint64 647 SyncedBytecodes hexutil.Uint64 648 SyncedBytecodeBytes hexutil.Uint64 649 SyncedStorage hexutil.Uint64 650 SyncedStorageBytes hexutil.Uint64 651 HealedTrienodes hexutil.Uint64 652 HealedTrienodeBytes hexutil.Uint64 653 HealedBytecodes hexutil.Uint64 654 HealedBytecodeBytes hexutil.Uint64 655 HealingTrienodes hexutil.Uint64 656 HealingBytecode hexutil.Uint64 657 } 658 659 func (p *rpcProgress) toSyncProgress() *zond.SyncProgress { 660 if p == nil { 661 return nil 662 } 663 return &zond.SyncProgress{ 664 StartingBlock: uint64(p.StartingBlock), 665 CurrentBlock: uint64(p.CurrentBlock), 666 HighestBlock: uint64(p.HighestBlock), 667 PulledStates: uint64(p.PulledStates), 668 KnownStates: uint64(p.KnownStates), 669 SyncedAccounts: uint64(p.SyncedAccounts), 670 SyncedAccountBytes: uint64(p.SyncedAccountBytes), 671 SyncedBytecodes: uint64(p.SyncedBytecodes), 672 SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes), 673 SyncedStorage: uint64(p.SyncedStorage), 674 SyncedStorageBytes: uint64(p.SyncedStorageBytes), 675 HealedTrienodes: uint64(p.HealedTrienodes), 676 HealedTrienodeBytes: uint64(p.HealedTrienodeBytes), 677 HealedBytecodes: uint64(p.HealedBytecodes), 678 HealedBytecodeBytes: uint64(p.HealedBytecodeBytes), 679 HealingTrienodes: uint64(p.HealingTrienodes), 680 HealingBytecode: uint64(p.HealingBytecode), 681 } 682 }