import { PermissionsCapability, PermissionsData, } from "../capabilities/permissions/index.js"; import { CallArray, PreparedCall_UserOpV060_Signed, PreparedCall_UserOpV070_Signed, PreparedCall_Authorization_Signed, Address, Base64UrlEncodedString, CreationOptionsBySignerAddress, Hex, SerializedInitcode, TypedDataSignatureRequest, Uuid, TypedDataDefinition, SignableMessage, EcdsaSig, StatusCode, TransactionReceipt, HexChainId, HexNumber, HexBigInt, } from "../schemas.js"; import { PrepareCallsRequestType, PrepareCallsReturnType, PrepareCallsReturnTypeWithoutChainId, PreparedCallsUserOperationDataWithoutCallId, } from "../prepareCalls.js"; import { SwapParams } from "./swaps.js"; import { SendPreparedCallsCapabilities } from "../capabilities/index.js"; import { PreparedCall_SolanaV0_Signed, SolanaGetCallsStatusResponse, } from "../solana.js"; import { object, union, z } from "../zod.js"; export const wallet_sendPreparedCalls = object( { Request: object({ method: z.literal("wallet_sendPreparedCalls"), params: z.tuple([ z.union([ z .intersection( z.union([ CallArray, PreparedCall_UserOpV060_Signed, PreparedCall_UserOpV070_Signed, PreparedCall_Authorization_Signed, ]), object({ capabilities: SendPreparedCallsCapabilities.optional(), callId: Hex().optional(), }), ) .describe("EVM request"), PreparedCall_SolanaV0_Signed, ]), ]), }), ReturnType: z.union([ object( { id: Hex(), // TODO: We should deprecate `preparedCallIds` eventually, but may need a // new `version` to ensure no breaking changes, b/c this affects a lot. preparedCallIds: z.array(Hex()).meta({ description: "To be deprecated. Please use `id` instead.", }), details: z.discriminatedUnion("type", [ object({ type: z.literal("user-operation"), data: PreparedCallsUserOperationDataWithoutCallId, }), object({ type: z.literal("delegation"), }), ]), }, { description: "EVM response" }, ), object( { id: Hex(), preparedCallIds: z.array(Hex()), details: object({ type: z.literal("solana-transaction-v0"), }), }, { description: "Solana response", }, ), ]), }, { description: "This method is used after signing the signatureRequest returned from prepareCalls to submit a user operation", }, ); export const wallet_prepareCalls = object( { Request: PrepareCallsRequestType, ReturnType: PrepareCallsReturnType, }, { description: "This method is used to prepare a user operation for submission. It will return a built user operation and a signature request which needs to be signed by the user before submitting to wallet_sendPreparedCalls", }, ); export const wallet_requestAccount = object( { Request: object({ method: z.literal("wallet_requestAccount"), params: z.tuple([ union( { errorMessage: "Must provide either 'signerAddress' (with optional 'id', 'creationHint', 'includeCounterfactualInfo') or 'accountAddress' (with optional 'includeCounterfactualInfo')", }, [ object( { signerAddress: Address(), id: Uuid.optional(), creationHint: CreationOptionsBySignerAddress, includeCounterfactualInfo: z .boolean() .meta({ default: false }) .optional(), }, { description: "Using signer address", }, ), object( { accountAddress: Address(), includeCounterfactualInfo: z .boolean() .meta({ default: false }) .optional(), }, { description: "Using smart contract account address", }, ), ], ), ]), }), ReturnType: object({ accountAddress: Address(), id: Uuid, counterfactualInfo: SerializedInitcode.optional(), delegation: Address().optional(), }), }, { description: `This method is used to get the smart account address and relevant info for a given signer. If an account does not already exist for a given signer, this method will create one before returning the counterfactual address.`, }, ); export const wallet_listAccounts = object( { Request: object({ method: z.literal("wallet_listAccounts"), params: z.tuple([ object({ signerAddress: Address(), limit: z.number().min(1).max(100).meta({ default: 100 }).optional(), after: Base64UrlEncodedString.optional(), }), ]), }), ReturnType: object({ accounts: z.array( object({ accountAddress: Address(), id: Uuid, }), ), meta: object({ totalCount: z.int(), after: z.union([Base64UrlEncodedString, z.null()]), }), }), }, { description: "This method is used to list all smart accounts for a given signer.", }, ); export const wallet_createSession = object( { Request: object({ method: z.literal("wallet_createSession"), params: z.tuple([ z.intersection( PermissionsData, object({ account: Address(), }), ), ]), }), ReturnType: object({ sessionId: Hex(), chainId: HexChainId(), signatureRequest: TypedDataSignatureRequest, }), }, { description: "This method is used to create a session for a given address with specified permissions.", }, ); export const wallet_getCallsStatus = object( { Request: object({ method: z.literal("wallet_getCallsStatus"), params: z.tuple([ Hex({ description: "The call ID returned from wallet_sendPreparedCalls", title: "callId", }), ]), }), ReturnType: z.union([ object( { id: Hex(), chainId: HexChainId(), atomic: z.boolean(), status: StatusCode, receipts: z.array(TransactionReceipt).optional(), details: z.discriminatedUnion("type", [ object({ type: z.literal("user-operation"), data: z.intersection( PreparedCallsUserOperationDataWithoutCallId, object({ pendingBundle: object({ txHash: Hex(), sentAtBlock: HexNumber(), }).optional(), }), ), }), object({ type: z.literal("delegation"), txHash: Hex().optional(), }), ]), }, { description: "EVM response" }, ), SolanaGetCallsStatusResponse, ]), }, { description: "This method is used to get the status of calls IDs returned from wallet_sendPreparedCalls.", }, ); export const wallet_getCrossChainStatus_v0 = object( { Request: object({ method: z.literal("wallet_getCrossChainStatus_v0"), params: z.tuple([ Hex({ description: "The call ID returned from wallet_sendPreparedCalls", title: "callId", }), ]), }), ReturnType: z.discriminatedUnion("type", [ object({ type: z.literal("same-chain"), id: Hex(), status: StatusCode, originTransaction: object({ chainId: HexChainId(), status: StatusCode, receipt: TransactionReceipt.optional(), }).optional(), }), object({ type: z.literal("cross-chain"), id: Hex(), status: StatusCode, originTransaction: object({ chainId: HexChainId(), status: StatusCode, receipt: TransactionReceipt.optional(), }).optional(), destinationTransaction: object({ chainId: HexChainId(), status: StatusCode, receipt: TransactionReceipt.optional(), }).optional(), }), ]), }, { description: "This method is used to get the status of a transaction (same-chain or cross-chain).", }, ); const InputSignatureRequest = z.discriminatedUnion("type", [ object( { type: z.literal("personal_sign"), data: SignableMessage, }, { description: "SignableMessage for personal_sign", }, ), object( { type: z.literal("eth_signTypedData_v4"), data: TypedDataDefinition, }, { description: "TypedDataDefinition for eth_signTypedData_v4", }, ), ]); export const wallet_prepareSign = object( { Request: object({ method: z.literal("wallet_prepareSign"), params: z.tuple([ object({ from: Address(), chainId: HexChainId(), signatureRequest: InputSignatureRequest, capabilities: object({ permissions: PermissionsCapability, }).optional(), }), ]), }), ReturnType: object({ chainId: HexChainId(), signatureRequest: InputSignatureRequest, }), }, { description: "This method is used to translate raw data into a signature request", }, ); export const wallet_formatSign = object( { Request: object({ method: z.literal("wallet_formatSign"), params: z.tuple([ object({ from: Address(), chainId: HexChainId(), signature: EcdsaSig.shape.signature, capabilities: object({ permissions: PermissionsCapability, }).optional(), }), ]), }), ReturnType: object({ signature: Hex(), }), }, { description: "This method is used to format ECDSA signatures", }, ); export const wallet_requestQuote_v0 = object( { Request: object({ method: z.literal("wallet_requestQuote_v0"), params: z.tuple([ z .union([ z .union([ z .union([ SwapParams.variant({ chain: "Same", execution: "SmartWallet", amount: "From", description: "Specify exact 'from' amount", }), SwapParams.variant({ chain: "Same", execution: "SmartWallet", amount: "MinimumTo", description: "Specify minimum 'to' amount", }), ]) .describe("Smart wallet execution"), z .union([ SwapParams.variant({ chain: "Same", execution: "Eoa", amount: "From", description: "Specify exact 'from' amount", }), SwapParams.variant({ chain: "Same", execution: "Eoa", amount: "MinimumTo", description: "Specify minimum 'to' amount", }), ]) .describe("EOA execution (raw calls)"), ]) .describe("Same-chain swap"), z .union([ z .union([ SwapParams.variant({ chain: "Cross", execution: "SmartWallet", amount: "From", description: "Specify exact 'from' amount", }), SwapParams.variant({ chain: "Cross", execution: "SmartWallet", amount: "MinimumTo", description: "Specify minimum 'to' amount", }), ]) .describe("Smart wallet execution"), z .union([ SwapParams.variant({ chain: "Cross", execution: "Eoa", amount: "From", description: "Specify exact 'from' amount", }), SwapParams.variant({ chain: "Cross", execution: "Eoa", amount: "MinimumTo", description: "Specify minimum 'to' amount", }), ]) .describe("EOA execution (raw calls)"), ]) .describe("Cross-chain swap"), ]) .describe("Swap options"), ]), }), ReturnType: z.intersection( object({ quote: object({ fromAmount: HexBigInt(), minimumToAmount: HexBigInt(), expiry: HexNumber(), }), chainId: HexChainId(), callId: Hex().optional(), }), z.union([ z .intersection( object({ rawCalls: z .literal(false) .meta({ description: "Always 'false'" }), }), PrepareCallsReturnTypeWithoutChainId, ) .describe("Prepared calls for smart wallet execution"), object( { rawCalls: z.literal(true).meta({ description: "Always 'true'" }), calls: z.array( object({ to: Address(), data: Hex().optional(), value: HexBigInt().optional(), }), ), }, { description: "Raw calls for externally owned account execution", }, ), ]), ), }, { description: "This method is used to request swap quotes", }, ); export const wallet_getCapabilities = object( { Request: object({ method: z.literal("wallet_getCapabilities"), params: union( { errorMessage: "Parameters must be either [walletAddress] or [walletAddress, chainIds]. Wallet address must be a valid hex address (e.g., '0xd46e8dd67c5d32be8058bb8eb970870f07244567'). Chain IDs must be an array of hex chain IDs (e.g., ['0x2105', '0x14A34'])", }, [ z.tuple([Address({ title: "Wallet Address" })]), z.tuple([ Address({ title: "Wallet Address" }), z.array(HexChainId()).meta({ title: "Chain IDs" }), ]), ], ), }), ReturnType: z .record( Hex(), z .record( z.string(), z.unknown().meta({ description: "Mapping from capability name to data", }), ) .meta({ description: "Mapping from capability name to data", }), ) .meta({ description: "Mapping from chain ID (hex) to capabilities", }), }, { description: "This method is used to request capabilities from a wallet", }, );