Skip to content

Commit

Permalink
feat: client sdk for eoa-paymaster (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
reneecok authored Sep 5, 2024
1 parent 3d2d826 commit 5ae45fc
Show file tree
Hide file tree
Showing 21 changed files with 10,165 additions and 1 deletion.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# http://editorconfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = 0
trim_trailing_whitespace = true
34 changes: 34 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
env: {
browser: true,
node: true,
},
rules: {
'semi': ['error', 'never'],
'@typescript-eslint/semi': ['error', 'never'],
'quotes': ['error', 'single'],
'eol-last': ['error', 'always'],
'comma-dangle': ['error', 'always-multiline'],
'@typescript-eslint/no-explicit-any': [0],
'@typescript-eslint/member-delimiter-style': ['error', {
'multiline': {
'delimiter': 'none',
'requireLast': true
},
'singleline': {
'delimiter': 'comma',
'requireLast': false
},
'multilineDetection': 'brackets'
}],
},
};
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/node_modules/
/build/
/lib/
/docs/
.idea/*

.DS_Store
coverage
*.log
/examples/
20 changes: 20 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/.github/
/.vscode/
/node_modules/
/build/
/tmp/
.idea/*
/docs/
/.idea/
/examples/

coverage
*.log
.gitlab-ci.yml

package-lock.json
yarn-lock.json
/*.tgz
/tmp*
/mnt/
/package/
104 changes: 103 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,103 @@
# megafuel-js-sdk
# megafuel-js-sdk

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).

## Network Endpoint

| Network | [Paymaster]( https://docs.nodereal.io/reference/pm-issponsorable) | [Sponsor](https://docs.nodereal.io/reference/pm-addtowhitelist) |
|:-------------:|:-------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------:|
| BSC mainnet | https://bsc-megafuel.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel |
| BSC testnet | https://bsc-megafuel-testnet.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel-testnet |
| opBNB mainnet | https://opbnb-megafuel.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel |
| opBNB testnet | https://opbnb-megafuel-testnet.nodereal.io | https://open-platform.nodereal.io/{YOUR_API_KEY}/megafuel-testnet |

## Quick Start
1. Install dependency

```shell
$ npm install megafuel-js-sdk
```

2. Example
```js
import 'dotenv/config';
import {ethers} from "ethers";
import { PaymasterClient } from 'megafuel-js-sdk';

const PAYMASTER_URL="https://bsc-megafuel-testnet.nodereal.io"
const CHAIN_URL="https://data-seed-prebsc-2-s1.binance.org:8545/"
const SPONSOR_URL="https://open-platform.nodereal.io/<api-key>/megafuel-testnet"
const CHAIN_ID="97"

const POLICY_UUID="a2381160-xxxx-xxxx-xxxxceca86556834"
const TOKEN_CONTRACT_ADDRESS="0xeD2.....12Ee"
const RECIPIENT_ADDRESS="0x8e9......3EA2"
const YOUR_PRIVATE_KEY="69......929"

const client = new SponsorClient(SPONSOR_URL, null, { staticNetwork: ethers.Network.from(Number(CHAIN_ID)) });

try {
// sponsor the tx that interact with the stable coin ERC20 contract
const res1 = await client.addToWhitelist({
PolicyUUID: POLICY_UUID,
WhitelistType: WhitelistType.ToAccountWhitelist,
Values: [RECIPIENT_ADDRESS]
});
console.log("Added ERC20 contract address to whitelist ", res1);
} catch (error){
console.error("Error:", error)
}

// Provider for assembling the transaction (e.g., mainnet)
const assemblyProvider = new ethers.JsonRpcProvider(CHAIN_URL);

// Provider for sending the transaction (e.g., could be a different network or provider)
const paymasterProvider = new PaymasterClient(PAYMASTER_URL);

const wallet = new ethers.Wallet(YOUR_PRIVATE_KEY, assemblyProvider);
// ERC20 token ABI (only including the transfer function)
const tokenAbi = [
"function transfer(address,uint256) returns (bool)"
];

// Create contract instance
const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet);

// Transaction details
const tokenAmount = ethers.parseUnits('1.0', 18); // Amount of tokens to send (adjust decimals as needed)

try {
// Get the current nonce for the sender's address
const nonce = await assemblyProvider.getTransactionCount(wallet.address);

// Create the transaction object
const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS, tokenAmount);

// 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 = 97;
transaction.gasPrice = 0; // Set gas price to 0

try {
const sponsorableInfo = await paymasterProvider.isSponsorable(transaction);
console.log('Sponsorable Information:', sponsorableInfo);
} catch (error) {
console.error('Error checking sponsorable status:', error);
}

// Sign the transaction
const signedTx = await wallet.signTransaction(transaction);

// Send the raw transaction using the sending provider
const tx = await paymasterProvider.sendRawTransaction(signedTx);
console.log('Transaction sent:', tx);

} catch (error) {
console.error('Error sending transaction:', error);
}
```

More examples can be found in the [examples](https://github.com/node-real/megafuel-client-example).

2 changes: 2 additions & 0 deletions dist/tsc/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './paymasterclient';
export * from './sponsorclient';
6 changes: 6 additions & 0 deletions dist/tsc/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/tsc/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions dist/tsc/paymasterclient.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish, TransactionRequest } from 'ethers';
import type { AddressLike } from 'ethers/src.ts/address';
import type { BigNumberish } from 'ethers/src.ts/utils';
export type IsSponsorableResponse = {
Sponsorable: boolean;
SponsorName: string;
SponsorIcon: string;
SponsorWebsite: string;
};
export declare enum GaslessTransactionStatus {
New = 0,
Pending = 1,
Confirmed = 2,
Failed = 3,
Invalid = 4
}
export type GaslessTransaction = {
readonly TxHash: string;
readonly BundleUUID: string;
readonly FromAddress?: AddressLike;
readonly ToAddress?: AddressLike;
readonly Nonce: number;
readonly RawData: string;
readonly Status: GaslessTransactionStatus;
readonly GasUsed: bigint;
readonly GasFee?: BigNumberish;
readonly PolicyUUID: bigint;
readonly Source: string;
readonly BornBlockNumber: bigint;
readonly ChainID: number;
};
export type SponsorTx = {
readonly TxHash: string;
readonly Address: AddressLike;
readonly BundleUUID: string;
readonly Status: GaslessTransactionStatus;
readonly GasPrice?: BigNumberish;
readonly GasFee?: BigNumberish;
readonly BornBlockNumber: bigint;
readonly ChainID: number;
};
export type Bundle = {
readonly BundleUUID: string;
readonly Status: GaslessTransactionStatus;
readonly AvgGasPrice?: BigNumberish;
readonly BornBlockNumber: bigint;
readonly ConfirmedBlockNumber: bigint;
readonly ConfirmedDate: bigint;
readonly ChainID: number;
};
export declare class PaymasterClient extends ethers.JsonRpcProvider {
constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions);
chainID(): Promise<string>;
isSponsorable(tx: TransactionRequest): Promise<IsSponsorableResponse>;
sendRawTransaction(signedTx: string): Promise<string>;
getGaslessTransactionByHash(hash: string): Promise<GaslessTransaction>;
getSponsorTxByTxHash(hash: string): Promise<SponsorTx>;
getSponsorTxByBundleUuid(bundleUuid: string): Promise<SponsorTx>;
getBundleByUuid(bundleUuid: string): Promise<Bundle>;
}
55 changes: 55 additions & 0 deletions dist/tsc/paymasterclient.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/tsc/paymasterclient.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions dist/tsc/sponsorclient.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish } from 'ethers';
import type { AddressLike } from 'ethers/src.ts/address';
import type { BigNumberish } from 'ethers/src.ts/utils';
export declare enum WhitelistType {
FromAccountWhitelist = "FromAccountWhitelist",
ToAccountWhitelist = "ToAccountWhitelist",
ContractMethodSigWhitelist = "ContractMethodSigWhitelist",
BEP20ReceiverWhiteList = "BEP20ReceiverWhiteList"
}
export type WhitelistArgs = {
PolicyUUID: string;
WhitelistType: WhitelistType;
Values: string[];
};
export type EmptyWhitelistArgs = {
PolicyUUID: string;
WhitelistType: WhitelistType;
};
export type GetWhitelistArgs = {
PolicyUUID: string;
WhitelistType: WhitelistType;
Offset: number;
Limit: number;
};
export type UserSpendData = {
UserAddress: AddressLike;
GasCost?: BigNumberish;
GasCostCurDay?: BigNumberish;
TxCountCurDay: bigint;
UpdateAt: bigint;
ChainID: number;
};
export type PolicySpendData = {
Cost?: BigNumberish;
UpdateAt: bigint;
ChainID: number;
};
export declare class SponsorClient extends ethers.JsonRpcProvider {
constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions);
addToWhitelist(params: WhitelistArgs): Promise<boolean>;
removeFromWhitelist(params: WhitelistArgs): Promise<boolean>;
emptyWhitelist(params: EmptyWhitelistArgs): Promise<boolean>;
getWhitelist(params: GetWhitelistArgs): Promise<string[]>;
getUserSpendData(fromAddress: AddressLike, policyUUID: string): Promise<UserSpendData>;
getPolicySpendData(policyUUID: string): Promise<PolicySpendData>;
}
Loading

0 comments on commit 5ae45fc

Please sign in to comment.