github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/avalanche/avalancherpc.go (about) 1 package avalanche 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/url" 8 9 jsontypes "github.com/ava-labs/avalanchego/utils/json" 10 "github.com/ava-labs/coreth/core/types" 11 "github.com/ava-labs/coreth/ethclient" 12 "github.com/ava-labs/coreth/interfaces" 13 "github.com/ava-labs/coreth/rpc" 14 "github.com/ethereum/go-ethereum/common" 15 "github.com/ethereum/go-ethereum/common/hexutil" 16 "github.com/golang/glog" 17 "github.com/juju/errors" 18 "github.com/trezor/blockbook/bchain" 19 "github.com/trezor/blockbook/bchain/coins/eth" 20 ) 21 22 const ( 23 // MainNet is production network 24 MainNet eth.Network = 43114 25 ) 26 27 // AvalancheRPC is an interface to JSON-RPC avalanche service. 28 type AvalancheRPC struct { 29 *eth.EthereumRPC 30 info *rpc.Client 31 } 32 33 // NewAvalancheRPC returns new AvalancheRPC instance. 34 func NewAvalancheRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { 35 c, err := eth.NewEthereumRPC(config, pushHandler) 36 if err != nil { 37 return nil, err 38 } 39 40 s := &AvalancheRPC{ 41 EthereumRPC: c.(*eth.EthereumRPC), 42 } 43 44 return s, nil 45 } 46 47 // Initialize avalanche rpc interface 48 func (b *AvalancheRPC) Initialize() error { 49 b.OpenRPC = func(url string) (bchain.EVMRPCClient, bchain.EVMClient, error) { 50 r, err := rpc.Dial(url) 51 if err != nil { 52 return nil, nil, err 53 } 54 rc := &AvalancheRPCClient{Client: r} 55 c := &AvalancheClient{Client: ethclient.NewClient(r)} 56 return rc, c, nil 57 } 58 59 rpcClient, client, err := b.OpenRPC(b.ChainConfig.RPCURL) 60 if err != nil { 61 return err 62 } 63 64 rpcUrl, err := url.Parse(b.ChainConfig.RPCURL) 65 if err != nil { 66 return err 67 } 68 69 scheme := "http" 70 if rpcUrl.Scheme == "wss" || rpcUrl.Scheme == "https" { 71 scheme = "https" 72 } 73 74 infoClient, err := rpc.DialHTTP(fmt.Sprintf("%s://%s/ext/info", scheme, rpcUrl.Host)) 75 if err != nil { 76 return err 77 } 78 79 // set chain specific 80 b.Client = client 81 b.RPC = rpcClient 82 b.info = infoClient 83 b.MainNetChainID = MainNet 84 b.NewBlock = &AvalancheNewBlock{channel: make(chan *types.Header)} 85 b.NewTx = &AvalancheNewTx{channel: make(chan common.Hash)} 86 87 ctx, cancel := context.WithTimeout(context.Background(), b.Timeout) 88 defer cancel() 89 90 id, err := b.Client.NetworkID(ctx) 91 if err != nil { 92 return err 93 } 94 95 // parameters for getInfo request 96 switch eth.Network(id.Uint64()) { 97 case MainNet: 98 b.Testnet = false 99 b.Network = "livenet" 100 default: 101 return errors.Errorf("Unknown network id %v", id) 102 } 103 104 glog.Info("rpc: block chain ", b.Network) 105 106 return nil 107 } 108 109 // GetChainInfo returns information about the connected backend 110 func (b *AvalancheRPC) GetChainInfo() (*bchain.ChainInfo, error) { 111 ci, err := b.EthereumRPC.GetChainInfo() 112 if err != nil { 113 fmt.Println(err) 114 return nil, err 115 } 116 117 ctx, cancel := context.WithTimeout(context.Background(), b.Timeout) 118 defer cancel() 119 120 var v struct { 121 Version string `json:"version"` 122 DatabaseVersion string `json:"databaseVersion"` 123 RPCProtocolVersion jsontypes.Uint32 `json:"rpcProtocolVersion"` 124 GitCommit string `json:"gitCommit"` 125 VMVersions map[string]string `json:"vmVersions"` 126 } 127 128 if err := b.info.CallContext(ctx, &v, "info.getNodeVersion"); err != nil { 129 return nil, err 130 } 131 132 if avm, ok := v.VMVersions["avm"]; ok { 133 ci.Version = avm 134 } 135 136 return ci, nil 137 } 138 139 // EthereumTypeEstimateGas returns estimation of gas consumption for given transaction parameters 140 func (b *AvalancheRPC) EthereumTypeEstimateGas(params map[string]interface{}) (uint64, error) { 141 ctx, cancel := context.WithTimeout(context.Background(), b.Timeout) 142 defer cancel() 143 msg := interfaces.CallMsg{} 144 if s, ok := eth.GetStringFromMap("from", params); ok && len(s) > 0 { 145 msg.From = common.HexToAddress(s) 146 } 147 if s, ok := eth.GetStringFromMap("to", params); ok && len(s) > 0 { 148 a := common.HexToAddress(s) 149 msg.To = &a 150 } 151 if s, ok := eth.GetStringFromMap("data", params); ok && len(s) > 0 { 152 msg.Data = common.FromHex(s) 153 } 154 if s, ok := eth.GetStringFromMap("value", params); ok && len(s) > 0 { 155 msg.Value, _ = hexutil.DecodeBig(s) 156 } 157 if s, ok := eth.GetStringFromMap("gas", params); ok && len(s) > 0 { 158 msg.Gas, _ = hexutil.DecodeUint64(s) 159 } 160 if s, ok := eth.GetStringFromMap("gasPrice", params); ok && len(s) > 0 { 161 msg.GasPrice, _ = hexutil.DecodeBig(s) 162 } 163 return b.Client.EstimateGas(ctx, msg) 164 }