Skip to content

Commit 5ae45fc

Browse files
authored
feat: client sdk for eoa-paymaster (#1)
1 parent 3d2d826 commit 5ae45fc

21 files changed

+10165
-1
lines changed

.editorconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
end_of_line = lf
7+
indent_size = 2
8+
indent_style = space
9+
insert_final_newline = true
10+
trim_trailing_whitespace = true
11+
12+
[*.md]
13+
max_line_length = 0
14+
trim_trailing_whitespace = true

.eslintrc.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module.exports = {
2+
root: true,
3+
parser: '@typescript-eslint/parser',
4+
plugins: [
5+
'@typescript-eslint',
6+
],
7+
extends: [
8+
'eslint:recommended',
9+
'plugin:@typescript-eslint/recommended',
10+
],
11+
env: {
12+
browser: true,
13+
node: true,
14+
},
15+
rules: {
16+
'semi': ['error', 'never'],
17+
'@typescript-eslint/semi': ['error', 'never'],
18+
'quotes': ['error', 'single'],
19+
'eol-last': ['error', 'always'],
20+
'comma-dangle': ['error', 'always-multiline'],
21+
'@typescript-eslint/no-explicit-any': [0],
22+
'@typescript-eslint/member-delimiter-style': ['error', {
23+
'multiline': {
24+
'delimiter': 'none',
25+
'requireLast': true
26+
},
27+
'singleline': {
28+
'delimiter': 'comma',
29+
'requireLast': false
30+
},
31+
'multilineDetection': 'brackets'
32+
}],
33+
},
34+
};

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/node_modules/
2+
/build/
3+
/lib/
4+
/docs/
5+
.idea/*
6+
7+
.DS_Store
8+
coverage
9+
*.log
10+
/examples/

.npmignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/.github/
2+
/.vscode/
3+
/node_modules/
4+
/build/
5+
/tmp/
6+
.idea/*
7+
/docs/
8+
/.idea/
9+
/examples/
10+
11+
coverage
12+
*.log
13+
.gitlab-ci.yml
14+
15+
package-lock.json
16+
yarn-lock.json
17+
/*.tgz
18+
/tmp*
19+
/mnt/
20+
/package/

README.md

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,103 @@
1-
# megafuel-js-sdk
1+
# megafuel-js-sdk
2+
3+
This JavaScript SDK is thin wrapper of MegaFuel clients, offering a streamlined interface to interact with the MegaFuel. For more information, please refer to the [API documentation](https://docs.nodereal.io/docs/megafuel-api).
4+
5+
## Network Endpoint
6+
7+
| Network | [Paymaster]( https://docs.nodereal.io/reference/pm-issponsorable) | [Sponsor](https://docs.nodereal.io/reference/pm-addtowhitelist) |
8+
|:-------------:|:-------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------:|
9+
| BSC mainnet | https://bsc-megafuel.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel |
10+
| BSC testnet | https://bsc-megafuel-testnet.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel-testnet |
11+
| opBNB mainnet | https://opbnb-megafuel.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel |
12+
| opBNB testnet | https://opbnb-megafuel-testnet.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel-testnet |
13+
14+
## Quick Start
15+
1. Install dependency
16+
17+
```shell
18+
$ npm install megafuel-js-sdk
19+
```
20+
21+
2. Example
22+
```js
23+
import 'dotenv/config';
24+
import {ethers} from "ethers";
25+
import { PaymasterClient } from 'megafuel-js-sdk';
26+
27+
const PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io"
28+
const CHAIN_URL="https://data-seed-prebsc-2-s1.binance.org:8545/"
29+
const SPONSOR_URL="https://open-platform.nodereal.io/<api-key>/megafuel-testnet"
30+
const CHAIN_ID="97"
31+
32+
const POLICY_UUID="a2381160-xxxx-xxxx-xxxxceca86556834"
33+
const TOKEN_CONTRACT_ADDRESS="0xeD2.....12Ee"
34+
const RECIPIENT_ADDRESS="0x8e9......3EA2"
35+
const YOUR_PRIVATE_KEY="69......929"
36+
37+
const client = new SponsorClient(SPONSOR_URL, null, { staticNetwork: ethers.Network.from(Number(CHAIN_ID)) });
38+
39+
try {
40+
// sponsor the tx that interact with the stable coin ERC20 contract
41+
const res1 = await client.addToWhitelist({
42+
PolicyUUID: POLICY_UUID,
43+
WhitelistType: WhitelistType.ToAccountWhitelist,
44+
Values: [RECIPIENT_ADDRESS]
45+
});
46+
console.log("Added ERC20 contract address to whitelist ", res1);
47+
} catch (error){
48+
console.error("Error:", error)
49+
}
50+
51+
// Provider for assembling the transaction (e.g., mainnet)
52+
const assemblyProvider = new ethers.JsonRpcProvider(CHAIN_URL);
53+
54+
// Provider for sending the transaction (e.g., could be a different network or provider)
55+
const paymasterProvider = new PaymasterClient(PAYMASTER_URL);
56+
57+
const wallet = new ethers.Wallet(YOUR_PRIVATE_KEY, assemblyProvider);
58+
// ERC20 token ABI (only including the transfer function)
59+
const tokenAbi = [
60+
"function transfer(address,uint256) returns (bool)"
61+
];
62+
63+
// Create contract instance
64+
const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet);
65+
66+
// Transaction details
67+
const tokenAmount = ethers.parseUnits('1.0', 18); // Amount of tokens to send (adjust decimals as needed)
68+
69+
try {
70+
// Get the current nonce for the sender's address
71+
const nonce = await assemblyProvider.getTransactionCount(wallet.address);
72+
73+
// Create the transaction object
74+
const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS, tokenAmount);
75+
76+
// Add nonce and gas settings
77+
transaction.from = wallet.address;
78+
transaction.nonce = nonce;
79+
transaction.gasLimit = 100000; // Adjust gas limit as needed for token transfers
80+
transaction.chainId = 97;
81+
transaction.gasPrice = 0; // Set gas price to 0
82+
83+
try {
84+
const sponsorableInfo = await paymasterProvider.isSponsorable(transaction);
85+
console.log('Sponsorable Information:', sponsorableInfo);
86+
} catch (error) {
87+
console.error('Error checking sponsorable status:', error);
88+
}
89+
90+
// Sign the transaction
91+
const signedTx = await wallet.signTransaction(transaction);
92+
93+
// Send the raw transaction using the sending provider
94+
const tx = await paymasterProvider.sendRawTransaction(signedTx);
95+
console.log('Transaction sent:', tx);
96+
97+
} catch (error) {
98+
console.error('Error sending transaction:', error);
99+
}
100+
```
101+
102+
More examples can be found in the [examples](https://github.com/node-real/megafuel-client-example).
103+

dist/tsc/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './paymasterclient';
2+
export * from './sponsorclient';

dist/tsc/index.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/tsc/index.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/tsc/paymasterclient.d.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish, TransactionRequest } from 'ethers';
2+
import type { AddressLike } from 'ethers/src.ts/address';
3+
import type { BigNumberish } from 'ethers/src.ts/utils';
4+
export type IsSponsorableResponse = {
5+
Sponsorable: boolean;
6+
SponsorName: string;
7+
SponsorIcon: string;
8+
SponsorWebsite: string;
9+
};
10+
export declare enum GaslessTransactionStatus {
11+
New = 0,
12+
Pending = 1,
13+
Confirmed = 2,
14+
Failed = 3,
15+
Invalid = 4
16+
}
17+
export type GaslessTransaction = {
18+
readonly TxHash: string;
19+
readonly BundleUUID: string;
20+
readonly FromAddress?: AddressLike;
21+
readonly ToAddress?: AddressLike;
22+
readonly Nonce: number;
23+
readonly RawData: string;
24+
readonly Status: GaslessTransactionStatus;
25+
readonly GasUsed: bigint;
26+
readonly GasFee?: BigNumberish;
27+
readonly PolicyUUID: bigint;
28+
readonly Source: string;
29+
readonly BornBlockNumber: bigint;
30+
readonly ChainID: number;
31+
};
32+
export type SponsorTx = {
33+
readonly TxHash: string;
34+
readonly Address: AddressLike;
35+
readonly BundleUUID: string;
36+
readonly Status: GaslessTransactionStatus;
37+
readonly GasPrice?: BigNumberish;
38+
readonly GasFee?: BigNumberish;
39+
readonly BornBlockNumber: bigint;
40+
readonly ChainID: number;
41+
};
42+
export type Bundle = {
43+
readonly BundleUUID: string;
44+
readonly Status: GaslessTransactionStatus;
45+
readonly AvgGasPrice?: BigNumberish;
46+
readonly BornBlockNumber: bigint;
47+
readonly ConfirmedBlockNumber: bigint;
48+
readonly ConfirmedDate: bigint;
49+
readonly ChainID: number;
50+
};
51+
export declare class PaymasterClient extends ethers.JsonRpcProvider {
52+
constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions);
53+
chainID(): Promise<string>;
54+
isSponsorable(tx: TransactionRequest): Promise<IsSponsorableResponse>;
55+
sendRawTransaction(signedTx: string): Promise<string>;
56+
getGaslessTransactionByHash(hash: string): Promise<GaslessTransaction>;
57+
getSponsorTxByTxHash(hash: string): Promise<SponsorTx>;
58+
getSponsorTxByBundleUuid(bundleUuid: string): Promise<SponsorTx>;
59+
getBundleByUuid(bundleUuid: string): Promise<Bundle>;
60+
}

dist/tsc/paymasterclient.js

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)