diff --git a/.changeset/large-hornets-scream.md b/.changeset/large-hornets-scream.md new file mode 100644 index 00000000000..24e36346adc --- /dev/null +++ b/.changeset/large-hornets-scream.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/engine": patch +--- + +Update to latest API diff --git a/.changeset/whole-ducks-cheat.md b/.changeset/whole-ducks-cheat.md new file mode 100644 index 00000000000..e2c3c6c9465 --- /dev/null +++ b/.changeset/whole-ducks-cheat.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Update server wallet config types for 7702 and EOA execution diff --git a/packages/engine/src/client/sdk.gen.ts b/packages/engine/src/client/sdk.gen.ts index d5d63f1a4b4..10b2115de55 100644 --- a/packages/engine/src/client/sdk.gen.ts +++ b/packages/engine/src/client/sdk.gen.ts @@ -169,7 +169,13 @@ export const signTypedData = ( /** * Read Contract - * Read from multiple smart contracts using multicall + * Read from smart contracts with intelligent execution strategy: + * - Single calls: Always executed directly for efficiency + * - Multiple calls: Uses multicall by default, or direct calls if disabled + * - Failed preparations: Returns preparation errors directly + * + * If multicall is not specified, it will be used by default. In case of multicall related errors, engine will fallback to direct calls. + * Only in the case where multicall is explicitly enabled, engine will not fallback to direct calls. */ export const readContract = ( options: Options, @@ -268,8 +274,8 @@ export const listAccounts = ( }; /** - * Create Server Wallet - * Create a new engine server wallet. This is a helper route for creating a new EOA with your KMS provider, provided as a convenient alternative to creating an EOA directly with your KMS provider. Your KMS credentials are not stored, and usage of created accounts require your KMS credentials to be sent with requests. + * Get or Create Server Wallet + * Create a new engine server wallet or retrieve an existing one. If the EOA already exists for the given label, it will be returned without creating a new one. */ export const createAccount = ( options?: Options, diff --git a/packages/engine/src/client/types.gen.ts b/packages/engine/src/client/types.gen.ts index 2dce1b1aae4..1d05d44f30e 100644 --- a/packages/engine/src/client/types.gen.ts +++ b/packages/engine/src/client/types.gen.ts @@ -18,7 +18,7 @@ export type TransactionsFilterNested = { }; /** - * ### Address + * EVM Address * Used to represent an EVM address. This is a string of length 42 with a `0x` prefix. Non-checksummed addresses are also supported, but will be converted to checksummed. */ export type AddressDef = string; @@ -368,7 +368,7 @@ export type BatchResultsSignResultData = { }; /** - * # Bytes + * Bytes * Used to represent "bytes". This is a 0x prefixed hex string. */ export type BytesDef = string; @@ -469,6 +469,21 @@ export type ContractWrite = ContractCall & { value?: null | U256Def; }; +/** + * EIP-7702 Execution Options + */ +export type Eip7702ExecutionOptions = { + /** + * The EOA address that will sign the EIP-7702 transaction + */ + from: AddressDef; +}; + +export type EmptyIdempotencySetResponse = { + queueName: string; + message: string; +}; + /** * Options for encoding contract function calls */ @@ -530,6 +545,37 @@ export type EntrypointAndFactoryDetailsDeserHelper = { export type EntrypointVersion = "0.6" | "0.7"; +/** + * ### EOA Execution Options + * This struct configures EOA (Externally Owned Account) direct execution. + * + * EOA execution sends transactions directly from an EOA address without + * smart contract abstraction. This is the most basic form of transaction + * execution and is suitable for simple transfers and contract interactions. + * + * ### Use Cases + * - Direct ETH transfers + * - Simple contract interactions + * - Gas-efficient transactions + * - When smart account features are not needed + * + * ### Features + * - Direct transaction execution from EOA + * - Automatic nonce management + * - Gas price optimization + * - Transaction confirmation tracking + * - Retry and recovery mechanisms + * - Support for EIP-1559, EIP-2930, and Legacy transactions + * - Support for EIP-7702 delegated transactions + */ +export type EoaExecutionOptions = { + /** + * The EOA address to send transactions from + * This account must have sufficient balance to pay for gas and transaction value + */ + from: AddressDef; +}; + /** * EOA signing options */ @@ -675,13 +721,18 @@ export type IawError = }); /** - * # InnerTransaction + * ### InnerTransaction * This is the actual encoded inner transaction data that will be sent to the blockchain. */ -export type InnerTransaction = { +export type InnerTransaction = (null | TransactionTypeData) & { to?: null | AddressDef; data?: BytesDef; value?: U256Def; + /** + * Gas limit for the transaction + * If not provided, engine will estimate the gas limit + */ + gasLimit?: number | null; }; export type MessageFormatDef = "text" | "hex"; @@ -700,6 +751,8 @@ export type MessageInput = { format?: MessageFormatDef; }; +export type MulticallDocType = boolean | AddressDef; + /** * # QueuedTransaction * Response for any request that queues one or more transactions @@ -742,14 +795,8 @@ export type ReadOptions = { /** * The blockchain network ID to read from */ - chainId: string; - /** - * Address of the Multicall3 contract to use for batching calls - * - * Defaults to the standard Multicall3 address: 0xcA11bde05977b3631167028862bE2a173976CA11 - * which is deployed on most networks - */ - multicallAddress?: AddressDef; + chainId: number; + multicall?: null | MulticallDocType; from?: null | AddressDef; }; @@ -782,9 +829,11 @@ export type RpcErrorKind = type: "NULL_RESP"; } | { + message: string; type: "UNSUPPORTED_FEATURE"; } | { + message: string; type: "INTERNAL_ERROR"; } | { @@ -811,6 +860,7 @@ export type RpcErrorKind = type: "TRANSPORT_HTTP_ERROR"; } | { + message: string; type: "OTHER_TRANSPORT_ERROR"; }; @@ -836,7 +886,7 @@ export type RpcErrorResponse = { export type SendTransactionRequest = { executionOptions: ExecutionOptions; params: Array; - webhookOptions?: Array | null; + webhookOptions?: Array; }; export type SerializableReqwestError = @@ -951,12 +1001,50 @@ export type SignTypedDataRequest = { params: Array; }; +/** + * EIP-7702 Signed Authorization + * EIP-7702 Signed Authorization structure for OpenAPI schema + * Contains an authorization plus the cryptographic signature + */ +export type SignedAuthorizationSchema = { + /** + * The chain ID of the authorization + * Must match the chain where the transaction will be executed + */ + chainId: U256Def; + /** + * The smart contract address to delegate to + * This contract will be able to execute logic on behalf of the EOA + */ + address: AddressDef; + /** + * The nonce for the authorization + * Must be the current nonce of the authorizing account + */ + nonce: number; + /** + * Signature parity value (0 or 1) + * Used for ECDSA signature recovery + */ + yParity: number; + /** + * Signature r value + * First component of the ECDSA signature + */ + r: U256Def; + /** + * Signature s value + * Second component of the ECDSA signature + */ + s: U256Def; +}; + /** * Configuration options for signing operations */ export type SigningOptions = | (EoaSigningOptions & { - type: "eoa"; + type: "EOA"; }) | (Erc4337SigningOptions & { type: "ERC4337"; @@ -983,8 +1071,21 @@ export type SpecificExecutionOptions = }) | (Erc4337ExecutionOptions & { type: "ERC4337"; + }) + | (EoaExecutionOptions & { + type: "EOA"; + }) + | (Eip7702ExecutionOptions & { + type: "EIP7702"; }); +export type SuccessResponseEmptyIdempotencySetResponse = { + result: { + queueName: string; + message: string; + }; +}; + export type SuccessResponseQueuedTransactionsResponse = { result: { transactions: Array; @@ -1016,11 +1117,73 @@ export type ThirdwebSerializationError = { }; }; +/** + * EIP-1559 Specific Transaction Data + * EIP-1559 transaction configuration + * Uses base fee + priority fee model for more predictable gas pricing + */ +export type Transaction1559Data = { + /** + * Maximum fee per gas willing to pay (in wei) + * This is the total fee cap including base fee and priority fee + */ + maxFeePerGas?: number | null; + /** + * Maximum priority fee per gas willing to pay (in wei) + * This is the tip paid to validators for transaction inclusion + */ + maxPriorityFeePerGas?: number | null; +}; + +/** + * EIP-7702 Specific Transaction Data + * EIP-7702 transaction configuration + * Allows delegation of EOA to smart contract logic temporarily + */ +export type Transaction7702Data = { + /** + * List of signed authorizations for contract delegation + * Each authorization allows the EOA to temporarily delegate to a smart contract + */ + authorizationList?: Array | null; + /** + * Maximum fee per gas willing to pay (in wei) + * This is the total fee cap including base fee and priority fee + */ + maxFeePerGas?: number | null; + /** + * Maximum priority fee per gas willing to pay (in wei) + * This is the tip paid to validators for transaction inclusion + */ + maxPriorityFeePerGas?: number | null; +}; + export type TransactionCancelResponse = { transactionId: string; result: CancelResult; }; +/** + * Legacy Specific Transaction Data + * Legacy transaction configuration + * Uses simple gas price model (pre-EIP-1559) + */ +export type TransactionLegacyData = { + /** + * Gas price willing to pay (in wei) + * This is the total price per unit of gas for legacy transactions + */ + gasPrice?: number | null; +}; + +/** + * Transaction Type Specific Data + */ +export type TransactionTypeData = + | Transaction7702Data + | Transaction1559Data + | TransactionLegacyData; + export type TypedDataDef = { /** * Signing domain metadata. The signing domain is the intended context for @@ -1059,7 +1222,7 @@ export type TypedDataDomainDef = { }; /** - * # U256 + * U256 * Used to represent a 256-bit unsigned integer. Engine can parse these from any valid encoding of the Ethereum "quantity" format. */ export type U256Def = string; @@ -1076,6 +1239,11 @@ export type Value = unknown; export type WebhookOptions = { url: string; secret?: string | null; + /** + * Custom metadata provided by the user to be included in webhook notifications. + * Limited to 4KB (4096 bytes) to prevent abuse. + */ + userMetadata?: string | null; }; /** @@ -1093,7 +1261,7 @@ export type WriteContractRequest = { * or as separate transactions if atomic batching is not supported */ params: Array; - webhookOptions?: Array | null; + webhookOptions?: Array; }; export type U64 = number; @@ -1267,7 +1435,10 @@ export type CancelTransactionResponse = export type ListAccountsData = { body?: never; path?: never; - query?: never; + query?: { + page?: number; + limit?: number; + }; url: "/v1/accounts"; }; @@ -1276,17 +1447,25 @@ export type ListAccountsResponses = { * Accounts retrieved successfully */ 200: { - result: Array<{ - /** - * EVM address in hex format - */ - address: string; - label?: string; - /** - * The predicted smart account address for use with the default thirdweb v0.7 AccountFactory - */ - smartAccountAddress?: string; - }>; + result: { + accounts: Array<{ + /** + * EVM address in hex format + */ + address: string; + label?: string; + createdAt: string; + /** + * The predicted smart account address for use with the default thirdweb v0.7 AccountFactory + */ + smartAccountAddress?: string; + }>; + pagination: { + totalCount: number; + page: number; + limit: number; + }; + }; }; }; @@ -1319,6 +1498,7 @@ export type CreateAccountResponses = { */ address: string; label?: string; + createdAt: string; /** * The predicted smart account address for use with the default thirdweb v0.7 AccountFactory */ @@ -1346,6 +1526,7 @@ export type GetTransactionsData = { * EVM address in hex format */ signerAddress?: string; + status?: "QUEUED" | "SUBMITTED" | "CONFIRMED" | "FAILED"; sortBy?: "createdAt" | "confirmedAt"; sortDirection?: "asc" | "desc"; }; diff --git a/packages/thirdweb/src/engine/list-server-wallets.ts b/packages/thirdweb/src/engine/list-server-wallets.ts index 53e4213ad64..57aa4ebc20c 100644 --- a/packages/thirdweb/src/engine/list-server-wallets.ts +++ b/packages/thirdweb/src/engine/list-server-wallets.ts @@ -6,6 +6,8 @@ import { getClientFetch } from "../utils/fetch.js"; export type GetServerWalletsArgs = { client: ThirdwebClient; + limit?: number; + page?: number; }; /** @@ -30,6 +32,10 @@ export async function getServerWallets(params: GetServerWalletsArgs) { baseUrl: getThirdwebBaseUrl("engineCloud"), bodySerializer: stringify, fetch: getClientFetch(client), + query: { + limit: params.limit, + page: params.page, + }, }); if (result.error) { diff --git a/packages/thirdweb/src/engine/server-wallet.test.ts b/packages/thirdweb/src/engine/server-wallet.test.ts index 6bf7f61130a..5b847ca3abf 100644 --- a/packages/thirdweb/src/engine/server-wallet.test.ts +++ b/packages/thirdweb/src/engine/server-wallet.test.ts @@ -16,7 +16,6 @@ import { setApprovalForAll } from "../extensions/erc1155/__generated__/IERC1155/ import { claimTo } from "../extensions/erc1155/drops/write/claimTo.js"; import { getAllActiveSigners } from "../extensions/erc4337/__generated__/IAccountPermissions/read/getAllActiveSigners.js"; import { sendTransaction } from "../transaction/actions/send-transaction.js"; -import { setThirdwebDomains } from "../utils/domains.js"; import { smartWallet } from "../wallets/smart/smart-wallet.js"; import { generateAccount } from "../wallets/utils/generateAccount.js"; import * as Engine from "./index.js"; @@ -35,15 +34,15 @@ describe.runIf( let serverWallet: Engine.ServerWallet; beforeAll(async () => { - setThirdwebDomains({ - bundler: "bundler.thirdweb-dev.com", - engineCloud: "engine.thirdweb-dev.com", - // engineCloud: "localhost:3009", - rpc: "rpc.thirdweb-dev.com", - storage: "storage.thirdweb-dev.com", - }); + // setThirdwebDomains({ + // bundler: "bundler.thirdweb-dev.com", + // engineCloud: "engine.thirdweb-dev.com", + // // engineCloud: "localhost:3009", + // rpc: "rpc.thirdweb-dev.com", + // storage: "storage.thirdweb-dev.com", + // }); serverWallet = Engine.serverWallet({ - address: process.env.ENGINE_CLOUD_WALLET_ADDRESS as string, + address: process.env.ENGINE_CLOUD_WALLET_ADDRESS_EOA as string, chain: sepolia, client: TEST_CLIENT, vaultAccessToken: process.env.VAULT_TOKEN as string, @@ -61,9 +60,9 @@ describe.runIf( client: TEST_CLIENT, }); expect(serverWallets).toBeDefined(); - expect(serverWallets.length).toBeGreaterThan(0); + expect(serverWallets.accounts.length).toBeGreaterThan(0); expect( - serverWallets.find((s) => s.address === serverWallet.address), + serverWallets.accounts.find((s) => s.address === serverWallet.address), ).toBeDefined(); }); @@ -111,7 +110,7 @@ describe.runIf( const tx = await sendTransaction({ account: serverWallet, transaction: { - chain: arbitrumSepolia, + chain: baseSepolia, client: TEST_CLIENT, to: TEST_ACCOUNT_B.address, value: 0n, diff --git a/packages/thirdweb/src/engine/server-wallet.ts b/packages/thirdweb/src/engine/server-wallet.ts index 8e97f6b818c..1e9cb6df9f7 100644 --- a/packages/thirdweb/src/engine/server-wallet.ts +++ b/packages/thirdweb/src/engine/server-wallet.ts @@ -181,6 +181,18 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet { chainId, type: "ERC4337", }; + case "EOA": + return { + chainId, + from: address, + type: "EOA", + }; + case "EIP7702": + return { + chainId, + from: address, + type: "EIP7702", + }; } }; @@ -192,7 +204,7 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet { if (!chainId) { return { from: address, - type: "eoa", + type: "EOA", }; } @@ -212,7 +224,6 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet { type: "ERC4337", }; } - case "auto": { return { chainId, @@ -220,6 +231,14 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet { type: "auto", }; } + case "EIP7702": + case "EOA": { + return { + chainId, + from: address, + type: "EOA", + }; + } } }; @@ -245,6 +264,7 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet { params: transaction.map((t) => ({ data: t.data, to: t.to, + gasLimit: t.gas ? Number(t.gas) : undefined, value: t.value?.toString(), })), };