Skip to content

Commit 1150f05

Browse files
committed
fix: create new private paymaster client
1 parent babb35e commit 1150f05

File tree

5 files changed

+198
-189
lines changed

5 files changed

+198
-189
lines changed

src/paymasterclient.ts

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@ export type IsSponsorableResponse = {
99
SponsorWebsite: string
1010
}
1111

12-
export type IsSponsorableOptions = {
13-
PrivatePolicyUUID?: string
14-
}
15-
1612
export type SendRawTransactionOptions = {
17-
PrivatePolicyUUID?: string
1813
UserAgent?: string
1914
}
2015

@@ -58,19 +53,46 @@ export type Bundle = {
5853
}
5954

6055
export class PaymasterClient extends ethers.JsonRpcProvider {
61-
constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) {
62-
super(url, network, options)
56+
private privatePolicyUUID?: string;
57+
58+
private constructor(
59+
url?: string | FetchRequest,
60+
network?: Networkish,
61+
options?: JsonRpcApiProviderOptions,
62+
privatePolicyUUID?: string
63+
) {
64+
super(url, network, options);
65+
this.privatePolicyUUID = privatePolicyUUID;
66+
}
67+
68+
// Static method to create a new standard PaymasterClient
69+
static new(
70+
url?: string | FetchRequest,
71+
network?: Networkish,
72+
options?: JsonRpcApiProviderOptions
73+
): PaymasterClient {
74+
return new PaymasterClient(url, network, options);
75+
}
76+
77+
// Static method to create a new PaymasterClient with private policy
78+
static newPrivatePaymaster(
79+
url: string | FetchRequest,
80+
privatePolicyUUID: string,
81+
network?: Networkish,
82+
options?: JsonRpcApiProviderOptions
83+
): PaymasterClient {
84+
return new PaymasterClient(url, network, options, privatePolicyUUID);
6385
}
6486

6587
async chainID(): Promise<string> {
66-
return await this.send('eth_chainId', [])
88+
return await this.send('eth_chainId', []);
6789
}
6890

69-
async isSponsorable(tx: TransactionRequest, opts: IsSponsorableOptions = {}): Promise<IsSponsorableResponse> {
70-
if (opts.PrivatePolicyUUID) {
91+
async isSponsorable(tx: TransactionRequest): Promise<IsSponsorableResponse> {
92+
const policyUUID = this.privatePolicyUUID;
93+
if (policyUUID) {
7194
const newConnection = this._getConnection();
72-
newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID);
73-
95+
newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID);
7496
const sponsorProviderWithHeader = new ethers.JsonRpcProvider(
7597
newConnection,
7698
(this as any)._network,
@@ -80,23 +102,24 @@ export class PaymasterClient extends ethers.JsonRpcProvider {
80102
polling: (this as any).polling
81103
}
82104
);
83-
84105
return await sponsorProviderWithHeader.send('pm_isSponsorable', [tx]);
85106
}
86107
return await this.send('pm_isSponsorable', [tx]);
87108
}
88109

89110
async sendRawTransaction(signedTx: string, opts: SendRawTransactionOptions = {}): Promise<string> {
90-
if (opts.UserAgent || opts.PrivatePolicyUUID) {
111+
const policyUUID = this.privatePolicyUUID;
112+
if (opts.UserAgent || this.privatePolicyUUID) {
91113
const newConnection = this._getConnection();
92114

93115
if (opts.UserAgent) {
94116
newConnection.setHeader("User-Agent", opts.UserAgent);
95117
}
96-
if (opts.PrivatePolicyUUID) {
97-
newConnection.setHeader("X-MegaFuel-Policy-Uuid", opts.PrivatePolicyUUID);
118+
if (policyUUID) {
119+
console.log("X-MegaFuel-Policy-Uuid", policyUUID)
120+
newConnection.setHeader("X-MegaFuel-Policy-Uuid", policyUUID);
98121
}
99-
122+
100123
const sponsorProvider = new ethers.JsonRpcProvider(
101124
newConnection,
102125
(this as any)._network,
@@ -106,8 +129,8 @@ export class PaymasterClient extends ethers.JsonRpcProvider {
106129
polling: (this as any).polling
107130
}
108131
);
109-
110-
if (opts.PrivatePolicyUUID) {
132+
133+
if (policyUUID) {
111134
return await sponsorProvider.send('eth_sendRawTransaction', [signedTx]);
112135
}
113136
}
@@ -129,4 +152,4 @@ export class PaymasterClient extends ethers.JsonRpcProvider {
129152
async getBundleByUuid(bundleUuid: string): Promise<Bundle> {
130153
return await this.send('pm_getBundleByUuid', [bundleUuid])
131154
}
132-
}
155+
}

src/sponsorclient.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { FetchRequest, JsonRpcApiProviderOptions, Networkish } from "ethers"
2-
import { PaymasterClient } from "./paymasterclient"
3-
import type { AddressLike } from "ethers/src.ts/address"
4-
import type { BigNumberish } from "ethers/src.ts/utils"
1+
import {ethers, FetchRequest, JsonRpcApiProviderOptions, Networkish} from 'ethers'
2+
import type {AddressLike} from 'ethers/src.ts/address'
3+
import type {BigNumberish} from 'ethers/src.ts/utils'
54

65
export enum WhitelistType {
76
FromAccountWhitelist = 'FromAccountWhitelist',
@@ -43,12 +42,8 @@ export type PolicySpendData = {
4342
ChainID: number
4443
}
4544

46-
export class SponsorClient extends PaymasterClient {
47-
constructor(
48-
url?: string | FetchRequest,
49-
network?: Networkish,
50-
options?: JsonRpcApiProviderOptions
51-
) {
45+
export class SponsorClient extends ethers.JsonRpcProvider {
46+
constructor(url?: string | FetchRequest, network?: Networkish, options?: JsonRpcApiProviderOptions) {
5247
super(url, network, options)
5348
}
5449

@@ -68,14 +63,11 @@ export class SponsorClient extends PaymasterClient {
6863
return this.send('pm_getWhitelist', [params])
6964
}
7065

71-
async getUserSpendData(
72-
fromAddress: AddressLike,
73-
policyUUID: string
74-
): Promise<UserSpendData> {
66+
async getUserSpendData(fromAddress: AddressLike, policyUUID: string): Promise<UserSpendData> {
7567
return this.send('pm_getUserSpendData', [fromAddress, policyUUID])
7668
}
7769

7870
async getPolicySpendData(policyUUID: string): Promise<PolicySpendData> {
7971
return this.send('pm_getPolicySpendData', [policyUUID])
8072
}
81-
}
73+
}

tests/paymaster.spec.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import {
66
transformIsSponsorableResponse,
77
transformToGaslessTransaction,
88
delay, transformSponsorTxResponse, transformBundleResponse,
9+
privatePaymasterClient,
910
} from './utils'
10-
import {TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS} from './env'
11-
import {ethers} from 'ethers'
11+
import { TOKEN_CONTRACT_ADDRESS, CHAIN_ID, RECIPIENT_ADDRESS } from './env'
12+
import { ethers } from 'ethers'
13+
import { SendRawTransactionOptions } from '../src'
1214

1315
let TX_HASH = ''
1416

@@ -96,4 +98,50 @@ describe('paymasterQuery', () => {
9698
expect(sponsorTx.TxHash).toEqual(tx.TxHash)
9799
}, 13000)
98100
})
101+
102+
103+
104+
/**
105+
* Test for checking if a private policy transaction is sponsorable.
106+
*/
107+
describe('isSponsorable', () => {
108+
test('should successfully determine if transaction is sponsorable', async () => {
109+
const tokenContract = new ethers.Contract(TOKEN_CONTRACT_ADDRESS, tokenAbi, wallet)
110+
const tokenAmount = ethers.parseUnits('0', 18)
111+
const nonce = await privatePaymasterClient.getTransactionCount(wallet.address, 'pending')
112+
113+
const transaction = await tokenContract.transfer.populateTransaction(RECIPIENT_ADDRESS.toLowerCase(), tokenAmount)
114+
transaction.from = wallet.address
115+
transaction.nonce = nonce
116+
transaction.gasLimit = BigInt(100000)
117+
transaction.chainId = BigInt(CHAIN_ID)
118+
transaction.gasPrice = BigInt(0)
119+
120+
const safeTransaction = {
121+
...transaction,
122+
gasLimit: transaction.gasLimit.toString(),
123+
chainId: transaction.chainId.toString(),
124+
gasPrice: transaction.gasPrice.toString(),
125+
}
126+
127+
console.log('Prepared transaction:', safeTransaction)
128+
129+
const resRaw = await privatePaymasterClient.isSponsorable(safeTransaction)
130+
const res = transformIsSponsorableResponse(resRaw)
131+
expect(res.Sponsorable).toEqual(true)
132+
133+
const txOpt: SendRawTransactionOptions = {
134+
UserAgent: "TEST USER AGENT"
135+
};
136+
137+
const signedTx = await wallet.signTransaction(safeTransaction)
138+
try {
139+
const tx = await privatePaymasterClient.sendRawTransaction(signedTx,txOpt)
140+
TX_HASH = tx
141+
console.log('Transaction hash received:', TX_HASH)
142+
} catch (error) {
143+
console.error('Transaction failed:', error)
144+
}
145+
}, 100000) // Extends the default timeout as this test involves network calls
146+
})
99147
})

0 commit comments

Comments
 (0)