From 3973cb0b858cf8a1516663645853700086650955 Mon Sep 17 00:00:00 2001 From: unclezoro <296179868@qq.com> Date: Mon, 30 Sep 2024 19:54:34 +0800 Subject: [PATCH] feat: add demo for cex collection --- cex-collection/go-example/.env | 10 + cex-collection/go-example/go.mod | 37 ++++ cex-collection/go-example/go.sum | 145 ++++++++++++++ cex-collection/go-example/main.go | 201 ++++++++++++++++++++ cex-collection/go-example/readme.md | 37 ++++ cex-collection/js-example/.env | 10 + cex-collection/js-example/index.js | 109 +++++++++++ cex-collection/js-example/package-lock.json | 196 +++++++++++++++++++ cex-collection/js-example/package.json | 15 ++ cex-collection/js-example/readme.md | 35 ++++ cex-collection/readme.md | 28 +++ cex/go-example/.env | 2 - cex/go-example/go.mod | 2 +- cex/go-example/go.sum | 4 +- cex/go-example/main.go | 13 +- 15 files changed, 829 insertions(+), 15 deletions(-) create mode 100644 cex-collection/go-example/.env create mode 100644 cex-collection/go-example/go.mod create mode 100644 cex-collection/go-example/go.sum create mode 100644 cex-collection/go-example/main.go create mode 100644 cex-collection/go-example/readme.md create mode 100644 cex-collection/js-example/.env create mode 100644 cex-collection/js-example/index.js create mode 100644 cex-collection/js-example/package-lock.json create mode 100644 cex-collection/js-example/package.json create mode 100644 cex-collection/js-example/readme.md create mode 100644 cex-collection/readme.md diff --git a/cex-collection/go-example/.env b/cex-collection/go-example/.env new file mode 100644 index 0000000..26e5e05 --- /dev/null +++ b/cex-collection/go-example/.env @@ -0,0 +1,10 @@ +#PAYMASTER_URL="https://bsc-megafuel.nodereal.io" +#SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel" + +PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io" +SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel-testnet" + +POLICY_UUID="xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" +TOKEN_CONTRACT_ADDRESS="0xeD24F....12Ee" +CONSOLIDATION_WALLET_ADDRESS="0x8e92....3EA2" +DEPOSIT_WALLET_PRIVATE_KEY="69...929" diff --git a/cex-collection/go-example/go.mod b/cex-collection/go-example/go.mod new file mode 100644 index 0000000..2c813f3 --- /dev/null +++ b/cex-collection/go-example/go.mod @@ -0,0 +1,37 @@ +module paymaster-example + +go 1.21 + +require ( + github.com/ethereum/go-ethereum v1.14.8 + github.com/gofrs/uuid v4.3.0+incompatible + github.com/joho/godotenv v1.5.1 + github.com/node-real/megafuel-go-sdk v1.0.1 +) + +require ( + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/holiman/uint256 v1.3.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/supranational/blst v0.3.11 // indirect + github.com/tklauser/go-sysconf v0.3.13 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/cex-collection/go-example/go.sum b/cex-collection/go-example/go.sum new file mode 100644 index 0000000..a6f86d1 --- /dev/null +++ b/cex-collection/go-example/go.sum @@ -0,0 +1,145 @@ +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= +github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.14.8 h1:NgOWvXS+lauK+zFukEvi85UmmsS/OkV0N23UZ1VTIig= +github.com/ethereum/go-ethereum v1.14.8/go.mod h1:TJhyuDq0JDppAkFXgqjwpdlQApywnu/m10kFPxh8vvs= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/node-real/megafuel-go-sdk v1.0.1 h1:p0wI/JxECAO5aliqcHorRF12/Ti1W7tYcDCORBhZ9r0= +github.com/node-real/megafuel-go-sdk v1.0.1/go.mod h1:viVAAOwIDDiS0yBBR47rmB/goDU2f+GFsP+qBuPeSHg= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/cex-collection/go-example/main.go b/cex-collection/go-example/main.go new file mode 100644 index 0000000..778462e --- /dev/null +++ b/cex-collection/go-example/main.go @@ -0,0 +1,201 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "encoding/json" + "fmt" + "log" + "math/big" + "os" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" + "github.com/gofrs/uuid" + "github.com/joho/godotenv" + "github.com/node-real/megafuel-go-sdk/pkg/paymasterclient" + "github.com/node-real/megafuel-go-sdk/pkg/sponsorclient" +) + +var ( + PaymasterURL string + SponsorURL string + + PolicyUUID uuid.UUID + TokenContractAddress common.Address + ConsolidationWalletAddress common.Address + DepositWalletPrivateKey string +) + +func init() { + err := godotenv.Load(".env") + + if err != nil { + log.Fatalf("Error loading .env file") + } + + PaymasterURL = os.Getenv("PAYMASTER_URL") + SponsorURL = os.Getenv("SPONSOR_URL") + + PolicyUUID, err = uuid.FromString(os.Getenv("POLICY_UUID")) + if err != nil { + log.Fatalf("Error parsing POLICY_UUID") + } + + TokenContractAddress = common.HexToAddress(os.Getenv("TOKEN_CONTRACT_ADDRESS")) + ConsolidationWalletAddress = common.HexToAddress(os.Getenv("CONSOLIDATION_WALLET_ADDRESS")) + DepositWalletPrivateKey = os.Getenv("DEPOSIT_WALLET_PRIVATE_KEY") +} + +func main() { + sponsorSetUpPolicyRules() + cexDoGaslessTransfer() +} + +func sponsorSetUpPolicyRules() { + sponsorClient, err := sponsorclient.New(context.Background(), SponsorURL) + if err != nil { + log.Fatal(err) + } + + // sponsor the tx that interact with the stable coin ERC20 contract + success, err := sponsorClient.AddToWhitelist(context.Background(), sponsorclient.WhiteListArgs{ + PolicyUUID: PolicyUUID, + WhitelistType: sponsorclient.ToAccountWhitelist, + Values: []string{TokenContractAddress.String()}, + }) + if err != nil || !success { + log.Fatal("failed to add token contract whitelist", err) + } + // add transfer signature + success, err = sponsorClient.AddToWhitelist(context.Background(), sponsorclient.WhiteListArgs{ + PolicyUUID: PolicyUUID, + WhitelistType: sponsorclient.ContractMethodSigWhitelist, + Values: []string{"0xa9059cbb"}, + }) + if err != nil || !success { + log.Fatal("failed to add contract method whitelist") + } + + // sponsor the tx whose BEP20 receiver is consolidation wallets + success, err = sponsorClient.AddToWhitelist(context.Background(), sponsorclient.WhiteListArgs{ + PolicyUUID: PolicyUUID, + WhitelistType: sponsorclient.BEP20ReceiverWhiteList, + Values: []string{ConsolidationWalletAddress.String()}, + }) + if err != nil || !success { + log.Fatal("failed to BEP20 receiver whitelist") + } +} + +func cexDoGaslessTransfer() { + transferAmount := big.NewInt(1e17) + + // Create a PaymasterClient (for transaction sending) + paymasterClient, err := paymasterclient.New(context.Background(), PaymasterURL) + if err != nil { + log.Fatalf("Failed to create PaymasterClient: %v", err) + } + + // Load your private key + privateKey, err := crypto.HexToECDSA(DepositWalletPrivateKey) + if err != nil { + log.Fatalf("Failed to load private key: %v", err) + } + + fromAddress := getAddressFromPrivateKey(DepositWalletPrivateKey) + + // Create ERC20 transfer data + data, err := createERC20TransferData(ConsolidationWalletAddress, transferAmount) + if err != nil { + log.Fatalf("Failed to create ERC20 transfer data: %v", err) + } + + // Get the latest nonce for the from address + nonce, err := paymasterClient.GetTransactionCount(context.Background(), fromAddress, rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)) + if err != nil { + log.Fatalf("Failed to get nonce: %v", err) + } + + // Create the transaction + gasPrice := big.NewInt(0) + tx := types.NewTransaction(nonce, TokenContractAddress, big.NewInt(0), 300000, gasPrice, data) + + // Get the chain ID + chainID, err := paymasterClient.ChainID(context.Background()) + if err != nil { + log.Fatalf("Failed to get chain ID: %v", err) + } + + // Sign the transaction + signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) + if err != nil { + log.Fatalf("Failed to sign transaction: %v", err) + } + + txInput, err := signedTx.MarshalBinary() + if err != nil { + log.Fatalf("Failed to marshal transaction: %v", err) + } + + // Convert to Transaction struct for IsSponsorable check + gasLimit := tx.Gas() + sponsorableTx := paymasterclient.TransactionArgs{ + To: &TokenContractAddress, + From: fromAddress, + Value: (*hexutil.Big)(big.NewInt(0)), + Gas: (*hexutil.Uint64)(&gasLimit), + Data: (*hexutil.Bytes)(&data), + } + + // Check if the transaction is sponsorable + sponsorableInfo, err := paymasterClient.IsSponsorable(context.Background(), sponsorableTx) + if err != nil { + log.Fatalf("Error checking sponsorable status: %v", err) + } + + jsonInfo, _ := json.MarshalIndent(sponsorableInfo, "", " ") + fmt.Printf("Sponsorable Information:\n%s\n", string(jsonInfo)) + + if sponsorableInfo.Sponsorable { + // Send the transaction using PaymasterClient + _, err := paymasterClient.SendRawTransaction(context.Background(), txInput) + if err != nil { + log.Fatalf("Failed to send sponsorable transaction: %v", err) + } + fmt.Printf("Sponsorable transaction sent: %s\n", signedTx.Hash()) + } else { + fmt.Println("Transaction is not sponsorable. You may need to send it as a regular transaction.") + } +} + +func getAddressFromPrivateKey(pk string) common.Address { + // Load your private key + privateKey, err := crypto.HexToECDSA(pk) + if err != nil { + log.Fatalf("Failed to load private key: %v", err) + } + + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatal("Error casting public key to ECDSA") + } + return crypto.PubkeyToAddress(*publicKeyECDSA) +} + +func createERC20TransferData(to common.Address, amount *big.Int) ([]byte, error) { + transferFnSignature := []byte("transfer(address,uint256)") + methodID := crypto.Keccak256(transferFnSignature)[:4] + paddedAddress := common.LeftPadBytes(to.Bytes(), 32) + paddedAmount := common.LeftPadBytes(amount.Bytes(), 32) + + var data []byte + data = append(data, methodID...) + data = append(data, paddedAddress...) + data = append(data, paddedAmount...) + return data, nil +} diff --git a/cex-collection/go-example/readme.md b/cex-collection/go-example/readme.md new file mode 100644 index 0000000..55de490 --- /dev/null +++ b/cex-collection/go-example/readme.md @@ -0,0 +1,37 @@ +# GO Example + +This repository contains a Go application demonstrating: + +1. Sponsor manage the policy to sponsor any transaction sent particular tokens to the consolidation/hot + wallets of the Cex +2. Cex do token transfer without pay gas fee through MegaFuel. + +## Quick Start + +The example is performed on BSC testnet or BSC mainnet, please ensure you have some test ERC20 on them. (You can get +some from the official faucet when using testnet) + +1. Install dependencies + ```shell + $ go mod tidy + ``` +2. Configure the .env file + Before running the application, you need to edit the `.env` to set up the following: + + - 'PAYMASTER_URL' with the Paymaster URL. + - 'CHAIN_URL' with the BSC testnet or BSC mainnet chain URL. + - 'SPONSOR_URL' to the API key created by the sponsor in the Nodereal dashboard. create one + from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it. + - 'POLICY_UUID' to the policy ID created by the sponsor on Megafuel Paymaster, create one + from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it. + - 'TOKEN_CONTRACT_ADDRESS' to the ERC20 token contract address that Cex want to collect. + - 'CONSOLIDATION_WALLET_ADDRESS' to the consolidation/hot wallet of Cex. + - 'DEPOSIT_WALLET_PRIVATE_KEY' to the Cex's deposit wallet private key, ensuring this wallet contains the required ERC20 + tokens. + +3. Run the example + ``` + $ go run ./ + ``` + + diff --git a/cex-collection/js-example/.env b/cex-collection/js-example/.env new file mode 100644 index 0000000..5514c0f --- /dev/null +++ b/cex-collection/js-example/.env @@ -0,0 +1,10 @@ +#PAYMASTER_URL="https://bsc-megafuel.nodereal.io" +#SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel" + +PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io" +SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel-testnet" + +POLICY_UUID="xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" +TOKEN_CONTRACT_ADDRESS="0xeD24F....12Ee" +CONSOLIDATION_WALLET_ADDRESS="0x8e92....3EA2" +DEPOSIT_WALLET_PRIVATE_KEY="69...929" \ No newline at end of file diff --git a/cex-collection/js-example/index.js b/cex-collection/js-example/index.js new file mode 100644 index 0000000..eba7797 --- /dev/null +++ b/cex-collection/js-example/index.js @@ -0,0 +1,109 @@ +import 'dotenv/config' +import {ethers} from 'ethers' +import {PaymasterClient, SponsorClient, WhitelistType} from 'megafuel-js-sdk' + +async function cexDoGaslessTransferTx() { + // Provider for sending the transaction (e.g., could be a different network or provider) + const paymasterClient = new PaymasterClient(process.env.PAYMASTER_URL) + const network = await paymasterClient.getNetwork() + + const wallet = new ethers.Wallet(process.env.DEPOSIT_WALLET_PRIVATE_KEY) + // ERC20 token ABI (only including the transfer function) + const tokenAbi = ['function transfer(address to, uint256 amount) returns (bool)'] + // Create contract instance + const tokenContract = new ethers.Contract(process.env.TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) + // Transaction details + const tokenAmount = ethers.parseUnits('1.0', 18) // Amount of tokens to send (adjust decimals as needed) + // Create the transaction object + const transaction = await tokenContract.transfer.populateTransaction(process.env.CONSOLIDATION_WALLET_ADDRESS, tokenAmount) + + const nonce = await paymasterClient.getTransactionCount(wallet.address, 'pending') + + // Add nonce and gas settings + transaction.from = wallet.address + transaction.nonce = nonce + transaction.gasLimit = 100000 // Adjust gas limit as needed for token transfers + transaction.chainId = network.chainId + transaction.gasPrice = 0 // Set gas price to 0 + + const safeTransaction = { + ...transaction, + gasLimit: transaction.gasLimit.toString(), + chainId: transaction.chainId.toString(), + gasPrice: transaction.gasPrice.toString(), + } + + try { + const sponsorableInfo = await paymasterClient.isSponsorable(safeTransaction) + console.log('Sponsorable Information:', sponsorableInfo) + } catch (error) { + console.error('Error checking sponsorable status:', error) + } + + try { + // Sign the transaction + const signedTx = await wallet.signTransaction(transaction) + // Send the raw transaction using the sending provider + const tx = await paymasterClient.sendRawTransaction(signedTx) + console.log('Transaction sent:', tx) + } catch (error) { + console.error('Error sending transaction:', error) + } +} + +async function sponsorSetUpPolicyRules() { + const paymasterClient = new PaymasterClient(process.env.PAYMASTER_URL) + const network = await paymasterClient.getNetwork() + const client = new SponsorClient(process.env.SPONSOR_URL, null, + {staticNetwork: ethers.Network.from(network.chainId)}) + + const wallet = new ethers.Wallet(process.env.DEPOSIT_WALLET_PRIVATE_KEY) + // sponsor the tx that interact with the stable coin ERC20 contract + try { + // You can empty the policy rules before re-try. + await client.emptyWhitelist({ + PolicyUUID: process.env.POLICY_UUID, + WhitelistType: WhitelistType.FromAccountWhitelist, + }); + await client.emptyWhitelist({ + PolicyUUID: process.env.POLICY_UUID, + WhitelistType: WhitelistType.ToAccountWhitelist, + }); + + const res1 = await client.addToWhitelist({ + PolicyUUID: process.env.POLICY_UUID, + WhitelistType: WhitelistType.ToAccountWhitelist, + Values: [process.env.TOKEN_CONTRACT_ADDRESS] + }); + console.log("Added ERC20 contract address to whitelist ", res1); + + // sponsor the tx that call the "transfer" interface of ERC20 contract + const res2 = await client.addToWhitelist({ + PolicyUUID: process.env.POLICY_UUID, + WhitelistType: WhitelistType.ContractMethodSigWhitelist, + Values: ["0xa9059cbb"] + }); + console.log("Added 'transfer' contract method to whitelist ", res2); + + // sponsor the tx that send token to consolidation wallet + const res3 = await client.addToWhitelist({ + PolicyUUID: process.env.POLICY_UUID, + WhitelistType: WhitelistType.BEP20ReceiverWhiteList, + Values: [process.env.CONSOLIDATION_WALLET_ADDRESS] + }); + console.log("Added consolidation wallet to BEP20 receiver whitelist ", res3); + } catch (error){ + console.error("Error:", error) + } +} + +async function main() { + try { + await sponsorSetUpPolicyRules() + await cexDoGaslessTransferTx() + } catch (error) { + console.error('Error:', error) + } +} + +main() diff --git a/cex-collection/js-example/package-lock.json b/cex-collection/js-example/package-lock.json new file mode 100644 index 0000000..2cadc59 --- /dev/null +++ b/cex-collection/js-example/package-lock.json @@ -0,0 +1,196 @@ +{ + "name": "megafuel-paymaster-example", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "megafuel-paymaster-example", + "version": "1.0.0", + "dependencies": { + "dotenv": "^16.4.5", + "ethers": "^6.3.0", + "megafuel-js-sdk": "^1.0.5" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ethers": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/megafuel-js-sdk": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/megafuel-js-sdk/-/megafuel-js-sdk-1.0.5.tgz", + "integrity": "sha512-Qfs47UjvDOlDuFnHsQlZn6VstVIrgBl0SPnRHL9jRbOo9n/jDzvITjGgXBLfMJDda0T/5YE9I1AulXUBsZD2tw==", + "dependencies": { + "ethers": "^6.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "requires": { + "@noble/hashes": "1.3.2" + } + }, + "@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" + }, + "@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, + "ethers": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", + "requires": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + } + }, + "megafuel-js-sdk": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/megafuel-js-sdk/-/megafuel-js-sdk-1.0.5.tgz", + "integrity": "sha512-Qfs47UjvDOlDuFnHsQlZn6VstVIrgBl0SPnRHL9jRbOo9n/jDzvITjGgXBLfMJDda0T/5YE9I1AulXUBsZD2tw==", + "requires": { + "ethers": "^6.3.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "requires": {} + } + } +} diff --git a/cex-collection/js-example/package.json b/cex-collection/js-example/package.json new file mode 100644 index 0000000..b2d79a2 --- /dev/null +++ b/cex-collection/js-example/package.json @@ -0,0 +1,15 @@ +{ + "name": "megafuel-paymaster-example", + "version": "1.0.0", + "description": "A script to send Ethereum transactions with 0 gas price through MegaFuel Paymaster", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "dotenv": "^16.4.5", + "ethers": "^6.3.0", + "megafuel-js-sdk": "^1.0.5" + }, + "type": "module" +} diff --git a/cex-collection/js-example/readme.md b/cex-collection/js-example/readme.md new file mode 100644 index 0000000..1234653 --- /dev/null +++ b/cex-collection/js-example/readme.md @@ -0,0 +1,35 @@ +# Js Example + +This repository contains a Go application demonstrating: + +1. Sponsor manage the policy to sponsor any transaction sent particular tokens to the consolidation/hot + wallets of the Cex +2. Cex do token transfer without pay gas fee through MegaFuel. + +## Quick Start + +The example is performed on BSC testnet or BSC mainnet, please ensure you have some test ERC20 on them. (You can get +some from the official faucet when using testnet) + +1. Install the dependency. + ```shell + $ npm install + ``` + +2. Configure the `.env`. + Open `.env` and replace the following placeholders: + + - 'PAYMASTER_URL' with the Paymaster URL. + - 'SPONSOR_URL' to the API key created by the sponsor in the Nodereal dashboard. create one + from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it. + - 'POLICY_UUID' to the policy UUID created by the sponsor on Megafuel Paymaster, create one + from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it. + - 'TOKEN_CONTRACT_ADDRESS' with the address of the ERC20 token user want to withdraw. + - 'CONSOLIDATION_WALLET_ADDRESS' to the consolidation/hot wallet of Cex. + - 'DEPOSIT_WALLET_PRIVATE_KEY' to the Cex's deposit wallet private key, ensuring this wallet contains the required ERC20 + tokens. + +3. Run script + ```shell + $ npm start + ``` diff --git a/cex-collection/readme.md b/cex-collection/readme.md new file mode 100644 index 0000000..40a03b3 --- /dev/null +++ b/cex-collection/readme.md @@ -0,0 +1,28 @@ +# Cex Deposit Wallet Collection Example + +MegaFuel provides a gasless solution for EOA (Externally Owned Account) users. +By integrating with MegaFuel, CEXs can achieve deposit wallet collection in a single transaction with minimal +modifications to their existing systems. This integration simultaneously reduces complexity, lowers costs, and enhances g +as token utilization efficiency. + +This example demonstrates how a CEX should manage the sponsor policy in such a scenario. + +## Prepare Work + +Before getting started, the Cex, needs to first register as a user on +Nodereal and then apply to create a policy. The specific process can be referred to in [this document](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines). + +After the application is approved, Nodereal will email the Sponsor with the ID of +the policy created for them. + +## Configure the Policy + +The scripts in the example demonstrate how the sponsor should configure the policy, as well as how Cex can +send transactions with 0 gas price: + +- The sponsor sets the policy rule through API: Any transactions that send particular tokens to the consolidation/hot +wallets of the Cex can be sponsored. +- Cex send the 0 gas price transaction through Paymaster endpoint. + + + diff --git a/cex/go-example/.env b/cex/go-example/.env index 2155002..480fd93 100644 --- a/cex/go-example/.env +++ b/cex/go-example/.env @@ -1,8 +1,6 @@ #PAYMASTER_URL="https://bsc-megafuel.nodereal.io" -#CHAIN_URL="https://bsc-dataseed4.binance.org" #SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel" PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io" -CHAIN_URL="https://data-seed-prebsc-2-s1.binance.org:8545/" SPONSOR_URL="https://open-platform-ap.nodereal.io/{YOUR_API_KEY}/megafuel-testnet" POLICY_UUID="xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" diff --git a/cex/go-example/go.mod b/cex/go-example/go.mod index 4d1d61d..2c813f3 100644 --- a/cex/go-example/go.mod +++ b/cex/go-example/go.mod @@ -6,7 +6,7 @@ require ( github.com/ethereum/go-ethereum v1.14.8 github.com/gofrs/uuid v4.3.0+incompatible github.com/joho/godotenv v1.5.1 - github.com/node-real/megafuel-go-sdk v1.0.0 + github.com/node-real/megafuel-go-sdk v1.0.1 ) require ( diff --git a/cex/go-example/go.sum b/cex/go-example/go.sum index 54348e8..0f697a1 100644 --- a/cex/go-example/go.sum +++ b/cex/go-example/go.sum @@ -115,8 +115,8 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/node-real/megafuel-go-sdk v1.0.0 h1:/O6/KAnb/eJJWSYgj3REgqVh0QA/zDxXyuUQICeXR4A= -github.com/node-real/megafuel-go-sdk v1.0.0/go.mod h1:bTrKp641ZKh7ZTeIx77IrIuhxNAkh/680vIiIA8Ihy4= +github.com/node-real/megafuel-go-sdk v1.0.1 h1:p0wI/JxECAO5aliqcHorRF12/Ti1W7tYcDCORBhZ9r0= +github.com/node-real/megafuel-go-sdk v1.0.1/go.mod h1:viVAAOwIDDiS0yBBR47rmB/goDU2f+GFsP+qBuPeSHg= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/cex/go-example/main.go b/cex/go-example/main.go index 3c84b8f..8f141db 100644 --- a/cex/go-example/main.go +++ b/cex/go-example/main.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" "github.com/gofrs/uuid" "github.com/joho/godotenv" "github.com/node-real/megafuel-go-sdk/pkg/paymasterclient" @@ -22,7 +22,6 @@ import ( var ( PaymasterURL string - ChainURL string SponsorURL string PolicyUUID uuid.UUID @@ -40,7 +39,6 @@ func init() { } PaymasterURL = os.Getenv("PAYMASTER_URL") - ChainURL = os.Getenv("CHAIN_URL") SponsorURL = os.Getenv("SPONSOR_URL") PolicyUUID, err = uuid.FromString(os.Getenv("POLICY_UUID")) @@ -89,11 +87,6 @@ func sponsorSetUpPolicyRules() { func cexDoGaslessWithdrawl() { withdrawAmount := big.NewInt(1e17) - // Connect to an Ethereum node (for transaction assembly) - client, err := ethclient.Dial(ChainURL) - if err != nil { - log.Fatalf("Failed to connect to the Ethereum network: %v", err) - } // Create a PaymasterClient (for transaction sending) paymasterClient, err := paymasterclient.New(context.Background(), PaymasterURL) @@ -116,7 +109,7 @@ func cexDoGaslessWithdrawl() { } // Get the latest nonce for the from address - nonce, err := client.PendingNonceAt(context.Background(), fromAddress) + nonce, err := paymasterClient.GetTransactionCount(context.Background(), fromAddress, rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)) if err != nil { log.Fatalf("Failed to get nonce: %v", err) } @@ -126,7 +119,7 @@ func cexDoGaslessWithdrawl() { tx := types.NewTransaction(nonce, TokenContractAddress, big.NewInt(0), 300000, gasPrice, data) // Get the chain ID - chainID, err := client.ChainID(context.Background()) + chainID, err := paymasterClient.ChainID(context.Background()) if err != nil { log.Fatalf("Failed to get chain ID: %v", err) }