Skip to content

Commit

Permalink
feat: add evm sdk (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
ytqaljn committed Apr 29, 2024
1 parent 0f967ad commit 080788a
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 0 deletions.
126 changes: 126 additions & 0 deletions chain/evm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package chain

import (
"fmt"
"log"
"strings"
"time"

"github.com/CESSProject/cess-go-sdk/core/pattern"
"github.com/CESSProject/cess-go-sdk/utils"
"github.com/centrifuge/go-substrate-rpc-client/v4/types"
"github.com/pkg/errors"
)

func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input types.Bytes, value types.U256, gasLimit types.U64, maxFeePerGas types.U256, accessList []pattern.AccessInfo) (string, error) {
c.lock.Lock()
defer func() {
c.lock.Unlock()
if err := recover(); err != nil {
log.Println(utils.RecoverError(err))
}
}()

var (
txhash string
accountInfo types.AccountInfo
)

if !c.GetChainState() {
return txhash, fmt.Errorf("chainSDK.UploadDeclaration(): GetChainState(): %v", pattern.ERR_RPC_CONNECTION)
}

var nonce types.Option[types.U256]
nonce.SetNone()

var maxPriorityFeePerGas types.Option[types.U256]
maxPriorityFeePerGas.SetNone()

call, err := types.NewCall(c.metadata, pattern.TX_EVM_CALL, source, target, input, value, gasLimit, maxFeePerGas, maxPriorityFeePerGas, nonce, accessList)
if err != nil {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}

ext := types.NewExtrinsic(call)

key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey)
if err != nil {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}

ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo)
if err != nil {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}

if !ok {
keyStr, _ := utils.NumsToByteStr(key, map[string]bool{})
return txhash, fmt.Errorf(
"chain rpc.state.GetStorageLatest[%v]: %v",
keyStr,
pattern.ERR_RPC_EMPTY_VALUE,
)
}

o := types.SignatureOptions{
BlockHash: c.genesisHash,
Era: types.ExtrinsicEra{IsMortalEra: false},
GenesisHash: c.genesisHash,
Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)),
SpecVersion: c.runtimeVersion.SpecVersion,
Tip: types.NewUCompactFromUInt(0),
TransactionVersion: c.runtimeVersion.TransactionVersion,
}

err = ext.Sign(c.keyring, o)
if err != nil {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}

sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext)
if err != nil {
if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) {
o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1))
err = ext.Sign(c.keyring, o)
if err != nil {
return txhash, errors.Wrap(err, "[Sign]")
}
sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext)
if err != nil {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}
} else {
err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.EVM, err)
c.SetChainState(false)
return txhash, err
}
}
defer sub.Unsubscribe()

timeout := time.NewTimer(c.packingTime)
defer timeout.Stop()

for {
select {
case status := <-sub.Chan():
if status.IsInBlock {
txhash = status.AsInBlock.Hex()
return txhash, err
}
case err = <-sub.Err():
return txhash, errors.Wrap(err, "[sub]")
case <-timeout.C:
return txhash, pattern.ERR_RPC_TIMEOUT
}
}
}
10 changes: 10 additions & 0 deletions core/pattern/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const (
BALANCES = "Balances"
// SYSTEM is a module about the system
SYSTEM = "System"
// EVM is a module about the evm contract
EVM = "EVM"
//
CessTreasury = "CessTreasury"
)
Expand Down Expand Up @@ -174,6 +176,9 @@ const (

// BALANCES
TX_BALANCES_FORCETRANSFER = "Balances" + DOT + "transfer"

// EVM
TX_EVM_CALL = EVM + DOT + "call"
)

// RPC Call
Expand Down Expand Up @@ -598,3 +603,8 @@ type UserInfo struct {
BucketName string
FileSize uint64
}

type AccessInfo struct {
r types.H160
c []types.H160
}
84 changes: 84 additions & 0 deletions example/evm/evm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import (
"context"
"encoding/hex"
"fmt"
"log"
"math/big"
"time"

cess "github.com/CESSProject/cess-go-sdk"
"github.com/CESSProject/cess-go-sdk/chain"
"github.com/CESSProject/cess-go-sdk/core/pattern"
"github.com/centrifuge/go-substrate-rpc-client/v4/types"
)

// Substrate well-known mnemonic:
//
// https://github.com/substrate-developer-hub/substrate-developer-hub.github.io/issues/613
var MY_MNEMONIC = "head achieve piano online exhaust bulk trust vote inflict room keen maximum"

var RPC_ADDRS = []string{
//devnet
"wss://devnet-rpc.cess.cloud/ws/",
//testnet
// "wss://testnet-rpc0.cess.cloud/ws/",
// "wss://testnet-rpc1.cess.cloud/ws/",
// "wss://testnet-rpc2.cess.cloud/ws/",
}

func main() {
// 1. new sdk
sdk, err := NewSDK()
if err != nil {
panic(err)
}

var (
source types.H160
target types.H160
input types.Bytes
value types.U256
gasLimit types.U64
maxFeePerGas types.U256
accessList []pattern.AccessInfo
)

s_h160, err := hex.DecodeString("1e3e1c69dfbd27d398e92da4844a9abdc2786ac0")
if err != nil {
log.Fatalln(err)
}
source = types.NewH160(s_h160)

t_h160, err := hex.DecodeString("7352188979857675C3aD1AA6662326ebD6DDBf6d")
if err != nil {
log.Fatalln(err)
}
target = types.NewH160(t_h160)

input_string, err := hex.DecodeString("a9059cbb00000000000000000000000085cdaca43a76c8ab769b974c2cf7306980742a310000000000000000000000000000000000000000000000000de0b6b3a7640000")
input = input_string

value = types.NewU256(*big.NewInt(0))

gasLimit = 3000000

maxFeePerGas = types.NewU256(*big.NewInt(500000000))

block_hash, err := sdk.SendEvmCall(source, target, input, value, gasLimit, maxFeePerGas, accessList)
if err != nil {
log.Fatalln(err)
}

fmt.Printf("%s", block_hash)
}

func NewSDK() (*chain.ChainClient, error) {
return cess.New(
context.Background(),
cess.ConnectRpcAddrs(RPC_ADDRS),
cess.Mnemonic(MY_MNEMONIC),
cess.TransactionTimeout(time.Second*10),
)
}
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
)

require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand All @@ -33,6 +34,7 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect
Expand All @@ -44,9 +46,19 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/vedhavyas/go-subkey/v2 v2.0.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/telemetry v0.0.0-20240209200032-7b892fcb8a78 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.18.1-0.20240412183611-d92ae0781217 // indirect
golang.org/x/tools/gopls v0.15.3 // indirect
golang.org/x/vuln v1.0.1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/tools v0.4.6 // indirect
mvdan.cc/gofumpt v0.6.0 // indirect
mvdan.cc/xurls/v2 v2.5.0 // indirect
)
25 changes: 25 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CESSProject/go-keyring v0.0.0-20220614131247-ee3a8da30fde h1:5MDRjjtg6PEhqyVjupwaapN96cOZiddOGAYwKQeaTu0=
github.com/CESSProject/go-keyring v0.0.0-20220614131247-ee3a8da30fde/go.mod h1:RUXBd3ROP98MYepEEa0Y0l/T0vQlIKqFJxI/ocdnRLM=
github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM=
Expand Down Expand Up @@ -45,6 +47,8 @@ github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3G
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
Expand Down Expand Up @@ -115,6 +119,10 @@ golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 h1:2O2DON6y3XMJiQRAS1UWU+54aec2uopH3x7MAiqGW6Y=
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand All @@ -134,12 +142,23 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240209200032-7b892fcb8a78 h1:vcVnuftN4J4UKLRcgetjzfU9FjjgXUUYUc3JhFplgV4=
golang.org/x/telemetry v0.0.0-20240209200032-7b892fcb8a78/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.18.1-0.20240412183611-d92ae0781217 h1:uH9jJYgeLCvblH0S+03kFO0qUDxRkbLRLFiKVVDl7ak=
golang.org/x/tools v0.18.1-0.20240412183611-d92ae0781217/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/tools/gopls v0.15.3 h1:zbdOidFrPTc8Bx0YrN5QKgJ0zCjyGi0L27sKQ/bDG5o=
golang.org/x/tools/gopls v0.15.3/go.mod h1:W/lfb6hIysrnNXreqA2nHP2Qaay881XwhrSRMfsGUdQ=
golang.org/x/vuln v1.0.1 h1:KUas02EjQK5LTuIx1OylBQdKKZ9jeugs+HiqO5HormU=
golang.org/x/vuln v1.0.1/go.mod h1:bb2hMwln/tqxg32BNY4CcxHWtHXuYa3SbIBmtsyjxtM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
Expand All @@ -149,3 +168,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=
honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0=
mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo=
mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA=
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=

0 comments on commit 080788a

Please sign in to comment.