Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add evm sdk #204

Merged
merged 2 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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=
Loading