Skip to content

Commit 573a29f

Browse files
authored
feat: using sdk to refact examples (#1)
1 parent e5e2a22 commit 573a29f

34 files changed

+1379
-2562
lines changed

cex/go-example/.env

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#PAYMASTER_URL="https://bsc-megafuel.nodereal.io"
2+
#CHAIN_URL="https://bsc-dataseed4.binance.org"
3+
#SPONSOR_URL="https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel"
4+
PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io"
5+
CHAIN_URL="https://data-seed-prebsc-2-s1.binance.org:8545/"
6+
SPONSOR_URL="https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel-testnet"
7+
8+
POLICY_UUID="xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
9+
TOKEN_CONTRACT_ADDRESS="0xeD24F....12Ee"
10+
WITHDRAW_RECIPIENT_ADDRESS="0x8e92....3EA2"
11+
HOTWALLET_PRIVATE_KEY="69...929"

cex/go-example/go.mod

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,36 @@ module paymaster-example
22

33
go 1.21
44

5-
require github.com/ethereum/go-ethereum v1.12.0
5+
require (
6+
github.com/ethereum/go-ethereum v1.14.8
7+
github.com/gofrs/uuid v4.3.0+incompatible
8+
github.com/joho/godotenv v1.5.1
9+
github.com/node-real/megafuel-go-sdk v1.0.0
10+
)
611

712
require (
8-
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
9-
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
10-
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
13+
github.com/Microsoft/go-winio v0.6.2 // indirect
14+
github.com/bits-and-blooms/bitset v1.10.0 // indirect
15+
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
16+
github.com/consensys/bavard v0.1.13 // indirect
17+
github.com/consensys/gnark-crypto v0.12.1 // indirect
18+
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
19+
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
1120
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
12-
github.com/go-ole/go-ole v1.2.1 // indirect
13-
github.com/go-stack/stack v1.8.1 // indirect
14-
github.com/gorilla/websocket v1.4.2 // indirect
15-
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
16-
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
17-
github.com/tklauser/go-sysconf v0.3.5 // indirect
18-
github.com/tklauser/numcpus v0.2.2 // indirect
19-
golang.org/x/crypto v0.1.0 // indirect
20-
golang.org/x/sys v0.7.0 // indirect
21-
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
21+
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
22+
github.com/go-ole/go-ole v1.3.0 // indirect
23+
github.com/gorilla/websocket v1.5.1 // indirect
24+
github.com/holiman/uint256 v1.3.1 // indirect
25+
github.com/mmcloughlin/addchain v0.4.0 // indirect
26+
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
27+
github.com/supranational/blst v0.3.11 // indirect
28+
github.com/tklauser/go-sysconf v0.3.13 // indirect
29+
github.com/tklauser/numcpus v0.7.0 // indirect
30+
github.com/yusufpapurcu/wmi v1.2.3 // indirect
31+
golang.org/x/crypto v0.22.0 // indirect
32+
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect
33+
golang.org/x/net v0.24.0 // indirect
34+
golang.org/x/sync v0.7.0 // indirect
35+
golang.org/x/sys v0.20.0 // indirect
36+
rsc.io/tmplfunc v0.0.3 // indirect
2237
)

cex/go-example/go.sum

Lines changed: 123 additions & 83 deletions
Large diffs are not rendered by default.

cex/go-example/main.go

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,68 @@ import (
77
"fmt"
88
"log"
99
"math/big"
10+
"os"
1011

1112
"github.com/ethereum/go-ethereum/common"
1213
"github.com/ethereum/go-ethereum/common/hexutil"
1314
"github.com/ethereum/go-ethereum/core/types"
1415
"github.com/ethereum/go-ethereum/crypto"
16+
"github.com/ethereum/go-ethereum/ethclient"
17+
"github.com/gofrs/uuid"
18+
"github.com/joho/godotenv"
19+
"github.com/node-real/megafuel-go-sdk/pkg/paymasterclient"
20+
"github.com/node-real/megafuel-go-sdk/pkg/sponsorclient"
1521
)
1622

17-
const TokenContractAddress = "0x.."
18-
const WithdrawRecipientAddress = "0x.."
19-
const SponsorPolicyId = ".."
20-
const HotwalletPrivateKey = ".."
23+
var (
24+
PaymasterURL string
25+
ChainURL string
26+
SponsorURL string
2127

22-
const sponsorAPIEndpoint = "https://open-platform.nodereal.io/{Your_API_key}/megafuel"
23-
const paymasterEndpoint = "https://bsc-megafuel.nodereal.io"
28+
PolicyUUID uuid.UUID
2429

25-
// testnet endpoint
26-
// const sponsorAPIEndpoint = "https://open-platform.nodereal.io/{Your_API_key}/megafuel-testnet"
27-
// const paymasterEndpoint = "https://bsc-megafuel-testnet.nodereal.io'"
30+
TokenContractAddress common.Address
31+
WithdrawRecipientAddress common.Address
32+
HotwalletPrivateKey string
33+
)
34+
35+
func init() {
36+
err := godotenv.Load(".env")
37+
38+
if err != nil {
39+
log.Fatalf("Error loading .env file")
40+
}
41+
42+
PaymasterURL = os.Getenv("PAYMASTER_URL")
43+
ChainURL = os.Getenv("CHAIN_URL")
44+
SponsorURL = os.Getenv("SPONSOR_URL")
45+
46+
PolicyUUID, err = uuid.FromString(os.Getenv("POLICY_UUID"))
47+
if err != nil {
48+
log.Fatalf("Error parsing POLICY_UUID")
49+
}
50+
51+
TokenContractAddress = common.HexToAddress(os.Getenv("TOKEN_CONTRACT_ADDRESS"))
52+
WithdrawRecipientAddress = common.HexToAddress(os.Getenv("WITHDRAW_RECIPIENT_ADDRESS"))
53+
HotwalletPrivateKey = os.Getenv("HOTWALLET_PRIVATE_KEY")
54+
}
2855

2956
func main() {
3057
sponsorSetUpPolicyRules()
3158
cexDoGaslessWithdrawl()
3259
}
3360

3461
func sponsorSetUpPolicyRules() {
35-
sponsorClient, err := NewSponsorClient(sponsorAPIEndpoint)
62+
sponsorClient, err := sponsorclient.New(context.Background(), SponsorURL)
3663
if err != nil {
3764
log.Fatal(err)
3865
}
66+
3967
// sponsor the tx that interact with the stable coin ERC20 contract
40-
success, err := sponsorClient.AddToWhitelist(context.Background(), WhitelistParams{
41-
PolicyUUID: SponsorPolicyId,
42-
WhitelistType: ToAccountWhitelist,
43-
Values: []string{TokenContractAddress},
68+
success, err := sponsorClient.AddToWhitelist(context.Background(), sponsorclient.WhiteListArgs{
69+
PolicyUUID: PolicyUUID,
70+
WhitelistType: sponsorclient.ToAccountWhitelist,
71+
Values: []string{TokenContractAddress.String()},
4472
})
4573
if err != nil || !success {
4674
log.Fatal("failed to add token contract whitelist", err)
@@ -49,9 +77,9 @@ func sponsorSetUpPolicyRules() {
4977
// sponsor the tx that from hotwallets
5078
fromAddress := getAddressFromPrivateKey(HotwalletPrivateKey)
5179

52-
success, err = sponsorClient.AddToWhitelist(context.Background(), WhitelistParams{
53-
PolicyUUID: SponsorPolicyId,
54-
WhitelistType: FromAccountWhitelist,
80+
success, err = sponsorClient.AddToWhitelist(context.Background(), sponsorclient.WhiteListArgs{
81+
PolicyUUID: PolicyUUID,
82+
WhitelistType: sponsorclient.FromAccountWhitelist,
5583
Values: []string{fromAddress.String()},
5684
})
5785
if err != nil || !success {
@@ -61,8 +89,14 @@ func sponsorSetUpPolicyRules() {
6189

6290
func cexDoGaslessWithdrawl() {
6391
withdrawAmount := big.NewInt(1e17)
92+
// Connect to an Ethereum node (for transaction assembly)
93+
client, err := ethclient.Dial(ChainURL)
94+
if err != nil {
95+
log.Fatalf("Failed to connect to the Ethereum network: %v", err)
96+
}
97+
6498
// Create a PaymasterClient (for transaction sending)
65-
paymasterClient, err := NewPaymasterClient(paymasterEndpoint)
99+
paymasterClient, err := paymasterclient.New(context.Background(), PaymasterURL)
66100
if err != nil {
67101
log.Fatalf("Failed to create PaymasterClient: %v", err)
68102
}
@@ -75,28 +109,24 @@ func cexDoGaslessWithdrawl() {
75109

76110
fromAddress := getAddressFromPrivateKey(HotwalletPrivateKey)
77111

78-
// Token contract address
79-
tokenAddress := common.HexToAddress(TokenContractAddress)
80-
81112
// Create ERC20 transfer data
82-
data, err := createERC20TransferData(common.HexToAddress(WithdrawRecipientAddress), withdrawAmount)
113+
data, err := createERC20TransferData(WithdrawRecipientAddress, withdrawAmount)
83114
if err != nil {
84115
log.Fatalf("Failed to create ERC20 transfer data: %v", err)
85116
}
86117

87-
// Get the pending nonce for the from address, strongly suggest to fetch nonce from paymaster endpoint when
88-
// submitting multiple transactions in rapid succession, to ensure that the nonce are sequential.
89-
nonce, err := paymasterClient.PendingNonceAt(context.Background(), fromAddress)
118+
// Get the latest nonce for the from address
119+
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
90120
if err != nil {
91121
log.Fatalf("Failed to get nonce: %v", err)
92122
}
93123

94124
// Create the transaction
95125
gasPrice := big.NewInt(0)
96-
tx := types.NewTransaction(nonce, tokenAddress, big.NewInt(0), 300000, gasPrice, data)
126+
tx := types.NewTransaction(nonce, TokenContractAddress, big.NewInt(0), 300000, gasPrice, data)
97127

98128
// Get the chain ID
99-
chainID, err := paymasterClient.ChainID(context.Background())
129+
chainID, err := client.ChainID(context.Background())
100130
if err != nil {
101131
log.Fatalf("Failed to get chain ID: %v", err)
102132
}
@@ -107,10 +137,15 @@ func cexDoGaslessWithdrawl() {
107137
log.Fatalf("Failed to sign transaction: %v", err)
108138
}
109139

140+
txInput, err := signedTx.MarshalBinary()
141+
if err != nil {
142+
log.Fatalf("Failed to marshal transaction: %v", err)
143+
}
144+
110145
// Convert to Transaction struct for IsSponsorable check
111146
gasLimit := tx.Gas()
112-
sponsorableTx := Transaction{
113-
To: &tokenAddress,
147+
sponsorableTx := paymasterclient.TransactionArgs{
148+
To: &TokenContractAddress,
114149
From: fromAddress,
115150
Value: (*hexutil.Big)(big.NewInt(0)),
116151
Gas: (*hexutil.Uint64)(&gasLimit),
@@ -128,7 +163,7 @@ func cexDoGaslessWithdrawl() {
128163

129164
if sponsorableInfo.Sponsorable {
130165
// Send the transaction using PaymasterClient
131-
err := paymasterClient.SendTransaction(context.Background(), signedTx)
166+
_, err := paymasterClient.SendRawTransaction(context.Background(), txInput)
132167
if err != nil {
133168
log.Fatalf("Failed to send sponsorable transaction: %v", err)
134169
}
@@ -152,3 +187,16 @@ func getAddressFromPrivateKey(pk string) common.Address {
152187
}
153188
return crypto.PubkeyToAddress(*publicKeyECDSA)
154189
}
190+
191+
func createERC20TransferData(to common.Address, amount *big.Int) ([]byte, error) {
192+
transferFnSignature := []byte("transfer(address,uint256)")
193+
methodID := crypto.Keccak256(transferFnSignature)[:4]
194+
paddedAddress := common.LeftPadBytes(to.Bytes(), 32)
195+
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
196+
197+
var data []byte
198+
data = append(data, methodID...)
199+
data = append(data, paddedAddress...)
200+
data = append(data, paddedAmount...)
201+
return data, nil
202+
}

cex/go-example/paymasterClient.go

Lines changed: 0 additions & 68 deletions
This file was deleted.

cex/go-example/readme.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
# GO Example
2+
23
This repository contains a Go application demonstrating:
4+
35
1. Sponsor manage the policy to sponsor any transaction sent by Cex hotwallets.
46
2. Cex do token withdrawal without pay gas fee through paymaster.
57

68
## Quick Start
79

8-
If the example is performed on BSC testnet, please ensure you have some test ERC20 on BSC testnet. (You can get some
9-
from the official faucet)
10+
The example is performed on BSC testnet or BSC mainnet, please ensure you have some test ERC20 on them. (You can get
11+
some from the official faucet when using testnet)
1012

1113
1. Install dependencies
1214
```shell
1315
$ go mod tidy
1416
```
15-
2. Configure the file
16-
Before running the application, you need to edit the `main.go` to set up the following:
17-
18-
- Set "TokenContractAddress" to the ERC20 token contract address that users want to withdraw.
19-
- Set "WithdrawRecipientAddress" to the receiver address of user's withdrawal request.
20-
- Set "SponsorPolicyId" to the policy ID created by the sponsor on MegaFuel Paymaster, create one
21-
from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it.
22-
- Set "SponsorAPIEndpoint" to the API key created by the sponsor in the Nodereal dashboard.
23-
create one from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it.
24-
- Set "HotwalletPrivateKey" to the Cex's hotwallet private key, ensuring this wallet contains the required ERC20 tokens.
17+
2. Configure the .env file
18+
Before running the application, you need to edit the `.env` to set up the following:
19+
20+
- 'PAYMASTER_URL' with the Paymaster URL.
21+
- 'CHAIN_URL' with the BSC testnet or BSC mainnet chain URL.
22+
- 'SPONSOR_URL' to the API key created by the sponsor in the Nodereal dashboard. create one
23+
from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it.
24+
- 'POLICY_UUID' to the policy ID created by the sponsor on Megafuel Paymaster, create one
25+
from [here](https://docs.nodereal.io/docs/megafuel-sponsor-guidelines) if you don't have it.
26+
- 'TOKEN_CONTRACT_ADDRESS' to the ERC20 token contract address that users want to withdraw.
27+
- 'WITHDRAW_RECIPIENT_ADDRESS' to the receiver address of user's withdrawal request.
28+
- 'HOTWALLET_PRIVATE_KEY' to the Cex's hotwallet private key, ensuring this wallet contains the required ERC20
29+
tokens.
2530

2631
3. Run the example
2732
```

0 commit comments

Comments
 (0)