From 00ff6e24b44bb059bd2328b2bbc82a9d418f8e3e Mon Sep 17 00:00:00 2001 From: AstaFrode Date: Mon, 27 May 2024 15:17:11 +0800 Subject: [PATCH] Rpc chain (#214) * add ChainGetBlock,ChainGetBlockHash,ChainGetFinalizedHead * add NewChainClientUnconnectedRpc --- chain/chain.go | 38 +++++++++++++++++++++-- chain/chainer.go | 5 ++- chain/pattern.go | 5 +++ chain/rpc_call.go | 57 ++++++++++++++++++++++++++++++++++ example/test/main.go | 73 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 example/test/main.go diff --git a/chain/chain.go b/chain/chain.go index 947a1d4..c655b8c 100755 --- a/chain/chain.go +++ b/chain/chain.go @@ -50,6 +50,40 @@ type ChainClient struct { var _ Chainer = (*ChainClient)(nil) +// NewChainClientUnconnectedRpc creates a chainclient unconnected rpc +// - ctx: context +// - name: customised name, can be empty +// - rpcs: rpc addresses +// - mnemonic: account mnemonic, can be empty +// - t: waiting time for transaction packing, default is 30 seconds +// +// Return: +// - *ChainClient: chain client +// - error: error message +func NewChainClientUnconnectedRpc(ctx context.Context, name string, rpcs []string, mnemonic string, t time.Duration) (*ChainClient, error) { + var err error + var chainClient = &ChainClient{ + lock: new(sync.Mutex), + chainStLock: new(sync.Mutex), + txTicker: time.NewTicker(BlockInterval), + rpcAddr: rpcs, + packingTime: t, + name: name, + } + if mnemonic != "" { + chainClient.keyring, err = signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return nil, err + } + chainClient.signatureAcc, err = utils.EncodePublicKeyAsCessAccount(chainClient.keyring.PublicKey) + if err != nil { + return nil, err + } + } + chainClient.SetRpcState(false) + return chainClient, nil +} + // NewChainClient creates a chainclient // - ctx: context // - name: customised name, can be empty @@ -184,7 +218,7 @@ func (c *ChainClient) GetRpcState() bool { // GetSignatureAcc get your current account address // // Note: -// - make sure you fill in mnemonic when you create the chain client +// - make sure you fill in mnemonic when you create the sdk client func (c *ChainClient) GetSignatureAcc() string { return c.signatureAcc } @@ -192,7 +226,7 @@ func (c *ChainClient) GetSignatureAcc() string { // GetSignatureAccPulickey get your current account public key // // Note: -// - make sure you fill in mnemonic when you create the chain client +// - make sure you fill in mnemonic when you create the sdk client func (c *ChainClient) GetSignatureAccPulickey() []byte { return c.keyring.PublicKey } diff --git a/chain/chainer.go b/chain/chainer.go index 13ca8dd..859cf71 100755 --- a/chain/chainer.go +++ b/chain/chainer.go @@ -137,11 +137,14 @@ type Chainer interface { QueryRoundReward(era uint32, block int32) (string, error) // rpc_call + ChainGetBlock(hash types.Hash) (types.SignedBlock, error) + ChainGetBlockHash(block uint32) (types.Hash, error) + ChainGetFinalizedHead() (types.Hash, error) + NetListening() (bool, error) SystemProperties() (SysProperties, error) SystemChain() (string, error) SystemSyncState() (SysSyncState, error) SystemVersion() (string, error) - NetListening() (bool, error) // chain_client GetSDKName() string diff --git a/chain/pattern.go b/chain/pattern.go index ec79e5f..b0279ee 100644 --- a/chain/pattern.go +++ b/chain/pattern.go @@ -206,6 +206,11 @@ const ( // RPC Call const ( + // Chain + RPC_Chain_getBlock = "chain_getBlock" + RPC_Chain_getBlockHash = "chain_getBlockHash" + RPC_Chain_getFinalizedHead = "chain_getFinalizedHead" + //Net RPC_NET_Listening = "net_listening" diff --git a/chain/rpc_call.go b/chain/rpc_call.go index 2ece41f..4ece481 100644 --- a/chain/rpc_call.go +++ b/chain/rpc_call.go @@ -14,6 +14,63 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) +// ChainGetBlock get SignedBlock info by block hash +// +// Return: +// - types.SignedBlock: SignedBlock info +// - error: error message +func (c *ChainClient) ChainGetBlock(hash types.Hash) (types.SignedBlock, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.SignedBlock + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_Chain_getBlock, hash) + return data, err +} + +// ChainGetBlockHash get block hash by block number +// +// Return: +// - types.Hash: block hash +// - error: error message +func (c *ChainClient) ChainGetBlockHash(block uint32) (types.Hash, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.Hash + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_Chain_getBlockHash, types.NewU32(block)) + return data, err +} + +// ChainGetFinalizedHead get finalized block hash +// +// Return: +// - types.Hash: block hash +// - error: error message +func (c *ChainClient) ChainGetFinalizedHead() (types.Hash, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.Hash + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_Chain_getFinalizedHead) + return data, err +} + // SystemProperties query system properties // // Return: diff --git a/example/test/main.go b/example/test/main.go new file mode 100644 index 0000000..53ab274 --- /dev/null +++ b/example/test/main.go @@ -0,0 +1,73 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package main + +import ( + "context" + "fmt" + "time" + + cess "github.com/CESSProject/cess-go-sdk" +) + +// Substrate well-known mnemonic: +// +// - https://github.com/substrate-developer-hub/substrate-developer-hub.github.io/issues/613 +// - cXgaee2N8E77JJv9gdsGAckv1Qsf3hqWYf7NL4q6ZuQzuAUtB +var MY_MNEMONIC = "bottom drive obey lake curtain smoke basket hold race lonely fit walk" + +var RPC_ADDRS = []string{ + //testnet + "wss://testnet-rpc0.cess.cloud/ws/", + "wss://testnet-rpc1.cess.cloud/ws/", + "wss://testnet-rpc2.cess.cloud/ws/", +} + +func main() { + sdk, err := cess.New( + context.Background(), + cess.ConnectRpcAddrs(RPC_ADDRS), + cess.Mnemonic(MY_MNEMONIC), + cess.TransactionTimeout(time.Second*10), + ) + if err != nil { + panic(err) + } + defer sdk.Close() + + // get sdk name + fmt.Println(sdk.GetSDKName()) + + // get the current rpc address being used + fmt.Println(sdk.GetCurrentRpcAddr()) + + // get the rpc connection status flag + // - true: connection is normal + // - false: connection failed + fmt.Println(sdk.GetRpcState()) + + // get your current account address + // - make sure you fill in mnemonic when you create the sdk client + fmt.Println(sdk.GetSignatureAcc()) + + // get your current account public key + // - make sure you fill in mnemonic when you create the sdk client + fmt.Println(sdk.GetSignatureAccPulickey()) + + // get substrate api + fmt.Println(sdk.GetSubstrateAPI()) + + // get the mnemonic for your current account + fmt.Println(sdk.GetURI()) + + // get token symbol + fmt.Println(sdk.GetTokenSymbol()) + + // get network environment + fmt.Println(sdk.GetNetworkEnv()) +}