Skip to content

Commit 59ca48f

Browse files
Merge pull request #426 from pimlicolabs/estimateErc20PaymasterCost
Add estimateErc20PaymasterCost
2 parents dff17ee + ba0e2bd commit 59ca48f

3 files changed

Lines changed: 130 additions & 0 deletions

File tree

.changeset/swift-experts-act.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"permissionless": patch
3+
---
4+
5+
Added estimateErc20PaymasterCost
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import {
2+
type Account,
3+
type Address,
4+
type Chain,
5+
ChainNotFoundError,
6+
type Client,
7+
type GetChainParameter,
8+
type Transport
9+
} from "viem"
10+
import type { EntryPointVersion, UserOperation } from "viem/account-abstraction"
11+
import { getAction } from "viem/utils"
12+
import type { PimlicoRpcSchema } from "../../types/pimlico.js"
13+
import { getRequiredPrefund } from "../../utils/getRequiredPrefund.js"
14+
import { getTokenQuotes } from "./getTokenQuotes.js"
15+
16+
/**
17+
* @costInToken represents the max amount of token that will be charged for this user operation in token decimals
18+
* @costInUsd represents the max amount of USD value of the token in 10^6 decimals
19+
*/
20+
export type EstimateErc20PaymasterCostReturnType = {
21+
costInToken: bigint
22+
costInUsd: bigint
23+
}
24+
25+
export type EstimateErc20PaymasterCostParameters<
26+
entryPointVersion extends EntryPointVersion,
27+
TChain extends Chain | undefined,
28+
TChainOverride extends Chain | undefined = Chain | undefined
29+
> = {
30+
entryPoint: { version: entryPointVersion; address: Address }
31+
userOperation: UserOperation<entryPointVersion>
32+
token: Address
33+
} & GetChainParameter<TChain, TChainOverride>
34+
35+
/**
36+
* Returns all related fields to calculate the potential cost of a userOperation in ERC-20 tokens.
37+
*
38+
* - Docs: https://docs.pimlico.io/permissionless/reference/pimlico-bundler-actions/EstimateErc20PaymasterCost
39+
*
40+
* @param client that you created using viem's createClient whose transport url is pointing to the Pimlico's bundler.
41+
* @returns quotes, see {@link EstimateErc20PaymasterCostReturnType}
42+
*
43+
*/
44+
export const estimateErc20PaymasterCost = async <
45+
entryPointVersion extends EntryPointVersion,
46+
TChain extends Chain | undefined,
47+
TChainOverride extends Chain | undefined = Chain | undefined
48+
>(
49+
client: Client<
50+
Transport,
51+
TChain,
52+
Account | undefined,
53+
PimlicoRpcSchema<entryPointVersion>
54+
>,
55+
args: EstimateErc20PaymasterCostParameters<
56+
entryPointVersion,
57+
TChain,
58+
TChainOverride
59+
>
60+
): Promise<EstimateErc20PaymasterCostReturnType> => {
61+
const chain = args.chain ?? client.chain
62+
63+
if (!chain) {
64+
throw new ChainNotFoundError()
65+
}
66+
67+
const { entryPoint, userOperation, token } = args
68+
69+
const quotes = await getAction(
70+
client,
71+
getTokenQuotes,
72+
"getTokenQuotes"
73+
)({
74+
tokens: [token],
75+
entryPointAddress: entryPoint.address,
76+
chain
77+
})
78+
79+
const postOpGas = quotes[0].postOpGas
80+
const exchangeRate = quotes[0].exchangeRate
81+
const exchangeRateNativeToUsd = quotes[0].exchangeRateNativeToUsd
82+
83+
const userOperationMaxCost = getRequiredPrefund({
84+
userOperation,
85+
entryPointVersion: entryPoint.version
86+
})
87+
88+
// represents the userOperation's max cost in denomination of wei
89+
const maxCostInWei =
90+
userOperationMaxCost + postOpGas * userOperation.maxFeePerGas
91+
92+
// represents the userOperation's max cost in token denomination (wei)
93+
const costInToken = (maxCostInWei * exchangeRate) / BigInt(1e18)
94+
95+
// represents the userOperation's max cost in usd (with 6 decimals of precision)
96+
const costInUsd = (maxCostInWei * exchangeRateNativeToUsd) / 10n ** 18n
97+
98+
return {
99+
costInToken,
100+
costInUsd
101+
}
102+
}

packages/permissionless/clients/decorators/pimlico.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import {
1010
sendCompressedUserOperation,
1111
validateSponsorshipPolicies
1212
} from "../../actions/pimlico.js"
13+
import {
14+
type EstimateErc20PaymasterCostParameters,
15+
type EstimateErc20PaymasterCostReturnType,
16+
estimateErc20PaymasterCost
17+
} from "../../actions/pimlico/estimateErc20PaymasterCost.js"
1318
import {
1419
type GetUserOperationGasPriceReturnType,
1520
getUserOperationGasPrice
@@ -124,6 +129,18 @@ export type PimlicoActions<
124129
>
125130
>
126131
) => Promise<Prettify<GetTokenQuotesReturnType>>
132+
estimateErc20PaymasterCost: <
133+
TChainOverride extends Chain | undefined = Chain | undefined
134+
>(
135+
args: Omit<
136+
EstimateErc20PaymasterCostParameters<
137+
entryPointVersion,
138+
TChain,
139+
TChainOverride
140+
>,
141+
"entryPoint"
142+
>
143+
) => Promise<Prettify<EstimateErc20PaymasterCostReturnType>>
127144
}
128145

129146
export const pimlicoActions =
@@ -162,5 +179,11 @@ export const pimlicoActions =
162179
...args,
163180
chain: args.chain,
164181
entryPointAddress: entryPoint.address
182+
}),
183+
estimateErc20PaymasterCost: async (args) =>
184+
estimateErc20PaymasterCost(client, {
185+
...args,
186+
entryPoint,
187+
chain: args.chain
165188
})
166189
})

0 commit comments

Comments
 (0)