From a78b57f4279a6bf1173aca7b884bd7863d7b5fef Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Tue, 15 Oct 2024 11:02:32 +0800 Subject: [PATCH 1/6] feat: support private policy --- src/paymasterclient.ts | 57 ++++++++++++++++++++++++++++++++--------- tests/env.ts | 1 + tests/paymaster.spec.ts | 54 ++++++++++++++++++++++++++++++++++++-- tests/utils.ts | 2 +- 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index fc58ad8..854e5a5 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -9,6 +9,14 @@ export type IsSponsorableResponse = { SponsorWebsite: string } +export type IsSponsorableOptions = { + PrivatePolicyUUID?: string +} + +export type SendRawTransactionOptions = { + PrivatePolicyUUID?: string +} + export enum GaslessTransactionStatus { New = 0, Pending = 1, Confirmed = 2, Failed = 3, Invalid = 4} export type GaslessTransaction = { @@ -48,36 +56,61 @@ export type Bundle = { readonly ChainID: number } -export class PaymasterClient extends ethers.JsonRpcProvider { - constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) { - super(url, network, options) +export class PaymasterClient { + private sponsorClient: ethers.JsonRpcProvider + private userClient: ethers.JsonRpcProvider + + constructor( + userUrl: string | FetchRequest, + sponsorUrl: string | FetchRequest, + network?: Networkish, + options?: JsonRpcApiProviderOptions + ) { + this.userClient = new ethers.JsonRpcProvider(userUrl, network, options) + this.sponsorClient = new ethers.JsonRpcProvider(sponsorUrl, network, options) } async chainID(): Promise { - return await this.send('eth_chainId', []) + return await this.userClient.send('eth_chainId', []) } - async isSponsorable(tx: TransactionRequest): Promise { - return await this.send('pm_isSponsorable', [tx]) + async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {} ): Promise { + if (opts.PrivatePolicyUUID) { + this.sponsorClient._getConnection().setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID) + return await this.sponsorClient.send('pm_isSponsorable', [tx]) + } + return await this.userClient.send('pm_isSponsorable', [tx]) } - async sendRawTransaction(signedTx: string): Promise { - return await this.send('eth_sendRawTransaction', [signedTx]) + async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions= {}): Promise { + if (opts.PrivatePolicyUUID) { + this.sponsorClient._getConnection().setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID) + return await this.sponsorClient.send('eth_sendRawTransaction', [signedTx]) + } + return await this.userClient.send('eth_sendRawTransaction', [signedTx]) } async getGaslessTransactionByHash(hash: string): Promise { - return await this.send('eth_getGaslessTransactionByHash', [hash]) + return await this.userClient.send('eth_getGaslessTransactionByHash', [hash]) } async getSponsorTxByTxHash(hash: string): Promise { - return await this.send('pm_getSponsorTxByTxHash', [hash]) + return await this.userClient.send('pm_getSponsorTxByTxHash', [hash]) } async getSponsorTxByBundleUuid(bundleUuid: string): Promise { - return await this.send('pm_getSponsorTxByBundleUuid', [bundleUuid]) + return await this.userClient.send('pm_getSponsorTxByBundleUuid', [bundleUuid]) } async getBundleByUuid(bundleUuid: string): Promise { - return await this.send('pm_getBundleByUuid', [bundleUuid]) + return await this.userClient.send('pm_getBundleByUuid', [bundleUuid]) + } + + getSponsorProvider(): ethers.JsonRpcProvider { + return this.sponsorClient + } + + getUserProvider(): ethers.JsonRpcProvider { + return this.userClient } } diff --git a/tests/env.ts b/tests/env.ts index 4b63a3f..acb3036 100644 --- a/tests/env.ts +++ b/tests/env.ts @@ -16,3 +16,4 @@ export const ACCOUNT_ADDRESS = '0xF9A8db17431DD8563747D6FC770297E438Aa12eB' export const CONTRACT_METHOD = '0xa9059cbb' export const TOKEN_CONTRACT_ADDRESS = '0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee' export const RECIPIENT_ADDRESS = '0xDE08B1Fd79b7016F8DD3Df11f7fa0FbfdF07c941' +export const PRIVATE_POLICY_UUID = "90f1ba4c-1f93-4759-b8a9-da4d59c668b4" diff --git a/tests/paymaster.spec.ts b/tests/paymaster.spec.ts index d1eed25..d32f7b5 100644 --- a/tests/paymaster.spec.ts +++ b/tests/paymaster.spec.ts @@ -7,7 +7,8 @@ import { transformToGaslessTransaction, delay, transformSponsorTxResponse, transformBundleResponse, } from './utils' -import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS} from './env' +import {IsSponsorableOptions, SendRawTransactionOptions} from '../src/paymasterclient' +import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS, PRIVATE_POLICY_UUID} from './env' import {ethers} from 'ethers' let TX_HASH = '' @@ -34,7 +35,7 @@ describe('paymasterQuery', () => { test('should successfully determine if transaction is sponsorable', async () => { const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) const tokenAmount = ethers.parseUnits('0', 18) - const nonce = await paymasterClient.getTransactionCount(wallet.address, 'pending') + const nonce = await paymasterClient.getUserProvider().getTransactionCount(wallet.address, 'pending') const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) transaction.from = wallet.address @@ -96,4 +97,53 @@ describe('paymasterQuery', () => { expect(sponsorTx.TxHash).toEqual(tx.TxHash) }, 13000) }) + + + /** + * Test for checking if a private policy transaction is sponsorable. + */ + describe('isSponsorable', () => { + test('should successfully determine if transaction is sponsorable', async () => { + const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) + const tokenAmount = ethers.parseUnits('0', 18) + const nonce = await paymasterClient.getUserProvider().getTransactionCount(wallet.address, 'pending') + + const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) + transaction.from = wallet.address + transaction.nonce = nonce + transaction.gasLimit = BigInt(100000) + transaction.chainId = BigInt(CHAIN_ID) + transaction.gasPrice = BigInt(0) + + const safeTransaction = { + ...transaction, + gasLimit: transaction.gasLimit.toString(), + chainId: transaction.chainId.toString(), + gasPrice: transaction.gasPrice.toString(), + } + + console.log('Prepared transaction:', safeTransaction) + + const opt: IsSponsorableOptions = { + PrivatePolicyUUID: PRIVATE_POLICY_UUID + }; + + const resRaw = await paymasterClient.isSponsorable(safeTransaction, opt) + const res = transformIsSponsorableResponse(resRaw) + expect(res.Sponsorable).toEqual(true) + + const txOpt: SendRawTransactionOptions = { + PrivatePolicyUUID: PRIVATE_POLICY_UUID + }; + + const signedTx = await wallet.signTransaction(safeTransaction) + try { + const tx = await paymasterClient.sendRawTransaction(signedTx,txOpt) + TX_HASH = tx + console.log('Transaction hash received:', TX_HASH) + } catch (error) { + console.error('Transaction failed:', error) + } + }, 100000) // Extends the default timeout as this test involves network calls + }) }) diff --git a/tests/utils.ts b/tests/utils.ts index b18e51b..050c1ca 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -16,7 +16,7 @@ export const sponsorClient = new SponsorClient(SPONSOR_URL, undefined, {staticNe export const assemblyProvider = new ethers.JsonRpcProvider(CHAIN_URL) // Provider for sending the transaction (e.g., could be a different network or provider) -export const paymasterClient = new PaymasterClient(PAYMASTER_URL) +export const paymasterClient = new PaymasterClient(PAYMASTER_URL,SPONSOR_URL+"/"+CHAIN_ID, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) export const wallet = new ethers.Wallet(PRIVATE_KEY, assemblyProvider) // ERC20 token ABI (only including the transfer function) From d922b2babace7ef6e05855d666450ce65113c28a Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Tue, 15 Oct 2024 17:36:39 +0800 Subject: [PATCH 2/6] feat: support user agent header --- src/paymasterclient.ts | 55 +++++++++++++++++++++++++++++++++++------ tests/paymaster.spec.ts | 3 ++- tests/sponsor.spec.ts | 4 +-- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index 854e5a5..dbd9813 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -15,6 +15,7 @@ export type IsSponsorableOptions = { export type SendRawTransactionOptions = { PrivatePolicyUUID?: string + UserAgent?: string } export enum GaslessTransactionStatus { New = 0, Pending = 1, Confirmed = 2, Failed = 3, Invalid = 4} @@ -74,20 +75,58 @@ export class PaymasterClient { return await this.userClient.send('eth_chainId', []) } - async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {} ): Promise { + async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {}): Promise { if (opts.PrivatePolicyUUID) { - this.sponsorClient._getConnection().setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID) - return await this.sponsorClient.send('pm_isSponsorable', [tx]) + // Create a new provider with the updated header + const newConnection = this.sponsorClient._getConnection(); + newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); + + // Create a new provider with the modified connection + const sponsorProviderWithHeader = new ethers.JsonRpcProvider( + newConnection, + (this.sponsorClient as any)._network, + { + staticNetwork: (this.sponsorClient as any)._network, + batchMaxCount: (this.sponsorClient as any).batchMaxCount, + polling: (this.sponsorClient as any).polling + } + ); + + return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]); } - return await this.userClient.send('pm_isSponsorable', [tx]) + return await this.userClient.send('pm_isSponsorable', [tx]); } - async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions= {}): Promise { + async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions = {}): Promise { + let sponsorProvider = this.sponsorClient; + + if (opts.UserAgent || opts.PrivatePolicyUUID) { + // Create a new provider with the updated headers + const newConnection = this.sponsorClient._getConnection(); + + if (opts.UserAgent) { + newConnection.setHeader("User-Agent", opts.UserAgent); + } + if (opts.PrivatePolicyUUID) { + newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); + } + + // Create a new provider with the modified connection + sponsorProvider = new ethers.JsonRpcProvider( + newConnection, + (this.sponsorClient as any)._network, + { + staticNetwork: (this.sponsorClient as any)._network, + batchMaxCount: (this.sponsorClient as any).batchMaxCount, + polling: (this.sponsorClient as any).polling + } + ); + } + if (opts.PrivatePolicyUUID) { - this.sponsorClient._getConnection().setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID) - return await this.sponsorClient.send('eth_sendRawTransaction', [signedTx]) + return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]); } - return await this.userClient.send('eth_sendRawTransaction', [signedTx]) + return await this.userClient.send('eth_sendRawTransaction', [signedTx]); } async getGaslessTransactionByHash(hash: string): Promise { diff --git a/tests/paymaster.spec.ts b/tests/paymaster.spec.ts index d32f7b5..5411a47 100644 --- a/tests/paymaster.spec.ts +++ b/tests/paymaster.spec.ts @@ -133,7 +133,8 @@ describe('paymasterQuery', () => { expect(res.Sponsorable).toEqual(true) const txOpt: SendRawTransactionOptions = { - PrivatePolicyUUID: PRIVATE_POLICY_UUID + PrivatePolicyUUID: PRIVATE_POLICY_UUID, + UserAgent: "TEST USER AGENT" }; const signedTx = await wallet.signTransaction(safeTransaction) diff --git a/tests/sponsor.spec.ts b/tests/sponsor.spec.ts index 33dfcba..5050a44 100644 --- a/tests/sponsor.spec.ts +++ b/tests/sponsor.spec.ts @@ -158,10 +158,10 @@ describe('sponsorQuery', () => { * Tests retrieving user spend data. */ describe('getUserSpendData', () => { - test('should return null for spend data when user has none', async () => { + test('should return not null for user spend data', async () => { const res = await sponsorClient.getUserSpendData(ACCOUNT_ADDRESS, POLICY_UUID) - expect(res).toBeNull() + expect(res).not.toBeNull() console.log('User spend data:', res) }) }) From b4f557d00635e1b94a7812e57c76c40701325bc9 Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Wed, 16 Oct 2024 10:26:24 +0800 Subject: [PATCH 3/6] fix: make sponsor url as optional --- src/paymasterclient.ts | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index dbd9813..f3d05e1 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -58,17 +58,31 @@ export type Bundle = { } export class PaymasterClient { - private sponsorClient: ethers.JsonRpcProvider private userClient: ethers.JsonRpcProvider - + private sponsorClient?: ethers.JsonRpcProvider + + /** + * Creates a new PaymasterClient with an optional sponsorUrl. + * If sponsorUrl is provided, it enables the use of private policies. + * The sponsorUrl is typically in the format: "https://open-platform-ap.nodereal.io/xxxx/megafuel-testnet" + * IsSponsorableOptions.PrivatePolicyUUID and SendRawTransactionOptions.PrivatePolicyUUID + * can only be used when sponsorUrl is provided. + * + * @param userUrl The URL for the user's JsonRpcProvider + * @param sponsorUrl Optional URL for the sponsor's JsonRpcProvider + * @param network Optional network information + * @param options Optional JsonRpcApiProviderOptions + */ constructor( userUrl: string | FetchRequest, - sponsorUrl: string | FetchRequest, + sponsorUrl?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions ) { this.userClient = new ethers.JsonRpcProvider(userUrl, network, options) - this.sponsorClient = new ethers.JsonRpcProvider(sponsorUrl, network, options) + if (sponsorUrl) { + this.sponsorClient = new ethers.JsonRpcProvider(sponsorUrl, network, options) + } } async chainID(): Promise { @@ -76,12 +90,10 @@ export class PaymasterClient { } async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {}): Promise { - if (opts.PrivatePolicyUUID) { - // Create a new provider with the updated header + if (this.sponsorClient && opts.PrivatePolicyUUID) { const newConnection = this.sponsorClient._getConnection(); newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); - // Create a new provider with the modified connection const sponsorProviderWithHeader = new ethers.JsonRpcProvider( newConnection, (this.sponsorClient as any)._network, @@ -98,10 +110,7 @@ export class PaymasterClient { } async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions = {}): Promise { - let sponsorProvider = this.sponsorClient; - - if (opts.UserAgent || opts.PrivatePolicyUUID) { - // Create a new provider with the updated headers + if (this.sponsorClient && (opts.UserAgent || opts.PrivatePolicyUUID)) { const newConnection = this.sponsorClient._getConnection(); if (opts.UserAgent) { @@ -111,8 +120,7 @@ export class PaymasterClient { newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); } - // Create a new provider with the modified connection - sponsorProvider = new ethers.JsonRpcProvider( + const sponsorProvider = new ethers.JsonRpcProvider( newConnection, (this.sponsorClient as any)._network, { @@ -121,10 +129,10 @@ export class PaymasterClient { polling: (this.sponsorClient as any).polling } ); - } - if (opts.PrivatePolicyUUID) { - return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]); + if (opts.PrivatePolicyUUID) { + return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]); + } } return await this.userClient.send('eth_sendRawTransaction', [signedTx]); } @@ -145,7 +153,7 @@ export class PaymasterClient { return await this.userClient.send('pm_getBundleByUuid', [bundleUuid]) } - getSponsorProvider(): ethers.JsonRpcProvider { + getSponsorProvider(): ethers.JsonRpcProvider | undefined { return this.sponsorClient } From babb35e70da442787ef43bc6832f181ff1da5794 Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Wed, 16 Oct 2024 13:40:43 +0800 Subject: [PATCH 4/6] fix: address comments --- src/paymasterclient.ts | 75 ++++++++++++----------------------------- src/sponsorclient.ts | 20 +++++++---- tests/paymaster.spec.ts | 55 ++---------------------------- tests/sponsor.spec.ts | 63 ++++++++++++++++++++++++++++++++-- tests/utils.ts | 4 +-- 5 files changed, 101 insertions(+), 116 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index f3d05e1..c21fa24 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -57,61 +57,38 @@ export type Bundle = { readonly ChainID: number } -export class PaymasterClient { - private userClient: ethers.JsonRpcProvider - private sponsorClient?: ethers.JsonRpcProvider - - /** - * Creates a new PaymasterClient with an optional sponsorUrl. - * If sponsorUrl is provided, it enables the use of private policies. - * The sponsorUrl is typically in the format: "https://open-platform-ap.nodereal.io/xxxx/megafuel-testnet" - * IsSponsorableOptions.PrivatePolicyUUID and SendRawTransactionOptions.PrivatePolicyUUID - * can only be used when sponsorUrl is provided. - * - * @param userUrl The URL for the user's JsonRpcProvider - * @param sponsorUrl Optional URL for the sponsor's JsonRpcProvider - * @param network Optional network information - * @param options Optional JsonRpcApiProviderOptions - */ - constructor( - userUrl: string | FetchRequest, - sponsorUrl?: string | FetchRequest, - network?: Networkish, - options?: JsonRpcApiProviderOptions - ) { - this.userClient = new ethers.JsonRpcProvider(userUrl, network, options) - if (sponsorUrl) { - this.sponsorClient = new ethers.JsonRpcProvider(sponsorUrl, network, options) - } +export class PaymasterClient extends ethers.JsonRpcProvider { + constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) { + super(url, network, options) } async chainID(): Promise { - return await this.userClient.send('eth_chainId', []) + return await this.send('eth_chainId', []) } async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {}): Promise { - if (this.sponsorClient && opts.PrivatePolicyUUID) { - const newConnection = this.sponsorClient._getConnection(); + if (opts.PrivatePolicyUUID) { + const newConnection = this._getConnection(); newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); const sponsorProviderWithHeader = new ethers.JsonRpcProvider( newConnection, - (this.sponsorClient as any)._network, + (this as any)._network, { - staticNetwork: (this.sponsorClient as any)._network, - batchMaxCount: (this.sponsorClient as any).batchMaxCount, - polling: (this.sponsorClient as any).polling + staticNetwork: (this as any)._network, + batchMaxCount: (this as any).batchMaxCount, + polling: (this as any).polling } ); return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]); } - return await this.userClient.send('pm_isSponsorable', [tx]); + return await this.send('pm_isSponsorable', [tx]); } async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions = {}): Promise { - if (this.sponsorClient && (opts.UserAgent || opts.PrivatePolicyUUID)) { - const newConnection = this.sponsorClient._getConnection(); + if (opts.UserAgent || opts.PrivatePolicyUUID) { + const newConnection = this._getConnection(); if (opts.UserAgent) { newConnection.setHeader("User-Agent", opts.UserAgent); @@ -122,11 +99,11 @@ export class PaymasterClient { const sponsorProvider = new ethers.JsonRpcProvider( newConnection, - (this.sponsorClient as any)._network, + (this as any)._network, { - staticNetwork: (this.sponsorClient as any)._network, - batchMaxCount: (this.sponsorClient as any).batchMaxCount, - polling: (this.sponsorClient as any).polling + staticNetwork: (this as any)._network, + batchMaxCount: (this as any).batchMaxCount, + polling: (this as any).polling } ); @@ -134,30 +111,22 @@ export class PaymasterClient { return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]); } } - return await this.userClient.send('eth_sendRawTransaction', [signedTx]); + return await this.send('eth_sendRawTransaction', [signedTx]); } async getGaslessTransactionByHash(hash: string): Promise { - return await this.userClient.send('eth_getGaslessTransactionByHash', [hash]) + return await this.send('eth_getGaslessTransactionByHash', [hash]) } async getSponsorTxByTxHash(hash: string): Promise { - return await this.userClient.send('pm_getSponsorTxByTxHash', [hash]) + return await this.send('pm_getSponsorTxByTxHash', [hash]) } async getSponsorTxByBundleUuid(bundleUuid: string): Promise { - return await this.userClient.send('pm_getSponsorTxByBundleUuid', [bundleUuid]) + return await this.send('pm_getSponsorTxByBundleUuid', [bundleUuid]) } async getBundleByUuid(bundleUuid: string): Promise { - return await this.userClient.send('pm_getBundleByUuid', [bundleUuid]) - } - - getSponsorProvider(): ethers.JsonRpcProvider | undefined { - return this.sponsorClient - } - - getUserProvider(): ethers.JsonRpcProvider { - return this.userClient + return await this.send('pm_getBundleByUuid', [bundleUuid]) } } diff --git a/src/sponsorclient.ts b/src/sponsorclient.ts index ad1bded..27aa531 100644 --- a/src/sponsorclient.ts +++ b/src/sponsorclient.ts @@ -1,6 +1,7 @@ -import {ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish} from 'ethers' -import type {AddressLike} from 'ethers/src.ts/address' -import type {BigNumberish} from 'ethers/src.ts/utils' +import { FetchRequest, JsonRpcApiProviderOptions, Networkish } from "ethers" +import { PaymasterClient } from "./paymasterclient" +import type { AddressLike } from "ethers/src.ts/address" +import type { BigNumberish } from "ethers/src.ts/utils" export enum WhitelistType { FromAccountWhitelist = 'FromAccountWhitelist', @@ -42,8 +43,12 @@ export type PolicySpendData = { ChainID: number } -export class SponsorClient extends ethers.JsonRpcProvider { - constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) { +export class SponsorClient extends PaymasterClient { + constructor( + url?: string | FetchRequest, + network?: Networkish, + options?: JsonRpcApiProviderOptions + ) { super(url, network, options) } @@ -63,7 +68,10 @@ export class SponsorClient extends ethers.JsonRpcProvider { return this.send('pm_getWhitelist', [params]) } - async getUserSpendData(fromAddress: AddressLike, policyUUID: string): Promise { + async getUserSpendData( + fromAddress: AddressLike, + policyUUID: string + ): Promise { return this.send('pm_getUserSpendData', [fromAddress, policyUUID]) } diff --git a/tests/paymaster.spec.ts b/tests/paymaster.spec.ts index 5411a47..d1eed25 100644 --- a/tests/paymaster.spec.ts +++ b/tests/paymaster.spec.ts @@ -7,8 +7,7 @@ import { transformToGaslessTransaction, delay, transformSponsorTxResponse, transformBundleResponse, } from './utils' -import {IsSponsorableOptions, SendRawTransactionOptions} from '../src/paymasterclient' -import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS, PRIVATE_POLICY_UUID} from './env' +import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS} from './env' import {ethers} from 'ethers' let TX_HASH = '' @@ -35,7 +34,7 @@ describe('paymasterQuery', () => { test('should successfully determine if transaction is sponsorable', async () => { const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) const tokenAmount = ethers.parseUnits('0', 18) - const nonce = await paymasterClient.getUserProvider().getTransactionCount(wallet.address, 'pending') + const nonce = await paymasterClient.getTransactionCount(wallet.address, 'pending') const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) transaction.from = wallet.address @@ -97,54 +96,4 @@ describe('paymasterQuery', () => { expect(sponsorTx.TxHash).toEqual(tx.TxHash) }, 13000) }) - - - /** - * Test for checking if a private policy transaction is sponsorable. - */ - describe('isSponsorable', () => { - test('should successfully determine if transaction is sponsorable', async () => { - const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) - const tokenAmount = ethers.parseUnits('0', 18) - const nonce = await paymasterClient.getUserProvider().getTransactionCount(wallet.address, 'pending') - - const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) - transaction.from = wallet.address - transaction.nonce = nonce - transaction.gasLimit = BigInt(100000) - transaction.chainId = BigInt(CHAIN_ID) - transaction.gasPrice = BigInt(0) - - const safeTransaction = { - ...transaction, - gasLimit: transaction.gasLimit.toString(), - chainId: transaction.chainId.toString(), - gasPrice: transaction.gasPrice.toString(), - } - - console.log('Prepared transaction:', safeTransaction) - - const opt: IsSponsorableOptions = { - PrivatePolicyUUID: PRIVATE_POLICY_UUID - }; - - const resRaw = await paymasterClient.isSponsorable(safeTransaction, opt) - const res = transformIsSponsorableResponse(resRaw) - expect(res.Sponsorable).toEqual(true) - - const txOpt: SendRawTransactionOptions = { - PrivatePolicyUUID: PRIVATE_POLICY_UUID, - UserAgent: "TEST USER AGENT" - }; - - const signedTx = await wallet.signTransaction(safeTransaction) - try { - const tx = await paymasterClient.sendRawTransaction(signedTx,txOpt) - TX_HASH = tx - console.log('Transaction hash received:', TX_HASH) - } catch (error) { - console.error('Transaction failed:', error) - } - }, 100000) // Extends the default timeout as this test involves network calls - }) }) diff --git a/tests/sponsor.spec.ts b/tests/sponsor.spec.ts index 5050a44..506994d 100644 --- a/tests/sponsor.spec.ts +++ b/tests/sponsor.spec.ts @@ -1,7 +1,16 @@ import {describe, expect, test} from '@jest/globals' -import {sponsorClient} from './utils' import {WhitelistType} from '../src' -import {POLICY_UUID, ACCOUNT_ADDRESS, CONTRACT_METHOD} from './env' +import {POLICY_UUID, ACCOUNT_ADDRESS, CONTRACT_METHOD, TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS, PRIVATE_POLICY_UUID} from './env' +import {ethers} from 'ethers' +import {IsSponsorableOptions, SendRawTransactionOptions} from '../src/paymasterclient' +import { + sponsorClient, + wallet, + tokenAbi, + transformIsSponsorableResponse, +} from './utils' + +let TX_HASH = '' /** * Test suite for Sponsor API methods involving whitelist management and spend data retrieval. @@ -192,4 +201,54 @@ describe('sponsorQuery', () => { console.log('Re-addition to FromAccountWhitelist response:', res) }) }) + + + /** + * Test for checking if a private policy transaction is sponsorable. + */ + describe('isSponsorable', () => { + test('should successfully determine if transaction is sponsorable', async () => { + const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) + const tokenAmount = ethers.parseUnits('0', 18) + const nonce = await sponsorClient.getTransactionCount(wallet.address, 'pending') + + const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) + transaction.from = wallet.address + transaction.nonce = nonce + transaction.gasLimit = BigInt(100000) + transaction.chainId = BigInt(CHAIN_ID) + transaction.gasPrice = BigInt(0) + + const safeTransaction = { + ...transaction, + gasLimit: transaction.gasLimit.toString(), + chainId: transaction.chainId.toString(), + gasPrice: transaction.gasPrice.toString(), + } + + console.log('Prepared transaction:', safeTransaction) + + const opt: IsSponsorableOptions = { + PrivatePolicyUUID: PRIVATE_POLICY_UUID + }; + + const resRaw = await sponsorClient.isSponsorable(safeTransaction, opt) + const res = transformIsSponsorableResponse(resRaw) + expect(res.Sponsorable).toEqual(true) + + const txOpt: SendRawTransactionOptions = { + PrivatePolicyUUID: PRIVATE_POLICY_UUID, + UserAgent: "TEST USER AGENT" + }; + + const signedTx = await wallet.signTransaction(safeTransaction) + try { + const tx = await sponsorClient.sendRawTransaction(signedTx,txOpt) + TX_HASH = tx + console.log('Transaction hash received:', TX_HASH) + } catch (error) { + console.error('Transaction failed:', error) + } + }, 100000) // Extends the default timeout as this test involves network calls + }) }) diff --git a/tests/utils.ts b/tests/utils.ts index 050c1ca..d9dfae1 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -10,13 +10,13 @@ import { import {CHAIN_ID, SPONSOR_URL, CHAIN_URL, PAYMASTER_URL, PRIVATE_KEY, TOKEN_CONTRACT_ADDRESS} from './env' import {ethers} from 'ethers' -export const sponsorClient = new SponsorClient(SPONSOR_URL, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) +export const sponsorClient = new SponsorClient(SPONSOR_URL+"/"+CHAIN_ID, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) // Provider for assembling the transaction (e.g., testnet) export const assemblyProvider = new ethers.JsonRpcProvider(CHAIN_URL) // Provider for sending the transaction (e.g., could be a different network or provider) -export const paymasterClient = new PaymasterClient(PAYMASTER_URL,SPONSOR_URL+"/"+CHAIN_ID, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) +export const paymasterClient = new PaymasterClient(PAYMASTER_URL, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) export const wallet = new ethers.Wallet(PRIVATE_KEY, assemblyProvider) // ERC20 token ABI (only including the transfer function) From ca4c90e658544b4d96af046849f6425893e0ddc5 Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Wed, 16 Oct 2024 16:39:13 +0800 Subject: [PATCH 5/6] fix: create new private paymaster client --- src/paymasterclient.ts | 76 ++++++++++++++++++++++++++--------------- src/sponsorclient.ts | 22 ++++-------- tests/paymaster.spec.ts | 52 ++++++++++++++++++++++++++-- tests/sponsor.spec.ts | 74 +++++---------------------------------- tests/utils.ts | 6 ++-- 5 files changed, 119 insertions(+), 111 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index c21fa24..36bf788 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -9,12 +9,7 @@ export type IsSponsorableResponse = { SponsorWebsite: string } -export type IsSponsorableOptions = { - PrivatePolicyUUID?: string -} - export type SendRawTransactionOptions = { - PrivatePolicyUUID?: string UserAgent?: string } @@ -58,19 +53,46 @@ export type Bundle = { } export class PaymasterClient extends ethers.JsonRpcProvider { - constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) { + private privatePolicyUUID?: string + + private constructor( + url?: string | FetchRequest, + network?: Networkish, + options?: JsonRpcApiProviderOptions, + privatePolicyUUID?: string + ) { super(url, network, options) + this.privatePolicyUUID = privatePolicyUUID + } + + // Static method to create a new standard PaymasterClient + static new( + url?: string | FetchRequest, + network?: Networkish, + options?: JsonRpcApiProviderOptions + ): PaymasterClient { + return new PaymasterClient(url, network, options) + } + + // Static method to create a new PaymasterClient with private policy + static newPrivatePaymaster( + url: string | FetchRequest, + privatePolicyUUID: string, + network?: Networkish, + options?: JsonRpcApiProviderOptions + ): PaymasterClient { + return new PaymasterClient(url, network, options, privatePolicyUUID) } async chainID(): Promise { return await this.send('eth_chainId', []) } - async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {}): Promise { - if (opts.PrivatePolicyUUID) { - const newConnection = this._getConnection(); - newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); - + async isSponsorable(tx: TransactionRequest): Promise { + const policyUUID = this.privatePolicyUUID + if (policyUUID) { + const newConnection = this._getConnection() + newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID) const sponsorProviderWithHeader = new ethers.JsonRpcProvider( newConnection, (this as any)._network, @@ -79,24 +101,24 @@ export class PaymasterClient extends ethers.JsonRpcProvider { batchMaxCount: (this as any).batchMaxCount, polling: (this as any).polling } - ); - - return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]); + ) + return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]) } - return await this.send('pm_isSponsorable', [tx]); + return await this.send('pm_isSponsorable', [tx]) } async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions = {}): Promise { - if (opts.UserAgent || opts.PrivatePolicyUUID) { - const newConnection = this._getConnection(); + const policyUUID = this.privatePolicyUUID + if (opts.UserAgent || this.privatePolicyUUID) { + const newConnection = this._getConnection() if (opts.UserAgent) { - newConnection.setHeader("User-Agent", opts.UserAgent); + newConnection.setHeader("User-Agent", opts.UserAgent) } - if (opts.PrivatePolicyUUID) { - newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID); + if (policyUUID) { + newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID) } - + const sponsorProvider = new ethers.JsonRpcProvider( newConnection, (this as any)._network, @@ -105,13 +127,13 @@ export class PaymasterClient extends ethers.JsonRpcProvider { batchMaxCount: (this as any).batchMaxCount, polling: (this as any).polling } - ); - - if (opts.PrivatePolicyUUID) { - return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]); + ) + + if (policyUUID) { + return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]) } } - return await this.send('eth_sendRawTransaction', [signedTx]); + return await this.send('eth_sendRawTransaction', [signedTx]) } async getGaslessTransactionByHash(hash: string): Promise { @@ -129,4 +151,4 @@ export class PaymasterClient extends ethers.JsonRpcProvider { async getBundleByUuid(bundleUuid: string): Promise { return await this.send('pm_getBundleByUuid', [bundleUuid]) } -} +} \ No newline at end of file diff --git a/src/sponsorclient.ts b/src/sponsorclient.ts index 27aa531..ebd64f1 100644 --- a/src/sponsorclient.ts +++ b/src/sponsorclient.ts @@ -1,7 +1,6 @@ -import { FetchRequest, JsonRpcApiProviderOptions, Networkish } from "ethers" -import { PaymasterClient } from "./paymasterclient" -import type { AddressLike } from "ethers/src.ts/address" -import type { BigNumberish } from "ethers/src.ts/utils" +import {ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish} from 'ethers' +import type {AddressLike} from 'ethers/src.ts/address' +import type {BigNumberish} from 'ethers/src.ts/utils' export enum WhitelistType { FromAccountWhitelist = 'FromAccountWhitelist', @@ -43,12 +42,8 @@ export type PolicySpendData = { ChainID: number } -export class SponsorClient extends PaymasterClient { - constructor( - url?: string | FetchRequest, - network?: Networkish, - options?: JsonRpcApiProviderOptions - ) { +export class SponsorClient extends ethers.JsonRpcProvider { + constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) { super(url, network, options) } @@ -68,14 +63,11 @@ export class SponsorClient extends PaymasterClient { return this.send('pm_getWhitelist', [params]) } - async getUserSpendData( - fromAddress: AddressLike, - policyUUID: string - ): Promise { + async getUserSpendData(fromAddress: AddressLike, policyUUID: string): Promise { return this.send('pm_getUserSpendData', [fromAddress, policyUUID]) } async getPolicySpendData(policyUUID: string): Promise { return this.send('pm_getPolicySpendData', [policyUUID]) } -} +} \ No newline at end of file diff --git a/tests/paymaster.spec.ts b/tests/paymaster.spec.ts index d1eed25..ff2f652 100644 --- a/tests/paymaster.spec.ts +++ b/tests/paymaster.spec.ts @@ -6,9 +6,11 @@ import { transformIsSponsorableResponse, transformToGaslessTransaction, delay, transformSponsorTxResponse, transformBundleResponse, + privatePaymasterClient, } from './utils' -import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS} from './env' -import {ethers} from 'ethers' +import { TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS } from './env' +import { ethers } from 'ethers' +import { SendRawTransactionOptions } from '../src' let TX_HASH = '' @@ -96,4 +98,50 @@ describe('paymasterQuery', () => { expect(sponsorTx.TxHash).toEqual(tx.TxHash) }, 13000) }) + + + + /** + * Test for checking if a private policy transaction is sponsorable. + */ + describe('isSponsorable', () => { + test('should successfully determine if transaction is sponsorable', async () => { + const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) + const tokenAmount = ethers.parseUnits('0', 18) + const nonce = await privatePaymasterClient.getTransactionCount(wallet.address, 'pending') + + const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) + transaction.from = wallet.address + transaction.nonce = nonce + transaction.gasLimit = BigInt(100000) + transaction.chainId = BigInt(CHAIN_ID) + transaction.gasPrice = BigInt(0) + + const safeTransaction = { + ...transaction, + gasLimit: transaction.gasLimit.toString(), + chainId: transaction.chainId.toString(), + gasPrice: transaction.gasPrice.toString(), + } + + console.log('Prepared transaction:', safeTransaction) + + const resRaw = await privatePaymasterClient.isSponsorable(safeTransaction) + const res = transformIsSponsorableResponse(resRaw) + expect(res.Sponsorable).toEqual(true) + + const txOpt: SendRawTransactionOptions = { + UserAgent: "TEST USER AGENT" + }; + + const signedTx = await wallet.signTransaction(safeTransaction) + try { + const tx = await privatePaymasterClient.sendRawTransaction(signedTx,txOpt) + TX_HASH = tx + console.log('Transaction hash received:', TX_HASH) + } catch (error) { + console.error('Transaction failed:', error) + } + }, 100000) // Extends the default timeout as this test involves network calls + }) }) diff --git a/tests/sponsor.spec.ts b/tests/sponsor.spec.ts index 506994d..1264c4f 100644 --- a/tests/sponsor.spec.ts +++ b/tests/sponsor.spec.ts @@ -1,16 +1,7 @@ -import {describe, expect, test} from '@jest/globals' -import {WhitelistType} from '../src' -import {POLICY_UUID, ACCOUNT_ADDRESS, CONTRACT_METHOD, TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS, PRIVATE_POLICY_UUID} from './env' -import {ethers} from 'ethers' -import {IsSponsorableOptions, SendRawTransactionOptions} from '../src/paymasterclient' -import { - sponsorClient, - wallet, - tokenAbi, - transformIsSponsorableResponse, -} from './utils' - -let TX_HASH = '' +import { describe, expect, test } from '@jest/globals' +import { WhitelistType } from '../src' +import { POLICY_UUID, ACCOUNT_ADDRESS, CONTRACT_METHOD } from './env' +import { sponsorClient } from './utils' /** * Test suite for Sponsor API methods involving whitelist management and spend data retrieval. @@ -168,7 +159,10 @@ describe('sponsorQuery', () => { */ describe('getUserSpendData', () => { test('should return not null for user spend data', async () => { - const res = await sponsorClient.getUserSpendData(ACCOUNT_ADDRESS, POLICY_UUID) + const res = await sponsorClient.getUserSpendData( + ACCOUNT_ADDRESS, + POLICY_UUID + ) expect(res).not.toBeNull() console.log('User spend data:', res) @@ -201,54 +195,4 @@ describe('sponsorQuery', () => { console.log('Re-addition to FromAccountWhitelist response:', res) }) }) - - - /** - * Test for checking if a private policy transaction is sponsorable. - */ - describe('isSponsorable', () => { - test('should successfully determine if transaction is sponsorable', async () => { - const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet) - const tokenAmount = ethers.parseUnits('0', 18) - const nonce = await sponsorClient.getTransactionCount(wallet.address, 'pending') - - const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount) - transaction.from = wallet.address - transaction.nonce = nonce - transaction.gasLimit = BigInt(100000) - transaction.chainId = BigInt(CHAIN_ID) - transaction.gasPrice = BigInt(0) - - const safeTransaction = { - ...transaction, - gasLimit: transaction.gasLimit.toString(), - chainId: transaction.chainId.toString(), - gasPrice: transaction.gasPrice.toString(), - } - - console.log('Prepared transaction:', safeTransaction) - - const opt: IsSponsorableOptions = { - PrivatePolicyUUID: PRIVATE_POLICY_UUID - }; - - const resRaw = await sponsorClient.isSponsorable(safeTransaction, opt) - const res = transformIsSponsorableResponse(resRaw) - expect(res.Sponsorable).toEqual(true) - - const txOpt: SendRawTransactionOptions = { - PrivatePolicyUUID: PRIVATE_POLICY_UUID, - UserAgent: "TEST USER AGENT" - }; - - const signedTx = await wallet.signTransaction(safeTransaction) - try { - const tx = await sponsorClient.sendRawTransaction(signedTx,txOpt) - TX_HASH = tx - console.log('Transaction hash received:', TX_HASH) - } catch (error) { - console.error('Transaction failed:', error) - } - }, 100000) // Extends the default timeout as this test involves network calls - }) -}) +}) \ No newline at end of file diff --git a/tests/utils.ts b/tests/utils.ts index d9dfae1..4619567 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -7,16 +7,18 @@ import { Bundle, GaslessTransactionStatus, } from '../src' -import {CHAIN_ID, SPONSOR_URL, CHAIN_URL, PAYMASTER_URL, PRIVATE_KEY, TOKEN_CONTRACT_ADDRESS} from './env' +import {CHAIN_ID, SPONSOR_URL, CHAIN_URL, PAYMASTER_URL, PRIVATE_KEY, TOKEN_CONTRACT_ADDRESS, PRIVATE_POLICY_UUID} from './env' import {ethers} from 'ethers' + export const sponsorClient = new SponsorClient(SPONSOR_URL+"/"+CHAIN_ID, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) // Provider for assembling the transaction (e.g., testnet) export const assemblyProvider = new ethers.JsonRpcProvider(CHAIN_URL) // Provider for sending the transaction (e.g., could be a different network or provider) -export const paymasterClient = new PaymasterClient(PAYMASTER_URL, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) +export const paymasterClient = PaymasterClient.new(PAYMASTER_URL, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) +export const privatePaymasterClient = PaymasterClient.newPrivatePaymaster(SPONSOR_URL+"/"+CHAIN_ID, PRIVATE_POLICY_UUID, undefined, {staticNetwork: ethers.Network.from(Number(CHAIN_ID))}) export const wallet = new ethers.Wallet(PRIVATE_KEY, assemblyProvider) // ERC20 token ABI (only including the transfer function) From 54a72671523ede3af448bcfc7bdb17d4c6e8d9d2 Mon Sep 17 00:00:00 2001 From: BarryTong65 Date: Wed, 16 Oct 2024 17:14:22 +0800 Subject: [PATCH 6/6] fix: rename variable --- src/paymasterclient.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/paymasterclient.ts b/src/paymasterclient.ts index 36bf788..c095f97 100644 --- a/src/paymasterclient.ts +++ b/src/paymasterclient.ts @@ -93,7 +93,7 @@ export class PaymasterClient extends ethers.JsonRpcProvider { if (policyUUID) { const newConnection = this._getConnection() newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID) - const sponsorProviderWithHeader = new ethers.JsonRpcProvider( + const provider = new ethers.JsonRpcProvider( newConnection, (this as any)._network, { @@ -102,7 +102,7 @@ export class PaymasterClient extends ethers.JsonRpcProvider { polling: (this as any).polling } ) - return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]) + return await provider.send('pm_isSponsorable', [tx]) } return await this.send('pm_isSponsorable', [tx]) } @@ -119,7 +119,7 @@ export class PaymasterClient extends ethers.JsonRpcProvider { newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID) } - const sponsorProvider = new ethers.JsonRpcProvider( + const provider = new ethers.JsonRpcProvider( newConnection, (this as any)._network, { @@ -128,10 +128,8 @@ export class PaymasterClient extends ethers.JsonRpcProvider { polling: (this as any).polling } ) - - if (policyUUID) { - return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]) - } + + return await provider.send('eth_sendRawTransaction', [signedTx]) } return await this.send('eth_sendRawTransaction', [signedTx]) }