Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/bcnmy/sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
GabiDev45 committed Mar 22, 2024
2 parents 6241353 + 6cfd8ed commit 0182262
Show file tree
Hide file tree
Showing 16 changed files with 570 additions and 112 deletions.
74 changes: 54 additions & 20 deletions src/accounts/actions/prepareUserOperationRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,61 @@ async function prepareUserOperationRequestForEntryPointV06<
typeof middleware !== "function" &&
middleware.sponsorUserOperation
) {
const sponsorUserOperationData = (await middleware.sponsorUserOperation({
userOperation,
mode: PaymasterMode.SPONSORED
} as {
userOperation: UserOperationStruct
mode: PaymasterMode
})) as Pick<
UserOperationStruct,
| "callGasLimit"
| "verificationGasLimit"
| "preVerificationGas"
| "paymasterAndData"
>
if (middleware.paymasterMode === PaymasterMode.ERC20) {
if (middleware.feeQuote) {
const sponsorUserOperationData = (await middleware.sponsorUserOperation(
{
userOperation,
mode: PaymasterMode.ERC20,
tokenInfo: {
feeTokenAddress: middleware.feeQuote.tokenAddress
}
} as {
userOperation: UserOperationStruct
mode: PaymasterMode
}
)) as Pick<
UserOperationStruct,
| "callGasLimit"
| "verificationGasLimit"
| "preVerificationGas"
| "paymasterAndData"
>

userOperation.callGasLimit =
sponsorUserOperationData.callGasLimit?.toString()
userOperation.verificationGasLimit =
sponsorUserOperationData.verificationGasLimit?.toString()
userOperation.preVerificationGas =
sponsorUserOperationData.preVerificationGas?.toString()
userOperation.paymasterAndData = sponsorUserOperationData.paymasterAndData
userOperation.callGasLimit =
sponsorUserOperationData.callGasLimit?.toString()
userOperation.verificationGasLimit =
sponsorUserOperationData.verificationGasLimit?.toString()
userOperation.preVerificationGas =
sponsorUserOperationData.preVerificationGas?.toString()
userOperation.paymasterAndData =
sponsorUserOperationData.paymasterAndData
} else {
throw new Error("No fee quote found for ERC20 Paymaster")
}
} else {
const sponsorUserOperationData = (await middleware.sponsorUserOperation({
userOperation,
mode: PaymasterMode.SPONSORED
} as {
userOperation: UserOperationStruct
mode: PaymasterMode
})) as Pick<
UserOperationStruct,
| "callGasLimit"
| "verificationGasLimit"
| "preVerificationGas"
| "paymasterAndData"
>

userOperation.callGasLimit =
sponsorUserOperationData.callGasLimit?.toString()
userOperation.verificationGasLimit =
sponsorUserOperationData.verificationGasLimit?.toString()
userOperation.preVerificationGas =
sponsorUserOperationData.preVerificationGas?.toString()
userOperation.paymasterAndData = sponsorUserOperationData.paymasterAndData
}
}

if (
Expand Down
1 change: 1 addition & 0 deletions src/accounts/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export const validateUserOp = (userOp: UserOperationStruct): boolean => {
return true
}

// biome-ignore lint/suspicious/noExplicitAny: Can be use on dynamic types
export const isNullOrUndefined = (value: any): value is undefined => {
return value === null || value === undefined
}
Expand Down
15 changes: 10 additions & 5 deletions src/accounts/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import type {
import type { PartialBy } from "viem/chains"
import type { IsUndefined, UnionOmit } from "viem/types/utils.js"
import type { BaseValidationModule } from "../../modules/index.js"
import type { PaymasterMode } from "../../paymaster/utils/types.js"
import type {
PaymasterFeeQuote,
PaymasterMode,
SponsorUserOperationParameters
} from "../../paymaster/utils/types.js"

export type BigNumberish = number | string | bigint
export type BytesLike = `0x${string}` | Uint8Array
Expand Down Expand Up @@ -167,10 +171,9 @@ export type Middleware = {
maxPriorityFeePerGas: bigint | string | undefined
maxFeePerGas: bigint | string | undefined
}>
sponsorUserOperation?: (args: {
userOperation: UserOperationStruct
mode: PaymasterMode
}) => Promise<
sponsorUserOperation?: (
args: SponsorUserOperationParameters
) => Promise<
Pick<
UserOperationStruct,
| "callGasLimit"
Expand All @@ -179,6 +182,8 @@ export type Middleware = {
| "paymasterAndData"
>
>
paymasterMode?: PaymasterMode
feeQuote?: PaymasterFeeQuote
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/bundler/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ export type UserOpReceipt = {
/* In case of revert, this is the revert reason. */
reason: string
/* The logs generated by this UserOperation (not including logs of other UserOperations in the same bundle). */
// biome-ignore lint/suspicious/noExplicitAny: difficult to type
logs: Array<any> // The logs generated by this UserOperation (not including logs of other UserOperations in the same bundle)
/* The TransactionReceipt object for the entire bundle, not only for this UserOperation. */
// biome-ignore lint/suspicious/noExplicitAny: difficult to type
receipt: any
}

Expand Down
12 changes: 11 additions & 1 deletion src/client/decorators/paymaster.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { Client } from "viem"
import { getPaymasterFeeQuotesOrData } from "../../paymaster/actions/getPaymasterFeeQuotesOrData"
import { sponsorUserOperation } from "../../paymaster/actions/sponsorUserOperation"
import type { PaymasterClient } from "../../paymaster/createPaymasterClient"
import type {
FeeQuoteOrDataParameters,
FeeQuotesOrDataERC20Response,
FeeQuotesOrDataSponsoredResponse,
SponsorUserOperationParameters,
SponsorUserOperationReturnType
} from "../../paymaster/utils/types"
Expand Down Expand Up @@ -33,6 +37,10 @@ export type PaymasterClientActions = {
args: SponsorUserOperationParameters
) => Promise<SponsorUserOperationReturnType>

getPaymasterFeeQuotesOrData: (
args: FeeQuoteOrDataParameters
) => Promise<FeeQuotesOrDataERC20Response | FeeQuotesOrDataSponsoredResponse>

/**
* Returns all the Paymaster addresses associated with an EntryPoint that’s owned by this service.
*
Expand Down Expand Up @@ -63,7 +71,9 @@ export const paymasterActions =
sponsorUserOperation: async (args) =>
sponsorUserOperation(client as PaymasterClient, {
...args
})
}),
getPaymasterFeeQuotesOrData: async (args) =>
getPaymasterFeeQuotesOrData(client as PaymasterClient, args)
// accounts: async (args) =>
// accounts(client as PaymasterClient, args)
})
37 changes: 37 additions & 0 deletions src/paymaster/actions/getPaymasterFeeQuotesOrData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { PaymasterClient } from "../createPaymasterClient"
import { deepHexlify } from "../utils/helpers"
import type {
FeeQuoteOrDataParameters,
FeeQuotesOrDataERC20Response
} from "../utils/types"
import type { FeeQuotesOrDataSponsoredResponse } from "./../utils/types"

export const getPaymasterFeeQuotesOrData = async (
client: PaymasterClient,
args: FeeQuoteOrDataParameters
): Promise<FeeQuotesOrDataERC20Response | FeeQuotesOrDataSponsoredResponse> => {
const response = await client.request({
method: "pm_getFeeQuoteOrData",
params: [
deepHexlify(args.userOperation),
{
mode: args.mode,
calculateGasLimits: args.calculateGasLimits ?? true,
expiryDuration: args.expiryDuration,
tokenInfo: {
tokenList: args.tokenList ?? [],
preferredToken: args.preferredToken
},
sponsorshipInfo: {
webhookData: args.webhookData,
smartAccountInfo: {
name: "BICONOMY",
version: "2.0.0"
}
}
}
]
})

return response
}
5 changes: 4 additions & 1 deletion src/paymaster/actions/sponsorUserOperation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ export const sponsorUserOperation = async (
deepHexlify(args.userOperation),
{
mode: args.mode,
calculateGasLimits: true,
calculateGasLimits: args.calculateGasLimits ?? true,
expiryDuration: args.expiryDuration,
tokenInfo: args.tokenInfo,
sponsorshipInfo: {
webhookData: args.webhookData,
smartAccountInfo: {
name: "BICONOMY",
version: "2.0.0"
Expand Down
1 change: 1 addition & 0 deletions src/paymaster/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const extractChainIdFromPaymasterUrl = (url: string): number => {
}
}

// biome-ignore lint/suspicious/noExplicitAny: Difficult to type
export function deepHexlify(obj: any): any {
if (typeof obj === "function") {
return undefined
Expand Down
128 changes: 123 additions & 5 deletions src/paymaster/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Address } from "viem"
import type { Address, Hash, Hex } from "viem"
import type { PartialBy } from "viem/chains"
import type { BytesLike, UserOperationStruct } from "../../accounts/utils/types"
import type {
BigNumberish,
BytesLike,
UserOperationStruct
} from "../../accounts/utils/types"

export type SponsorUserOperationReturnType = {
callGasLimit: string
Expand All @@ -9,14 +13,67 @@ export type SponsorUserOperationReturnType = {
paymasterAndData: BytesLike
}

export enum PaymasterMode {
ERC20 = "ERC20",
SPONSORED = "SPONSORED"
}

export type FeeTokenInfo = {
feeTokenAddress: string
}

export type SmartAccountInfo = {
/** name: Name of the smart account */
name: string
/** version: Version of the smart account */
version: string
}

export type SponsorUserOperationParameters = {
userOperation: UserOperationStruct
mode: PaymasterMode
calculateGasLimits?: boolean
expiryDuration?: number
tokenInfo?: FeeTokenInfo
/** Webhooks to be fired after user op is sent */
webhookData?: Record<string, any>
}

export enum PaymasterMode {
ERC20 = "ERC20",
SPONSORED = "SPONSORED"
export type FeeQuoteOrDataParameters = {
userOperation: UserOperationStruct
/** mode: sponsored or erc20 */
mode?: PaymasterMode
/** Expiry duration in seconds */
expiryDuration?: number
/** Always recommended, especially when using token paymaster */
calculateGasLimits?: boolean
/** List of tokens to be used for fee quotes, if ommitted fees for all supported will be returned */
tokenList?: string[]
/** preferredToken: Can be ommitted to return all quotes */
preferredToken?: string
/** Webhooks to be fired after user op is sent */
webhookData?: Record<string, any>
/** Smart account meta data */
sponsorshipInfo?: {
smartAccountInfo: {
name: string
version: string
}
}
}

export type FeeQuotesOrDataContext = {
mode: PaymasterMode | undefined
calculateGasLimits: boolean
expiryDuration: number | undefined
tokenInfo: {
tokenList: string[]
preferredToken: string | undefined
}
sponsorshipInfo: {
webhookData: Record<string, any> | undefined
smartAccountInfo: SmartAccountInfo
}
}

export type PaymasterContext = {
Expand All @@ -30,6 +87,56 @@ export type PaymasterContext = {
}
}

export type PaymasterFeeQuote = {
/** symbol: Token symbol */
symbol: string
/** tokenAddress: Token address */
tokenAddress: string
/** decimal: Token decimal */
decimal: number
logoUrl?: string
/** maxGasFee: in wei */
maxGasFee: number
/** maxGasFee: in dollars */
maxGasFeeUSD?: number
usdPayment?: number
/** The premium paid on the token */
premiumPercentage: number
/** validUntil: Unix timestamp */
validUntil?: number
}

export type FeeQuotesOrDataSponsoredResponse = {
mode: PaymasterMode
/** Normally set to the spender in the proceeding call to send the tx */
paymasterAddress?: Hex
/** Relevant Data returned from the paymaster */
paymasterAndData?: Uint8Array | Hex
/* Gas overhead of this UserOperation */
preVerificationGas?: BigNumberish
/* Actual gas used by the validation of this UserOperation */
verificationGasLimit?: BigNumberish
/* Value used by inner account execution */
callGasLimit?: BigNumberish
userOpHash: Hash
}

export type FeeQuotesOrDataERC20Response = {
mode: PaymasterMode
/** Array of results from the paymaster */
feeQuotes?: PaymasterFeeQuote[]
/** Normally set to the spender in the proceeding call to send the tx */
paymasterAddress?: Hex
/** Relevant Data returned from the paymaster */
paymasterAndData?: Uint8Array | Hex
/* Gas overhead of this UserOperation */
preVerificationGas?: BigNumberish
/* Actual gas used by the validation of this UserOperation */
verificationGasLimit?: BigNumberish
/* Value used by inner account execution */
callGasLimit?: BigNumberish
}

export type PaymasterRpcSchema = [
{
Method: "pm_sponsorUserOperation"
Expand All @@ -47,6 +154,17 @@ export type PaymasterRpcSchema = [
callGasLimit: string
}
},
{
Method: "pm_getFeeQuoteOrData"
Parameters: [
userOperation: PartialBy<
UserOperationStruct,
"callGasLimit" | "preVerificationGas" | "verificationGasLimit"
>,
context: FeeQuotesOrDataContext
]
ReturnType: FeeQuotesOrDataERC20Response | FeeQuotesOrDataSponsoredResponse
},
{
Method: "pm_accounts"
Parameters: [entryPoint: Address]
Expand Down
Loading

0 comments on commit 0182262

Please sign in to comment.