Skip to content

Commit 9644bc5

Browse files
committed
feat: add github test workflow
1 parent a43e94f commit 9644bc5

File tree

10 files changed

+440
-13
lines changed

10 files changed

+440
-13
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: 'CI setup'
2+
description: NPM install deps
3+
runs:
4+
using: composite
5+
steps:
6+
- uses: actions/setup-node@v4
7+
with:
8+
node-version: '18.20.2'
9+
10+
- name: Install dependencies
11+
shell: bash
12+
run: npm install

.github/workflows/test.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Test Case
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
jobs:
7+
8+
run-tests:
9+
runs-on: ubuntu-latest
10+
11+
env:
12+
ACCOUNT_ADDRESS: ${{ secrets.ACCOUNT_ADDRESS }}
13+
ACCOUNT_PRIVATEKEY: ${{ secrets.ACCOUNT_PRIVATEKEY }}
14+
OPEN_PLATFORM_PRIVATE_KEY: ${{ secrets.OPEN_PLATFORM_PRIVATE_KEY }}
15+
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
16+
17+
steps:
18+
- uses: actions/checkout@v3
19+
with:
20+
persist-credentials: false
21+
22+
- uses: ./.github/actions/ci-setup
23+
24+
# - name: Build
25+
# run: npm run build
26+
27+
- name: Run Test
28+
run: npm run test

jest.config.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1+
const { pathsToModuleNameMapper } = require('ts-jest');
2+
3+
// Assuming you have some TypeScript path aliases defined in your tsconfig.json
4+
const { compilerOptions } = require('./tsconfig');
5+
/** @type {import('ts-jest').JestConfigWithTsJest} */
16
module.exports = {
2-
roots: ['<rootDir>/src'],
3-
testMatch: [
4-
"**/__tests__/**/*.+(ts|tsx|js)",
5-
"**/?(*.)+(spec|test).+(ts|tsx|js)"
6-
],
7+
preset: 'ts-jest',
8+
testEnvironment: 'node',
9+
modulePathIgnorePatterns: ['<rootDir>/src/config.spec.ts'],
10+
moduleNameMapper: {
11+
...pathsToModuleNameMapper({ '@/*': ['./src/*'] }, { prefix: '<rootDir>/' }),
12+
'^(\\.{1,2}/.*)\\.js$': '$1',
13+
},
14+
// transformIgnorePatterns: ['node_modules/(?!(@bnb-chain/greenfield-cosmos-types)/)'],
15+
extensionsToTreatAsEsm: ['.ts'],
716
transform: {
8-
"^.+\\.(ts|tsx)$": "ts-jest"
17+
'^.+\\.ts?$': [
18+
'ts-jest',
19+
{
20+
// tsconfig: './config/tsconfig-cjs.json',
21+
useESM: true,
22+
},
23+
],
924
},
10-
moduleDirectories: ['node_modules', 'src'],
11-
testTimeout: 30000,
12-
}
25+
setupFilesAfterEnv: ['<rootDir>/tests/env.ts', '<rootDir>/tests/utils.ts']
26+
};

package-lock.json

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"devDependencies": {
2525
"@types/jest": "^29.2.4",
2626
"@types/node": "^18.11.10",
27+
"@types/ws": "^8.5.12",
2728
"@typescript-eslint/eslint-plugin": "^5.45.0",
2829
"@typescript-eslint/parser": "^5.45.0",
2930
"esbuild": "^0.15.18",
@@ -35,6 +36,7 @@
3536
"typescript": "^4.9.3"
3637
},
3738
"dependencies": {
38-
"ethers": "^6.3.0"
39+
"dotenv": "^16.4.5",
40+
"ethers": "^6.13.2"
3941
}
4042
}

tests/env.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import dotenv from 'dotenv'
2+
3+
dotenv.config({
4+
path: process.cwd() + '/tests/.env',
5+
})
6+
7+
// testnet env
8+
export const OPEN_PLATFORM_PRIVATE_KEY = process.env.OPEN_PLATFORM_PRIVATE_KEY
9+
export const SPONSOR_URL = `https://open-platform.nodereal.io/${OPEN_PLATFORM_PRIVATE_KEY}/megafuel-testnet`
10+
export const CHAIN_ID = '97'
11+
export const CHAIN_URL = `https://bsc-testnet.nodereal.io/v1/${OPEN_PLATFORM_PRIVATE_KEY}`
12+
export const PAYMASTER_URL = 'https://bsc-megafuel-testnet.nodereal.io/97'
13+
export const PRIVATE_KEY = process.env.PRIVATE_KEY as string
14+
export const POLICY_UUID = '72191372-5550-4cf6-956e-b70d1e4786cf'
15+
export const ACCOUNT_ADDRESS = '0xF9A8db17431DD8563747D6FC770297E438Aa12eB'
16+
export const CONTRACT_METHOD = '0xa9059cbb'
17+
export const TOKEN_CONTRACT_ADDRESS = '0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee'
18+
export const RECIPIENT_ADDRESS = '0xDE08B1Fd79b7016F8DD3Df11f7fa0FbfdF07c941'

tests/paymaster.spec.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import {describe, expect, test} from '@jest/globals'
2+
import {
3+
paymasterProvider,
4+
wallet,
5+
tokenAbi,
6+
transformIsSponsorableResponse,
7+
transformToGaslessTransaction,
8+
delay, transformSponsorTxResponse,
9+
} from './utils'
10+
import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS} from './env'
11+
import {ethers} from 'ethers'
12+
13+
14+
let TX_HASH = ''
15+
16+
/**
17+
* test paymaster apis
18+
*/
19+
20+
describe('paymasterQuery', () => {
21+
22+
describe('chainID', () => {
23+
test('it works', async () => {
24+
const res = await paymasterProvider.chainID()
25+
expect(res).toEqual('0x61')
26+
})
27+
})
28+
29+
describe('isSponsorable', () => {
30+
test('it works', async () => {
31+
// Create contract instance
32+
const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet)
33+
34+
// Transaction details
35+
const tokenAmount = ethers.parseUnits('1.0', 18) // Amount of tokens to send (adjust decimals as needed)
36+
// Get the current nonce for the sender's address
37+
const nonce = await paymasterProvider.getTransactionCount(wallet.address, 'pending')
38+
39+
40+
// Create the transaction object
41+
const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount)
42+
43+
// Add nonce and gas settings
44+
transaction.from = wallet.address
45+
console.log('wallet.address:', transaction.from)
46+
transaction.nonce = nonce
47+
transaction.gasLimit = BigInt(100000) // Adjust gas limit as needed for token transfers
48+
transaction.chainId = BigInt(CHAIN_ID)
49+
transaction.gasPrice = BigInt(0) // Set gas price to 0
50+
51+
const safeTransaction = {
52+
...transaction,
53+
gasLimit: transaction.gasLimit.toString(),
54+
chainId: transaction.chainId.toString(),
55+
gasPrice: transaction.gasPrice.toString(),
56+
}
57+
console.log(safeTransaction)
58+
const resRaw = await paymasterProvider.isSponsorable(safeTransaction)
59+
const res = transformIsSponsorableResponse(resRaw)
60+
console.log(res)
61+
expect(res.Sponsorable).toEqual(true)
62+
63+
const signedTx = await wallet.signTransaction(safeTransaction)
64+
try {
65+
const tx = await paymasterProvider.sendRawTransaction(signedTx)
66+
TX_HASH = tx
67+
console.log('Transaction sent:', tx)
68+
console.log('TX_HASH:', TX_HASH)
69+
} catch (error) {
70+
console.error('Error sending transaction:', error)
71+
}
72+
}, 100000)
73+
})
74+
75+
describe('getGaslessTransactionByHash', () => {
76+
test('it works', async () => {
77+
console.log('Waiting for the transaction to be confirmed and queryable on the blockchain.')
78+
await delay(8000)
79+
console.log('getGaslessTransactionByHash TX_HASH:', TX_HASH)
80+
const resRaw = await paymasterProvider.getGaslessTransactionByHash(TX_HASH)
81+
const res = transformToGaslessTransaction(resRaw)
82+
console.log(res)
83+
expect(res.ToAddress).toEqual(TOKEN_CONTRACT_ADDRESS.toLowerCase())
84+
85+
console.log('getSponsorTxByBundleUuid res.BundleUUID:', res.BundleUUID)
86+
const txRaw = await paymasterProvider.getSponsorTxByBundleUuid(res.BundleUUID)
87+
const tx = transformSponsorTxResponse(txRaw)
88+
expect(resRaw).not.toBeNull()
89+
console.log(tx)
90+
91+
const bundle = await paymasterProvider.getBundleByUuid(res.BundleUUID)
92+
expect(bundle).not.toBeNull()
93+
console.log(bundle)
94+
95+
const sponsorTx = await paymasterProvider.getSponsorTxByTxHash(tx.TxHash)
96+
console.log('sponsorTx: ', sponsorTx)
97+
expect(sponsorTx).not.toBeNull()
98+
}, 13000)
99+
})
100+
})

0 commit comments

Comments
 (0)