diff --git a/README.md b/README.md index 1527f0a..31d219e 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,29 @@ func main() { } ``` +### Use middleware to hook rpc request + +Client applies method `UseCallRpcMiddleware` to set middleware for hooking `callRpc` method which is the core of all single rpc related methods. And `UseBatchCallRpcMiddleware` to set middleware for hooking `batchCallRPC`. + +For example, use `CallRpcLogMiddleware` to log for rpc requests. +```golang +client.UseCallRpcMiddleware(middleware.CallRpcLogMiddleware) +``` + +Also you could +- customize middleware +- use multiple middleware + +Notice that the middleware chain exectuion order is like onion, for example, use middleware A first and then middleware B +```go +client.UseCallRpcMiddleware(A) +client.UseCallRpcMiddleware(B) +``` +the middleware execution order is +``` +B --> A --> client.callRpc --> A --> B +``` + ## Appendix ### Mapping of solidity types to go types This is a mapping table for map solidity types to go types when using contract methods GetData/Call/SendTransaction/DecodeEvent diff --git a/api.md b/api.md index b1305d3..ba7ab13 100644 --- a/api.md +++ b/api.md @@ -236,6 +236,9 @@ request is reported through the Error field of the corresponding BatchElem. Note that batch calls may not be executed atomically on the server side. +You could use UseBatchCallRpcMiddleware to add middleware for hooking +BatchCallRPC + #### func (*Client) BatchGetBlockConfirmationRisk ```go @@ -286,6 +289,8 @@ result if no error occurred. The result must be a pointer so that package json can unmarshal into it. You can also pass nil, in which case the result is ignored. +You could use UseCallRpcMiddleware to add middleware for hooking CallRPC + #### func (*Client) CheckBalanceAgainstTransaction ```go @@ -704,6 +709,24 @@ func (client *Client) SubscribeNewHeads(channel chan types.BlockHeader) (*rpc.Cl SubscribeNewHeads subscribes all new block headers participating in the consensus. +#### func (*Client) UseBatchCallRpcMiddleware + +```go +func (client *Client) UseBatchCallRpcMiddleware(middleware middleware.BatchCallRpcMiddleware) +``` +UseBatchCallRpcMiddleware set middleware to hook BatchCallRpc, for example use +middleware.BatchCallRpcLogMiddleware for logging batch request info. You can +customize your BatchCallRpcMiddleware and use multi BatchCallRpcMiddleware. + +#### func (*Client) UseCallRpcMiddleware + +```go +func (client *Client) UseCallRpcMiddleware(middleware middleware.CallRpcMiddleware) +``` +UseCallRpcMiddleware set middleware to hook CallRpc, for example use +middleware.CallRpcLogMiddleware for logging request info. You can customize your +CallRpcMiddleware and use multi CallRpcMiddleware. + #### func (*Client) WaitForTransationBePacked ```go @@ -722,11 +745,12 @@ WaitForTransationReceipt waits for transaction receipt valid ```go type ClientOption struct { - KeystorePath string - RetryCount int - RetryInterval time.Duration - CallRpcLog func(method string, args []interface{}, result interface{}, resultError error, duration time.Duration) - BatchCallRPCLog func(b []rpc.BatchElem, err error, duration time.Duration) + KeystorePath string + // retry + RetryCount int + RetryInterval time.Duration + // timeout of request + RequestTimeout time.Duration } ``` diff --git a/changeLog.md b/changeLog.md index 1ba3c83..c4d6b07 100644 --- a/changeLog.md +++ b/changeLog.md @@ -1,5 +1,7 @@ # Go-conflux-sdk Change Log - +## v1.0.9 +- Apply middleware for hooking call rpc and batch call rpc +- Support set request rpc timeout in Client ## v1.0.0 Note: v1.0.0 is not impatable with v0.x, the changes are - Change address format follow [CIP-37](https://github.com/Conflux-Chain/CIPs/blob/master/CIPs/cip-37.md) diff --git a/client.go b/client.go index 0e97c89..adbb4a2 100644 --- a/client.go +++ b/client.go @@ -6,11 +6,13 @@ package sdk import ( "context" + "math/big" "reflect" "time" "github.com/Conflux-Chain/go-conflux-sdk/constants" + "github.com/Conflux-Chain/go-conflux-sdk/middleware" "github.com/Conflux-Chain/go-conflux-sdk/rpc" "github.com/Conflux-Chain/go-conflux-sdk/types" "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" @@ -24,22 +26,25 @@ const errMsgApplyTxValues = "failed to apply default transaction values" // Client represents a client to interact with Conflux blockchain. type Client struct { - AccountManager AccountManagerOperator - nodeURL string - rpcRequester RpcRequester - networkID uint32 - option ClientOption + AccountManager AccountManagerOperator + nodeURL string + rpcRequester RpcRequester + networkID uint32 + option ClientOption + callRpcHandler middleware.CallRpcHandler + batchCallRpcHandler middleware.BatchCallRpcHandler } // ClientOption for set keystore path and flags for retry // // The simplest way to set logger is to use the types.DefaultCallRpcLog and types.DefaultBatchCallRPCLog type ClientOption struct { - KeystorePath string - RetryCount int - RetryInterval time.Duration - CallRpcLog func(method string, args []interface{}, result interface{}, resultError error, duration time.Duration) - BatchCallRPCLog func(b []rpc.BatchElem, err error, duration time.Duration) + KeystorePath string + // retry + RetryCount int + RetryInterval time.Duration + // timeout of request + RequestTimeout time.Duration } // NewClient creates an instance of Client with specified conflux node url, it will creat account manager if option.KeystorePath not empty. @@ -72,6 +77,8 @@ func newClientWithRetry(nodeURL string, clientOption ClientOption) (*Client, err var client Client client.nodeURL = nodeURL client.option = clientOption + client.callRpcHandler = middleware.CallRpcHandlerFunc(client.callRpc) + client.batchCallRpcHandler = middleware.BatchCallRpcHandlerFunc(client.batchCallRPC) rpcClient, err := rpc.Dial(nodeURL) if err != nil { @@ -93,15 +100,6 @@ func newClientWithRetry(nodeURL string, clientOption ClientOption) (*Client, err } } - if client.option.CallRpcLog == nil { - client.option.CallRpcLog = func(method string, args []interface{}, result interface{}, resultError error, duration time.Duration) { - } - } - - if client.option.BatchCallRPCLog == nil { - client.option.BatchCallRPCLog = func(b []rpc.BatchElem, err error, duration time.Duration) {} - } - _, err = client.GetNetworkID() if err != nil { return nil, errors.Wrap(err, "failed to get networkID") @@ -144,11 +142,24 @@ func (client *Client) MustNewAddress(base32OrHex string) types.Address { // // The result must be a pointer so that package json can unmarshal into it. You // can also pass nil, in which case the result is ignored. +// +// You could use UseCallRpcMiddleware to add middleware for hooking CallRPC func (client *Client) CallRPC(result interface{}, method string, args ...interface{}) error { - start := time.Now() - err := client.rpcRequester.Call(result, method, args...) - client.option.CallRpcLog(method, args, result, err, time.Since(start)) - return err + return client.callRpcHandler.Handle(result, method, args...) +} + +func (client *Client) callRpc(result interface{}, method string, args ...interface{}) error { + ctx, cancelFunc := client.genContext() + if cancelFunc != nil { + defer cancelFunc() + } + return client.rpcRequester.CallContext(ctx, result, method, args...) +} + +// UseCallRpcMiddleware set middleware to hook CallRpc, for example use middleware.CallRpcLogMiddleware for logging request info. +// You can customize your CallRpcMiddleware and use multi CallRpcMiddleware. +func (client *Client) UseCallRpcMiddleware(middleware middleware.CallRpcMiddleware) { + client.callRpcHandler = middleware(client.callRpcHandler) } // BatchCallRPC sends all given requests as a single batch and waits for the server @@ -158,11 +169,25 @@ func (client *Client) CallRPC(result interface{}, method string, args ...interfa // a request is reported through the Error field of the corresponding BatchElem. // // Note that batch calls may not be executed atomically on the server side. +// +// You could use UseBatchCallRpcMiddleware to add middleware for hooking BatchCallRPC func (client *Client) BatchCallRPC(b []rpc.BatchElem) error { - start := time.Now() - err := client.rpcRequester.BatchCall(b) - client.option.BatchCallRPCLog(b, err, time.Since(start)) - return err + return client.batchCallRpcHandler.Handle(b) +} + +func (client *Client) batchCallRPC(b []rpc.BatchElem) error { + ctx, cancelFunc := client.genContext() + if cancelFunc != nil { + defer cancelFunc() + } + + return client.rpcRequester.BatchCallContext(ctx, b) +} + +// UseBatchCallRpcMiddleware set middleware to hook BatchCallRpc, for example use middleware.BatchCallRpcLogMiddleware for logging batch request info. +// You can customize your BatchCallRpcMiddleware and use multi BatchCallRpcMiddleware. +func (client *Client) UseBatchCallRpcMiddleware(middleware middleware.BatchCallRpcMiddleware) { + client.batchCallRpcHandler = middleware(client.batchCallRpcHandler) } // SetAccountManager sets account manager for sign transaction @@ -1089,3 +1114,10 @@ func get1stEpochIfy(epoch []*types.Epoch) *types.Epoch { } return realEpoch } + +func (client *Client) genContext() (context.Context, context.CancelFunc) { + if client.option.RequestTimeout > 0 { + return context.WithTimeout(context.Background(), client.option.RequestTimeout) + } + return context.Background(), nil +} diff --git a/client_retry.go b/client_retry.go index 5201d84..fafebea 100644 --- a/client_retry.go +++ b/client_retry.go @@ -16,11 +16,14 @@ type rpcClientWithRetry struct { } func (r *rpcClientWithRetry) Call(resultPtr interface{}, method string, args ...interface{}) error { + return r.CallContext(context.Background(), resultPtr, method, args...) +} +func (r *rpcClientWithRetry) CallContext(ctx context.Context, resultPtr interface{}, method string, args ...interface{}) error { remain := r.retryCount for { - err := r.inner.Call(resultPtr, method, args...) + err := r.inner.CallContext(ctx, resultPtr, method, args...) if err == nil { return nil } @@ -42,7 +45,11 @@ func (r *rpcClientWithRetry) Call(resultPtr interface{}, method string, args ... } func (r *rpcClientWithRetry) BatchCall(b []rpc.BatchElem) error { - err := r.inner.BatchCall(b) + return r.BatchCallContext(context.Background(), b) +} + +func (r *rpcClientWithRetry) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + err := r.inner.BatchCallContext(ctx, b) if err == nil { return nil } @@ -53,7 +60,7 @@ func (r *rpcClientWithRetry) BatchCall(b []rpc.BatchElem) error { remain := r.retryCount for { - if err = r.inner.BatchCall(b); err == nil { + if err = r.inner.BatchCallContext(ctx, b); err == nil { return nil } diff --git a/example/context/config.toml b/example/context/config.toml index 0214614..feed249 100644 --- a/example/context/config.toml +++ b/example/context/config.toml @@ -1,5 +1,5 @@ -NodeURL = "http://127.0.0.1:12537" -BlockHash = "0x589c98650b0531883edab079acceeae4eefd892a73871ef6e8f1b4f9a82dc1bf" -TransactionHash = "0xca3c7b7b43e0290bc7ba103f42cfabd78ced8504ec5b920276891a8da67ca6b1" -BlockHashOfNewContract = "0xf7a26c4455f320ea298226635c74e87e8f1de78d7d38ba2f8beb7b97bc826b94" -ERC20Address = "NET3469801582:TYPE.CONTRACT:ACC2PMEWZKPR34N3DEU10S2DM47SSBMXS2JVY6JGXV" +NodeURL = "ws://test.confluxrpc.com/ws" +BlockHash = "0x5379d291e1489dc9359d857c6fdaf44e673a109dfa813cc6460a8795566f60d3" +TransactionHash = "0x485404cac57cb1e58f1f3285d02044fc9722f5427ecc726149c9ea7468c6f64c" +BlockHashOfNewContract = "0x50da8bc04047c48aed189b96b8d907e145a3b919e8dd73bd3ca51a9aca86844a" +ERC20Address = "cfxtest:acfpjyyu1wp1h79h589dcxhms3z40zgj1y41cj8u3k" diff --git a/example/context/prepare.go b/example/context/prepare.go index d39a969..3f1fde7 100644 --- a/example/context/prepare.go +++ b/example/context/prepare.go @@ -71,7 +71,10 @@ func initClient() { var err error keyStorePath := path.Join(currentDir, "keystore") - client, err = sdk.NewClient(config.NodeURL, sdk.ClientOption{KeystorePath: keyStorePath}) + client, err = sdk.NewClient(config.NodeURL, sdk.ClientOption{ + KeystorePath: keyStorePath, + RequestTimeout: time.Second * 10, + }) if err != nil { panic(err) } @@ -80,11 +83,10 @@ func initClient() { // init retry client option := sdk.ClientOption{ - KeystorePath: keyStorePath, - RetryCount: 10, - RetryInterval: time.Second, - // CallRpcLog: types.DefaultCallRPCLog, - // BatchCallRPCLog: types.DefaultBatchCallRPCLog, + KeystorePath: keyStorePath, + RetryCount: 10, + RetryInterval: time.Second, + RequestTimeout: time.Second * 10, } retryclient, err := sdk.NewClient(config.NodeURL, option) if err != nil { diff --git a/example/example_client/main.go b/example/example_client/main.go index 3ad9f19..d55357e 100644 --- a/example/example_client/main.go +++ b/example/example_client/main.go @@ -8,6 +8,7 @@ import ( sdk "github.com/Conflux-Chain/go-conflux-sdk" "github.com/Conflux-Chain/go-conflux-sdk/example/context" exampletypes "github.com/Conflux-Chain/go-conflux-sdk/example/context/types" + "github.com/Conflux-Chain/go-conflux-sdk/middleware" "github.com/Conflux-Chain/go-conflux-sdk/rpc" "github.com/Conflux-Chain/go-conflux-sdk/types" "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" @@ -40,6 +41,11 @@ func init() { } func main() { + config.GetClient().UseCallRpcMiddleware(middleware.CallRpcConsoleMiddleware) + config.GetClient().UseBatchCallRpcMiddleware(middleware.BatchCallRpcConsoleMiddleware) + + config.GetRetryClient().UseCallRpcMiddleware(middleware.CallRpcConsoleMiddleware) + config.GetRetryClient().UseBatchCallRpcMiddleware(middleware.BatchCallRpcConsoleMiddleware) fmt.Printf("\n=======start excute client methods without retry=========\n") run(config.GetClient()) @@ -107,6 +113,7 @@ func run(_client *sdk.Client) { } func newAddress() { + fmt.Println("\n- start new address") addr, err := client.NewAddress("0x0000000000000000000000000000000000000000") printResult("NewAddress", []interface{}{"0x0000000000000000000000000000000000000000"}, addr, err) addr, err = client.NewAddress("0x2000000000000000000000000000000000000000") @@ -119,6 +126,7 @@ func newAddress() { } func mustNewAddress() { + fmt.Println("\n- start must new address") addr := client.MustNewAddress("0x0000000000000000000000000000000000000000") printResult("MustNewAddress", []interface{}{"0x0000000000000000000000000000000000000000"}, addr, nil) // addr = client.MustNewAddress("0x2000000000000000000000000000000000000000") @@ -131,253 +139,198 @@ func mustNewAddress() { } func getAdmin() { - result, err := client.GetAdmin(config.ERC20Address, nil) - printResult("GetAdmin", []interface{}{config.ERC20Address, nil}, result, err) + fmt.Println("\n- start get admin") + client.GetAdmin(config.ERC20Address, nil) + // printResult("GetAdmin", []interface{}{config.ERC20Address, nil}, result, err) - result, err = client.GetAdmin(address.MustNewFromHex("0x0000000000000000000000000000000000000000"), nil) - printResult("GetAdmin", []interface{}{address.MustNewFromHex("0x0000000000000000000000000000000000000000"), nil}, result, err) + client.GetAdmin(address.MustNewFromHex("0x0000000000000000000000000000000000000000"), nil) + // printResult("GetAdmin", []interface{}{address.MustNewFromHex("0x0000000000000000000000000000000000000000"), nil}, result, err) } func getSponsorInfo() { + fmt.Println("\n- start get sponsor info") // result, err := client.GetSponsorInfo(*defaultAccount, nil) - result, err := client.GetSponsorInfo(config.ERC20Address, nil) - printResult("GetSponsorInfo", []interface{}{config.ERC20Address, nil}, result, err) + client.GetSponsorInfo(config.ERC20Address, nil) + // printResult("GetSponsorInfo", []interface{}{config.ERC20Address, nil}, result, err) } func getStakingBalance() { - result, err := client.GetStakingBalance(*defaultAccount, nil) - printResult("GetStakingBalance", []interface{}{*defaultAccount, nil}, result, err) + fmt.Println("\n- start get staking balance") + client.GetStakingBalance(*defaultAccount, nil) + // printResult("GetStakingBalance", []interface{}{*defaultAccount, nil}, result, err) } func getCollateralForStorage() { - result, err := client.GetCollateralForStorage(*defaultAccount, nil) - printResult("GetCollateralForStorage", []interface{}{*defaultAccount, nil}, result, err) + fmt.Println("\n- start get collateral for storage") + client.GetCollateralForStorage(*defaultAccount, nil) + // printResult("GetCollateralForStorage", []interface{}{*defaultAccount, nil}, result, err) } func getStorageAt() { - result, err := client.GetStorageAt(config.ERC20Address, "0x8549225e0f8e0f4a2ea0d9c0e562e986994ded65da69d91aa3768ac6da0a1635", nil) - printResult("GetStorageAt", []interface{}{config.ERC20Address, "0x8549225e0f8e0f4a2ea0d9c0e562e986994ded65da69d91aa3768ac6da0a1635", nil}, result, err) + fmt.Println("\n- start get storage at") + client.GetStorageAt(config.ERC20Address, "0x8549225e0f8e0f4a2ea0d9c0e562e986994ded65da69d91aa3768ac6da0a1635", nil) + // printResult("GetStorageAt", []interface{}{config.ERC20Address, "0x8549225e0f8e0f4a2ea0d9c0e562e986994ded65da69d91aa3768ac6da0a1635", nil}, result, err) } func getStorageRoot() { - result, err := client.GetStorageRoot(config.ERC20Address, nil) - printResult("GetStorageRoot", []interface{}{config.ERC20Address, nil}, result, err) + fmt.Println("\n- start get storage root") + client.GetStorageRoot(config.ERC20Address, nil) + // printResult("GetStorageRoot", []interface{}{config.ERC20Address, nil}, result, err) } func getBlockByHashWithPivotAssumption() { - result, err := client.GetBlockByHashWithPivotAssumption(types.Hash("0x08de0feea8cc989029f86a00ef6aabbf4de16d9bf21207c8ba9f011f10b1456d"), types.Hash("0x8cf781d04606e195f7fc5e03a73d8e2ef5bf7d9bfba11b11e73cd056f190c67a"), hexutil.Uint64(0x176334)) - printResult("GetBlockByHashWithPivotAssumption", []interface{}{types.Hash("0x08de0feea8cc989029f86a00ef6aabbf4de16d9bf21207c8ba9f011f10b1456d"), types.Hash("0x8cf781d04606e195f7fc5e03a73d8e2ef5bf7d9bfba11b11e73cd056f190c67a"), hexutil.Uint64(0x176334)}, result, err) + fmt.Println("\n- start get block hash with pivot assumption") + client.GetBlockByHashWithPivotAssumption(types.Hash("0x08de0feea8cc989029f86a00ef6aabbf4de16d9bf21207c8ba9f011f10b1456d"), types.Hash("0x8cf781d04606e195f7fc5e03a73d8e2ef5bf7d9bfba11b11e73cd056f190c67a"), hexutil.Uint64(0x176334)) + // printResult("GetBlockByHashWithPivotAssumption", []interface{}{types.Hash("0x08de0feea8cc989029f86a00ef6aabbf4de16d9bf21207c8ba9f011f10b1456d"), types.Hash("0x8cf781d04606e195f7fc5e03a73d8e2ef5bf7d9bfba11b11e73cd056f190c67a"), hexutil.Uint64(0x176334)}, result, err) } func checkBalanceAgainstTransaction() { - result, err := client.CheckBalanceAgainstTransaction(*defaultAccount, config.ERC20Address, types.NewBigInt(1000), types.NewBigInt(1000), types.NewBigInt(1000), nil) - printResult("CheckBalanceAgainstTransaction", []interface{}{*defaultAccount, *defaultAccount, types.NewBigInt(1000), types.NewBigInt(1000), types.NewBigInt(1000), types.EpochLatestState}, result, err) + fmt.Println("\n- start check balance against transaction") + client.CheckBalanceAgainstTransaction(*defaultAccount, config.ERC20Address, types.NewBigInt(1000), types.NewBigInt(1000), types.NewBigInt(1000), nil) + // printResult("CheckBalanceAgainstTransaction", []interface{}{*defaultAccount, *defaultAccount, types.NewBigInt(1000), types.NewBigInt(1000), types.NewBigInt(1000), types.EpochLatestState}, result, err) } func getSkippedBlocksByEpoch() { - result, err := client.GetSkippedBlocksByEpoch(types.EpochLatestState) - printResult("GetSkippedBlocksByEpoch", []interface{}{nil}, result, err) + fmt.Println("\n- start get skipped blocks by epoch") + client.GetSkippedBlocksByEpoch(types.EpochLatestState) + // printResult("GetSkippedBlocksByEpoch", []interface{}{nil}, result, err) } func getAccountInfo() { - result, err := client.GetAccountInfo(*defaultAccount, nil) - printResult("GetAccountInfo", []interface{}{*defaultAccount, nil}, result, err) + fmt.Println("\n- start get account info") + client.GetAccountInfo(*defaultAccount, nil) + // printResult("GetAccountInfo", []interface{}{*defaultAccount, nil}, result, err) } // GetInterestRate() func getInterestRate() { - result, err := client.GetInterestRate(nil) - printResult("GetInterestRate", []interface{}{nil}, result, err) + fmt.Println("\n- start get interest rate") + client.GetInterestRate(nil) + // printResult("GetInterestRate", []interface{}{nil}, result, err) } // GetAccumulateInterestRate() func getAccumulateInterestRate() { - result, err := client.GetAccumulateInterestRate(nil) - printResult("GetAccumulateInterestRate", []interface{}{nil}, result, err) + fmt.Println("\n- start get accumulate interest rate") + client.GetAccumulateInterestRate(nil) + // printResult("GetAccumulateInterestRate", []interface{}{nil}, result, err) } // GetBlockRewardInfo() func getBlockRewardInfo() { - result, err := client.GetBlockRewardInfo(*types.EpochLatestState) - printResult("GetBlockRewardInfo", []interface{}{*types.EpochLatestState}, result, err) + fmt.Println("\n- start get block reward info") + client.GetBlockRewardInfo(*types.EpochLatestState) + // printResult("GetBlockRewardInfo", []interface{}{*types.EpochLatestState}, result, err) } // ClientVersion() func getClientVersion() { - result, err := client.GetClientVersion() - printResult("ClientVersion", []interface{}{}, result, err) + fmt.Println("\n- start get client version") + client.GetClientVersion() + // printResult("ClientVersion", []interface{}{}, result, err) } func getEpochNumber() { - fmt.Println("- start get epoch number") + fmt.Println("\n- start get epoch number") for _, e := range epochs { - epochnumber, err := client.GetEpochNumber(e) - if err != nil { - fmt.Printf("- get epoch %v error: %v\n\n", e, err.Error()) - } else { - fmt.Printf(" epoch of %v : %v\n\n", e, epochnumber) - } + client.GetEpochNumber(e) } } func getGasPrice() { - - gasPrice, err := client.GetGasPrice() - if err != nil { - fmt.Printf("- gasprice error: %#v\n\n", err.Error()) - } else { - fmt.Printf("- gasprice: %v\n\n", gasPrice.String()) - } - + fmt.Println("\n- start get gas price") + client.GetGasPrice() } func getNextNonce() { - fmt.Println("- start get nextNonce") + fmt.Println("\n- start get nextNonce") for _, e := range epochs { - nonce, err := client.GetNextNonce(*defaultAccount, e) - if err != nil { - fmt.Printf(" nonce of epoch %v error: %v\n\n", e, err.Error()) - } else { - fmt.Printf(" nonce of epoch %v : %v\n\n", e, nonce) - } + client.GetNextNonce(*defaultAccount, e) } } func getStatus() { - status, err := client.GetStatus() - if err != nil { - fmt.Printf("- get status error: %v\n\n", err.Error()) - } else { - fmt.Printf("- get status result:\n%v\n\n", context.JSONFmt(status)) - } - + fmt.Println("\n- start get status") + client.GetStatus() } func getBalance() { - + fmt.Println("\n- start get balance") addr := *defaultAccount - balance, err := client.GetBalance(addr) - if err != nil { - fmt.Printf("- get balance of %v: %v\n\n", addr, err.Error()) - } else { - fmt.Printf("- balance of %v: %#v\n\n", addr, balance) - } + client.GetBalance(addr) } func getBestBlockHash() { - bestBlockHash, err := client.GetBestBlockHash() - if err != nil { - fmt.Printf("- get best block hash error: %v\n\n", err.Error()) - } else { - fmt.Printf("- best block hash: %#v\n\n", bestBlockHash) - } + fmt.Println("\n- start get best block hash") + client.GetBestBlockHash() } func getBlockByEpoch() { - epochNumber, err := client.GetEpochNumber() - block, err := client.GetBlockByEpoch(types.NewEpochNumber(epochNumber)) - if err != nil { - fmt.Printf("- get block of epoch %v error:%#v\n\n", epochNumber, err.Error()) - } else { - fmt.Printf("- block of epoch %v:\n%v\n\n", epochNumber, context.JSONFmt(block)) + fmt.Println("\n- start get block by epoch") + if epochNumber, err := client.GetEpochNumber(); err == nil { + client.GetBlockByEpoch(types.NewEpochNumber(epochNumber)) } } func getBlocksByEpoch() { - epochNumber, err := client.GetEpochNumber() - blocks, err := client.GetBlocksByEpoch(types.NewEpochNumber(epochNumber)) - if err != nil { - fmt.Printf("- get blocks of epoch %v error:%#v\n\n", epochNumber, err.Error()) - } else { - fmt.Printf("- blocks of epoch %v:%#v\n\n", epochNumber, blocks) + fmt.Println("\n- start get blocks by epoch") + if epochNumber, err := client.GetEpochNumber(); err == nil { + client.GetBlocksByEpoch(types.NewEpochNumber(epochNumber)) } - } func getBlockByHash() { + fmt.Println("\n- start get block by hash") blockHash := types.Hash(config.BlockHash) - block, err := client.GetBlockByHash(blockHash) - if err != nil { - fmt.Printf("- get block of hash %v error:\n%#v\n\n", blockHash, err.Error()) - } else { - fmt.Printf("- block of hash %v:\n%v\n\n", blockHash, context.JSONFmt(block)) - } + client.GetBlockByHash(blockHash) } func getBlockSummaryByEpoch() { - epochNumber, err := client.GetEpochNumber() - blockSummary, err := client.GetBlockSummaryByEpoch(types.NewEpochNumber(epochNumber)) - if err != nil { - fmt.Printf("- get block summary of epoch %v error:%#v\n\n", epochNumber, err.Error()) - } else { - fmt.Printf("- block summary of epoch %v:\n%v\n\n", epochNumber, context.JSONFmt(blockSummary)) + fmt.Println("\n- start get block summary by epoch") + if epochNumber, err := client.GetEpochNumber(); err == nil { + client.GetBlockSummaryByEpoch(types.NewEpochNumber(epochNumber)) } } func getBlockSummaryByHash() { - + fmt.Println("\n- start get block summary by hash") blockHash := types.Hash(config.BlockHash) - blockSummary, err := client.GetBlockSummaryByHash(blockHash) - if err != nil { - fmt.Printf("- get block summary of block hash %v error:%#v\n\n", blockHash, err.Error()) - } else { - fmt.Printf("- block summary of block hash %v:\n%v\n\n", blockHash, context.JSONFmt(blockSummary)) - } + client.GetBlockSummaryByHash(blockHash) } func getCode() { + fmt.Println("\n- start get code") contractAddr := *defaultAccount // config.ERC20Address - // code, err := client.GetCode(contractAddr) - code, err := client.GetCode(address.MustNewFromHex("0x19f4bcf113e0b896d9b34294fd3da86b4adf0301")) - if err != nil { - fmt.Printf("- get code of address %v err: %v\n\n", contractAddr, err.Error()) - } else { - fmt.Printf("- get code of address %v:%v\n\n", contractAddr, code) - } + client.GetCode(contractAddr) + client.GetCode(address.MustNewFromHex("0x19f4bcf113e0b896d9b34294fd3da86b4adf0301")) } func getTransactionByHash() { + fmt.Println("\n- start get transaction by hash") txhash := types.Hash(config.TransactionHash) - tx, err := client.GetTransactionByHash(txhash) - if err != nil { - fmt.Printf("- get Transaction By Hash %v error:%v\n\n", txhash, err.Error()) - } else { - fmt.Printf("- get Transaction By Hash %v:\n%v\n\n", txhash, context.JSONFmt(tx)) - } + client.GetTransactionByHash(txhash) } func getTransactionReceipt() { + fmt.Println("\n- start get transaction receipt") txhash := types.Hash(config.TransactionHash) - receipt, err := client.GetTransactionReceipt(txhash) - if err != nil { - fmt.Printf("- transaction receipt of txhash %v error:%v\n\n", txhash, err.Error()) - } else { - fmt.Printf("- transaction receipt of txhash %v:\n%v\n\n", txhash, context.JSONFmt(receipt)) - } + client.GetTransactionReceipt(txhash) } func estimateGasAndCollateral() { + fmt.Println("\n- start estimate gas and collateral") to := cfxaddress.MustNewFromHex("0x10f4bcf113e0b896d9b34294fd3da86b4adf0302") request := types.CallRequest{ To: &to, Value: types.NewBigInt(1), } - est, err := client.EstimateGasAndCollateral(request) - if err != nil { - fmt.Printf("- estimate request %v error: %v\n\n", request, err.Error()) - } else { - fmt.Printf("- estimate result: %v\n\n", context.JSONFmt(est)) - } + client.EstimateGasAndCollateral(request) } func sendRawTransaction() { + fmt.Println("\n- start send raw transaction") rawtx := context.CreateSignedTx(client) txhash, err := client.SendRawTransaction(rawtx) - if err != nil { - fmt.Printf("- send Signed Transaction result error :%v\n\n", err.Error()) - } else { - fmt.Printf("- send Signed Transaction result :%#v\n\n", txhash) - } if err == nil { context.WaitPacked(client, txhash) } @@ -386,6 +339,7 @@ func sendRawTransaction() { func createAndSendUnsignedTransaction() { //send transaction + fmt.Println("\n- start create and send unsigned transaction") chainID, err := client.GetNetworkID() context.PanicIfErrf(err, "failed to get chainID") utx, err := client.CreateUnsignedTransaction(*defaultAccount, cfxaddress.MustNewFromHex("0x1cad0b19bb29d4674531d6f115237e16afce377d", chainID), types.NewBigInt(1000000), nil) @@ -396,11 +350,6 @@ func createAndSendUnsignedTransaction() { fmt.Printf("- creat a new unsigned transaction:\n%v\n\n", context.JSONFmt(utx)) txhash, err := client.SendTransaction(utx) - if err != nil { - fmt.Printf("- send transaction error: %v\n\n", err.Error()) - } else { - fmt.Printf("- send transaction done, tx hash is: %v\n\n", txhash) - } if err == nil { context.WaitPacked(client, txhash) } @@ -408,23 +357,13 @@ func createAndSendUnsignedTransaction() { } func getRawBlockConfirmationRisk() { - risk, err := client.GetRawBlockConfirmationRisk(config.BlockHash) - if err != nil { - fmt.Printf("- get risk of block %v error: %v\n", config.BlockHash, err.Error()) - } else { - fmt.Printf("- get risk of block %v : %v\n", config.BlockHash, risk) - } - - risk, err = client.GetRawBlockConfirmationRisk(types.Hash("0x0000000000000000000000000000000000000000000000000000000000000000")) - if err != nil { - fmt.Printf("- get risk of block %v error: %v\n", config.BlockHash, err.Error()) - } else { - fmt.Printf("- get risk of block %v : %v\n", config.BlockHash, risk) - } - + fmt.Println("\n- start get raw block confirmation risk") + client.GetRawBlockConfirmationRisk(config.BlockHash) + client.GetRawBlockConfirmationRisk(types.Hash("0x0000000000000000000000000000000000000000000000000000000000000000")) } func getBlockConfirmationRisk() { + fmt.Println("\n- start get block confirmation risk") rate, err := client.GetBlockConfirmationRisk(config.BlockHash) if err != nil { fmt.Printf("- get revert rate of block %v error: %v\n", config.BlockHash, err.Error()) @@ -434,80 +373,51 @@ func getBlockConfirmationRisk() { } func getSupplyInfo() { - info, err := client.GetSupplyInfo() - if err != nil { - fmt.Printf("- get supply info error: %v\n", err.Error()) - } else { - fmt.Printf("- get supply info :%v \n", context.JSONFmt(info)) - } + fmt.Println("\n- start get supply info") + client.GetSupplyInfo() } func getEpochReceipts() { + fmt.Println("\n- start get epoch receipts") b, _ := client.GetBlockByHash(config.BlockHashOfNewContract) - - receipts, err := client.GetEpochReceipts(*types.NewEpochNumber(b.EpochNumber)) - if err != nil { - fmt.Printf("- get epoch receipts error: %+v\n", err) - } else { - fmt.Printf("- get rpoch receipts info:%v \n", context.JSONFmt(receipts)) - } + client.GetEpochReceipts(*types.NewEpochNumber(b.EpochNumber)) } func getAccountPendingInfo() { + fmt.Println("\n- start get account pending info") fmt.Println("default account:", *defaultAccount) - result, err := client.GetAccountPendingInfo(*defaultAccount) - printResult("GetAccountPendingInfo", []interface{}{*defaultAccount}, result, err) + client.GetAccountPendingInfo(*defaultAccount) + // printResult("GetAccountPendingInfo", []interface{}{*defaultAccount}, result, err) } func traceBlock() { - traces, err := client.GetBlockTraces(config.BlockHashOfNewContract) - if err != nil { - fmt.Printf("- get block trace of create error: %+v\n", err) - } else { - fmt.Printf("- get block info of create: %+v\n", context.JSONFmt(traces)) - } - - traces, err = client.GetBlockTraces(config.BlockHash) - if err != nil { - fmt.Printf("- get block trace of call error: %+v\n", err) - } else { - fmt.Printf("- get block info of call: %+v\n", context.JSONFmt(traces)) - } + fmt.Println("\n- start get block trace") + client.GetBlockTraces(config.BlockHashOfNewContract) + client.GetBlockTraces(config.BlockHash) } func traceFilter() { - traces, err := client.FilterTraces(types.TraceFilter{ + fmt.Println("\n- start trace filter") + client.FilterTraces(types.TraceFilter{ FromEpoch: types.NewEpochNumberUint64(1), ActionTypes: []string{"call", "create"}, }) - if err != nil { - fmt.Printf("- filter trace error: %+v\n", err) - } else { - fmt.Printf("- filter trace result: %+v", context.JSONFmt(traces)) - } } func tarceTransaction() { - traces, err := client.GetTransactionTraces(config.TransactionHash) - if err != nil { - fmt.Printf("- get transcation trace of create error: %+v\n", err) - } else { - fmt.Printf("- get transcation trace of create: %+v", context.JSONFmt(traces)) - } + fmt.Println("\n- start trace transaction") + client.GetTransactionTraces(config.TransactionHash) } func callRPC() { + fmt.Println("\n- start call rpc") b := new(types.Block) - err := client.CallRPC(b, "cfx_getBlockByHash", config.BlockHash, true) - if err != nil { - fmt.Printf("- use CallRPC get block by hash error:%+v\n\n", err.Error()) - } else { - fmt.Printf("- use CallRPC get block by hash result:\n%v\n\n", context.JSONFmt(b)) - } + client.CallRPC(b, "cfx_getBlockByHash", config.BlockHash, true) + } func subscribeNewHeads() { - fmt.Printf("- subscribe new heads\n") + fmt.Printf("\n- subscribe new heads\n") channel := make(chan types.BlockHeader, 100) sub, err := client.SubscribeNewHeads(channel) if err != nil { @@ -530,7 +440,7 @@ func subscribeNewHeads() { } func subscribeEpochs() { - fmt.Printf("- subscribe epochs\n") + fmt.Printf("\n- subscribe epochs\n") channel := make(chan types.WebsocketEpochResponse, 100) sub, err := client.SubscribeEpochs(channel) if err != nil { @@ -553,7 +463,7 @@ func subscribeEpochs() { } func subscribeLogs() { - fmt.Printf("- subscribe logs\n") + fmt.Printf("\n- subscribe logs\n") logChannel := make(chan types.Log, 100) reorgChannel := make(chan types.ChainReorg, 100) sub, err := client.SubscribeLogs(logChannel, reorgChannel, types.LogFilter{ @@ -606,21 +516,17 @@ func subscribeLogs() { } func batchCall() { + fmt.Println("\n- start batch call") elems := make([]rpc.BatchElem, 2) elems[0] = rpc.BatchElem{Method: "cfx_epochNumber", Result: &hexutil.Big{}, Args: []interface{}{}} elems[1] = rpc.BatchElem{Method: "cfx_getBalance", Result: &hexutil.Big{}, Args: []interface{}{client.MustNewAddress("cfxtest:aap9kthvctunvf030rbkk9k7zbzyz12dajp1u3sp4g")}} - err := client.BatchCallRPC(elems) - if err != nil { - panic(err) - } else { - fmt.Printf("batch call rpc done:%+v\n", elems) - } + client.BatchCallRPC(elems) } func printResult(method string, args []interface{}, result interface{}, err error) { if err != nil { - fmt.Printf("- call method %v with args %+v error: %v\n\n", method, args, err.Error()) + fmt.Printf("- function %v with args %+v error: %v\n\n", method, args, err.Error()) } else { - fmt.Printf("- call method %v with args %+v result: %+v\n\n", method, args, context.JSONFmt(result)) + fmt.Printf("- function %v with args %+v result: %+v\n\n", method, args, context.JSONFmt(result)) } } diff --git a/example/example_transaction/main.go b/example/example_transaction/main.go index 5f07bcc..8a02ffa 100644 --- a/example/example_transaction/main.go +++ b/example/example_transaction/main.go @@ -47,15 +47,5 @@ func main() { fmt.Printf("send transaction hash: %v\n\n", txhash) fmt.Println("wait for transaction be packed") - for { - time.Sleep(time.Duration(1) * time.Second) - tx, err := client.GetTransactionByHash(txhash) - if err != nil { - panic(err) - } - if tx.Status != nil { - fmt.Printf("transaction is packed:%+v\n\n", tx) - break - } - } + context.WaitPacked(client, txhash) } diff --git a/go.mod b/go.mod index f9b3180..b87f9c6 100644 --- a/go.mod +++ b/go.mod @@ -8,11 +8,14 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea github.com/ethereum/go-ethereum v1.9.25 + github.com/fatih/color v1.3.0 github.com/golang/mock v1.4.3 github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989 github.com/pkg/errors v0.9.1 github.com/smartystreets/goconvey v1.6.4 + github.com/stretchr/testify v1.5.1 // indirect github.com/valyala/fasthttp v1.13.1 + google.golang.org/protobuf v1.25.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce ) diff --git a/go.sum b/go.sum index e9ed17a..bea7421 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= @@ -33,12 +34,14 @@ github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -50,12 +53,15 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 h1:Y9vTBSsV4hSwPSj4bacAU/eSnV3dAxVpepaghAdhGoQ= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= github.com/fatih/color v1.3.0 h1:YehCCcyeQ6Km0D6+IapqPinWBK6y+0eB5umvZXK9WPs= @@ -78,25 +84,33 @@ github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIi github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -170,6 +184,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 h1:ZeU+auZj1iNzN8iVhff6M38Mfu73FQiJve/GEXYJBjE= @@ -200,6 +215,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= @@ -218,16 +235,23 @@ golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -236,9 +260,11 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -258,11 +284,16 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -270,13 +301,26 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= @@ -296,5 +340,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/interface.go b/interface.go index aaefdb4..248b9c2 100644 --- a/interface.go +++ b/interface.go @@ -10,6 +10,7 @@ import ( "net/http" "time" + "github.com/Conflux-Chain/go-conflux-sdk/middleware" "github.com/Conflux-Chain/go-conflux-sdk/rpc" "github.com/Conflux-Chain/go-conflux-sdk/types" "github.com/ethereum/go-ethereum/common/hexutil" @@ -37,6 +38,9 @@ type ClientOperator interface { CallRPC(result interface{}, method string, args ...interface{}) error BatchCallRPC(b []rpc.BatchElem) error + UseCallRpcMiddleware(middleware middleware.CallRpcMiddleware) + UseBatchCallRpcMiddleware(middleware middleware.BatchCallRpcMiddleware) + SetAccountManager(accountManager AccountManagerOperator) GetGasPrice() (*hexutil.Big, error) @@ -137,17 +141,9 @@ type AccountManagerOperator interface { type RpcRequester interface { Call(resultPtr interface{}, method string, args ...interface{}) error + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error BatchCall(b []rpc.BatchElem) error + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) Close() } - -type CallRPCLogger interface { - Info(method string, args []interface{}, result interface{}, duration time.Duration) - Error(method string, args []interface{}, resultError error, duration time.Duration) -} - -type BatchCallRPCLogger interface { - Info(b []rpc.BatchElem, duration time.Duration) - Error(b []rpc.BatchElem, err error, duration time.Duration) -} diff --git a/middleware/call_rpc.go b/middleware/call_rpc.go new file mode 100644 index 0000000..8527d32 --- /dev/null +++ b/middleware/call_rpc.go @@ -0,0 +1,57 @@ +package middleware + +import ( + "encoding/json" + "fmt" + + "time" + + "github.com/Conflux-Chain/go-conflux-sdk/utils" + "github.com/fatih/color" +) + +type CallRpcHandler interface { + Handle(result interface{}, method string, args ...interface{}) error +} + +type CallRpcHandlerFunc func(result interface{}, method string, args ...interface{}) error + +type CallRpcMiddleware func(CallRpcHandler) CallRpcHandler + +func (c CallRpcHandlerFunc) Handle(result interface{}, method string, args ...interface{}) error { + return c(result, method, args...) +} + +func CallRpcConsoleMiddleware(handler CallRpcHandler) CallRpcHandler { + logFn := func(result interface{}, method string, args ...interface{}) error { + + argsStr := fmt.Sprintf("%+v", args) + argsJson, err := json.Marshal(args) + if err == nil { + argsStr = string(argsJson) + } + + start := time.Now() + err = handler.Handle(result, method, args...) + duration := time.Since(start) + + if err == nil { + fmt.Printf("%v Method %v, Params %v, Result %v, Use %v\n", + color.GreenString("[Call RPC Done]"), + color.YellowString(method), + color.CyanString(argsStr), + color.CyanString(utils.PrettyJSON(result)), + color.CyanString(duration.String())) + return nil + } + + color.Red("%v Method %v, Params %v, Error %v, Use %v\n", + color.RedString("[Call RPC Fail]"), + color.YellowString(method), + color.CyanString(string(argsJson)), + color.RedString(fmt.Sprintf("%+v", err)), + color.CyanString(duration.String())) + return err + } + return CallRpcHandlerFunc(logFn) +} diff --git a/middleware/call_rpc_batch.go b/middleware/call_rpc_batch.go new file mode 100644 index 0000000..a60982c --- /dev/null +++ b/middleware/call_rpc_batch.go @@ -0,0 +1,46 @@ +package middleware + +import ( + "fmt" + "time" + + "github.com/Conflux-Chain/go-conflux-sdk/rpc" + "github.com/Conflux-Chain/go-conflux-sdk/utils" + "github.com/fatih/color" +) + +type BatchCallRpcHandler interface { + Handle(b []rpc.BatchElem) error +} + +type BatchCallRpcHandlerFunc func(b []rpc.BatchElem) error + +type BatchCallRpcMiddleware func(BatchCallRpcHandler) BatchCallRpcHandler + +func (brh BatchCallRpcHandlerFunc) Handle(b []rpc.BatchElem) error { + return brh(b) +} + +func BatchCallRpcConsoleMiddleware(handler BatchCallRpcHandler) BatchCallRpcHandler { + logFn := func(b []rpc.BatchElem) error { + start := time.Now() + + err := handler.Handle(b) + + duration := time.Since(start) + if err == nil { + fmt.Printf("%v BatchElems %v, Use %v\n", + color.GreenString("[Batch Call RPC Done]"), + color.CyanString(utils.PrettyJSON(b)), + color.CyanString(duration.String())) + return nil + } + fmt.Printf("%v BatchElems %v, Error: %v, Use %v\n", + color.RedString("[Batch Call RPC Fail]"), + color.CyanString(utils.PrettyJSON(b)), + color.RedString(fmt.Sprintf("%+v", err)), + duration) + return err + } + return BatchCallRpcHandlerFunc(logFn) +} diff --git a/rpc/http.go b/rpc/http.go index 0a1d7a6..b42d125 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -105,18 +105,6 @@ var DefaultHTTPTimeouts = HTTPTimeouts{ // DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP // using the provided HTTP Client. func DialHTTPWithClient(endpoint string, client *fasthttp.Client) (*Client, error) { - // req, err := http.NewRequest(http.MethodPost, endpoint, nil) - // if err != nil { - // return nil, err - // } - - // req := fasthttp.Request{} - // req.SetRequestURI(endpoint) - - // req.Header.SetMethod("POST") - // req.Header.Set("Content-Type", contentType) - // req.Header.Set("Accept", contentType) - initctx := context.Background() return newClient(initctx, func(context.Context) (ServerCodec, error) { req := fasthttp.Request{} @@ -139,9 +127,6 @@ func DialHTTP(endpoint string) (*Client, error) { func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error { hc := c.writeConn.(*httpConn) respBody, err := hc.doRequest(ctx, msg) - // if respBody != nil { - // defer respBody.Close() - // } if err != nil { if respBody != nil { @@ -195,7 +180,13 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.Reader, resp := &fasthttp.Response{} // resp, err := hc.client.Do(req) - err = hc.client.Do(req, resp) + deadline, ok := ctx.Deadline() + timeout := time.Duration(0) + if ok { + timeout = time.Until(deadline) + } + + err = hc.client.DoTimeout(req, resp, timeout) if err != nil { return nil, err } diff --git a/types/rpc_log.go b/types/rpc_log.go deleted file mode 100644 index 48011aa..0000000 --- a/types/rpc_log.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -import ( - "fmt" - "time" - - "github.com/Conflux-Chain/go-conflux-sdk/rpc" - "github.com/Conflux-Chain/go-conflux-sdk/utils" -) - -func DefaultCallRPCLog(method string, args []interface{}, result interface{}, resultError error, duration time.Duration) { - if resultError == nil { - fmt.Printf("call rpc %v sucessfully, args %+v, result %+v, use %v\n", method, utils.PrettyJSON(args), utils.PrettyJSON(result), duration) - return - } - fmt.Printf("call rpc %v failed, args %+v, error: %+v, use %v\n", method, args, resultError, duration) -} - -func DefaultBatchCallRPCLog(b []rpc.BatchElem, err error, duration time.Duration) { - if err == nil { - fmt.Printf("batch call %+v sucessfully, use %v\n", b, duration) - return - } - fmt.Printf("batch call %+v failed, error: %+v, use %v\n", b, err, duration) -}