From c99b9179a9bd31c4c74fe1c88f17bfd3aae170a8 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:34:26 +0100 Subject: [PATCH 1/8] add getTokenQuotes action --- .../mock-paymaster/helpers/schema.ts | 8 +++ .../mock-aa-infra/mock-paymaster/relay.ts | 50 ++++++++++++++-- packages/permissionless/actions/pimlico.ts | 12 +++- .../actions/pimlico/getTokenQuotes.test.ts | 36 +++++++++++ .../actions/pimlico/getTokenQuotes.ts | 60 +++++++++++++++++++ .../clients/decorators/pimlico.ts | 13 +++- packages/permissionless/types/pimlico.ts | 14 +++++ 7 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 packages/permissionless/actions/pimlico/getTokenQuotes.test.ts create mode 100644 packages/permissionless/actions/pimlico/getTokenQuotes.ts diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts index 5c294bc6..6d728920 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts @@ -259,6 +259,14 @@ export const pmGetPaymasterStubDataParamsSchema = z return [val[0], val[1], val[2], val[3] ?? null] as const }) +export const pimlicoGetTokenQuotesSchema = z.tuple([ + z.object({ + tokens: z.array(addressSchema) + }), + addressSchema, // entryPoint + hexNumberSchema +]) + export type UserOperationV7 = zodInfer export type UserOperationV6 = zodInfer export type JsonRpcSchema = zodInfer diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts index fc20a018..3a592e60 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts @@ -1,8 +1,8 @@ import util from "node:util" import type { FastifyReply, FastifyRequest } from "fastify" import { - type Account, BaseError, + type Account, type Chain, type Client, type GetContractReturnType, @@ -11,14 +11,15 @@ import { type RpcRequestError, type Transport, type WalletClient, + type Address, concat, encodeAbiParameters, - toHex + toHex, + getAddress } from "viem" import { type BundlerClient, type UserOperation, - entryPoint06Abi, entryPoint06Address, entryPoint07Address } from "viem/account-abstraction" @@ -37,7 +38,8 @@ import { jsonRpcSchema, pmGetPaymasterData, pmGetPaymasterStubDataParamsSchema, - pmSponsorUserOperationParamsSchema + pmSponsorUserOperationParamsSchema, + pimlicoGetTokenQuotesSchema } from "./helpers/schema" import { maxBigInt } from "./helpers/utils" @@ -260,7 +262,7 @@ const handleMethod = async ( verifyingPaymasterV06: GetContractReturnType< typeof VERIFYING_PAYMASTER_V06_ABI >, - publicClient: PublicClient, + publicClient: PublicClient, walletClient: WalletClient, parsedBody: JsonRpcSchema ) => { @@ -405,6 +407,42 @@ const handleMethod = async ( ] } + if (parsedBody.method === "pimlico_getTokenQuotes") { + const params = pimlicoGetTokenQuotesSchema.safeParse(parsedBody.params) + + if (!params.success) { + throw new RpcError( + fromZodError(params.error).message, + ValidationErrors.InvalidFields + ) + } + + const [context, entryPoint] = params.data + const { tokens } = context + + const quotes = { + [getAddress("0xffffffffffffffffffffffffffffffffffffffff")]: { + exchangeRate: "0x5cc717fbb3450c0000", + postOpGas: "0xc350" + } + } + + let paymaster: Address + if (entryPoint === entryPoint07Address) { + paymaster = verifyingPaymasterV07.address + } else { + paymaster = verifyingPaymasterV06.address + } + + return tokens + .filter((t) => quotes[t]) // Filter out unrecongized tokens + .map((token) => ({ + ...quotes[token], + paymaster, + token + })) + } + throw new RpcError( `Attempted to call an unknown method ${parsedBody.method}`, ValidationErrors.InvalidFields @@ -419,7 +457,7 @@ export const createRpcHandler = ( verifyingPaymasterV06: GetContractReturnType< typeof VERIFYING_PAYMASTER_V06_ABI >, - publicClient: PublicClient, + publicClient: PublicClient, walletClient: WalletClient ) => { return async (request: FastifyRequest, _reply: FastifyReply) => { diff --git a/packages/permissionless/actions/pimlico.ts b/packages/permissionless/actions/pimlico.ts index c067c254..f158dfbb 100644 --- a/packages/permissionless/actions/pimlico.ts +++ b/packages/permissionless/actions/pimlico.ts @@ -16,6 +16,11 @@ import { type SponsorUserOperationReturnType, sponsorUserOperation } from "./pimlico/sponsorUserOperation" +import { + type GetTokenQuotesParameters, + type GetTokenQuotesReturnType, + getTokenQuotes +} from "./pimlico/getTokenQuotes" import type { PimlicoActions } from "../clients/decorators/pimlico" import { pimlicoActions } from "../clients/decorators/pimlico" @@ -35,7 +40,9 @@ export type { SendCompressedUserOperationParameters, SponsorUserOperationReturnType, ValidateSponsorshipPolicies, - ValidateSponsorshipPoliciesParameters + ValidateSponsorshipPoliciesParameters, + GetTokenQuotesParameters, + GetTokenQuotesReturnType } export { @@ -44,5 +51,6 @@ export { pimlicoActions, sendCompressedUserOperation, sponsorUserOperation, - validateSponsorshipPolicies + validateSponsorshipPolicies, + getTokenQuotes } diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts new file mode 100644 index 00000000..ef943ddd --- /dev/null +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -0,0 +1,36 @@ +import { describe, expect } from "vitest" +import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" +import { getPimlicoClient } from "../../../permissionless-test/src/utils" +import { getTokenQuotes } from "./getTokenQuotes" +import { entryPoint07Address } from "viem/_types/account-abstraction" +import { foundry } from "viem/chains" +import { getAddress, isAddress } from "viem" + +describe("getTokenQuotes", () => { + testWithRpc("getTokenQuotes", async ({ rpc }) => { + const pimlicoBundlerClient = getPimlicoClient({ + entryPointVersion: "0.7", + altoRpc: rpc.altoRpc + }) + + const token = getAddress("0xffffffffffffffffffffffffffffffffffffffff") + + const quotes = await getTokenQuotes(pimlicoBundlerClient, { + tokens: [token], + entryPointAddress: entryPoint07Address, + chainId: BigInt(foundry.id) + }) + + expect(quotes).toBeTruthy() + expect(Array.isArray(quotes)).toBe(true) + expect(quotes[0].token).toBeTruthy() + expect(isAddress(quotes[0].token)) + expect(quotes[0].token).toEqual(token) + expect(quotes[0].paymaster).toBeTruthy() + expect(isAddress(quotes[0].paymaster)) + expect(quotes[0].exchangeRate).toBeTruthy() + expect(quotes[0].exchangeRate).toBeGreaterThan(0n) + expect(quotes[0].postOpGas).toBeTruthy() + expect(quotes[0].postOpGas).toBeGreaterThan(0n) + }) +}) diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts new file mode 100644 index 00000000..bb67d482 --- /dev/null +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -0,0 +1,60 @@ +import { + hexToBigInt, + numberToHex, + type Account, + type Address, + type Chain, + type Client, + type Transport +} from "viem" +import type { PimlicoRpcSchema } from "../../types/pimlico" + +export type GetTokenQuotesParameters = { + tokens: Address[] + entryPointAddress: Address + chainId: bigint +} + +export type GetTokenQuotesReturnType = { + paymaster: Address + token: Address + postOpGas: bigint + exchangeRate: bigint +}[] + +/** + * Returns all related fields to calculate the potential cost of a userOperation in ERC-20 tokens. + * + * - Docs: https://docs.pimlico.io/permissionless/reference/pimlico-bundler-actions/getTokenQuotes + * + * @param client that you created using viem's createClient whose transport url is pointing to the Pimlico's bundler. + * @returns slow, standard & fast values for maxFeePerGas & maxPriorityFeePerGas + * @returns quotes, see {@link GetTokenQuotesReturnType} + * + */ +export const getTokenQuotes = async ( + client: Client< + Transport, + Chain | undefined, + Account | undefined, + PimlicoRpcSchema + >, + args: GetTokenQuotesParameters +): Promise => { + const res = await client.request({ + method: "pimlico_getTokenQuotes", + params: [ + { tokens: args.tokens }, + args.entryPointAddress, + numberToHex(args.chainId) + ] + }) + + return { + ...res.quotes.map((quote) => ({ + ...quote, + postOpGas: hexToBigInt(quote.postOpGas), + exchangeRate: hexToBigInt(quote.exchangeRate) + })) + } +} diff --git a/packages/permissionless/clients/decorators/pimlico.ts b/packages/permissionless/clients/decorators/pimlico.ts index 624e4314..ad242672 100644 --- a/packages/permissionless/clients/decorators/pimlico.ts +++ b/packages/permissionless/clients/decorators/pimlico.ts @@ -7,8 +7,11 @@ import { type SendCompressedUserOperationParameters, type ValidateSponsorshipPolicies, type ValidateSponsorshipPoliciesParameters, + type GetTokenQuotesParameters, + type GetTokenQuotesReturnType, sendCompressedUserOperation, - validateSponsorshipPolicies + validateSponsorshipPolicies, + getTokenQuotes } from "../../actions/pimlico" import { type GetUserOperationGasPriceReturnType, @@ -129,6 +132,9 @@ export type PimlicoActions< > > ) => Promise[]> + getTokenQuotes: ( + args: Prettify> + ) => Promise> } export const pimlicoActions = @@ -163,5 +169,10 @@ export const pimlicoActions = validateSponsorshipPolicies(client, { ...args, entryPointAddress: entryPoint.address + }), + getTokenQuotes: async (args) => + getTokenQuotes(client, { + ...args, + entryPointAddress: entryPoint.address }) }) diff --git a/packages/permissionless/types/pimlico.ts b/packages/permissionless/types/pimlico.ts index 08b2ccfb..ad016c52 100644 --- a/packages/permissionless/types/pimlico.ts +++ b/packages/permissionless/types/pimlico.ts @@ -32,6 +32,15 @@ export type PimlicoUserOperationStatus = { transactionHash: Hash | null } +type GetTokenQuotesWithBigIntAsHex = { + quotes: { + paymaster: Address + token: Address + postOpGas: Hex + exchangeRate: Hex + }[] +} + export type PimlicoRpcSchema< entryPointAddress extends | typeof entryPoint06Address @@ -123,5 +132,10 @@ export type PimlicoRpcSchema< description: string | null } }[] + }, + { + Method: "pimlico_getTokenQuotes" + Parameters: [{ tokens: Address[] }, entryPoint: Address, chainId: Hex] + ReturnType: GetTokenQuotesWithBigIntAsHex } ] From fd0d4c932e58af131425e7b2ab6a5e6343a88c43 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:34:46 +0100 Subject: [PATCH 2/8] lint --- .../mock-aa-infra/mock-paymaster/relay.ts | 12 ++++++------ packages/permissionless/actions/pimlico.ts | 10 +++++----- .../actions/pimlico/getTokenQuotes.test.ts | 6 +++--- .../permissionless/actions/pimlico/getTokenQuotes.ts | 6 +++--- .../permissionless/clients/decorators/pimlico.ts | 8 ++++---- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts index 3a592e60..5043f8b4 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts @@ -1,8 +1,9 @@ import util from "node:util" import type { FastifyReply, FastifyRequest } from "fastify" import { - BaseError, type Account, + type Address, + BaseError, type Chain, type Client, type GetContractReturnType, @@ -11,11 +12,10 @@ import { type RpcRequestError, type Transport, type WalletClient, - type Address, concat, encodeAbiParameters, - toHex, - getAddress + getAddress, + toHex } from "viem" import { type BundlerClient, @@ -36,10 +36,10 @@ import { RpcError, ValidationErrors, jsonRpcSchema, + pimlicoGetTokenQuotesSchema, pmGetPaymasterData, pmGetPaymasterStubDataParamsSchema, - pmSponsorUserOperationParamsSchema, - pimlicoGetTokenQuotesSchema + pmSponsorUserOperationParamsSchema } from "./helpers/schema" import { maxBigInt } from "./helpers/utils" diff --git a/packages/permissionless/actions/pimlico.ts b/packages/permissionless/actions/pimlico.ts index f158dfbb..908aba0d 100644 --- a/packages/permissionless/actions/pimlico.ts +++ b/packages/permissionless/actions/pimlico.ts @@ -1,3 +1,8 @@ +import { + type GetTokenQuotesParameters, + type GetTokenQuotesReturnType, + getTokenQuotes +} from "./pimlico/getTokenQuotes" import { type GetUserOperationGasPriceReturnType, getUserOperationGasPrice @@ -16,11 +21,6 @@ import { type SponsorUserOperationReturnType, sponsorUserOperation } from "./pimlico/sponsorUserOperation" -import { - type GetTokenQuotesParameters, - type GetTokenQuotesReturnType, - getTokenQuotes -} from "./pimlico/getTokenQuotes" import type { PimlicoActions } from "../clients/decorators/pimlico" import { pimlicoActions } from "../clients/decorators/pimlico" diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts index ef943ddd..5e8b2412 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -1,10 +1,10 @@ +import { getAddress, isAddress } from "viem" +import { entryPoint07Address } from "viem/_types/account-abstraction" +import { foundry } from "viem/chains" import { describe, expect } from "vitest" import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" import { getPimlicoClient } from "../../../permissionless-test/src/utils" import { getTokenQuotes } from "./getTokenQuotes" -import { entryPoint07Address } from "viem/_types/account-abstraction" -import { foundry } from "viem/chains" -import { getAddress, isAddress } from "viem" describe("getTokenQuotes", () => { testWithRpc("getTokenQuotes", async ({ rpc }) => { diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts index bb67d482..67d85e72 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -1,11 +1,11 @@ import { - hexToBigInt, - numberToHex, type Account, type Address, type Chain, type Client, - type Transport + type Transport, + hexToBigInt, + numberToHex } from "viem" import type { PimlicoRpcSchema } from "../../types/pimlico" diff --git a/packages/permissionless/clients/decorators/pimlico.ts b/packages/permissionless/clients/decorators/pimlico.ts index ad242672..3730cdb7 100644 --- a/packages/permissionless/clients/decorators/pimlico.ts +++ b/packages/permissionless/clients/decorators/pimlico.ts @@ -4,14 +4,14 @@ import type { entryPoint07Address } from "viem/account-abstraction" import { + type GetTokenQuotesParameters, + type GetTokenQuotesReturnType, type SendCompressedUserOperationParameters, type ValidateSponsorshipPolicies, type ValidateSponsorshipPoliciesParameters, - type GetTokenQuotesParameters, - type GetTokenQuotesReturnType, + getTokenQuotes, sendCompressedUserOperation, - validateSponsorshipPolicies, - getTokenQuotes + validateSponsorshipPolicies } from "../../actions/pimlico" import { type GetUserOperationGasPriceReturnType, From 296165c47c506de75320e23a22bf9ca00ec935d4 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:52:16 +0100 Subject: [PATCH 3/8] fix failing tests --- .../mock-aa-infra/mock-paymaster/relay.ts | 16 +++++++++------- .../actions/pimlico/getTokenQuotes.test.ts | 4 ++-- .../actions/pimlico/getTokenQuotes.ts | 12 +++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts index 5043f8b4..7fa46e95 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts @@ -434,13 +434,15 @@ const handleMethod = async ( paymaster = verifyingPaymasterV06.address } - return tokens - .filter((t) => quotes[t]) // Filter out unrecongized tokens - .map((token) => ({ - ...quotes[token], - paymaster, - token - })) + return { + quotes: tokens + .filter((t) => quotes[t]) // Filter out unrecongized tokens + .map((token) => ({ + ...quotes[token], + paymaster, + token + })) + } } throw new RpcError( diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts index 5e8b2412..6029b8b5 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -1,5 +1,5 @@ import { getAddress, isAddress } from "viem" -import { entryPoint07Address } from "viem/_types/account-abstraction" +import { entryPoint07Address } from "viem/account-abstraction" import { foundry } from "viem/chains" import { describe, expect } from "vitest" import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" @@ -10,7 +10,7 @@ describe("getTokenQuotes", () => { testWithRpc("getTokenQuotes", async ({ rpc }) => { const pimlicoBundlerClient = getPimlicoClient({ entryPointVersion: "0.7", - altoRpc: rpc.altoRpc + altoRpc: rpc.paymasterRpc }) const token = getAddress("0xffffffffffffffffffffffffffffffffffffffff") diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts index 67d85e72..c3d1169d 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -50,11 +50,9 @@ export const getTokenQuotes = async ( ] }) - return { - ...res.quotes.map((quote) => ({ - ...quote, - postOpGas: hexToBigInt(quote.postOpGas), - exchangeRate: hexToBigInt(quote.exchangeRate) - })) - } + return res.quotes.map((quote) => ({ + ...quote, + postOpGas: hexToBigInt(quote.postOpGas), + exchangeRate: hexToBigInt(quote.exchangeRate) + })) } From 96055238c179c98fde0c2628b073095bf0248090 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Fri, 30 Aug 2024 17:38:59 +0100 Subject: [PATCH 4/8] use number for chainId --- packages/permissionless/actions/pimlico/getTokenQuotes.test.ts | 2 +- packages/permissionless/actions/pimlico/getTokenQuotes.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts index 6029b8b5..bfb53f1b 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -18,7 +18,7 @@ describe("getTokenQuotes", () => { const quotes = await getTokenQuotes(pimlicoBundlerClient, { tokens: [token], entryPointAddress: entryPoint07Address, - chainId: BigInt(foundry.id) + chainId: foundry.id }) expect(quotes).toBeTruthy() diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts index c3d1169d..f4aaa8d9 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -12,7 +12,7 @@ import type { PimlicoRpcSchema } from "../../types/pimlico" export type GetTokenQuotesParameters = { tokens: Address[] entryPointAddress: Address - chainId: bigint + chainId: number } export type GetTokenQuotesReturnType = { From 5609b5bb2b30b7ea9f28159d730db034b447974e Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:18:39 +0100 Subject: [PATCH 5/8] allow for chain overrides --- .../actions/pimlico/getTokenQuotes.test.ts | 28 ++++++++++++++- .../actions/pimlico/getTokenQuotes.ts | 35 ++++++++++++------- .../clients/decorators/pimlico.ts | 19 +++++++--- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts index bfb53f1b..691cbe37 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -18,7 +18,33 @@ describe("getTokenQuotes", () => { const quotes = await getTokenQuotes(pimlicoBundlerClient, { tokens: [token], entryPointAddress: entryPoint07Address, - chainId: foundry.id + chain: foundry + }) + + expect(quotes).toBeTruthy() + expect(Array.isArray(quotes)).toBe(true) + expect(quotes[0].token).toBeTruthy() + expect(isAddress(quotes[0].token)) + expect(quotes[0].token).toEqual(token) + expect(quotes[0].paymaster).toBeTruthy() + expect(isAddress(quotes[0].paymaster)) + expect(quotes[0].exchangeRate).toBeTruthy() + expect(quotes[0].exchangeRate).toBeGreaterThan(0n) + expect(quotes[0].postOpGas).toBeTruthy() + expect(quotes[0].postOpGas).toBeGreaterThan(0n) + }) + + testWithRpc("get chain from client", async ({ rpc }) => { + const pimlicoBundlerClient = getPimlicoClient({ + entryPointVersion: "0.7", + altoRpc: rpc.paymasterRpc + }) + + const token = getAddress("0xffffffffffffffffffffffffffffffffffffffff") + + const quotes = pimlicoBundlerClient.getTokenQuotes({ + tokens: [token], + entryPointAddress: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }) expect(quotes).toBeTruthy() diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts index f4aaa8d9..4466cedb 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -4,16 +4,20 @@ import { type Chain, type Client, type Transport, + type GetChainParameter, hexToBigInt, - numberToHex + numberToHex, + ChainNotFoundError } from "viem" import type { PimlicoRpcSchema } from "../../types/pimlico" -export type GetTokenQuotesParameters = { +export type GetTokenQuotesParameters< + TChain extends Chain | undefined, + TChainOverride extends Chain | undefined = Chain | undefined +> = { tokens: Address[] entryPointAddress: Address - chainId: number -} +} & GetChainParameter export type GetTokenQuotesReturnType = { paymaster: Address @@ -32,21 +36,26 @@ export type GetTokenQuotesReturnType = { * @returns quotes, see {@link GetTokenQuotesReturnType} * */ -export const getTokenQuotes = async ( - client: Client< - Transport, - Chain | undefined, - Account | undefined, - PimlicoRpcSchema - >, - args: GetTokenQuotesParameters +export const getTokenQuotes = async < + TChain extends Chain | undefined, + TTransport extends Transport = Transport, + TChainOverride extends Chain | undefined = Chain | undefined +>( + client: Client, + args: GetTokenQuotesParameters ): Promise => { + const chainId = args.chain?.id ?? client.chain?.id + + if (!chainId) { + throw new ChainNotFoundError() + } + const res = await client.request({ method: "pimlico_getTokenQuotes", params: [ { tokens: args.tokens }, args.entryPointAddress, - numberToHex(args.chainId) + numberToHex(chainId) ] }) diff --git a/packages/permissionless/clients/decorators/pimlico.ts b/packages/permissionless/clients/decorators/pimlico.ts index 696b8644..a7824904 100644 --- a/packages/permissionless/clients/decorators/pimlico.ts +++ b/packages/permissionless/clients/decorators/pimlico.ts @@ -1,4 +1,4 @@ -import type { Address, Client, Hash, Prettify } from "viem" +import type { Address, Chain, Client, Hash, Prettify, Transport } from "viem" import { type GetTokenQuotesParameters, type GetTokenQuotesReturnType, @@ -25,6 +25,7 @@ import { } from "../../actions/pimlico/sponsorUserOperation" export type PimlicoActions< + TChain extends Chain | undefined, entryPointVersion extends "0.6" | "0.7" = "0.6" | "0.7" > = { /** @@ -114,8 +115,12 @@ export type PimlicoActions< Omit > ) => Promise[]> - getTokenQuotes: ( - args: Prettify> + getTokenQuotes: < + TChainOverride extends Chain | undefined = Chain | undefined + >( + args: Prettify< + Omit, "entryPoint"> + > ) => Promise> } @@ -125,7 +130,12 @@ export const pimlicoActions = }: { entryPoint: { address: Address; version: entryPointVersion } }) => - (client: Client): PimlicoActions => ({ + < + TTransport extends Transport, + TChain extends Chain | undefined = Chain | undefined + >( + client: Client + ): PimlicoActions => ({ getUserOperationGasPrice: async () => getUserOperationGasPrice(client), getUserOperationStatus: async ( args: GetUserOperationStatusParameters @@ -150,6 +160,7 @@ export const pimlicoActions = getTokenQuotes: async (args) => getTokenQuotes(client, { ...args, + chain: args.chain, entryPointAddress: entryPoint.address }) }) From b1d86589255b0bf535d47266fb2e538540ac0123 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:18:45 +0100 Subject: [PATCH 6/8] allow for chain overrides --- packages/permissionless/actions/pimlico/getTokenQuotes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.ts index 4466cedb..59d47b78 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.ts @@ -2,12 +2,12 @@ import { type Account, type Address, type Chain, + ChainNotFoundError, type Client, - type Transport, type GetChainParameter, + type Transport, hexToBigInt, - numberToHex, - ChainNotFoundError + numberToHex } from "viem" import type { PimlicoRpcSchema } from "../../types/pimlico" From a66598b9b907c2e7ac8c9b19d13d08711264035c Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:22:41 +0100 Subject: [PATCH 7/8] fix --- packages/permissionless/clients/pimlico.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/permissionless/clients/pimlico.ts b/packages/permissionless/clients/pimlico.ts index 33c4cda2..4cd141b9 100644 --- a/packages/permissionless/clients/pimlico.ts +++ b/packages/permissionless/clients/pimlico.ts @@ -42,7 +42,7 @@ export type PimlicoClient< : [...BundlerRpcSchema, ...PimlicoRpcSchema], BundlerActions & PaymasterActions & - PimlicoActions + PimlicoActions > > From 4c0a8a2e99f09f7d47d8988affa2426f3ac59226 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:33:48 +0100 Subject: [PATCH 8/8] fix --- packages/permissionless-test/src/utils.ts | 7 +---- .../actions/pimlico/getTokenQuotes.test.ts | 26 ------------------- .../clients/decorators/pimlico.ts | 5 +++- 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/packages/permissionless-test/src/utils.ts b/packages/permissionless-test/src/utils.ts index 47700f52..0acdc9f7 100644 --- a/packages/permissionless-test/src/utils.ts +++ b/packages/permissionless-test/src/utils.ts @@ -186,12 +186,7 @@ export const getPimlicoClient = ({ entryPointVersion: entryPointVersion altoRpc: string }) => - createPimlicoClient< - entryPointVersion extends "0.6" - ? typeof entryPoint06Address - : typeof entryPoint07Address, - entryPointVersion - >({ + createPimlicoClient({ chain: foundry, entryPoint: { address: (entryPointVersion === "0.6" diff --git a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts index 691cbe37..db6f26ca 100644 --- a/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts +++ b/packages/permissionless/actions/pimlico/getTokenQuotes.test.ts @@ -33,30 +33,4 @@ describe("getTokenQuotes", () => { expect(quotes[0].postOpGas).toBeTruthy() expect(quotes[0].postOpGas).toBeGreaterThan(0n) }) - - testWithRpc("get chain from client", async ({ rpc }) => { - const pimlicoBundlerClient = getPimlicoClient({ - entryPointVersion: "0.7", - altoRpc: rpc.paymasterRpc - }) - - const token = getAddress("0xffffffffffffffffffffffffffffffffffffffff") - - const quotes = pimlicoBundlerClient.getTokenQuotes({ - tokens: [token], - entryPointAddress: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }) - - expect(quotes).toBeTruthy() - expect(Array.isArray(quotes)).toBe(true) - expect(quotes[0].token).toBeTruthy() - expect(isAddress(quotes[0].token)) - expect(quotes[0].token).toEqual(token) - expect(quotes[0].paymaster).toBeTruthy() - expect(isAddress(quotes[0].paymaster)) - expect(quotes[0].exchangeRate).toBeTruthy() - expect(quotes[0].exchangeRate).toBeGreaterThan(0n) - expect(quotes[0].postOpGas).toBeTruthy() - expect(quotes[0].postOpGas).toBeGreaterThan(0n) - }) }) diff --git a/packages/permissionless/clients/decorators/pimlico.ts b/packages/permissionless/clients/decorators/pimlico.ts index a7824904..8525a2ee 100644 --- a/packages/permissionless/clients/decorators/pimlico.ts +++ b/packages/permissionless/clients/decorators/pimlico.ts @@ -119,7 +119,10 @@ export type PimlicoActions< TChainOverride extends Chain | undefined = Chain | undefined >( args: Prettify< - Omit, "entryPoint"> + Omit< + GetTokenQuotesParameters, + "entryPointAddress" + > > ) => Promise> }