From cb6aa6500707bb5ca117e7f4ce864cc202f4403d Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 01:13:41 -0500 Subject: [PATCH 01/59] Functional impl --- src/client/api.ts | 772 ++++++++++++++++++++++ src/client/configuration.ts | 8 +- src/coinbase/actions/sendUserOperation.ts | 115 ++++ src/coinbase/actions/signTransaction.ts | 0 src/coinbase/utils/wait.ts | 31 + src/coinbase/wallets/createSmartWallet.ts | 32 + src/coinbase/wallets/types.ts | 45 ++ test_new_smart_wallet.ts | 47 ++ 8 files changed, 1049 insertions(+), 1 deletion(-) create mode 100644 src/coinbase/actions/sendUserOperation.ts create mode 100644 src/coinbase/actions/signTransaction.ts create mode 100644 src/coinbase/utils/wait.ts create mode 100644 src/coinbase/wallets/createSmartWallet.ts create mode 100644 src/coinbase/wallets/types.ts create mode 100644 test_new_smart_wallet.ts diff --git a/src/client/api.ts b/src/client/api.ts index da0e706f..8b24f319 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -417,6 +417,19 @@ export interface BroadcastTransferRequest { */ 'signed_payload': string; } +/** + * + * @export + * @interface BroadcastUserOperationRequest + */ +export interface BroadcastUserOperationRequest { + /** + * The hex-encoded signature of the user operation. + * @type {string} + * @memberof BroadcastUserOperationRequest + */ + 'signature': string; +} /** * * @export @@ -454,6 +467,31 @@ export interface BuildStakingOperationRequest { */ 'options': { [key: string]: string; }; } +/** + * An action that will be bundled into a user operation. + * @export + * @interface Call + */ +export interface Call { + /** + * The address the call is interacting with. + * @type {string} + * @memberof Call + */ + 'to': string; + /** + * The hex-encoded data to send with the call. + * @type {string} + * @memberof Call + */ + 'data': string; + /** + * The string-encoded integer value to send with the call. + * @type {string} + * @memberof Call + */ + 'value': string; +} /** * * @export @@ -938,6 +976,19 @@ export interface CreateSmartContractRequest { } +/** + * + * @export + * @interface CreateSmartWalletRequest + */ +export interface CreateSmartWalletRequest { + /** + * The address of the owner of the smart wallet. + * @type {string} + * @memberof CreateSmartWalletRequest + */ + 'owner': string; +} /** * * @export @@ -1037,6 +1088,19 @@ export interface CreateTransferRequest { */ 'skip_batching'?: boolean; } +/** + * + * @export + * @interface CreateUserOperationRequest + */ +export interface CreateUserOperationRequest { + /** + * The list of calls to make from the smart wallet. + * @type {Array} + * @memberof CreateUserOperationRequest + */ + 'calls': Array; +} /** * * @export @@ -3043,6 +3107,56 @@ export const SmartContractType = { export type SmartContractType = typeof SmartContractType[keyof typeof SmartContractType]; +/** + * + * @export + * @interface SmartWallet + */ +export interface SmartWallet { + /** + * The onchain address of the smart wallet. + * @type {string} + * @memberof SmartWallet + */ + 'address': string; + /** + * The list of owner addresses for the smart wallet. + * @type {Array} + * @memberof SmartWallet + */ + 'owners': Array; +} +/** + * Paginated list of smart wallets + * @export + * @interface SmartWalletList + */ +export interface SmartWalletList { + /** + * + * @type {Array} + * @memberof SmartWalletList + */ + 'data': Array; + /** + * True if this list has another page of items after this one that can be fetched. + * @type {boolean} + * @memberof SmartWalletList + */ + 'has_more': boolean; + /** + * The page token to be used to fetch the next page. + * @type {string} + * @memberof SmartWalletList + */ + 'next_page': string; + /** + * The total number of wallets + * @type {number} + * @memberof SmartWalletList + */ + 'total_count': number; +} /** * * @export @@ -3261,6 +3375,12 @@ export interface StakingContextContext { * @memberof StakingContextContext */ 'unstakeable_balance': Balance; + /** + * + * @type {Balance} + * @memberof StakingContextContext + */ + 'pending_claimable_balance': Balance; /** * * @type {Balance} @@ -3870,6 +3990,60 @@ export interface User { */ 'display_name'?: string; } +/** + * + * @export + * @interface UserOperation + */ +export interface UserOperation { + /** + * The ID of the user operation. + * @type {string} + * @memberof UserOperation + */ + 'id': string; + /** + * The ID of the network the user operation is being created on. + * @type {string} + * @memberof UserOperation + */ + 'network_id': string; + /** + * The list of calls to make from the smart wallet. + * @type {Array} + * @memberof UserOperation + */ + 'calls': Array; + /** + * The hex-encoded hash that must be signed by the user. + * @type {string} + * @memberof UserOperation + */ + 'unsigned_payload': string; + /** + * The hex-encoded signature of the user operation. + * @type {string} + * @memberof UserOperation + */ + 'signature'?: string; + /** + * The status of the user operation. + * @type {string} + * @memberof UserOperation + */ + 'status'?: UserOperationStatusEnum; +} + +export const UserOperationStatusEnum = { + Pending: 'pending', + Signed: 'signed', + Broadcast: 'broadcast', + Complete: 'complete', + Failed: 'failed' +} as const; + +export type UserOperationStatusEnum = typeof UserOperationStatusEnum[keyof typeof UserOperationStatusEnum]; + /** * A validator onchain. * @export @@ -9716,6 +9890,604 @@ export class SmartContractsApi extends BaseAPI implements SmartContractsApiInter +/** + * SmartWalletsApi - axios parameter creator + * @export + */ +export const SmartWalletsApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * Broadcast a user operation + * @summary Broadcast a user operation + * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. + * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + broadcastUserOperation: async (smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'smartWalletAddress' is not null or undefined + assertParamExists('broadcastUserOperation', 'smartWalletAddress', smartWalletAddress) + // verify required parameter 'userOperationId' is not null or undefined + assertParamExists('broadcastUserOperation', 'userOperationId', userOperationId) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}/broadcast` + .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))) + .replace(`{${"user_operation_id"}}`, encodeURIComponent(String(userOperationId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(broadcastUserOperationRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Create a new smart wallet, not scoped to a given network. + * @summary Create a new smart wallet + * @param {CreateSmartWalletRequest} [createSmartWalletRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createSmartWallet: async (createSmartWalletRequest?: CreateSmartWalletRequest, options: RawAxiosRequestConfig = {}): Promise => { + const localVarPath = `/v1/smart_wallets`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(createSmartWalletRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Create a new user operation on a smart wallet. + * @summary Create a new user operation + * @param {string} smartWalletAddress The address of the smart wallet to create the user operation on. + * @param {string} networkId The ID of the network to create the user operation on. + * @param {CreateUserOperationRequest} [createUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createUserOperation: async (smartWalletAddress: string, networkId: string, createUserOperationRequest?: CreateUserOperationRequest, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'smartWalletAddress' is not null or undefined + assertParamExists('createUserOperation', 'smartWalletAddress', smartWalletAddress) + // verify required parameter 'networkId' is not null or undefined + assertParamExists('createUserOperation', 'networkId', networkId) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/networks/{network_id}/user_operations` + .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))) + .replace(`{${"network_id"}}`, encodeURIComponent(String(networkId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(createUserOperationRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get smart wallet + * @summary Get smart wallet by address + * @param {string} smartWalletAddress The address of that smart wallet to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSmartWallet: async (smartWalletAddress: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'smartWalletAddress' is not null or undefined + assertParamExists('getSmartWallet', 'smartWalletAddress', smartWalletAddress) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}` + .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + // authentication session required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get user operation + * @summary Get user operation + * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. + * @param {string} userOperationId The ID of the user operation to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getUserOperation: async (smartWalletAddress: string, userOperationId: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'smartWalletAddress' is not null or undefined + assertParamExists('getUserOperation', 'smartWalletAddress', smartWalletAddress) + // verify required parameter 'userOperationId' is not null or undefined + assertParamExists('getUserOperation', 'userOperationId', userOperationId) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}` + .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))) + .replace(`{${"user_operation_id"}}`, encodeURIComponent(String(userOperationId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + // authentication session required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * List smart wallets + * @summary List smart wallets + * @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + * @param {string} [page] A cursor for pagination across multiple pages of results. Don\'t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listSmartWallets: async (limit?: number, page?: string, options: RawAxiosRequestConfig = {}): Promise => { + const localVarPath = `/v1/smart_wallets`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication apiKey required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + // authentication session required + await setApiKeyToObject(localVarHeaderParameter, "Jwt", configuration) + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (page !== undefined) { + localVarQueryParameter['page'] = page; + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * SmartWalletsApi - functional programming interface + * @export + */ +export const SmartWalletsApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = SmartWalletsApiAxiosParamCreator(configuration) + return { + /** + * Broadcast a user operation + * @summary Broadcast a user operation + * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. + * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.broadcastUserOperation']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Create a new smart wallet, not scoped to a given network. + * @summary Create a new smart wallet + * @param {CreateSmartWalletRequest} [createSmartWalletRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createSmartWallet(createSmartWalletRequest?: CreateSmartWalletRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.createSmartWallet(createSmartWalletRequest, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.createSmartWallet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Create a new user operation on a smart wallet. + * @summary Create a new user operation + * @param {string} smartWalletAddress The address of the smart wallet to create the user operation on. + * @param {string} networkId The ID of the network to create the user operation on. + * @param {CreateUserOperationRequest} [createUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createUserOperation(smartWalletAddress: string, networkId: string, createUserOperationRequest?: CreateUserOperationRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.createUserOperation(smartWalletAddress, networkId, createUserOperationRequest, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.createUserOperation']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Get smart wallet + * @summary Get smart wallet by address + * @param {string} smartWalletAddress The address of that smart wallet to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getSmartWallet(smartWalletAddress: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getSmartWallet(smartWalletAddress, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.getSmartWallet']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * Get user operation + * @summary Get user operation + * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. + * @param {string} userOperationId The ID of the user operation to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getUserOperation(smartWalletAddress, userOperationId, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.getUserOperation']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * List smart wallets + * @summary List smart wallets + * @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + * @param {string} [page] A cursor for pagination across multiple pages of results. Don\'t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listSmartWallets(limit?: number, page?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listSmartWallets(limit, page, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.listSmartWallets']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * SmartWalletsApi - factory interface + * @export + */ +export const SmartWalletsApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = SmartWalletsApiFp(configuration) + return { + /** + * Broadcast a user operation + * @summary Broadcast a user operation + * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. + * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options).then((request) => request(axios, basePath)); + }, + /** + * Create a new smart wallet, not scoped to a given network. + * @summary Create a new smart wallet + * @param {CreateSmartWalletRequest} [createSmartWalletRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createSmartWallet(createSmartWalletRequest?: CreateSmartWalletRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.createSmartWallet(createSmartWalletRequest, options).then((request) => request(axios, basePath)); + }, + /** + * Create a new user operation on a smart wallet. + * @summary Create a new user operation + * @param {string} smartWalletAddress The address of the smart wallet to create the user operation on. + * @param {string} networkId The ID of the network to create the user operation on. + * @param {CreateUserOperationRequest} [createUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createUserOperation(smartWalletAddress: string, networkId: string, createUserOperationRequest?: CreateUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.createUserOperation(smartWalletAddress, networkId, createUserOperationRequest, options).then((request) => request(axios, basePath)); + }, + /** + * Get smart wallet + * @summary Get smart wallet by address + * @param {string} smartWalletAddress The address of that smart wallet to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSmartWallet(smartWalletAddress: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getSmartWallet(smartWalletAddress, options).then((request) => request(axios, basePath)); + }, + /** + * Get user operation + * @summary Get user operation + * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. + * @param {string} userOperationId The ID of the user operation to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getUserOperation(smartWalletAddress, userOperationId, options).then((request) => request(axios, basePath)); + }, + /** + * List smart wallets + * @summary List smart wallets + * @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + * @param {string} [page] A cursor for pagination across multiple pages of results. Don\'t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listSmartWallets(limit?: number, page?: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listSmartWallets(limit, page, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * SmartWalletsApi - interface + * @export + * @interface SmartWalletsApi + */ +export interface SmartWalletsApiInterface { + /** + * Broadcast a user operation + * @summary Broadcast a user operation + * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. + * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * Create a new smart wallet, not scoped to a given network. + * @summary Create a new smart wallet + * @param {CreateSmartWalletRequest} [createSmartWalletRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + createSmartWallet(createSmartWalletRequest?: CreateSmartWalletRequest, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * Create a new user operation on a smart wallet. + * @summary Create a new user operation + * @param {string} smartWalletAddress The address of the smart wallet to create the user operation on. + * @param {string} networkId The ID of the network to create the user operation on. + * @param {CreateUserOperationRequest} [createUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + createUserOperation(smartWalletAddress: string, networkId: string, createUserOperationRequest?: CreateUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * Get smart wallet + * @summary Get smart wallet by address + * @param {string} smartWalletAddress The address of that smart wallet to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + getSmartWallet(smartWalletAddress: string, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * Get user operation + * @summary Get user operation + * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. + * @param {string} userOperationId The ID of the user operation to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * List smart wallets + * @summary List smart wallets + * @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + * @param {string} [page] A cursor for pagination across multiple pages of results. Don\'t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApiInterface + */ + listSmartWallets(limit?: number, page?: string, options?: RawAxiosRequestConfig): AxiosPromise; + +} + +/** + * SmartWalletsApi - object-oriented interface + * @export + * @class SmartWalletsApi + * @extends {BaseAPI} + */ +export class SmartWalletsApi extends BaseAPI implements SmartWalletsApiInterface { + /** + * Broadcast a user operation + * @summary Broadcast a user operation + * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. + * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * Create a new smart wallet, not scoped to a given network. + * @summary Create a new smart wallet + * @param {CreateSmartWalletRequest} [createSmartWalletRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public createSmartWallet(createSmartWalletRequest?: CreateSmartWalletRequest, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).createSmartWallet(createSmartWalletRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * Create a new user operation on a smart wallet. + * @summary Create a new user operation + * @param {string} smartWalletAddress The address of the smart wallet to create the user operation on. + * @param {string} networkId The ID of the network to create the user operation on. + * @param {CreateUserOperationRequest} [createUserOperationRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public createUserOperation(smartWalletAddress: string, networkId: string, createUserOperationRequest?: CreateUserOperationRequest, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).createUserOperation(smartWalletAddress, networkId, createUserOperationRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * Get smart wallet + * @summary Get smart wallet by address + * @param {string} smartWalletAddress The address of that smart wallet to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public getSmartWallet(smartWalletAddress: string, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).getSmartWallet(smartWalletAddress, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * Get user operation + * @summary Get user operation + * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. + * @param {string} userOperationId The ID of the user operation to fetch. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).getUserOperation(smartWalletAddress, userOperationId, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * List smart wallets + * @summary List smart wallets + * @param {number} [limit] A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + * @param {string} [page] A cursor for pagination across multiple pages of results. Don\'t include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartWalletsApi + */ + public listSmartWallets(limit?: number, page?: string, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).listSmartWallets(limit, page, options).then((request) => request(this.axios, this.basePath)); + } +} + + + /** * StakeApi - axios parameter creator * @export diff --git a/src/client/configuration.ts b/src/client/configuration.ts index 1fc8a134..a1a0c93e 100644 --- a/src/client/configuration.ts +++ b/src/client/configuration.ts @@ -89,7 +89,13 @@ export class Configuration { this.accessToken = param.accessToken; this.basePath = param.basePath; this.serverIndex = param.serverIndex; - this.baseOptions = param.baseOptions; + this.baseOptions = { + headers: { + ...param.baseOptions?.headers, + 'User-Agent': "OpenAPI-Generator/typescript-axios" + }, + ...param.baseOptions + }; this.formDataCtor = param.formDataCtor; } diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts new file mode 100644 index 00000000..7c403e21 --- /dev/null +++ b/src/coinbase/actions/sendUserOperation.ts @@ -0,0 +1,115 @@ +import { UserOperationCalls } from "viem/_types/account-abstraction" +import { SmartWallet } from "../wallets/types" +import { NetworkIdentifier, UserOperationStatusEnum } from "../../client" +import { encodeFunctionData } from "viem" +import { Coinbase } from "../coinbase" +import { wait } from "../utils/wait" + +export type SendUserOperationOptions = { + calls: UserOperationCalls +} + +export type SendUserOperationReturnType = { + id: string + networkId: NetworkIdentifier + smartWalletAddress: string + status: UserOperationStatusEnum + wait: () => Promise +} + + +export async function sendUserOperation( + wallet: SmartWallet, + options: SendUserOperationOptions +): Promise { + if (!wallet.networkId) { + throw new Error('Network not set - call use({networkId}) first'); + } + const networkId = wallet.networkId; + + const encodedCalls = options.calls.map((call) => { + if ('abi' in call) { + return { + data: encodeFunctionData({ + abi: call.abi, + functionName: call.functionName, + args: call.args + }), + to: call.to, + value: call.value.toString() || '0' + } + } + return { + data: call.data, + to: call.to, + value: call.value.toString() || '0' + } + }) + + const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( + wallet.address, + networkId, + { + calls: encodedCalls + } + ) + + if (!createOpResponse.data) { + throw new Error('Failed to create user operation') + } + + if (!wallet.account.sign) { + throw new Error('Account does not support signing') + } + + const signature = await wallet.account.sign({ hash: createOpResponse.data.unsigned_payload as `0x${string}` }) + + const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( + wallet.address, + createOpResponse.data.id, + { + signature, + } + ) + + if (!broadcastResponse.data) { + throw new Error('Failed to broadcast user operation') + } + + const returnValue: SendUserOperationReturnType = { + id: broadcastResponse.data.id, + networkId: networkId, + smartWalletAddress: wallet.address, + status: broadcastResponse.data.status!, + wait: async () => { + const reload = async () => { + const result = await Coinbase.apiClients.smartWallet!.getUserOperation( + wallet.address, + broadcastResponse.data.id + ); + + if (!result.data) { + throw new Error('Failed to get user operation status'); + } + + return { + id: result.data.id, + networkId: networkId, + smartWalletAddress: wallet.address, + status: result.data.status!, + wait: returnValue.wait + }; + }; + + return wait( + reload, + (op) => op.status === UserOperationStatusEnum.Complete || op.status === UserOperationStatusEnum.Failed, + { intervalSeconds: 0.2, timeoutSeconds: 10 } + ); + } + }; + + return returnValue; +} + + diff --git a/src/coinbase/actions/signTransaction.ts b/src/coinbase/actions/signTransaction.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/coinbase/utils/wait.ts b/src/coinbase/utils/wait.ts new file mode 100644 index 00000000..37f464b7 --- /dev/null +++ b/src/coinbase/utils/wait.ts @@ -0,0 +1,31 @@ +import { TimeoutError } from "../errors"; + + +export type WaitOptions = { + intervalSeconds?: number + timeoutSeconds?: number +} +export async function wait( + reload: () => Promise, + isTerminal: (obj: T) => boolean, + options: WaitOptions = {} +): Promise { + const { + intervalSeconds = 0.2, + timeoutSeconds = 10, + } = options; + + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutSeconds * 1000) { + const updatedObject = await reload(); + + if (isTerminal(updatedObject)) { + return updatedObject; + } + + await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000)); + } + + throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); +} \ No newline at end of file diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts new file mode 100644 index 00000000..6667a371 --- /dev/null +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -0,0 +1,32 @@ +import type { + SmartWallet, +} from './types' +import { Coinbase } from '../coinbase' +import { sendUserOperation } from '../actions/sendUserOperation' +import type { LocalAccount } from 'viem' + + +export type CreateSmartWalletOptions = { + account: LocalAccount +} + +export async function createSmartWallet( + options: CreateSmartWalletOptions +): Promise { + const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ + owner: options.account.address, + }) + + if (!result.data) { + throw new Error('Failed to create smart wallet') + } + + const wallet: SmartWallet = { + address: result.data.address as `0x${string}`, + account: options.account, + type: 'smart', + sendUserOperation: (options) => sendUserOperation(wallet, options) + } + + return wallet +} \ No newline at end of file diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts new file mode 100644 index 00000000..e759490b --- /dev/null +++ b/src/coinbase/wallets/types.ts @@ -0,0 +1,45 @@ +import type { Address } from 'abitype' +import type { LocalAccount } from 'viem' +import type { NetworkIdentifier } from '../../client' +import { SendUserOperationOptions, SendUserOperationReturnType } from '../actions/sendUserOperation' + + +export type SmartWallet = { + address: Address + account: LocalAccount + networkId?: NetworkIdentifier + type: 'smart' + sendUserOperation: (options: SendUserOperationOptions) => Promise +} + +// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. +// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. +// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. +// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. +// export type BaseWallet = { +// sign: (parameters: { hash: Hash }) => Promise +// signMessage: ({ message }: { message: SignableMessage }) => Promise +// signTypedData: ( +// typedData: TypedData | { [key: string]: unknown }, +// ) => Promise +// } + +// export type PrivateKeyWallet = Prettify Promise; +// }> + +// export type HDKeyWallet = Prettify + +// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise +// }> diff --git a/test_new_smart_wallet.ts b/test_new_smart_wallet.ts new file mode 100644 index 00000000..e688c531 --- /dev/null +++ b/test_new_smart_wallet.ts @@ -0,0 +1,47 @@ +import { createWalletClient, http, parseEther } from 'viem' +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts' +import { Coinbase, Wallet } from './src' +import { mainnet } from 'viem/chains'; +import { createSmartWallet } from './src/coinbase/wallets/createSmartWallet' + +Coinbase.configureFromJson({ + filePath: "~/.apikeys/dev.json", + debugging: true, + basePath: "http://localhost:8002" +}); + +async function main() { + + // create a smart wallet with viem wallet owner + const privateKey = generatePrivateKey() + const owner = privateKeyToAccount(privateKey) + const smartWallet = await createSmartWallet({account: owner}) + + smartWallet.use({networkId: Coinbase.networks.BaseSepolia }) + + // I believe that SCW-Manager should automatically sponsor all base-sepolia user operations so we don't need to have additional funds for gas + const userOperation = await smartWallet.sendUserOperation({ + calls: [ + { + to: (await wallet.getDefaultAddress()).getId() as `0x${string}`, + value: parseEther(halfBalance.toString()), + data: '0x' + }, + // { + // to: (await wallet.getDefaultAddress()).getId() as `0x${string}`, + // abi: myAbi, + // functionName: "transfer", + // args: [ + // (await wallet.getDefaultAddress()).getId() as `0x${string}`, + // parseEther(halfBalance.toString()) + // ], + // value: parseEther(halfBalance.toString()) + // } + ] + }) + await userOperation.wait() + + console.log(userOperation.getStatus()) +} + +main(); From bbebfa7bb0a1ebfe5459e416aea42dd011641ae6 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 01:18:51 -0500 Subject: [PATCH 02/59] cleanup --- src/coinbase/actions/sendUserOperation.ts | 1 - src/coinbase/types.ts | 79 ++++++++++++++++++++++- src/coinbase/utils/wait.ts | 1 + src/coinbase/wallets/createSmartWallet.ts | 6 +- src/coinbase/wallets/types.ts | 1 + test_new_smart_wallet.ts | 29 +++++---- 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 7c403e21..8b65ce80 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -17,7 +17,6 @@ export type SendUserOperationReturnType = { wait: () => Promise } - export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 8aef4db2..34409377 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -12,6 +12,7 @@ import { CreateTransferRequest, TransferList, Wallet as WalletModel, + SmartWallet as SmartWalletModel, Transfer as TransferModel, Trade as TradeModel, Asset as AssetModel, @@ -68,6 +69,10 @@ import { CompiledSmartContract, BroadcastExternalTransactionRequest, BroadcastExternalTransaction200Response, + CreateSmartWalletRequest, + CreateUserOperationRequest, + UserOperation as UserOperationModel, + BroadcastUserOperationRequest, } from "./../client/api"; import { Address } from "./address"; import { Wallet } from "./wallet"; @@ -244,6 +249,77 @@ export type WalletAPIClient = { ): AxiosPromise; }; +/** + * SmartWalletAPI client type definition. + */ +export type SmartWalletAPIClient = { + /** + * Create a new smart wallet scoped to the user. + * + * @class + * @param createdSmartWalletRequest - The smart wallet creation request. + * @param options - Axios request options. + * @throws {APIError} If the request fails. + */ + createSmartWallet: ( + createSmartWalletRequest?: CreateSmartWalletRequest, + options?: RawAxiosRequestConfig, + ) => AxiosPromise; + + /* + Get the smart wallet by address + + @param smartWalletAddress - The address of the smart wallet to fetch. + @param options - Override http request option. + @throws {APIError} If the request fails. + */ + getSmartWallet: ( + smartWalletAddress: string, + options?: RawAxiosRequestConfig, + ) => AxiosPromise; + + /* + Create a user operation + + @param createUserOperationRequest - The user operation creation request. + @param options - Override http request option. + @throws {APIError} If the request fails. + */ + createUserOperation: ( + smartWalletAddress: string, + networkId: string, + createUserOperationRequest: CreateUserOperationRequest, + options?: RawAxiosRequestConfig, + ) => AxiosPromise; + + /* + Broadcast a user operation + + @param broadcastUserOperationRequest - The user operation broadcast request. + @param options - Override http request option. + @throws {APIError} If the request fails. + */ + broadcastUserOperation: ( + smartWalletAddress: string, + userOperationId: string, + broadcastUserOperationRequest: BroadcastUserOperationRequest, + options?: RawAxiosRequestConfig, + ) => AxiosPromise; + + /* + Get a user operation by ID + + @param userOperationId - The ID of the user operation to fetch. + @param options - Override http request option. + @throws {APIError} If the request fails. + */ + getUserOperation: ( + smartWalletAddress: string, + userOperationId: string, + options?: RawAxiosRequestConfig, + ) => AxiosPromise; +}; + /** * AddressAPI client type definition. */ @@ -751,6 +827,7 @@ export type ApiClients = { smartContract?: SmartContractAPIClient; fund?: FundOperationApiClient; addressReputation?: AddressReputationApiClient; + smartWallet?: SmartWalletAPIClient; }; /** @@ -1726,4 +1803,4 @@ export interface PaginationResponse { export interface BroadcastExternalTransactionResponse { transactionHash: string; transactionLink?: string; -} +} \ No newline at end of file diff --git a/src/coinbase/utils/wait.ts b/src/coinbase/utils/wait.ts index 37f464b7..e1b8d772 100644 --- a/src/coinbase/utils/wait.ts +++ b/src/coinbase/utils/wait.ts @@ -5,6 +5,7 @@ export type WaitOptions = { intervalSeconds?: number timeoutSeconds?: number } + export async function wait( reload: () => Promise, isTerminal: (obj: T) => boolean, diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts index 6667a371..3613302d 100644 --- a/src/coinbase/wallets/createSmartWallet.ts +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -4,6 +4,7 @@ import type { import { Coinbase } from '../coinbase' import { sendUserOperation } from '../actions/sendUserOperation' import type { LocalAccount } from 'viem' +import { NetworkIdentifier } from '../../client' export type CreateSmartWalletOptions = { @@ -25,7 +26,10 @@ export async function createSmartWallet( address: result.data.address as `0x${string}`, account: options.account, type: 'smart', - sendUserOperation: (options) => sendUserOperation(wallet, options) + sendUserOperation: (options) => sendUserOperation(wallet, options), + use: (options: { networkId: NetworkIdentifier }) => { + wallet.networkId = options.networkId + } } return wallet diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts index e759490b..82498af8 100644 --- a/src/coinbase/wallets/types.ts +++ b/src/coinbase/wallets/types.ts @@ -10,6 +10,7 @@ export type SmartWallet = { networkId?: NetworkIdentifier type: 'smart' sendUserOperation: (options: SendUserOperationOptions) => Promise + use: (options: { networkId: NetworkIdentifier }) => void } // In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. diff --git a/test_new_smart_wallet.ts b/test_new_smart_wallet.ts index e688c531..709a7ade 100644 --- a/test_new_smart_wallet.ts +++ b/test_new_smart_wallet.ts @@ -11,6 +11,12 @@ Coinbase.configureFromJson({ }); async function main() { + // create a wallet + const wallet = await Wallet.create(); + + // faucet it + const faucet = await wallet.faucet(); + await faucet.wait(); // create a smart wallet with viem wallet owner const privateKey = generatePrivateKey() @@ -19,6 +25,17 @@ async function main() { smartWallet.use({networkId: Coinbase.networks.BaseSepolia }) + // send ETH from wallet to smart wallet so the smart wallet has funds to send back + const currentBalance = await wallet.getBalance("eth") + const halfBalance = currentBalance.div(2) + + const transfer = await wallet.createTransfer({ + amount: halfBalance, // send half since we need some funds for gas + assetId: "eth", + destination: smartWallet.address, + }) + await transfer.wait() + // I believe that SCW-Manager should automatically sponsor all base-sepolia user operations so we don't need to have additional funds for gas const userOperation = await smartWallet.sendUserOperation({ calls: [ @@ -27,21 +44,11 @@ async function main() { value: parseEther(halfBalance.toString()), data: '0x' }, - // { - // to: (await wallet.getDefaultAddress()).getId() as `0x${string}`, - // abi: myAbi, - // functionName: "transfer", - // args: [ - // (await wallet.getDefaultAddress()).getId() as `0x${string}`, - // parseEther(halfBalance.toString()) - // ], - // value: parseEther(halfBalance.toString()) - // } ] }) await userOperation.wait() - console.log(userOperation.getStatus()) + console.log(userOperation.status) } main(); From 17d5b7ba6fedde99066880c928073606147bec55 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 01:30:59 -0500 Subject: [PATCH 03/59] Changes --- src/coinbase/coinbase.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coinbase/coinbase.ts b/src/coinbase/coinbase.ts index 6b9fd818..03165cc2 100644 --- a/src/coinbase/coinbase.ts +++ b/src/coinbase/coinbase.ts @@ -20,6 +20,7 @@ import { MPCWalletStakeApiFactory, FundApiFactory, ReputationApiFactory, + SmartWalletsApiFactory, } from "../client"; import { BASE_PATH } from "./../client/base"; import { Configuration } from "./../client/configuration"; @@ -144,6 +145,7 @@ export class Coinbase { ); Coinbase.apiClients.wallet = WalletsApiFactory(config, basePath, axiosInstance); + Coinbase.apiClients.smartWallet = SmartWalletsApiFactory(config, basePath, axiosInstance); Coinbase.apiClients.address = AddressesApiFactory(config, basePath, axiosInstance); Coinbase.apiClients.transfer = TransfersApiFactory(config, basePath, axiosInstance); Coinbase.apiClients.trade = TradesApiFactory(config, basePath, axiosInstance); From eb240a967211566c9460392e6bcbffafcf380714 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 01:37:56 -0500 Subject: [PATCH 04/59] Dev --- test_new_smart_wallet.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_new_smart_wallet.ts b/test_new_smart_wallet.ts index 709a7ade..af029f80 100644 --- a/test_new_smart_wallet.ts +++ b/test_new_smart_wallet.ts @@ -7,9 +7,10 @@ import { createSmartWallet } from './src/coinbase/wallets/createSmartWallet' Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", debugging: true, - basePath: "http://localhost:8002" + basePath: "https://cloud-api-dev.cbhq.net/platform" }); + async function main() { // create a wallet const wallet = await Wallet.create(); From ca8ec12ec3b35401bb02d55783c64ce3c68314ad Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 10:32:10 -0500 Subject: [PATCH 05/59] Delete --- src/coinbase/actions/signTransaction.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/coinbase/actions/signTransaction.ts diff --git a/src/coinbase/actions/signTransaction.ts b/src/coinbase/actions/signTransaction.ts deleted file mode 100644 index e69de29b..00000000 From 5a329038c0d1f922ccab5a3aac0d115b593c62b8 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 10:55:37 -0500 Subject: [PATCH 06/59] Change wait --- src/coinbase/actions/sendUserOperation.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 8b65ce80..b3547001 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -92,9 +92,7 @@ export async function sendUserOperation( } return { - id: result.data.id, - networkId: networkId, - smartWalletAddress: wallet.address, + ...returnValue, status: result.data.status!, wait: returnValue.wait }; From 517fa51b76c5f068fa02bac27234543c5b84a634 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 10:56:15 -0500 Subject: [PATCH 07/59] format lint --- src/coinbase/actions/sendUserOperation.ts | 86 ++++++++++++----------- src/coinbase/types.ts | 54 +++++++------- src/coinbase/utils/wait.ts | 16 ++--- src/coinbase/wallets/createSmartWallet.ts | 39 +++++----- src/coinbase/wallets/types.ts | 28 ++++---- test_new_smart_wallet.ts | 45 ++++++------ 6 files changed, 132 insertions(+), 136 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index b3547001..79e9f8ce 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -1,78 +1,80 @@ -import { UserOperationCalls } from "viem/_types/account-abstraction" -import { SmartWallet } from "../wallets/types" -import { NetworkIdentifier, UserOperationStatusEnum } from "../../client" -import { encodeFunctionData } from "viem" -import { Coinbase } from "../coinbase" -import { wait } from "../utils/wait" +import { UserOperationCalls } from "viem/_types/account-abstraction"; +import { SmartWallet } from "../wallets/types"; +import { NetworkIdentifier, UserOperationStatusEnum } from "../../client"; +import { encodeFunctionData } from "viem"; +import { Coinbase } from "../coinbase"; +import { wait } from "../utils/wait"; export type SendUserOperationOptions = { - calls: UserOperationCalls -} + calls: UserOperationCalls; +}; export type SendUserOperationReturnType = { - id: string - networkId: NetworkIdentifier - smartWalletAddress: string - status: UserOperationStatusEnum - wait: () => Promise -} + id: string; + networkId: NetworkIdentifier; + smartWalletAddress: string; + status: UserOperationStatusEnum; + wait: () => Promise; +}; export async function sendUserOperation( wallet: SmartWallet, - options: SendUserOperationOptions + options: SendUserOperationOptions, ): Promise { if (!wallet.networkId) { - throw new Error('Network not set - call use({networkId}) first'); + throw new Error("Network not set - call use({networkId}) first"); } const networkId = wallet.networkId; - const encodedCalls = options.calls.map((call) => { - if ('abi' in call) { + const encodedCalls = options.calls.map(call => { + if ("abi" in call) { return { data: encodeFunctionData({ abi: call.abi, functionName: call.functionName, - args: call.args + args: call.args, }), to: call.to, - value: call.value.toString() || '0' - } + value: call.value.toString() || "0", + }; } return { data: call.data, to: call.to, - value: call.value.toString() || '0' - } - }) + value: call.value.toString() || "0", + }; + }); const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( wallet.address, networkId, { - calls: encodedCalls - } - ) + calls: encodedCalls, + }, + ); if (!createOpResponse.data) { - throw new Error('Failed to create user operation') + throw new Error("Failed to create user operation"); } if (!wallet.account.sign) { - throw new Error('Account does not support signing') + throw new Error("Account does not support signing"); } - const signature = await wallet.account.sign({ hash: createOpResponse.data.unsigned_payload as `0x${string}` }) + const signature = await wallet.account.sign({ + hash: createOpResponse.data.unsigned_payload as `0x${string}`, + }); const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( wallet.address, createOpResponse.data.id, { signature, - } - ) + }, + ); if (!broadcastResponse.data) { - throw new Error('Failed to broadcast user operation') + throw new Error("Failed to broadcast user operation"); } const returnValue: SendUserOperationReturnType = { @@ -84,29 +86,29 @@ export async function sendUserOperation( const reload = async () => { const result = await Coinbase.apiClients.smartWallet!.getUserOperation( wallet.address, - broadcastResponse.data.id + broadcastResponse.data.id, ); - + if (!result.data) { - throw new Error('Failed to get user operation status'); + throw new Error("Failed to get user operation status"); } return { ...returnValue, status: result.data.status!, - wait: returnValue.wait + wait: returnValue.wait, }; }; return wait( reload, - (op) => op.status === UserOperationStatusEnum.Complete || op.status === UserOperationStatusEnum.Failed, - { intervalSeconds: 0.2, timeoutSeconds: 10 } + op => + op.status === UserOperationStatusEnum.Complete || + op.status === UserOperationStatusEnum.Failed, + { intervalSeconds: 0.2, timeoutSeconds: 10 }, ); - } + }, }; return returnValue; } - - diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 34409377..623aad91 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -267,52 +267,52 @@ export type SmartWalletAPIClient = { ) => AxiosPromise; /* - Get the smart wallet by address - - @param smartWalletAddress - The address of the smart wallet to fetch. - @param options - Override http request option. - @throws {APIError} If the request fails. - */ + *Get the smart wallet by address + * + *@param smartWalletAddress - The address of the smart wallet to fetch. + *@param options - Override http request option. + *@throws {APIError} If the request fails. + */ getSmartWallet: ( smartWalletAddress: string, options?: RawAxiosRequestConfig, ) => AxiosPromise; /* - Create a user operation - - @param createUserOperationRequest - The user operation creation request. - @param options - Override http request option. - @throws {APIError} If the request fails. - */ + *Create a user operation + * + *@param createUserOperationRequest - The user operation creation request. + *@param options - Override http request option. + *@throws {APIError} If the request fails. + */ createUserOperation: ( smartWalletAddress: string, networkId: string, createUserOperationRequest: CreateUserOperationRequest, options?: RawAxiosRequestConfig, ) => AxiosPromise; - - /* - Broadcast a user operation - @param broadcastUserOperationRequest - The user operation broadcast request. - @param options - Override http request option. - @throws {APIError} If the request fails. - */ + /* + *Broadcast a user operation + * + *@param broadcastUserOperationRequest - The user operation broadcast request. + *@param options - Override http request option. + *@throws {APIError} If the request fails. + */ broadcastUserOperation: ( - smartWalletAddress: string, + smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig, ) => AxiosPromise; /* - Get a user operation by ID - - @param userOperationId - The ID of the user operation to fetch. - @param options - Override http request option. - @throws {APIError} If the request fails. - */ + *Get a user operation by ID + * + *@param userOperationId - The ID of the user operation to fetch. + *@param options - Override http request option. + *@throws {APIError} If the request fails. + */ getUserOperation: ( smartWalletAddress: string, userOperationId: string, @@ -1803,4 +1803,4 @@ export interface PaginationResponse { export interface BroadcastExternalTransactionResponse { transactionHash: string; transactionLink?: string; -} \ No newline at end of file +} diff --git a/src/coinbase/utils/wait.ts b/src/coinbase/utils/wait.ts index e1b8d772..b928d7cf 100644 --- a/src/coinbase/utils/wait.ts +++ b/src/coinbase/utils/wait.ts @@ -1,20 +1,16 @@ import { TimeoutError } from "../errors"; - export type WaitOptions = { - intervalSeconds?: number - timeoutSeconds?: number -} + intervalSeconds?: number; + timeoutSeconds?: number; +}; export async function wait( reload: () => Promise, isTerminal: (obj: T) => boolean, - options: WaitOptions = {} + options: WaitOptions = {}, ): Promise { - const { - intervalSeconds = 0.2, - timeoutSeconds = 10, - } = options; + const { intervalSeconds = 0.2, timeoutSeconds = 10 } = options; const startTime = Date.now(); @@ -29,4 +25,4 @@ export async function wait( } throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); -} \ No newline at end of file +} diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts index 3613302d..a5231162 100644 --- a/src/coinbase/wallets/createSmartWallet.ts +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -1,36 +1,31 @@ -import type { - SmartWallet, -} from './types' -import { Coinbase } from '../coinbase' -import { sendUserOperation } from '../actions/sendUserOperation' -import type { LocalAccount } from 'viem' -import { NetworkIdentifier } from '../../client' - +import type { SmartWallet } from "./types"; +import { Coinbase } from "../coinbase"; +import { sendUserOperation } from "../actions/sendUserOperation"; +import type { LocalAccount } from "viem"; +import { NetworkIdentifier } from "../../client"; export type CreateSmartWalletOptions = { - account: LocalAccount -} + account: LocalAccount; +}; -export async function createSmartWallet( - options: CreateSmartWalletOptions -): Promise { +export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ owner: options.account.address, - }) + }); if (!result.data) { - throw new Error('Failed to create smart wallet') + throw new Error("Failed to create smart wallet"); } const wallet: SmartWallet = { address: result.data.address as `0x${string}`, account: options.account, - type: 'smart', - sendUserOperation: (options) => sendUserOperation(wallet, options), + type: "smart", + sendUserOperation: options => sendUserOperation(wallet, options), use: (options: { networkId: NetworkIdentifier }) => { - wallet.networkId = options.networkId - } - } + wallet.networkId = options.networkId; + }, + }; - return wallet -} \ No newline at end of file + return wallet; +} diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts index 82498af8..1f4ce9ee 100644 --- a/src/coinbase/wallets/types.ts +++ b/src/coinbase/wallets/types.ts @@ -1,17 +1,21 @@ -import type { Address } from 'abitype' -import type { LocalAccount } from 'viem' -import type { NetworkIdentifier } from '../../client' -import { SendUserOperationOptions, SendUserOperationReturnType } from '../actions/sendUserOperation' - +import type { Address } from "abitype"; +import type { LocalAccount } from "viem"; +import type { NetworkIdentifier } from "../../client"; +import { + SendUserOperationOptions, + SendUserOperationReturnType, +} from "../actions/sendUserOperation"; export type SmartWallet = { - address: Address - account: LocalAccount - networkId?: NetworkIdentifier - type: 'smart' - sendUserOperation: (options: SendUserOperationOptions) => Promise - use: (options: { networkId: NetworkIdentifier }) => void -} + address: Address; + account: LocalAccount; + networkId?: NetworkIdentifier; + type: "smart"; + sendUserOperation: ( + options: SendUserOperationOptions, + ) => Promise; + use: (options: { networkId: NetworkIdentifier }) => void; +}; // In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. // We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. diff --git a/test_new_smart_wallet.ts b/test_new_smart_wallet.ts index af029f80..232a865f 100644 --- a/test_new_smart_wallet.ts +++ b/test_new_smart_wallet.ts @@ -1,41 +1,40 @@ -import { createWalletClient, http, parseEther } from 'viem' -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts' -import { Coinbase, Wallet } from './src' -import { mainnet } from 'viem/chains'; -import { createSmartWallet } from './src/coinbase/wallets/createSmartWallet' +import { createWalletClient, http, parseEther } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { Coinbase, Wallet } from "./src"; +import { mainnet } from "viem/chains"; +import { createSmartWallet } from "./src/coinbase/wallets/createSmartWallet"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", debugging: true, - basePath: "https://cloud-api-dev.cbhq.net/platform" + basePath: "https://cloud-api-dev.cbhq.net/platform", }); - async function main() { // create a wallet const wallet = await Wallet.create(); - // faucet it - const faucet = await wallet.faucet(); - await faucet.wait(); + // faucet it + const faucet = await wallet.faucet(); + await faucet.wait(); // create a smart wallet with viem wallet owner - const privateKey = generatePrivateKey() - const owner = privateKeyToAccount(privateKey) - const smartWallet = await createSmartWallet({account: owner}) + const privateKey = generatePrivateKey(); + const owner = privateKeyToAccount(privateKey); + const smartWallet = await createSmartWallet({ account: owner }); - smartWallet.use({networkId: Coinbase.networks.BaseSepolia }) + smartWallet.use({ networkId: Coinbase.networks.BaseSepolia }); // send ETH from wallet to smart wallet so the smart wallet has funds to send back - const currentBalance = await wallet.getBalance("eth") - const halfBalance = currentBalance.div(2) + const currentBalance = await wallet.getBalance("eth"); + const halfBalance = currentBalance.div(2); const transfer = await wallet.createTransfer({ amount: halfBalance, // send half since we need some funds for gas assetId: "eth", destination: smartWallet.address, - }) - await transfer.wait() + }); + await transfer.wait(); // I believe that SCW-Manager should automatically sponsor all base-sepolia user operations so we don't need to have additional funds for gas const userOperation = await smartWallet.sendUserOperation({ @@ -43,13 +42,13 @@ async function main() { { to: (await wallet.getDefaultAddress()).getId() as `0x${string}`, value: parseEther(halfBalance.toString()), - data: '0x' + data: "0x", }, - ] - }) - await userOperation.wait() + ], + }); + await userOperation.wait(); - console.log(userOperation.status) + console.log(userOperation.status); } main(); From 5a3ce957a079b0d95c4b49f91102ec45476bcb2f Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 10:57:04 -0500 Subject: [PATCH 08/59] Fix --- test_new_smart_wallet.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_new_smart_wallet.ts b/test_new_smart_wallet.ts index 232a865f..4a12fe49 100644 --- a/test_new_smart_wallet.ts +++ b/test_new_smart_wallet.ts @@ -46,9 +46,9 @@ async function main() { }, ], }); - await userOperation.wait(); + const completedUserOperation = await userOperation.wait(); - console.log(userOperation.status); + console.log(completedUserOperation.status); } main(); From f5d325295618d567adea1b1e55ba9fb57fb0b47f Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 11:00:26 -0500 Subject: [PATCH 09/59] Rename --- test_new_smart_wallet.ts => testNewSmartWallet.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test_new_smart_wallet.ts => testNewSmartWallet.ts (100%) diff --git a/test_new_smart_wallet.ts b/testNewSmartWallet.ts similarity index 100% rename from test_new_smart_wallet.ts rename to testNewSmartWallet.ts From acab0ef36a71415e610e68d1ff2b008182a8ba56 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 11:33:22 -0500 Subject: [PATCH 10/59] Feedback --- src/coinbase/actions/sendUserOperation.ts | 10 +++---- src/coinbase/wallets/createSmartWallet.ts | 2 +- src/coinbase/wallets/types.ts | 2 +- testNewSmartWallet.ts | 33 ++++++----------------- 4 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 79e9f8ce..0c5ca5de 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -1,7 +1,7 @@ import { UserOperationCalls } from "viem/_types/account-abstraction"; import { SmartWallet } from "../wallets/types"; import { NetworkIdentifier, UserOperationStatusEnum } from "../../client"; -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase"; import { wait } from "../utils/wait"; @@ -21,10 +21,10 @@ export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, ): Promise { - if (!wallet.networkId) { + const { networkId } = wallet; + if (!networkId) { throw new Error("Network not set - call use({networkId}) first"); } - const networkId = wallet.networkId; const encodedCalls = options.calls.map(call => { if ("abi" in call) { @@ -62,7 +62,7 @@ export async function sendUserOperation( } const signature = await wallet.account.sign({ - hash: createOpResponse.data.unsigned_payload as `0x${string}`, + hash: createOpResponse.data.unsigned_payload as Hex, }); const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( @@ -79,7 +79,7 @@ export async function sendUserOperation( const returnValue: SendUserOperationReturnType = { id: broadcastResponse.data.id, - networkId: networkId, + networkId, smartWalletAddress: wallet.address, status: broadcastResponse.data.status!, wait: async () => { diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts index a5231162..bea47439 100644 --- a/src/coinbase/wallets/createSmartWallet.ts +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -22,7 +22,7 @@ export async function createSmartWallet(options: CreateSmartWalletOptions): Prom account: options.account, type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), - use: (options: { networkId: NetworkIdentifier }) => { + useNetwork: (options: { networkId: NetworkIdentifier }) => { wallet.networkId = options.networkId; }, }; diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts index 1f4ce9ee..6b1ec657 100644 --- a/src/coinbase/wallets/types.ts +++ b/src/coinbase/wallets/types.ts @@ -14,7 +14,7 @@ export type SmartWallet = { sendUserOperation: ( options: SendUserOperationOptions, ) => Promise; - use: (options: { networkId: NetworkIdentifier }) => void; + useNetwork: (options: { networkId: NetworkIdentifier }) => void; }; // In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 4a12fe49..5a751bfa 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,6 +1,6 @@ import { createWalletClient, http, parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Coinbase, Wallet } from "./src"; +import { Coinbase, ExternalAddress, Wallet } from "./src"; import { mainnet } from "viem/chains"; import { createSmartWallet } from "./src/coinbase/wallets/createSmartWallet"; @@ -11,44 +11,27 @@ Coinbase.configureFromJson({ }); async function main() { - // create a wallet - const wallet = await Wallet.create(); - - // faucet it - const faucet = await wallet.faucet(); - await faucet.wait(); - // create a smart wallet with viem wallet owner const privateKey = generatePrivateKey(); const owner = privateKeyToAccount(privateKey); const smartWallet = await createSmartWallet({ account: owner }); + smartWallet.useNetwork({ networkId: Coinbase.networks.BaseSepolia }); - smartWallet.use({ networkId: Coinbase.networks.BaseSepolia }); - - // send ETH from wallet to smart wallet so the smart wallet has funds to send back - const currentBalance = await wallet.getBalance("eth"); - const halfBalance = currentBalance.div(2); - - const transfer = await wallet.createTransfer({ - amount: halfBalance, // send half since we need some funds for gas - assetId: "eth", - destination: smartWallet.address, - }); - await transfer.wait(); + // Faucet the smart wallet using an External Address + const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); + const faucet = await externalAdress.faucet(); + await faucet.wait(); - // I believe that SCW-Manager should automatically sponsor all base-sepolia user operations so we don't need to have additional funds for gas const userOperation = await smartWallet.sendUserOperation({ calls: [ { - to: (await wallet.getDefaultAddress()).getId() as `0x${string}`, - value: parseEther(halfBalance.toString()), + to: "0x1234567890123456789012345678901234567890", + value: parseEther("0.00001"), data: "0x", }, ], }); const completedUserOperation = await userOperation.wait(); - - console.log(completedUserOperation.status); } main(); From 0dbe1a3c7efda9bb954b9b897ac6da01f6823803 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 11:36:25 -0500 Subject: [PATCH 11/59] Feedback --- src/coinbase/actions/sendUserOperation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 0c5ca5de..7c6348f0 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -73,7 +73,7 @@ export async function sendUserOperation( }, ); - if (!broadcastResponse.data) { + if (!broadcastResponse.data || !broadcastResponse.data.status) { throw new Error("Failed to broadcast user operation"); } @@ -81,7 +81,7 @@ export async function sendUserOperation( id: broadcastResponse.data.id, networkId, smartWalletAddress: wallet.address, - status: broadcastResponse.data.status!, + status: broadcastResponse.data.status, wait: async () => { const reload = async () => { const result = await Coinbase.apiClients.smartWallet!.getUserOperation( From f8ec203fc8b3c355ef91e3dfe1a9ab037b6349b2 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 11:36:47 -0500 Subject: [PATCH 12/59] Fix --- src/coinbase/actions/sendUserOperation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 7c6348f0..9b1ffde8 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -73,7 +73,7 @@ export async function sendUserOperation( }, ); - if (!broadcastResponse.data || !broadcastResponse.data.status) { + if (!broadcastResponse.data.status) { throw new Error("Failed to broadcast user operation"); } From 3f718339e1abc66f37a686acd0673dae62263bad Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 16:21:30 -0500 Subject: [PATCH 13/59] WIP --- src/coinbase/actions/sendUserOperation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index 9b1ffde8..a43eb244 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -12,7 +12,7 @@ export type SendUserOperationOptions = { export type SendUserOperationReturnType = { id: string; networkId: NetworkIdentifier; - smartWalletAddress: string; + smartWalletAddress: Hex; status: UserOperationStatusEnum; wait: () => Promise; }; From 7086127434267359d13e8c3f89651457ce8d562a Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 11 Feb 2025 21:31:48 -0500 Subject: [PATCH 14/59] WIP --- src/coinbase/actions/sendUserOperation.ts | 19 +++++++------- src/coinbase/types.ts | 32 +++++++++++++++++++++++ src/coinbase/wallets/createSmartWallet.ts | 8 +++--- src/coinbase/wallets/types.ts | 11 +++++--- testNewSmartWallet.ts | 20 ++++++++++---- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts index a43eb244..6a1d5817 100644 --- a/src/coinbase/actions/sendUserOperation.ts +++ b/src/coinbase/actions/sendUserOperation.ts @@ -1,9 +1,10 @@ import { UserOperationCalls } from "viem/_types/account-abstraction"; import { SmartWallet } from "../wallets/types"; -import { NetworkIdentifier, UserOperationStatusEnum } from "../../client"; +import { UserOperationStatusEnum } from "../../client"; import { encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase"; import { wait } from "../utils/wait"; +import { Network } from "../types"; export type SendUserOperationOptions = { calls: UserOperationCalls; @@ -11,7 +12,7 @@ export type SendUserOperationOptions = { export type SendUserOperationReturnType = { id: string; - networkId: NetworkIdentifier; + network: Network; smartWalletAddress: Hex; status: UserOperationStatusEnum; wait: () => Promise; @@ -19,11 +20,11 @@ export type SendUserOperationReturnType = { export async function sendUserOperation( wallet: SmartWallet, - options: SendUserOperationOptions, + options: { calls: UserOperationCalls }, ): Promise { - const { networkId } = wallet; - if (!networkId) { - throw new Error("Network not set - call use({networkId}) first"); + const { network } = wallet; + if (!network) { + throw new Error("Network not set - call useNetwork({chainId}) first"); } const encodedCalls = options.calls.map(call => { @@ -47,7 +48,7 @@ export async function sendUserOperation( const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( wallet.address, - networkId, + network.networkId, { calls: encodedCalls, }, @@ -79,7 +80,7 @@ export async function sendUserOperation( const returnValue: SendUserOperationReturnType = { id: broadcastResponse.data.id, - networkId, + network, smartWalletAddress: wallet.address, status: broadcastResponse.data.status, wait: async () => { @@ -105,7 +106,7 @@ export async function sendUserOperation( op => op.status === UserOperationStatusEnum.Complete || op.status === UserOperationStatusEnum.Failed, - { intervalSeconds: 0.2, timeoutSeconds: 10 }, + { intervalSeconds: 0.2 }, ); }, }; diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 623aad91..1455b6ca 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -73,11 +73,43 @@ import { CreateUserOperationRequest, UserOperation as UserOperationModel, BroadcastUserOperationRequest, + NetworkIdentifier, } from "./../client/api"; import { Address } from "./address"; import { Wallet } from "./wallet"; import { HistoricalBalance } from "./historical_balance"; import { Transaction } from "./transaction"; +import { Chain } from "viem"; + +export const CHAIN_ID_TO_NETWORK_ID = { + 1: "ethereum-mainnet", + 11155111: "ethereum-sepolia", + 137: "polygon-mainnet", + 80001: "polygon-mumbai", + 8453: "base-mainnet", + 84532: "base-sepolia", + 42161: "arbitrum-mainnet", + 421614: "arbitrum-sepolia", + 10: "optimism-mainnet", + 11155420: "optimism-sepolia", +} as const; + +export type SupportedChainId = keyof typeof CHAIN_ID_TO_NETWORK_ID; +export type SupportedViemChain = Chain & { + id: SupportedChainId +} + +export type Network = { + chainId: SupportedChainId; + networkId: NetworkIdentifier; +}; + +export function createNetwork(chainId: SupportedChainId): Network { + return { + chainId, + networkId: CHAIN_ID_TO_NETWORK_ID[chainId] as NetworkIdentifier, + }; +} export type AssetAPIClient = { /** diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts index bea47439..15265d8e 100644 --- a/src/coinbase/wallets/createSmartWallet.ts +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -1,8 +1,8 @@ -import type { SmartWallet } from "./types"; +import { type SmartWallet } from "./types"; import { Coinbase } from "../coinbase"; import { sendUserOperation } from "../actions/sendUserOperation"; import type { LocalAccount } from "viem"; -import { NetworkIdentifier } from "../../client"; +import { createNetwork, SupportedViemChain } from "../types"; export type CreateSmartWalletOptions = { account: LocalAccount; @@ -22,8 +22,8 @@ export async function createSmartWallet(options: CreateSmartWalletOptions): Prom account: options.account, type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), - useNetwork: (options: { networkId: NetworkIdentifier }) => { - wallet.networkId = options.networkId; + useNetwork: (options: { chain: SupportedViemChain }) => { + wallet.network = createNetwork(options.chain.id); }, }; diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts index 6b1ec657..1fc62b44 100644 --- a/src/coinbase/wallets/types.ts +++ b/src/coinbase/wallets/types.ts @@ -1,20 +1,23 @@ import type { Address } from "abitype"; import type { LocalAccount } from "viem"; -import type { NetworkIdentifier } from "../../client"; import { SendUserOperationOptions, SendUserOperationReturnType, } from "../actions/sendUserOperation"; +import { Network, SupportedViemChain } from "../types"; +import { UserOperationCalls } from "viem/_types/account-abstraction"; + + export type SmartWallet = { address: Address; account: LocalAccount; - networkId?: NetworkIdentifier; + network?: Network; type: "smart"; sendUserOperation: ( - options: SendUserOperationOptions, + options: { calls: UserOperationCalls } ) => Promise; - useNetwork: (options: { networkId: NetworkIdentifier }) => void; + useNetwork: (options: { chain: SupportedViemChain }) => void; }; // In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 5a751bfa..9da331df 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,7 +1,7 @@ -import { createWalletClient, http, parseEther } from "viem"; +import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { Coinbase, ExternalAddress, Wallet } from "./src"; -import { mainnet } from "viem/chains"; +import { baseSepolia } from "viem/chains"; import { createSmartWallet } from "./src/coinbase/wallets/createSmartWallet"; Coinbase.configureFromJson({ @@ -15,23 +15,33 @@ async function main() { const privateKey = generatePrivateKey(); const owner = privateKeyToAccount(privateKey); const smartWallet = await createSmartWallet({ account: owner }); - smartWallet.useNetwork({ networkId: Coinbase.networks.BaseSepolia }); + smartWallet.useNetwork({ chain: baseSepolia }); // Faucet the smart wallet using an External Address const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); const faucet = await externalAdress.faucet(); await faucet.wait(); + // create a wallet address to send to and check its balance after + const wallet = await Wallet.create(); + const walletAddress = await wallet.getDefaultAddress(); + const userOperation = await smartWallet.sendUserOperation({ calls: [ { - to: "0x1234567890123456789012345678901234567890", - value: parseEther("0.00001"), + to: walletAddress.getId(), + value: parseEther("0.000001"), data: "0x", }, ], }); + console.log("userOperation status", userOperation.status); const completedUserOperation = await userOperation.wait(); + console.log("completedUserOperation status", completedUserOperation.status); + + // get final balance now + const finalBalance = await walletAddress.getBalance("eth"); + console.log("finalBalance", finalBalance); } main(); From fd288e34cb6a3e86cd35e24e0b1042870a7fd9ca Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 12:37:03 -0500 Subject: [PATCH 15/59] WIP --- src/actions/sendUserOperation.ts | 154 ++++++++++++++++++++++ src/actions/wallets/createSmartWallet.ts | 31 +++++ src/actions/wallets/types.ts | 52 ++++++++ src/client/api.ts | 20 ++- src/coinbase/types.ts | 34 +---- src/coinbase/wallets/createSmartWallet.ts | 7 +- src/coinbase/wallets/types.ts | 6 +- src/index.ts | 1 + src/types/chain.ts | 21 +++ src/utils/chain.ts | 9 ++ src/utils/wait.ts | 28 ++++ src/wallets/createSmartWallet.ts | 31 +++++ src/wallets/types.ts | 52 ++++++++ testNewSmartWallet.ts | 11 +- 14 files changed, 410 insertions(+), 47 deletions(-) create mode 100644 src/actions/sendUserOperation.ts create mode 100644 src/actions/wallets/createSmartWallet.ts create mode 100644 src/actions/wallets/types.ts create mode 100644 src/types/chain.ts create mode 100644 src/utils/chain.ts create mode 100644 src/utils/wait.ts create mode 100644 src/wallets/createSmartWallet.ts create mode 100644 src/wallets/types.ts diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts new file mode 100644 index 00000000..c907c4a4 --- /dev/null +++ b/src/actions/sendUserOperation.ts @@ -0,0 +1,154 @@ +import { UserOperationCalls } from "viem/_types/account-abstraction"; +import { SmartWallet } from "../wallets/types"; +import { UserOperationStatusEnum } from "../client"; +import { encodeFunctionData, Hex, Prettify } from "viem"; +import { Coinbase } from "../coinbase/coinbase"; +import { wait } from "../utils/wait"; +import { Network } from "../types/chain"; + +export type SendUserOperationOptions = { + calls: UserOperationCalls; +}; + +type BaseUserOperation = { + id: string; + network: Network; + smartWalletAddress: Hex; + wait: () => Promise; +}; + +type CompletedOperation = Prettify + +type FailedOperation = Prettify + +type PendingOperation = Prettify; + transactionHash?: string; +}> + +export type SendUserOperationReturnType = CompletedOperation | PendingOperation | FailedOperation; + +export async function sendUserOperation( + wallet: SmartWallet, + options: { calls: UserOperationCalls }, +): Promise { + const { network } = wallet; + if (!network) { + throw new Error("Network not set - call useNetwork({chainId}) first"); + } + + const encodedCalls = options.calls.map(call => { + if ("abi" in call) { + return { + data: encodeFunctionData({ + abi: call.abi, + functionName: call.functionName, + args: call.args, + }), + to: call.to, + value: call.value.toString() || "0", + }; + } + return { + data: call.data, + to: call.to, + value: call.value.toString() || "0", + }; + }); + + const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( + wallet.address, + network.networkId, + { + calls: encodedCalls, + }, + ); + + if (!createOpResponse.data) { + throw new Error("Failed to create user operation"); + } + + if (!wallet.account.sign) { + throw new Error("Account does not support signing"); + } + + const signature = await wallet.account.sign({ + hash: createOpResponse.data.unsigned_payload as Hex, + }); + + const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( + wallet.address, + createOpResponse.data.id, + { + signature, + }, + ); + + if (!broadcastResponse.data.status) { + throw new Error("Failed to broadcast user operation"); + } + + const returnValue: SendUserOperationReturnType = { + id: broadcastResponse.data.id, + network, + smartWalletAddress: wallet.address, + status: broadcastResponse.data.status, + transactionHash: broadcastResponse.data.transaction_hash, + wait: async () => { + const reload = async () => { + const result = await Coinbase.apiClients.smartWallet!.getUserOperation( + wallet.address, + broadcastResponse.data.id, + ); + + if (!result.data) { + throw new Error("Failed to get user operation status"); + } + + if (result.data.status === UserOperationStatusEnum.Complete) { + return { + ...returnValue, + status: result.data.status, + transactionHash: result.data.transaction_hash!, + wait: returnValue.wait, + } as CompletedOperation; + } else if (result.data.status === UserOperationStatusEnum.Failed) { + return { + ...returnValue, + status: result.data.status, + transactionHash: result.data.transaction_hash, + wait: returnValue.wait, + } as FailedOperation; + } else { + return { + ...returnValue, + status: result.data.status, + transactionHash: result.data.transaction_hash, + wait: returnValue.wait, + } as PendingOperation; + } + }; + + return wait( + reload, + (op: SendUserOperationReturnType) => + op.status === UserOperationStatusEnum.Complete || + op.status === UserOperationStatusEnum.Failed, + { intervalSeconds: 0.2 }, + ); + }, + } as SendUserOperationReturnType; + + return returnValue; +} diff --git a/src/actions/wallets/createSmartWallet.ts b/src/actions/wallets/createSmartWallet.ts new file mode 100644 index 00000000..b1a35b4c --- /dev/null +++ b/src/actions/wallets/createSmartWallet.ts @@ -0,0 +1,31 @@ +import { type SmartWallet } from "./types"; +import { Coinbase } from "../coinbase"; +import { sendUserOperation } from "../actions/sendUserOperation"; +import type { LocalAccount } from "viem"; +import { createNetwork, SupportedChainId } from "../types"; + +export type CreateSmartWalletOptions = { + account: LocalAccount; +}; + +export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { + const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ + owner: options.account.address, + }); + + if (!result.data) { + throw new Error("Failed to create smart wallet"); + } + + const wallet: SmartWallet = { + address: result.data.address as `0x${string}`, + account: options.account, + type: "smart", + sendUserOperation: options => sendUserOperation(wallet, options), + switchChain: (options: { chainId: SupportedChainId }) => { + wallet.network = createNetwork(options.chainId); + }, + }; + + return wallet; +} diff --git a/src/actions/wallets/types.ts b/src/actions/wallets/types.ts new file mode 100644 index 00000000..4b9c57d6 --- /dev/null +++ b/src/actions/wallets/types.ts @@ -0,0 +1,52 @@ +import type { Address } from "abitype"; +import type { LocalAccount } from "viem"; +import { + SendUserOperationReturnType +} from '../actions/sendUserOperation' +import { Network, SupportedChainId } from "../types"; +import { UserOperationCalls } from "viem/_types/account-abstraction"; + + + +export type SmartWallet = { + address: Address; + account: LocalAccount; + network?: Network; + type: "smart"; + sendUserOperation: ( + options: { calls: UserOperationCalls } + ) => Promise; + switchChain: (options: { chainId: SupportedChainId }) => void; +}; + +// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. +// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. +// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. +// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. +// export type BaseWallet = { +// sign: (parameters: { hash: Hash }) => Promise +// signMessage: ({ message }: { message: SignableMessage }) => Promise +// signTypedData: ( +// typedData: TypedData | { [key: string]: unknown }, +// ) => Promise +// } + +// export type PrivateKeyWallet = Prettify Promise; +// }> + +// export type HDKeyWallet = Prettify + +// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise +// }> diff --git a/src/client/api.ts b/src/client/api.ts index 8b24f319..5457e874 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -1784,6 +1784,18 @@ export interface EthereumValidatorMetadata { * @memberof EthereumValidatorMetadata */ 'effective_balance': Balance; + /** + * The address for execution layer rewards (MEV & tx fees). If using a reward splitter plan, this is a smart contract address that splits rewards based on defined commissions and send a portion to the forwarded_fee_recipient_address. + * @type {string} + * @memberof EthereumValidatorMetadata + */ + 'fee_recipient_address': string; + /** + * If using a reward splitter plan, this address receives a defined percentage of the total execution layer rewards. + * @type {string} + * @memberof EthereumValidatorMetadata + */ + 'forwarded_fee_recipient_address'?: string; } /** * The faucet transaction @@ -4026,12 +4038,18 @@ export interface UserOperation { * @memberof UserOperation */ 'signature'?: string; + /** + * The hash of the transaction that was broadcast. + * @type {string} + * @memberof UserOperation + */ + 'transaction_hash'?: string; /** * The status of the user operation. * @type {string} * @memberof UserOperation */ - 'status'?: UserOperationStatusEnum; + 'status': UserOperationStatusEnum; } export const UserOperationStatusEnum = { diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 1455b6ca..d8516ff3 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -72,44 +72,12 @@ import { CreateSmartWalletRequest, CreateUserOperationRequest, UserOperation as UserOperationModel, - BroadcastUserOperationRequest, - NetworkIdentifier, + BroadcastUserOperationRequest } from "./../client/api"; import { Address } from "./address"; import { Wallet } from "./wallet"; import { HistoricalBalance } from "./historical_balance"; import { Transaction } from "./transaction"; -import { Chain } from "viem"; - -export const CHAIN_ID_TO_NETWORK_ID = { - 1: "ethereum-mainnet", - 11155111: "ethereum-sepolia", - 137: "polygon-mainnet", - 80001: "polygon-mumbai", - 8453: "base-mainnet", - 84532: "base-sepolia", - 42161: "arbitrum-mainnet", - 421614: "arbitrum-sepolia", - 10: "optimism-mainnet", - 11155420: "optimism-sepolia", -} as const; - -export type SupportedChainId = keyof typeof CHAIN_ID_TO_NETWORK_ID; -export type SupportedViemChain = Chain & { - id: SupportedChainId -} - -export type Network = { - chainId: SupportedChainId; - networkId: NetworkIdentifier; -}; - -export function createNetwork(chainId: SupportedChainId): Network { - return { - chainId, - networkId: CHAIN_ID_TO_NETWORK_ID[chainId] as NetworkIdentifier, - }; -} export type AssetAPIClient = { /** diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts index 15265d8e..e98257b5 100644 --- a/src/coinbase/wallets/createSmartWallet.ts +++ b/src/coinbase/wallets/createSmartWallet.ts @@ -2,7 +2,8 @@ import { type SmartWallet } from "./types"; import { Coinbase } from "../coinbase"; import { sendUserOperation } from "../actions/sendUserOperation"; import type { LocalAccount } from "viem"; -import { createNetwork, SupportedViemChain } from "../types"; +import { SupportedChainId } from "../../types/chain"; +import { createNetwork } from "../../utils/chain"; export type CreateSmartWalletOptions = { account: LocalAccount; @@ -22,8 +23,8 @@ export async function createSmartWallet(options: CreateSmartWalletOptions): Prom account: options.account, type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), - useNetwork: (options: { chain: SupportedViemChain }) => { - wallet.network = createNetwork(options.chain.id); + switchChain: (options: { chainId: SupportedChainId }) => { + wallet.network = createNetwork(options.chainId); }, }; diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts index 1fc62b44..dd2d3c18 100644 --- a/src/coinbase/wallets/types.ts +++ b/src/coinbase/wallets/types.ts @@ -4,7 +4,7 @@ import { SendUserOperationOptions, SendUserOperationReturnType, } from "../actions/sendUserOperation"; -import { Network, SupportedViemChain } from "../types"; +import { Network, SupportedChainId } from "../../types/chain"; import { UserOperationCalls } from "viem/_types/account-abstraction"; @@ -17,7 +17,7 @@ export type SmartWallet = { sendUserOperation: ( options: { calls: UserOperationCalls } ) => Promise; - useNetwork: (options: { chain: SupportedViemChain }) => void; + switchChain: (options: { chainId: SupportedChainId }) => void; }; // In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. @@ -25,7 +25,7 @@ export type SmartWallet = { // We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. // We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. // export type BaseWallet = { -// sign: (parameters: { hash: Hash }) => Promise +// sign: (parameters: { hash: Hash }) => Promise Promise // signTypedData: ( // typedData: TypedData | { [key: string]: unknown }, diff --git a/src/index.ts b/src/index.ts index d5412e89..8ad6005a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,3 +32,4 @@ export * from "./coinbase/crypto_amount"; export * from "./coinbase/fiat_amount"; export * from "./coinbase/fund_operation"; export * from "./coinbase/fund_quote"; +export * from "./types/chain"; \ No newline at end of file diff --git a/src/types/chain.ts b/src/types/chain.ts new file mode 100644 index 00000000..cf8bd513 --- /dev/null +++ b/src/types/chain.ts @@ -0,0 +1,21 @@ +import { NetworkIdentifier } from "../client/api"; + +export const CHAIN_ID_TO_NETWORK_ID = { + 1: "ethereum-mainnet", + 11155111: "ethereum-sepolia", + 137: "polygon-mainnet", + 80001: "polygon-mumbai", + 8453: "base-mainnet", + 84532: "base-sepolia", + 42161: "arbitrum-mainnet", + 421614: "arbitrum-sepolia", + 10: "optimism-mainnet", + 11155420: "optimism-sepolia", +} as const; + +export type SupportedChainId = keyof typeof CHAIN_ID_TO_NETWORK_ID; + +export type Network = { + chainId: SupportedChainId; + networkId: NetworkIdentifier; +}; \ No newline at end of file diff --git a/src/utils/chain.ts b/src/utils/chain.ts new file mode 100644 index 00000000..a3792d97 --- /dev/null +++ b/src/utils/chain.ts @@ -0,0 +1,9 @@ +import { NetworkIdentifier } from "../client/api"; +import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId, Network } from "../types/chain"; + +export function createNetwork(chainId: SupportedChainId): Network { + return { + chainId, + networkId: CHAIN_ID_TO_NETWORK_ID[chainId] as NetworkIdentifier, + }; +} diff --git a/src/utils/wait.ts b/src/utils/wait.ts new file mode 100644 index 00000000..b928d7cf --- /dev/null +++ b/src/utils/wait.ts @@ -0,0 +1,28 @@ +import { TimeoutError } from "../errors"; + +export type WaitOptions = { + intervalSeconds?: number; + timeoutSeconds?: number; +}; + +export async function wait( + reload: () => Promise, + isTerminal: (obj: T) => boolean, + options: WaitOptions = {}, +): Promise { + const { intervalSeconds = 0.2, timeoutSeconds = 10 } = options; + + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutSeconds * 1000) { + const updatedObject = await reload(); + + if (isTerminal(updatedObject)) { + return updatedObject; + } + + await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000)); + } + + throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); +} diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts new file mode 100644 index 00000000..b1a35b4c --- /dev/null +++ b/src/wallets/createSmartWallet.ts @@ -0,0 +1,31 @@ +import { type SmartWallet } from "./types"; +import { Coinbase } from "../coinbase"; +import { sendUserOperation } from "../actions/sendUserOperation"; +import type { LocalAccount } from "viem"; +import { createNetwork, SupportedChainId } from "../types"; + +export type CreateSmartWalletOptions = { + account: LocalAccount; +}; + +export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { + const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ + owner: options.account.address, + }); + + if (!result.data) { + throw new Error("Failed to create smart wallet"); + } + + const wallet: SmartWallet = { + address: result.data.address as `0x${string}`, + account: options.account, + type: "smart", + sendUserOperation: options => sendUserOperation(wallet, options), + switchChain: (options: { chainId: SupportedChainId }) => { + wallet.network = createNetwork(options.chainId); + }, + }; + + return wallet; +} diff --git a/src/wallets/types.ts b/src/wallets/types.ts new file mode 100644 index 00000000..4b9c57d6 --- /dev/null +++ b/src/wallets/types.ts @@ -0,0 +1,52 @@ +import type { Address } from "abitype"; +import type { LocalAccount } from "viem"; +import { + SendUserOperationReturnType +} from '../actions/sendUserOperation' +import { Network, SupportedChainId } from "../types"; +import { UserOperationCalls } from "viem/_types/account-abstraction"; + + + +export type SmartWallet = { + address: Address; + account: LocalAccount; + network?: Network; + type: "smart"; + sendUserOperation: ( + options: { calls: UserOperationCalls } + ) => Promise; + switchChain: (options: { chainId: SupportedChainId }) => void; +}; + +// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. +// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. +// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. +// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. +// export type BaseWallet = { +// sign: (parameters: { hash: Hash }) => Promise +// signMessage: ({ message }: { message: SignableMessage }) => Promise +// signTypedData: ( +// typedData: TypedData | { [key: string]: unknown }, +// ) => Promise +// } + +// export type PrivateKeyWallet = Prettify Promise; +// }> + +// export type HDKeyWallet = Prettify + +// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise +// }> diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 9da331df..bd0da6c8 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,13 +1,12 @@ import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { Coinbase, ExternalAddress, Wallet } from "./src"; -import { baseSepolia } from "viem/chains"; import { createSmartWallet } from "./src/coinbase/wallets/createSmartWallet"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", debugging: true, - basePath: "https://cloud-api-dev.cbhq.net/platform", + basePath: "https://cloud-api-dev.cbhq.net/platform/" }); async function main() { @@ -15,7 +14,7 @@ async function main() { const privateKey = generatePrivateKey(); const owner = privateKeyToAccount(privateKey); const smartWallet = await createSmartWallet({ account: owner }); - smartWallet.useNetwork({ chain: baseSepolia }); + smartWallet.switchChain({ chainId: 84532 }); // Faucet the smart wallet using an External Address const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); @@ -29,15 +28,13 @@ async function main() { const userOperation = await smartWallet.sendUserOperation({ calls: [ { - to: walletAddress.getId(), + to: walletAddress.getId() as `0x${string}`, value: parseEther("0.000001"), data: "0x", }, ], }); - console.log("userOperation status", userOperation.status); - const completedUserOperation = await userOperation.wait(); - console.log("completedUserOperation status", completedUserOperation.status); + const userOperationResult = await userOperation.wait(); // get final balance now const finalBalance = await walletAddress.getBalance("eth"); From bb748d2a5508080b225bd94b624219ccf0345e80 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 12:57:23 -0500 Subject: [PATCH 16/59] WIP --- src/actions/wallets/createSmartWallet.ts | 31 -------------- src/actions/wallets/types.ts | 52 ------------------------ src/wallets/createSmartWallet.ts | 5 ++- 3 files changed, 3 insertions(+), 85 deletions(-) delete mode 100644 src/actions/wallets/createSmartWallet.ts delete mode 100644 src/actions/wallets/types.ts diff --git a/src/actions/wallets/createSmartWallet.ts b/src/actions/wallets/createSmartWallet.ts deleted file mode 100644 index b1a35b4c..00000000 --- a/src/actions/wallets/createSmartWallet.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { type SmartWallet } from "./types"; -import { Coinbase } from "../coinbase"; -import { sendUserOperation } from "../actions/sendUserOperation"; -import type { LocalAccount } from "viem"; -import { createNetwork, SupportedChainId } from "../types"; - -export type CreateSmartWalletOptions = { - account: LocalAccount; -}; - -export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { - const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ - owner: options.account.address, - }); - - if (!result.data) { - throw new Error("Failed to create smart wallet"); - } - - const wallet: SmartWallet = { - address: result.data.address as `0x${string}`, - account: options.account, - type: "smart", - sendUserOperation: options => sendUserOperation(wallet, options), - switchChain: (options: { chainId: SupportedChainId }) => { - wallet.network = createNetwork(options.chainId); - }, - }; - - return wallet; -} diff --git a/src/actions/wallets/types.ts b/src/actions/wallets/types.ts deleted file mode 100644 index 4b9c57d6..00000000 --- a/src/actions/wallets/types.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { Address } from "abitype"; -import type { LocalAccount } from "viem"; -import { - SendUserOperationReturnType -} from '../actions/sendUserOperation' -import { Network, SupportedChainId } from "../types"; -import { UserOperationCalls } from "viem/_types/account-abstraction"; - - - -export type SmartWallet = { - address: Address; - account: LocalAccount; - network?: Network; - type: "smart"; - sendUserOperation: ( - options: { calls: UserOperationCalls } - ) => Promise; - switchChain: (options: { chainId: SupportedChainId }) => void; -}; - -// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. -// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. -// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. -// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. -// export type BaseWallet = { -// sign: (parameters: { hash: Hash }) => Promise -// signMessage: ({ message }: { message: SignableMessage }) => Promise -// signTypedData: ( -// typedData: TypedData | { [key: string]: unknown }, -// ) => Promise -// } - -// export type PrivateKeyWallet = Prettify Promise; -// }> - -// export type HDKeyWallet = Prettify - -// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise -// }> diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index b1a35b4c..9317046f 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,8 +1,9 @@ import { type SmartWallet } from "./types"; -import { Coinbase } from "../coinbase"; +import { Coinbase } from "../index" import { sendUserOperation } from "../actions/sendUserOperation"; import type { LocalAccount } from "viem"; -import { createNetwork, SupportedChainId } from "../types"; +import { SupportedChainId } from "../types/chain"; +import { createNetwork } from "../utils/chain"; export type CreateSmartWalletOptions = { account: LocalAccount; From 7e9e50c884dec18ce4ced27c5857738eb3a174ba Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 13:09:13 -0500 Subject: [PATCH 17/59] WIP --- package-lock.json | 130 ++++++++++++---------- package.json | 2 +- src/actions/sendUserOperation.ts | 6 +- src/coinbase/actions/sendUserOperation.ts | 115 ------------------- src/coinbase/wallets/createSmartWallet.ts | 32 ------ src/coinbase/wallets/types.ts | 53 --------- src/index.ts | 5 +- src/wallets/types.ts | 6 +- testNewSmartWallet.ts | 4 +- 9 files changed, 84 insertions(+), 269 deletions(-) delete mode 100644 src/coinbase/actions/sendUserOperation.ts delete mode 100644 src/coinbase/wallets/createSmartWallet.ts delete mode 100644 src/coinbase/wallets/types.ts diff --git a/package-lock.json b/package-lock.json index 0399d8ce..0882ae38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@coinbase/coinbase-sdk", - "version": "0.16.0", + "version": "0.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@coinbase/coinbase-sdk", - "version": "0.16.0", + "version": "0.17.0", "license": "ISC", "dependencies": { "@scure/bip32": "^1.4.0", @@ -21,7 +21,7 @@ "ethers": "^6.12.1", "node-jose": "^2.2.0", "secp256k1": "^5.0.0", - "viem": "^2.21.26" + "viem": "^2.23.2" }, "devDependencies": { "@types/jest": "^29.5.12", @@ -1248,12 +1248,12 @@ } }, "node_modules/@noble/curves": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", - "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.5.0" + "@noble/hashes": "1.7.1" }, "engines": { "node": "^14.21.3 || >=16" @@ -1263,9 +1263,9 @@ } }, "node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", "license": "MIT", "engines": { "node": "^14.21.3 || >=16" @@ -1322,36 +1322,36 @@ } }, "node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.4.tgz", + "integrity": "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==", "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", - "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", "license": "MIT", "dependencies": { - "@noble/curves": "~1.6.0", - "@noble/hashes": "~1.5.0", - "@scure/base": "~1.1.7" + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.4.0.tgz", - "integrity": "sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", "license": "MIT", "dependencies": { - "@noble/hashes": "~1.5.0", - "@scure/base": "~1.1.8" + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -1786,9 +1786,9 @@ "dev": true }, "node_modules/abitype": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", - "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" @@ -3141,6 +3141,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -5114,6 +5120,35 @@ "node": ">= 0.8.0" } }, + "node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6507,9 +6542,9 @@ } }, "node_modules/viem": { - "version": "2.21.26", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.21.26.tgz", - "integrity": "sha512-qanTFUzU5y3tCZTwYlwA/LXCR4X7OsCPvvKOmxOyuY8gEvWKMS/oh+FBxYO/2bXOhDG/ylg1V3toIbRuMseF8w==", + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", "funding": [ { "type": "github", @@ -6518,14 +6553,13 @@ ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.11.0", - "@noble/curves": "1.6.0", - "@noble/hashes": "1.5.0", - "@scure/bip32": "1.5.0", - "@scure/bip39": "1.4.0", - "abitype": "1.0.6", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", "isows": "1.0.6", - "webauthn-p256": "0.0.10", + "ox": "0.6.7", "ws": "8.18.0" }, "peerDependencies": { @@ -6537,12 +6571,6 @@ } } }, - "node_modules/viem/node_modules/@adraffy/ens-normalize": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", - "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", - "license": "MIT" - }, "node_modules/viem/node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -6585,22 +6613,6 @@ "makeerror": "1.0.12" } }, - "node_modules/webauthn-p256": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", - "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@noble/curves": "^1.4.0", - "@noble/hashes": "^1.4.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 222d7b75..0565431f 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "ethers": "^6.12.1", "node-jose": "^2.2.0", "secp256k1": "^5.0.0", - "viem": "^2.21.26" + "viem": "^2.23.2" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index c907c4a4..1863f33f 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,13 +1,13 @@ -import { UserOperationCalls } from "viem/_types/account-abstraction"; import { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; import { encodeFunctionData, Hex, Prettify } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { wait } from "../utils/wait"; import { Network } from "../types/chain"; +import { Calls } from "viem/_types/types/calls"; export type SendUserOperationOptions = { - calls: UserOperationCalls; + calls: Calls; }; type BaseUserOperation = { @@ -41,7 +41,7 @@ export type SendUserOperationReturnType = CompletedOperation | PendingOperation export async function sendUserOperation( wallet: SmartWallet, - options: { calls: UserOperationCalls }, + options: { calls: Calls }, ): Promise { const { network } = wallet; if (!network) { diff --git a/src/coinbase/actions/sendUserOperation.ts b/src/coinbase/actions/sendUserOperation.ts deleted file mode 100644 index 6a1d5817..00000000 --- a/src/coinbase/actions/sendUserOperation.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { UserOperationCalls } from "viem/_types/account-abstraction"; -import { SmartWallet } from "../wallets/types"; -import { UserOperationStatusEnum } from "../../client"; -import { encodeFunctionData, Hex } from "viem"; -import { Coinbase } from "../coinbase"; -import { wait } from "../utils/wait"; -import { Network } from "../types"; - -export type SendUserOperationOptions = { - calls: UserOperationCalls; -}; - -export type SendUserOperationReturnType = { - id: string; - network: Network; - smartWalletAddress: Hex; - status: UserOperationStatusEnum; - wait: () => Promise; -}; - -export async function sendUserOperation( - wallet: SmartWallet, - options: { calls: UserOperationCalls }, -): Promise { - const { network } = wallet; - if (!network) { - throw new Error("Network not set - call useNetwork({chainId}) first"); - } - - const encodedCalls = options.calls.map(call => { - if ("abi" in call) { - return { - data: encodeFunctionData({ - abi: call.abi, - functionName: call.functionName, - args: call.args, - }), - to: call.to, - value: call.value.toString() || "0", - }; - } - return { - data: call.data, - to: call.to, - value: call.value.toString() || "0", - }; - }); - - const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( - wallet.address, - network.networkId, - { - calls: encodedCalls, - }, - ); - - if (!createOpResponse.data) { - throw new Error("Failed to create user operation"); - } - - if (!wallet.account.sign) { - throw new Error("Account does not support signing"); - } - - const signature = await wallet.account.sign({ - hash: createOpResponse.data.unsigned_payload as Hex, - }); - - const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( - wallet.address, - createOpResponse.data.id, - { - signature, - }, - ); - - if (!broadcastResponse.data.status) { - throw new Error("Failed to broadcast user operation"); - } - - const returnValue: SendUserOperationReturnType = { - id: broadcastResponse.data.id, - network, - smartWalletAddress: wallet.address, - status: broadcastResponse.data.status, - wait: async () => { - const reload = async () => { - const result = await Coinbase.apiClients.smartWallet!.getUserOperation( - wallet.address, - broadcastResponse.data.id, - ); - - if (!result.data) { - throw new Error("Failed to get user operation status"); - } - - return { - ...returnValue, - status: result.data.status!, - wait: returnValue.wait, - }; - }; - - return wait( - reload, - op => - op.status === UserOperationStatusEnum.Complete || - op.status === UserOperationStatusEnum.Failed, - { intervalSeconds: 0.2 }, - ); - }, - }; - - return returnValue; -} diff --git a/src/coinbase/wallets/createSmartWallet.ts b/src/coinbase/wallets/createSmartWallet.ts deleted file mode 100644 index e98257b5..00000000 --- a/src/coinbase/wallets/createSmartWallet.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { type SmartWallet } from "./types"; -import { Coinbase } from "../coinbase"; -import { sendUserOperation } from "../actions/sendUserOperation"; -import type { LocalAccount } from "viem"; -import { SupportedChainId } from "../../types/chain"; -import { createNetwork } from "../../utils/chain"; - -export type CreateSmartWalletOptions = { - account: LocalAccount; -}; - -export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { - const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ - owner: options.account.address, - }); - - if (!result.data) { - throw new Error("Failed to create smart wallet"); - } - - const wallet: SmartWallet = { - address: result.data.address as `0x${string}`, - account: options.account, - type: "smart", - sendUserOperation: options => sendUserOperation(wallet, options), - switchChain: (options: { chainId: SupportedChainId }) => { - wallet.network = createNetwork(options.chainId); - }, - }; - - return wallet; -} diff --git a/src/coinbase/wallets/types.ts b/src/coinbase/wallets/types.ts deleted file mode 100644 index dd2d3c18..00000000 --- a/src/coinbase/wallets/types.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { Address } from "abitype"; -import type { LocalAccount } from "viem"; -import { - SendUserOperationOptions, - SendUserOperationReturnType, -} from "../actions/sendUserOperation"; -import { Network, SupportedChainId } from "../../types/chain"; -import { UserOperationCalls } from "viem/_types/account-abstraction"; - - - -export type SmartWallet = { - address: Address; - account: LocalAccount; - network?: Network; - type: "smart"; - sendUserOperation: ( - options: { calls: UserOperationCalls } - ) => Promise; - switchChain: (options: { chainId: SupportedChainId }) => void; -}; - -// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. -// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. -// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. -// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. -// export type BaseWallet = { -// sign: (parameters: { hash: Hash }) => Promise Promise -// signTypedData: ( -// typedData: TypedData | { [key: string]: unknown }, -// ) => Promise -// } - -// export type PrivateKeyWallet = Prettify Promise; -// }> - -// export type HDKeyWallet = Prettify - -// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise -// }> diff --git a/src/index.ts b/src/index.ts index 8ad6005a..7543c7b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,4 +32,7 @@ export * from "./coinbase/crypto_amount"; export * from "./coinbase/fiat_amount"; export * from "./coinbase/fund_operation"; export * from "./coinbase/fund_quote"; -export * from "./types/chain"; \ No newline at end of file +export * from "./types/chain"; +export * from "./wallets/types"; +export * from "./wallets/createSmartWallet"; +export * from "./actions/sendUserOperation"; diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 4b9c57d6..1b9350ac 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -3,8 +3,8 @@ import type { LocalAccount } from "viem"; import { SendUserOperationReturnType } from '../actions/sendUserOperation' -import { Network, SupportedChainId } from "../types"; -import { UserOperationCalls } from "viem/_types/account-abstraction"; +import { Network, SupportedChainId } from "../types/chain"; +import { Calls } from "viem/_types/types/calls"; @@ -14,7 +14,7 @@ export type SmartWallet = { network?: Network; type: "smart"; sendUserOperation: ( - options: { calls: UserOperationCalls } + options: { calls: Calls } ) => Promise; switchChain: (options: { chainId: SupportedChainId }) => void; }; diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index bd0da6c8..4c097cd7 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,7 +1,7 @@ import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Coinbase, ExternalAddress, Wallet } from "./src"; -import { createSmartWallet } from "./src/coinbase/wallets/createSmartWallet"; +import { Coinbase, ExternalAddress, Wallet } from './src/index' +import { createSmartWallet } from './src/index' Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", From 3fcf41fcc7d1ee4df299d66bc5b66409cffc9808 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 13:10:09 -0500 Subject: [PATCH 18/59] Fix --- src/utils/wait.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/wait.ts b/src/utils/wait.ts index b928d7cf..e0335188 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -1,4 +1,4 @@ -import { TimeoutError } from "../errors"; +import { TimeoutError } from "../coinbase/errors"; export type WaitOptions = { intervalSeconds?: number; From f7612fbcd20df7536bc4905efb06449c66b98445 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 17:55:04 -0500 Subject: [PATCH 19/59] Fix --- src/actions/sendUserOperation.ts | 98 ++++++----------------------- src/actions/waitForUserOperation.ts | 6 ++ src/wallets/createSmartWallet.ts | 15 ++++- src/wallets/types.ts | 56 +++++------------ 4 files changed, 53 insertions(+), 122 deletions(-) create mode 100644 src/actions/waitForUserOperation.ts diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 1863f33f..7d0043d0 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -2,53 +2,36 @@ import { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; import { encodeFunctionData, Hex, Prettify } from "viem"; import { Coinbase } from "../coinbase/coinbase"; -import { wait } from "../utils/wait"; -import { Network } from "../types/chain"; +import { CHAIN_ID_TO_NETWORK_ID, Network, SupportedChainId } from "../types/chain"; import { Calls } from "viem/_types/types/calls"; export type SendUserOperationOptions = { calls: Calls; + chainId: SupportedChainId; + paymasterUrl?: string; }; -type BaseUserOperation = { +export type BroadcastedOperation = { id: string; - network: Network; - smartWalletAddress: Hex; - wait: () => Promise; -}; + status: typeof UserOperationStatusEnum.Broadcast; +} -type CompletedOperation = Prettify - -type FailedOperation = Prettify - -type PendingOperation = Prettify; - transactionHash?: string; -}> +} -export type SendUserOperationReturnType = CompletedOperation | PendingOperation | FailedOperation; +export type SendUserOperationReturnType = BroadcastedOperation | CompletedOperation; export async function sendUserOperation( wallet: SmartWallet, - options: { calls: Calls }, -): Promise { - const { network } = wallet; - if (!network) { - throw new Error("Network not set - call useNetwork({chainId}) first"); - } + options: SendUserOperationOptions, +): Promise { + const { calls, chainId, paymasterUrl } = options + const network = CHAIN_ID_TO_NETWORK_ID[chainId]; - const encodedCalls = options.calls.map(call => { + const encodedCalls = calls.map(call => { if ("abi" in call) { return { data: encodeFunctionData({ @@ -69,7 +52,7 @@ export async function sendUserOperation( const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( wallet.address, - network.networkId, + network, { calls: encodedCalls, }, @@ -99,56 +82,11 @@ export async function sendUserOperation( throw new Error("Failed to broadcast user operation"); } - const returnValue: SendUserOperationReturnType = { + const returnValue = { id: broadcastResponse.data.id, - network, - smartWalletAddress: wallet.address, status: broadcastResponse.data.status, transactionHash: broadcastResponse.data.transaction_hash, - wait: async () => { - const reload = async () => { - const result = await Coinbase.apiClients.smartWallet!.getUserOperation( - wallet.address, - broadcastResponse.data.id, - ); - - if (!result.data) { - throw new Error("Failed to get user operation status"); - } - - if (result.data.status === UserOperationStatusEnum.Complete) { - return { - ...returnValue, - status: result.data.status, - transactionHash: result.data.transaction_hash!, - wait: returnValue.wait, - } as CompletedOperation; - } else if (result.data.status === UserOperationStatusEnum.Failed) { - return { - ...returnValue, - status: result.data.status, - transactionHash: result.data.transaction_hash, - wait: returnValue.wait, - } as FailedOperation; - } else { - return { - ...returnValue, - status: result.data.status, - transactionHash: result.data.transaction_hash, - wait: returnValue.wait, - } as PendingOperation; - } - }; - - return wait( - reload, - (op: SendUserOperationReturnType) => - op.status === UserOperationStatusEnum.Complete || - op.status === UserOperationStatusEnum.Failed, - { intervalSeconds: 0.2 }, - ); - }, - } as SendUserOperationReturnType; + } as BroadcastedOperation; return returnValue; } diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts new file mode 100644 index 00000000..3defa52d --- /dev/null +++ b/src/actions/waitForUserOperation.ts @@ -0,0 +1,6 @@ +import { Network } from "../types/chain"; + +export type WaitForUserOperationOptions = { + +} + diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index 9317046f..3cf109fe 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,4 +1,4 @@ -import { type SmartWallet } from "./types"; +import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; import { Coinbase } from "../index" import { sendUserOperation } from "../actions/sendUserOperation"; import type { LocalAccount } from "viem"; @@ -23,8 +23,17 @@ export async function createSmartWallet(options: CreateSmartWalletOptions): Prom account: options.account, type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), - switchChain: (options: { chainId: SupportedChainId }) => { - wallet.network = createNetwork(options.chainId); + useNetwork: (options: SmartWalletNetworkOptions) => { + const network = createNetwork(options.chainId); + return { + ...wallet, + network, + paymasterUrl: options.paymasterUrl, + sendUserOperation: options => sendUserOperation(wallet, { + ...options, + chainId: network.chainId, + }), + } as NetworkScopedSmartWallet; }, }; diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 1b9350ac..41ffb685 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,52 +1,30 @@ import type { Address } from "abitype"; import type { LocalAccount } from "viem"; import { - SendUserOperationReturnType -} from '../actions/sendUserOperation' + BroadcastedOperation, SendUserOperationOptions +} from '../actions/sendUserOperation'; import { Network, SupportedChainId } from "../types/chain"; -import { Calls } from "viem/_types/types/calls"; - +import { Prettify } from "viem"; +export type SmartWalletNetworkOptions = { + chainId: SupportedChainId; + paymasterUrl?: string; +} export type SmartWallet = { address: Address; account: LocalAccount; - network?: Network; type: "smart"; sendUserOperation: ( - options: { calls: Calls } - ) => Promise; - switchChain: (options: { chainId: SupportedChainId }) => void; + options: SendUserOperationOptions + ) => Promise; + useNetwork: (options: SmartWalletNetworkOptions) => NetworkScopedSmartWallet; }; -// In the future, we may introduce BaseWallet (or named differently to avoid Base chain confusion). BaseWallet would be a base class for all wallets. -// We would have a PrivateKeyWallet type that extends BaseWallet and adds signTransaction which is specific to private key wallets. -// We would have a HDKeyWallet type that extends the PrivateKeyWallet type and adds a method to get the HD key used by the private key wallet. -// We would update the SmartWallet type to extend BaseWallet to add support for common wallet signing methods. -// export type BaseWallet = { -// sign: (parameters: { hash: Hash }) => Promise -// signMessage: ({ message }: { message: SignableMessage }) => Promise -// signTypedData: ( -// typedData: TypedData | { [key: string]: unknown }, -// ) => Promise -// } - -// export type PrivateKeyWallet = Prettify Promise; -// }> - -// export type HDKeyWallet = Prettify - -// export type SmartWallet = Prettify(options: SendUserOperationOptions) => Promise -// }> +export type NetworkScopedSmartWallet = Prettify & { + network: Network; + paymasterUrl?: string; + sendUserOperation: ( + options: Prettify, "chainId" | "paymasterUrl">> + ) => Promise; +}> \ No newline at end of file From c1e6a05a8609e3a0e443df9eca872808ca13c920 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 18:38:33 -0500 Subject: [PATCH 20/59] Fix --- src/actions/sendUserOperation.ts | 20 +++++-------- src/actions/waitForUserOperation.ts | 46 ++++++++++++++++++++++++++++- src/wallets/types.ts | 6 ++-- testNewSmartWallet.ts | 14 +++++++-- 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 7d0043d0..912a642b 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,6 +1,6 @@ import { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; -import { encodeFunctionData, Hex, Prettify } from "viem"; +import { Address, encodeFunctionData, Hex, Prettify } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, Network, SupportedChainId } from "../types/chain"; import { Calls } from "viem/_types/types/calls"; @@ -11,23 +11,16 @@ export type SendUserOperationOptions = { paymasterUrl?: string; }; -export type BroadcastedOperation = { +export type SendUserOperationReturnType = { id: string; + smartWalletAddress: Address; status: typeof UserOperationStatusEnum.Broadcast; -} - -export type CompletedOperation = { - id: string; - status: typeof UserOperationStatusEnum.Complete; - transactionHash: string; -} - -export type SendUserOperationReturnType = BroadcastedOperation | CompletedOperation; +} export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, -): Promise { +): Promise { const { calls, chainId, paymasterUrl } = options const network = CHAIN_ID_TO_NETWORK_ID[chainId]; @@ -84,9 +77,10 @@ export async function sendUserOperation( const returnValue = { id: broadcastResponse.data.id, + smartWalletAddress: wallet.address, status: broadcastResponse.data.status, transactionHash: broadcastResponse.data.transaction_hash, - } as BroadcastedOperation; + } as SendUserOperationReturnType; return returnValue; } diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 3defa52d..dd7d5be6 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -1,6 +1,50 @@ +import { Address } from "viem"; import { Network } from "../types/chain"; +import { Coinbase } from "../coinbase/coinbase"; +import { wait, WaitOptions } from "../utils/wait"; +import { UserOperationStatusEnum } from "../client"; export type WaitForUserOperationOptions = { - + id: string; + smartWalletAddress: Address; + waitOptions?: WaitOptions +} + +export type FailedOperation = { + id: string; + smartWalletAddress: Address; + status: typeof UserOperationStatusEnum.Failed; } +export type CompletedOperation = { + id: string; + smartWalletAddress: Address; + status: typeof UserOperationStatusEnum.Complete; + transactionHash: string; +} + +export type WaitForUserOperationReturnType = FailedOperation | CompletedOperation; + + +export async function waitForUserOperation(options: WaitForUserOperationOptions): Promise { + const { id, smartWalletAddress } = options; + + const reload = async () => { + const userOperation = await Coinbase.apiClients.smartWallet!.getUserOperation(smartWalletAddress, id); + + if (!userOperation.data) { + throw new Error("User operation not found"); + } + + return { + id: userOperation.data.id, + smartWalletAddress: smartWalletAddress, + status: userOperation.data.status, + transactionHash: userOperation.data.transaction_hash, + } as WaitForUserOperationReturnType; + } + + return wait(reload, (userOperation: WaitForUserOperationReturnType) => { + return userOperation.status === UserOperationStatusEnum.Complete || userOperation.status === UserOperationStatusEnum.Failed; + }, options.waitOptions); +} diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 41ffb685..63b09145 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,7 +1,7 @@ import type { Address } from "abitype"; import type { LocalAccount } from "viem"; import { - BroadcastedOperation, SendUserOperationOptions + SendUserOperationOptions, SendUserOperationReturnType } from '../actions/sendUserOperation'; import { Network, SupportedChainId } from "../types/chain"; import { Prettify } from "viem"; @@ -17,7 +17,7 @@ export type SmartWallet = { type: "smart"; sendUserOperation: ( options: SendUserOperationOptions - ) => Promise; + ) => Promise; useNetwork: (options: SmartWalletNetworkOptions) => NetworkScopedSmartWallet; }; @@ -26,5 +26,5 @@ export type NetworkScopedSmartWallet = Prettify( options: Prettify, "chainId" | "paymasterUrl">> - ) => Promise; + ) => Promise; }> \ No newline at end of file diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 4c097cd7..b71fdb18 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -2,6 +2,8 @@ import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { Coinbase, ExternalAddress, Wallet } from './src/index' import { createSmartWallet } from './src/index' +import { waitForUserOperation } from "./src/actions/waitForUserOperation"; +import { UserOperationStatusEnum } from "./src/client"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", @@ -14,7 +16,6 @@ async function main() { const privateKey = generatePrivateKey(); const owner = privateKeyToAccount(privateKey); const smartWallet = await createSmartWallet({ account: owner }); - smartWallet.switchChain({ chainId: 84532 }); // Faucet the smart wallet using an External Address const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); @@ -33,8 +34,17 @@ async function main() { data: "0x", }, ], + chainId: 84532, }); - const userOperationResult = await userOperation.wait(); + + const userOperationResult = await waitForUserOperation(userOperation); + + console.log("userOperationResult", userOperationResult); + +// const userOperationResult = await userOperation.wait(); + + // const userOperationResult = await waitForUserOperation(userOperation) + // get final balance now const finalBalance = await walletAddress.getBalance("eth"); From 72550b9d9792f4de1a8b627d8faa0c20af1a34a7 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 18:46:39 -0500 Subject: [PATCH 21/59] WIP --- src/wallets/getSmartWallet.ts | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/wallets/getSmartWallet.ts diff --git a/src/wallets/getSmartWallet.ts b/src/wallets/getSmartWallet.ts new file mode 100644 index 00000000..7179ef0e --- /dev/null +++ b/src/wallets/getSmartWallet.ts @@ -0,0 +1,46 @@ +import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; +import { Coinbase } from "../index" +import { sendUserOperation } from "../actions/sendUserOperation"; +import type { Address, LocalAccount } from "viem"; +import { SupportedChainId } from "../types/chain"; +import { createNetwork } from "../utils/chain"; + +export type GetSmartWalletOptions = { + smartWalletAddress: Address; + account: LocalAccount; +}; + +export async function getSmartWallet(options: GetSmartWalletOptions): Promise { + const result = await Coinbase.apiClients.smartWallet!.getSmartWallet(options.smartWalletAddress); + + // if (!result.data) { + // throw new Error("Failed to get smart wallet"); + // } + + if (result.data.owners.some(owner => owner.toLowerCase() === options.account.address.toLowerCase())) { + throw new Error('Account is not an owner of the smart wallet'); + } + + + + const wallet: SmartWallet = { + address: result.data.address as `0x${string}`, + account: options.account, + type: "smart", + sendUserOperation: options => sendUserOperation(wallet, options), + useNetwork: (options: SmartWalletNetworkOptions) => { + const network = createNetwork(options.chainId); + return { + ...wallet, + network, + paymasterUrl: options.paymasterUrl, + sendUserOperation: options => sendUserOperation(wallet, { + ...options, + chainId: network.chainId, + }), + } as NetworkScopedSmartWallet; + }, + }; + + return wallet; +} From e657b1c33ce2b7c4dc783f4dd0026cb3d3007193 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 19:06:43 -0500 Subject: [PATCH 22/59] Changes" --- src/actions/sendUserOperation.ts | 4 +-- src/wallets/createSmartWallet.ts | 34 ++++--------------- .../{getSmartWallet.ts => toSmartWallet..ts} | 21 +++--------- 3 files changed, 13 insertions(+), 46 deletions(-) rename src/wallets/{getSmartWallet.ts => toSmartWallet..ts} (58%) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 912a642b..85f0fc41 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,8 +1,8 @@ import { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; -import { Address, encodeFunctionData, Hex, Prettify } from "viem"; +import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; -import { CHAIN_ID_TO_NETWORK_ID, Network, SupportedChainId } from "../types/chain"; +import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; import { Calls } from "viem/_types/types/calls"; export type SendUserOperationOptions = { diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index 3cf109fe..02430293 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,9 +1,9 @@ -import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; -import { Coinbase } from "../index" +import { SmartWalletNetworkOptions, type SmartWallet } from "./types"; +import { Coinbase } from "../index"; import { sendUserOperation } from "../actions/sendUserOperation"; -import type { LocalAccount } from "viem"; -import { SupportedChainId } from "../types/chain"; +import type { Address, LocalAccount } from "viem"; import { createNetwork } from "../utils/chain"; +import { toSmartWallet } from "./toSmartWallet."; export type CreateSmartWalletOptions = { account: LocalAccount; @@ -14,28 +14,8 @@ export async function createSmartWallet(options: CreateSmartWalletOptions): Prom owner: options.account.address, }); - if (!result.data) { - throw new Error("Failed to create smart wallet"); - } - - const wallet: SmartWallet = { - address: result.data.address as `0x${string}`, + return toSmartWallet({ + smartWalletAddress: result.data.address as Address, account: options.account, - type: "smart", - sendUserOperation: options => sendUserOperation(wallet, options), - useNetwork: (options: SmartWalletNetworkOptions) => { - const network = createNetwork(options.chainId); - return { - ...wallet, - network, - paymasterUrl: options.paymasterUrl, - sendUserOperation: options => sendUserOperation(wallet, { - ...options, - chainId: network.chainId, - }), - } as NetworkScopedSmartWallet; - }, - }; - - return wallet; + }); } diff --git a/src/wallets/getSmartWallet.ts b/src/wallets/toSmartWallet..ts similarity index 58% rename from src/wallets/getSmartWallet.ts rename to src/wallets/toSmartWallet..ts index 7179ef0e..9c75b76e 100644 --- a/src/wallets/getSmartWallet.ts +++ b/src/wallets/toSmartWallet..ts @@ -1,30 +1,17 @@ import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; -import { Coinbase } from "../index" +import { Coinbase } from "../index"; import { sendUserOperation } from "../actions/sendUserOperation"; import type { Address, LocalAccount } from "viem"; -import { SupportedChainId } from "../types/chain"; import { createNetwork } from "../utils/chain"; -export type GetSmartWalletOptions = { +export type ToSmartWalletOptions = { smartWalletAddress: Address; account: LocalAccount; }; -export async function getSmartWallet(options: GetSmartWalletOptions): Promise { - const result = await Coinbase.apiClients.smartWallet!.getSmartWallet(options.smartWalletAddress); - - // if (!result.data) { - // throw new Error("Failed to get smart wallet"); - // } - - if (result.data.owners.some(owner => owner.toLowerCase() === options.account.address.toLowerCase())) { - throw new Error('Account is not an owner of the smart wallet'); - } - - - +export async function toSmartWallet(options: ToSmartWalletOptions): Promise { const wallet: SmartWallet = { - address: result.data.address as `0x${string}`, + address: options.smartWalletAddress, account: options.account, type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), From ffecbcf65895c0170bcab2517adaffe8a0dbf6e8 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 19:14:01 -0500 Subject: [PATCH 23/59] Fix --- src/actions/sendUserOperation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 85f0fc41..d811ec5f 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -3,7 +3,7 @@ import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; -import { Calls } from "viem/_types/types/calls"; +import { Calls } from "viem/types/calls" export type SendUserOperationOptions = { calls: Calls; From 77387db4315f2dcf93f7468c13fe3eda9a913437 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 12 Feb 2025 19:15:28 -0500 Subject: [PATCH 24/59] so much better --- src/actions/sendUserOperation.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index d811ec5f..d8acaa46 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -51,10 +51,6 @@ export async function sendUserOperation( }, ); - if (!createOpResponse.data) { - throw new Error("Failed to create user operation"); - } - if (!wallet.account.sign) { throw new Error("Account does not support signing"); } @@ -71,10 +67,6 @@ export async function sendUserOperation( }, ); - if (!broadcastResponse.data.status) { - throw new Error("Failed to broadcast user operation"); - } - const returnValue = { id: broadcastResponse.data.id, smartWalletAddress: wallet.address, From 51299d18d09322b37d04f530903b021332851787 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 11:38:47 -0500 Subject: [PATCH 25/59] Fix --- src/actions/waitForUserOperation.ts | 10 ++++------ src/wallets/createSmartWallet.ts | 4 +--- src/wallets/toSmartWallet..ts | 1 - testNewSmartWallet.ts | 11 +++++++---- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index dd7d5be6..705252ae 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -1,14 +1,12 @@ -import { Address } from "viem"; -import { Network } from "../types/chain"; +import { Address, Prettify } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { wait, WaitOptions } from "../utils/wait"; import { UserOperationStatusEnum } from "../client"; -export type WaitForUserOperationOptions = { +export type WaitForUserOperationOptions = Prettify<{ id: string; smartWalletAddress: Address; - waitOptions?: WaitOptions -} +} & WaitOptions> export type FailedOperation = { id: string; @@ -43,7 +41,7 @@ export async function waitForUserOperation(options: WaitForUserOperationOptions) transactionHash: userOperation.data.transaction_hash, } as WaitForUserOperationReturnType; } - + return wait(reload, (userOperation: WaitForUserOperationReturnType) => { return userOperation.status === UserOperationStatusEnum.Complete || userOperation.status === UserOperationStatusEnum.Failed; }, options.waitOptions); diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index 02430293..c04c555e 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,8 +1,6 @@ -import { SmartWalletNetworkOptions, type SmartWallet } from "./types"; +import { type SmartWallet } from "./types"; import { Coinbase } from "../index"; -import { sendUserOperation } from "../actions/sendUserOperation"; import type { Address, LocalAccount } from "viem"; -import { createNetwork } from "../utils/chain"; import { toSmartWallet } from "./toSmartWallet."; export type CreateSmartWalletOptions = { diff --git a/src/wallets/toSmartWallet..ts b/src/wallets/toSmartWallet..ts index 9c75b76e..260169ff 100644 --- a/src/wallets/toSmartWallet..ts +++ b/src/wallets/toSmartWallet..ts @@ -1,5 +1,4 @@ import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; -import { Coinbase } from "../index"; import { sendUserOperation } from "../actions/sendUserOperation"; import type { Address, LocalAccount } from "viem"; import { createNetwork } from "../utils/chain"; diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index b71fdb18..6861844c 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,9 +1,8 @@ import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Coinbase, ExternalAddress, Wallet } from './src/index' -import { createSmartWallet } from './src/index' +import { Coinbase, ExternalAddress, Wallet } from './src/index'; +import { createSmartWallet } from './src/index'; import { waitForUserOperation } from "./src/actions/waitForUserOperation"; -import { UserOperationStatusEnum } from "./src/client"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", @@ -37,7 +36,11 @@ async function main() { chainId: 84532, }); - const userOperationResult = await waitForUserOperation(userOperation); + const userOperationResult = await waitForUserOperation({ + ...userOperation, + timeoutSeconds: 10000, + intervalSeconds: 1, + }); console.log("userOperationResult", userOperationResult); From fc0e1424ec9d4ed9f4cb0550645eb435fbf36e6e Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 13:10:27 -0500 Subject: [PATCH 26/59] changes --- src/actions/waitForUserOperation.ts | 54 +++++++++++++++++++---------- src/utils/wait.ts | 10 +++--- testNewSmartWallet.ts | 41 ++++++++++++++++++---- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 705252ae..ff53b763 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -1,12 +1,14 @@ -import { Address, Prettify } from "viem"; +import { Address } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { wait, WaitOptions } from "../utils/wait"; -import { UserOperationStatusEnum } from "../client"; +import { UserOperation, UserOperationStatusEnum } from "../client"; +import { SendUserOperationReturnType } from "./sendUserOperation"; -export type WaitForUserOperationOptions = Prettify<{ +export type WaitForUserOperationOptions = { id: string; smartWalletAddress: Address; -} & WaitOptions> + waitOptions?: WaitOptions; +} export type FailedOperation = { id: string; @@ -23,26 +25,42 @@ export type CompletedOperation = { export type WaitForUserOperationReturnType = FailedOperation | CompletedOperation; - export async function waitForUserOperation(options: WaitForUserOperationOptions): Promise { const { id, smartWalletAddress } = options; const reload = async () => { - const userOperation = await Coinbase.apiClients.smartWallet!.getUserOperation(smartWalletAddress, id); + const response = await Coinbase.apiClients.smartWallet!.getUserOperation(smartWalletAddress, id); + return response.data; + } - if (!userOperation.data) { - throw new Error("User operation not found"); - } + const isTerminal = ( + operation: UserOperation + ): boolean => { + return operation.status === UserOperationStatusEnum.Complete || operation.status === UserOperationStatusEnum.Failed; + }; - return { - id: userOperation.data.id, - smartWalletAddress: smartWalletAddress, - status: userOperation.data.status, - transactionHash: userOperation.data.transaction_hash, - } as WaitForUserOperationReturnType; + const transform = (operation: UserOperation): WaitForUserOperationReturnType => { + if (operation.status === UserOperationStatusEnum.Failed) { + return { + id: operation.id, + smartWalletAddress: smartWalletAddress, + status: operation.status, + } satisfies FailedOperation; + } else if (operation.status === UserOperationStatusEnum.Complete) { + return { + id: operation.id, + smartWalletAddress: smartWalletAddress, + status: operation.status, + transactionHash: operation.transaction_hash, + } as CompletedOperation; + } else { + throw new Error("User operation is not terminal"); + } } - return wait(reload, (userOperation: WaitForUserOperationReturnType) => { - return userOperation.status === UserOperationStatusEnum.Complete || userOperation.status === UserOperationStatusEnum.Failed; - }, options.waitOptions); + const waitOptions = options.waitOptions || { + timeoutSeconds: 30, + }; + + return await wait(reload, isTerminal, transform, waitOptions); } diff --git a/src/utils/wait.ts b/src/utils/wait.ts index e0335188..77615e93 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -5,24 +5,24 @@ export type WaitOptions = { timeoutSeconds?: number; }; -export async function wait( +export async function wait( reload: () => Promise, isTerminal: (obj: T) => boolean, + transform: (obj: T) => K = (obj: T) => obj as unknown as K, options: WaitOptions = {}, -): Promise { +): Promise { const { intervalSeconds = 0.2, timeoutSeconds = 10 } = options; - const startTime = Date.now(); while (Date.now() - startTime < timeoutSeconds * 1000) { const updatedObject = await reload(); if (isTerminal(updatedObject)) { - return updatedObject; + return transform(updatedObject); } await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000)); } throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); -} +} \ No newline at end of file diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 6861844c..13be9dd6 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -3,6 +3,7 @@ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { Coinbase, ExternalAddress, Wallet } from './src/index'; import { createSmartWallet } from './src/index'; import { waitForUserOperation } from "./src/actions/waitForUserOperation"; +import { UserOperationStatusEnum } from "./src/client"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", @@ -25,7 +26,25 @@ async function main() { const wallet = await Wallet.create(); const walletAddress = await wallet.getDefaultAddress(); - const userOperation = await smartWallet.sendUserOperation({ + // const userOperation = await smartWallet.sendUserOperation({ + // calls: [ + // { + // to: walletAddress.getId() as `0x${string}`, + // value: parseEther("0.000001"), + // data: "0x", + // }, + // ], + // chainId: 84532, + // }); + + // const userOperationResult = await waitForUserOperation(userOperation); + + // connect to a network + const networkScopedSmartWallet = smartWallet.useNetwork({ + chainId: 84532, + }); + + const userOperation2 = await networkScopedSmartWallet.sendUserOperation({ calls: [ { to: walletAddress.getId() as `0x${string}`, @@ -33,16 +52,24 @@ async function main() { data: "0x", }, ], - chainId: 84532, }); - const userOperationResult = await waitForUserOperation({ - ...userOperation, - timeoutSeconds: 10000, - intervalSeconds: 1, + const userOperationResult2 = await waitForUserOperation({ + ...userOperation2, + waitOptions: { + timeoutSeconds: 10000, + intervalSeconds: 1, + }, }); - console.log("userOperationResult", userOperationResult); + if (userOperationResult2.status === UserOperationStatusEnum.Failed) { + userOperationResult2 // type is FailedOperation + } else { + userOperationResult2 // type is CompletedOperation + console.log(userOperationResult2.transactionHash) + } + + // const userOperationResult = await userOperation.wait(); From 2b13d810ab130fdd8b48d14a940ef844d88c719c Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 13:13:18 -0500 Subject: [PATCH 27/59] Fix --- src/actions/sendUserOperation.ts | 6 +++--- src/actions/waitForUserOperation.ts | 28 +++++++++++++++++----------- src/coinbase/types.ts | 2 +- src/tests/e2e.ts | 28 ++++++++++++++-------------- src/tests/external_address_test.ts | 4 ++-- src/tests/wallet_address_test.ts | 4 ++-- src/tests/wallet_test.ts | 4 ++-- src/types/chain.ts | 2 +- src/utils/wait.ts | 2 +- src/wallets/toSmartWallet..ts | 9 +++++---- src/wallets/types.ts | 25 ++++++++++++++----------- testNewSmartWallet.ts | 19 ++++++------------- 12 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index d8acaa46..1ba58043 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -3,7 +3,7 @@ import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; -import { Calls } from "viem/types/calls" +import { Calls } from "viem/types/calls"; export type SendUserOperationOptions = { calls: Calls; @@ -15,13 +15,13 @@ export type SendUserOperationReturnType = { id: string; smartWalletAddress: Address; status: typeof UserOperationStatusEnum.Broadcast; -} +}; export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, ): Promise { - const { calls, chainId, paymasterUrl } = options + const { calls, chainId, paymasterUrl } = options; const network = CHAIN_ID_TO_NETWORK_ID[chainId]; const encodedCalls = calls.map(call => { diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index ff53b763..5070b35e 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -8,35 +8,41 @@ export type WaitForUserOperationOptions = { id: string; smartWalletAddress: Address; waitOptions?: WaitOptions; -} +}; export type FailedOperation = { id: string; smartWalletAddress: Address; status: typeof UserOperationStatusEnum.Failed; -} +}; export type CompletedOperation = { id: string; smartWalletAddress: Address; status: typeof UserOperationStatusEnum.Complete; transactionHash: string; -} +}; export type WaitForUserOperationReturnType = FailedOperation | CompletedOperation; -export async function waitForUserOperation(options: WaitForUserOperationOptions): Promise { +export async function waitForUserOperation( + options: WaitForUserOperationOptions, +): Promise { const { id, smartWalletAddress } = options; const reload = async () => { - const response = await Coinbase.apiClients.smartWallet!.getUserOperation(smartWalletAddress, id); + const response = await Coinbase.apiClients.smartWallet!.getUserOperation( + smartWalletAddress, + id, + ); return response.data; - } + }; - const isTerminal = ( - operation: UserOperation - ): boolean => { - return operation.status === UserOperationStatusEnum.Complete || operation.status === UserOperationStatusEnum.Failed; + const isTerminal = (operation: UserOperation): boolean => { + return ( + operation.status === UserOperationStatusEnum.Complete || + operation.status === UserOperationStatusEnum.Failed + ); }; const transform = (operation: UserOperation): WaitForUserOperationReturnType => { @@ -56,7 +62,7 @@ export async function waitForUserOperation(options: WaitForUserOperationOptions) } else { throw new Error("User operation is not terminal"); } - } + }; const waitOptions = options.waitOptions || { timeoutSeconds: 30, diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index d8516ff3..623aad91 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -72,7 +72,7 @@ import { CreateSmartWalletRequest, CreateUserOperationRequest, UserOperation as UserOperationModel, - BroadcastUserOperationRequest + BroadcastUserOperationRequest, } from "./../client/api"; import { Address } from "./address"; import { Wallet } from "./wallet"; diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index d258ceaa..8ac0146d 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -151,39 +151,39 @@ describe("Coinbase SDK E2E Test", () => { }); }, 60000); - it("Should be able to invoke a contract and retrieve the transaction receipt", async() => { + it("Should be able to invoke a contract and retrieve the transaction receipt", async () => { const seedFile = JSON.parse(process.env.WALLET_DATA || ""); const walletId = Object.keys(seedFile)[0]; const seed = seedFile[walletId].seed; - + const importedWallet = await Wallet.import({ seed, walletId, networkId: Coinbase.networks.BaseSepolia, }); - + const faucetTransaction = await importedWallet.faucet(Coinbase.assets.Usdc); await faucetTransaction.wait(); - + const secondWallet = await Wallet.create(); const secondWalletAddress = (await secondWallet.getDefaultAddress()).getId(); - + const transferArgs = { to: secondWalletAddress, - value: "1" - } - + value: "1", + }; + const contractInvocation = await importedWallet.invokeContract({ contractAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", method: "transfer", args: transferArgs, }); - + await contractInvocation.wait(); - + const transactionContent = contractInvocation.getTransaction().content(); const receipt = transactionContent!.receipt; - + expect(receipt).toBeDefined(); if (!receipt?.logs) { @@ -191,10 +191,10 @@ describe("Coinbase SDK E2E Test", () => { } const logs = receipt.logs; - + expect(logs).toBeDefined(); expect(logs.length).toEqual(1); - + const log = logs[0]; expect(log.address).toEqual("0x036CbD53842c5426634e7929541eC2318f3dCF7e"); expect(log.topics?.[0]).toEqual("Transfer"); @@ -202,7 +202,7 @@ describe("Coinbase SDK E2E Test", () => { expect(log.topics?.[2]).toEqual(`to: ${(await secondWallet.getDefaultAddress()).getId()}`); expect(log.data).toEqual("0x0000000000000000000000000000000000000000000000000000000000000001"); }, 60000); - + it.skip("should be able to make gasless transfers", async () => { // Import wallet with balance const seedFile = JSON.parse(process.env.WALLET_DATA || ""); diff --git a/src/tests/external_address_test.ts b/src/tests/external_address_test.ts index a2bf9a30..690bd841 100644 --- a/src/tests/external_address_test.ts +++ b/src/tests/external_address_test.ts @@ -70,8 +70,8 @@ describe("ExternalAddress", () => { network_id: Coinbase.networks.EthereumHolesky, decimals: 18, contract_address: "0x", - } - } + }, + }, }, }; const STAKING_OPERATION_MODEL: StakingOperationModel = { diff --git a/src/tests/wallet_address_test.ts b/src/tests/wallet_address_test.ts index 22b99195..2b78b7e4 100644 --- a/src/tests/wallet_address_test.ts +++ b/src/tests/wallet_address_test.ts @@ -404,8 +404,8 @@ describe("WalletAddress", () => { network_id: Coinbase.networks.EthereumHolesky, decimals: 18, contract_address: "0x", - } - } + }, + }, }, }; diff --git a/src/tests/wallet_test.ts b/src/tests/wallet_test.ts index 0cfa6385..fce39dd2 100644 --- a/src/tests/wallet_test.ts +++ b/src/tests/wallet_test.ts @@ -181,8 +181,8 @@ describe("Wallet Class", () => { network_id: Coinbase.networks.EthereumHolesky, decimals: 18, contract_address: "0x", - } - } + }, + }, }, }; diff --git a/src/types/chain.ts b/src/types/chain.ts index cf8bd513..79fadc2f 100644 --- a/src/types/chain.ts +++ b/src/types/chain.ts @@ -18,4 +18,4 @@ export type SupportedChainId = keyof typeof CHAIN_ID_TO_NETWORK_ID; export type Network = { chainId: SupportedChainId; networkId: NetworkIdentifier; -}; \ No newline at end of file +}; diff --git a/src/utils/wait.ts b/src/utils/wait.ts index 77615e93..e3f2767b 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -25,4 +25,4 @@ export async function wait( } throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); -} \ No newline at end of file +} diff --git a/src/wallets/toSmartWallet..ts b/src/wallets/toSmartWallet..ts index 260169ff..9bed3d34 100644 --- a/src/wallets/toSmartWallet..ts +++ b/src/wallets/toSmartWallet..ts @@ -20,10 +20,11 @@ export async function toSmartWallet(options: ToSmartWalletOptions): Promise sendUserOperation(wallet, { - ...options, - chainId: network.chainId, - }), + sendUserOperation: options => + sendUserOperation(wallet, { + ...options, + chainId: network.chainId, + }), } as NetworkScopedSmartWallet; }, }; diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 63b09145..da19d1f4 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,30 +1,33 @@ import type { Address } from "abitype"; import type { LocalAccount } from "viem"; import { - SendUserOperationOptions, SendUserOperationReturnType -} from '../actions/sendUserOperation'; + SendUserOperationOptions, + SendUserOperationReturnType, +} from "../actions/sendUserOperation"; import { Network, SupportedChainId } from "../types/chain"; import { Prettify } from "viem"; export type SmartWalletNetworkOptions = { chainId: SupportedChainId; paymasterUrl?: string; -} +}; export type SmartWallet = { address: Address; account: LocalAccount; type: "smart"; sendUserOperation: ( - options: SendUserOperationOptions + options: SendUserOperationOptions, ) => Promise; useNetwork: (options: SmartWalletNetworkOptions) => NetworkScopedSmartWallet; }; -export type NetworkScopedSmartWallet = Prettify & { - network: Network; - paymasterUrl?: string; - sendUserOperation: ( - options: Prettify, "chainId" | "paymasterUrl">> - ) => Promise; -}> \ No newline at end of file +export type NetworkScopedSmartWallet = Prettify< + Omit & { + network: Network; + paymasterUrl?: string; + sendUserOperation: ( + options: Prettify, "chainId" | "paymasterUrl">>, + ) => Promise; + } +>; diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index 13be9dd6..f632961a 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -1,14 +1,14 @@ import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Coinbase, ExternalAddress, Wallet } from './src/index'; -import { createSmartWallet } from './src/index'; +import { Coinbase, ExternalAddress, Wallet } from "./src/index"; +import { createSmartWallet } from "./src/index"; import { waitForUserOperation } from "./src/actions/waitForUserOperation"; import { UserOperationStatusEnum } from "./src/client"; Coinbase.configureFromJson({ filePath: "~/.apikeys/dev.json", debugging: true, - basePath: "https://cloud-api-dev.cbhq.net/platform/" + basePath: "https://cloud-api-dev.cbhq.net/platform/", }); async function main() { @@ -63,19 +63,12 @@ async function main() { }); if (userOperationResult2.status === UserOperationStatusEnum.Failed) { - userOperationResult2 // type is FailedOperation + userOperationResult2; // type is FailedOperation } else { - userOperationResult2 // type is CompletedOperation - console.log(userOperationResult2.transactionHash) + userOperationResult2; // type is CompletedOperation + console.log(userOperationResult2.transactionHash); } - - -// const userOperationResult = await userOperation.wait(); - - // const userOperationResult = await waitForUserOperation(userOperation) - - // get final balance now const finalBalance = await walletAddress.getBalance("eth"); console.log("finalBalance", finalBalance); From 3f083c4ac4acbb96f736ed8ec1e98e16858498ac Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 13:26:45 -0500 Subject: [PATCH 28/59] Fix --- src/actions/sendUserOperation.ts | 8 ++++++++ testNewSmartWallet.ts | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 1ba58043..049a52ed 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -5,6 +5,14 @@ import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; import { Calls } from "viem/types/calls"; + +/** + * Options for sending a user operation + * @template T - Array type for the calls parameter + * @property {Calls} calls - Array of contract calls to execute in the user operation + * @property {SupportedChainId} chainId - Chain ID of the network to execute on + * @property {string} [paymasterUrl] - Optional URL of the paymaster service to use for gas sponsorship + */ export type SendUserOperationOptions = { calls: Calls; chainId: SupportedChainId; diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index f632961a..f3fe68b0 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -26,18 +26,18 @@ async function main() { const wallet = await Wallet.create(); const walletAddress = await wallet.getDefaultAddress(); - // const userOperation = await smartWallet.sendUserOperation({ - // calls: [ - // { - // to: walletAddress.getId() as `0x${string}`, - // value: parseEther("0.000001"), - // data: "0x", - // }, - // ], - // chainId: 84532, - // }); + const userOperation = await smartWallet.sendUserOperation({ + calls: [ + { + to: walletAddress.getId() as `0x${string}`, + value: parseEther("0.0000005"), + data: "0x", + }, + ], + chainId: 84532, + }); - // const userOperationResult = await waitForUserOperation(userOperation); + const userOperationResult = await waitForUserOperation(userOperation); // connect to a network const networkScopedSmartWallet = smartWallet.useNetwork({ @@ -48,7 +48,7 @@ async function main() { calls: [ { to: walletAddress.getId() as `0x${string}`, - value: parseEther("0.000001"), + value: parseEther("0.0000005"), data: "0x", }, ], From b2b3f4381a7a4c1a883b35fbfdfaad73da1e6a85 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 13:54:16 -0500 Subject: [PATCH 29/59] Fix --- src/actions/sendUserOperation.ts | 7 ++++--- src/wallets/toSmartWallet..ts | 2 +- src/wallets/types.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 049a52ed..73095f28 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -5,7 +5,6 @@ import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; import { Calls } from "viem/types/calls"; - /** * Options for sending a user operation * @template T - Array type for the calls parameter @@ -59,11 +58,13 @@ export async function sendUserOperation( }, ); - if (!wallet.account.sign) { + const owner = wallet.owners[0]; + + if (!owner.sign) { throw new Error("Account does not support signing"); } - const signature = await wallet.account.sign({ + const signature = await owner.sign({ hash: createOpResponse.data.unsigned_payload as Hex, }); diff --git a/src/wallets/toSmartWallet..ts b/src/wallets/toSmartWallet..ts index 9bed3d34..09c0fcde 100644 --- a/src/wallets/toSmartWallet..ts +++ b/src/wallets/toSmartWallet..ts @@ -11,7 +11,7 @@ export type ToSmartWalletOptions = { export async function toSmartWallet(options: ToSmartWalletOptions): Promise { const wallet: SmartWallet = { address: options.smartWalletAddress, - account: options.account, + owners: [options.account], type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), useNetwork: (options: SmartWalletNetworkOptions) => { diff --git a/src/wallets/types.ts b/src/wallets/types.ts index da19d1f4..8757a462 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -14,7 +14,7 @@ export type SmartWalletNetworkOptions = { export type SmartWallet = { address: Address; - account: LocalAccount; + owners: LocalAccount[]; type: "smart"; sendUserOperation: ( options: SendUserOperationOptions, From 8ea21cdd1f46a3ab70b60bf30de4f07addd3ad0d Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 16:21:44 -0500 Subject: [PATCH 30/59] Fix --- src/wallets/createSmartWallet.ts | 10 +++++----- src/wallets/toSmartWallet..ts | 11 ++++++++--- src/wallets/types.ts | 33 ++++++++++++++++++++++++++++++-- testNewSmartWallet.ts | 2 +- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index c04c555e..27784368 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,19 +1,19 @@ -import { type SmartWallet } from "./types"; +import { Signer, type SmartWallet } from "./types"; import { Coinbase } from "../index"; -import type { Address, LocalAccount } from "viem"; +import type { Address } from "viem"; import { toSmartWallet } from "./toSmartWallet."; export type CreateSmartWalletOptions = { - account: LocalAccount; + signer: Signer; }; export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ - owner: options.account.address, + owner: options.signer.address, }); return toSmartWallet({ smartWalletAddress: result.data.address as Address, - account: options.account, + signer: options.signer, }); } diff --git a/src/wallets/toSmartWallet..ts b/src/wallets/toSmartWallet..ts index 09c0fcde..34dc981b 100644 --- a/src/wallets/toSmartWallet..ts +++ b/src/wallets/toSmartWallet..ts @@ -1,17 +1,22 @@ -import { NetworkScopedSmartWallet, SmartWalletNetworkOptions, type SmartWallet } from "./types"; +import { + NetworkScopedSmartWallet, + Signer, + SmartWalletNetworkOptions, + type SmartWallet, +} from "./types"; import { sendUserOperation } from "../actions/sendUserOperation"; import type { Address, LocalAccount } from "viem"; import { createNetwork } from "../utils/chain"; export type ToSmartWalletOptions = { smartWalletAddress: Address; - account: LocalAccount; + signer: Signer; }; export async function toSmartWallet(options: ToSmartWalletOptions): Promise { const wallet: SmartWallet = { address: options.smartWalletAddress, - owners: [options.account], + owners: [options.signer], type: "smart", sendUserOperation: options => sendUserOperation(wallet, options), useNetwork: (options: SmartWalletNetworkOptions) => { diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 8757a462..e56a2c34 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,5 +1,5 @@ import type { Address } from "abitype"; -import type { LocalAccount } from "viem"; +import type { Hash, Hex } from "viem"; import { SendUserOperationOptions, SendUserOperationReturnType, @@ -7,25 +7,54 @@ import { import { Network, SupportedChainId } from "../types/chain"; import { Prettify } from "viem"; +/** + * Options for configuring a SmartWallet for a specific network + */ export type SmartWalletNetworkOptions = { + /** The chain ID of the network to connect to */ chainId: SupportedChainId; + /** Optional URL for the paymaster service */ paymasterUrl?: string; }; +/** + * Represents a signer that can sign messages + */ +export type Signer = { + /** The address of the signer */ + address: Address; + /** Signs a message hash and returns the signature as a hex string */ + sign: (parameters: { hash: Hash }) => Promise; +}; + +/** + * Represents a SmartWallet with user operation capabilities + */ export type SmartWallet = { + /** The smart wallet's address */ address: Address; - owners: LocalAccount[]; + /** Array of signers that own the wallet (currently only supports one owner) */ + owners: Signer[]; + /** Identifier for the wallet type */ type: "smart"; + /** Sends a user operation to the network */ sendUserOperation: ( options: SendUserOperationOptions, ) => Promise; + /** Configures the wallet for a specific network */ useNetwork: (options: SmartWalletNetworkOptions) => NetworkScopedSmartWallet; }; +/** + * A smart wallet that's configured for a specific network + */ export type NetworkScopedSmartWallet = Prettify< Omit & { + /** The network configuration */ network: Network; + /** Optional URL for the paymaster service */ paymasterUrl?: string; + /** Sends a user operation to the configured network */ sendUserOperation: ( options: Prettify, "chainId" | "paymasterUrl">>, ) => Promise; diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts index f3fe68b0..118588de 100644 --- a/testNewSmartWallet.ts +++ b/testNewSmartWallet.ts @@ -15,7 +15,7 @@ async function main() { // create a smart wallet with viem wallet owner const privateKey = generatePrivateKey(); const owner = privateKeyToAccount(privateKey); - const smartWallet = await createSmartWallet({ account: owner }); + const smartWallet = await createSmartWallet({ signer: owner }); // Faucet the smart wallet using an External Address const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); From 67e21e44cf869485937e5b689e03a02e68c6c17c Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 17:58:02 -0500 Subject: [PATCH 31/59] WIP --- src/actions/sendUserOperation.ts | 57 ++++++++++++++----- src/actions/waitForUserOperation.ts | 52 +++++++++++++++-- src/coinbase/utils/wait.ts | 28 --------- src/index.ts | 2 + src/types/chain.ts | 9 +++ src/utils/wait.ts | 20 +++++++ src/wallets/createSmartWallet.ts | 30 +++++++++- .../{toSmartWallet..ts => toSmartWallet.ts} | 23 +++++++- src/wallets/types.ts | 6 +- 9 files changed, 175 insertions(+), 52 deletions(-) delete mode 100644 src/coinbase/utils/wait.ts rename src/wallets/{toSmartWallet..ts => toSmartWallet.ts} (56%) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 73095f28..45bc72f3 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,29 +1,66 @@ -import { SmartWallet } from "../wallets/types"; +import type { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; -import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; -import { Calls } from "viem/types/calls"; +import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; +import type { Calls } from "viem/types/calls"; /** * Options for sending a user operation * @template T - Array type for the calls parameter - * @property {Calls} calls - Array of contract calls to execute in the user operation - * @property {SupportedChainId} chainId - Chain ID of the network to execute on - * @property {string} [paymasterUrl] - Optional URL of the paymaster service to use for gas sponsorship */ export type SendUserOperationOptions = { + /** Array of contract calls to execute in the user operation */ calls: Calls; + /** Chain ID of the network to execute on */ chainId: SupportedChainId; + /** Optional URL of the paymaster service to use for gas sponsorship. Must be ERC-7677 compliant. */ paymasterUrl?: string; }; +/** + * Return type for the sendUserOperation function + */ export type SendUserOperationReturnType = { + /** The ID of the user operation */ id: string; + /** The address of the smart wallet */ smartWalletAddress: Address; + /** The status of the user operation */ status: typeof UserOperationStatusEnum.Broadcast; }; +/** + * Sends a user operation to the network + * + * @example + * ```ts + * import { sendUserOperation } from "@coinbase/coinbase-sdk"; + * import { parseEther } from "viem"; + + * + * const result = await sendUserOperation(wallet, { + * calls: [ + * { + * abi: erc20Abi, + * functionName: "transfer", + * args: [to, amount], + * }, + * { + * to: "0x1234567890123456789012345678901234567890", + * data: "0x", + * value: parseEther("0.0000005"), + * }, + * ], + * chainId: 1, + * paymasterUrl: "https://api.developer.coinbase.com/rpc/v1/base/someapikey", + * }); + * ``` + * + * @param {SmartWallet} wallet - The smart wallet to send the user operation from + * @param {SendUserOperationOptions} options - The options for the user operation + * @returns {Promise} The result of the user operation + */ export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, @@ -60,10 +97,6 @@ export async function sendUserOperation( const owner = wallet.owners[0]; - if (!owner.sign) { - throw new Error("Account does not support signing"); - } - const signature = await owner.sign({ hash: createOpResponse.data.unsigned_payload as Hex, }); @@ -76,12 +109,10 @@ export async function sendUserOperation( }, ); - const returnValue = { + return { id: broadcastResponse.data.id, smartWalletAddress: wallet.address, status: broadcastResponse.data.status, transactionHash: broadcastResponse.data.transaction_hash, } as SendUserOperationReturnType; - - return returnValue; } diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 5070b35e..ec8da5bb 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -2,29 +2,69 @@ import { Address } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { wait, WaitOptions } from "../utils/wait"; import { UserOperation, UserOperationStatusEnum } from "../client"; -import { SendUserOperationReturnType } from "./sendUserOperation"; +/** + * Options for waiting for a user operation + */ export type WaitForUserOperationOptions = { + /** The ID of the user operation */ id: string; + /** The address of the smart wallet */ smartWalletAddress: Address; + /** Optional options for the wait operation */ waitOptions?: WaitOptions; }; +/** + * Represents a failed user operation + */ export type FailedOperation = { + /** The ID of the user operation */ id: string; + /** The address of the smart wallet */ smartWalletAddress: Address; + /** The status of the user operation */ status: typeof UserOperationStatusEnum.Failed; }; +/** + * Represents a completed user operation + */ export type CompletedOperation = { + /** The ID of the user operation */ id: string; + /** The address of the smart wallet */ smartWalletAddress: Address; - status: typeof UserOperationStatusEnum.Complete; + /** The transaction hash of the user operation */ transactionHash: string; + /** The status of the user operation */ + status: typeof UserOperationStatusEnum.Complete; }; +/** + * Represents the return type of the waitForUserOperation function + */ export type WaitForUserOperationReturnType = FailedOperation | CompletedOperation; +/** + * Waits for a user operation to complete or fail + * + * @example + * ```ts + * import { waitForUserOperation } from "@coinbase/coinbase-sdk"; + * + * const result = await waitForUserOperation({ + * id: "123", + * smartWalletAddress: "0x1234567890123456789012345678901234567890", + * waitOptions: { + * timeoutSeconds: 30, + * }, + * }); + * ``` + * + * @param {WaitForUserOperationOptions} options - The options for the wait operation + * @returns {Promise} The result of the user operation + */ export async function waitForUserOperation( options: WaitForUserOperationOptions, ): Promise { @@ -50,15 +90,15 @@ export async function waitForUserOperation( return { id: operation.id, smartWalletAddress: smartWalletAddress, - status: operation.status, + status: UserOperationStatusEnum.Failed, } satisfies FailedOperation; } else if (operation.status === UserOperationStatusEnum.Complete) { return { id: operation.id, smartWalletAddress: smartWalletAddress, - status: operation.status, - transactionHash: operation.transaction_hash, - } as CompletedOperation; + transactionHash: operation.transaction_hash!, + status: UserOperationStatusEnum.Complete, + } satisfies CompletedOperation; } else { throw new Error("User operation is not terminal"); } diff --git a/src/coinbase/utils/wait.ts b/src/coinbase/utils/wait.ts deleted file mode 100644 index b928d7cf..00000000 --- a/src/coinbase/utils/wait.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { TimeoutError } from "../errors"; - -export type WaitOptions = { - intervalSeconds?: number; - timeoutSeconds?: number; -}; - -export async function wait( - reload: () => Promise, - isTerminal: (obj: T) => boolean, - options: WaitOptions = {}, -): Promise { - const { intervalSeconds = 0.2, timeoutSeconds = 10 } = options; - - const startTime = Date.now(); - - while (Date.now() - startTime < timeoutSeconds * 1000) { - const updatedObject = await reload(); - - if (isTerminal(updatedObject)) { - return updatedObject; - } - - await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000)); - } - - throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); -} diff --git a/src/index.ts b/src/index.ts index 7543c7b8..c1c9f288 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,4 +35,6 @@ export * from "./coinbase/fund_quote"; export * from "./types/chain"; export * from "./wallets/types"; export * from "./wallets/createSmartWallet"; +export * from "./wallets/toSmartWallet"; export * from "./actions/sendUserOperation"; +export * from "./actions/waitForUserOperation"; diff --git a/src/types/chain.ts b/src/types/chain.ts index 79fadc2f..098479b0 100644 --- a/src/types/chain.ts +++ b/src/types/chain.ts @@ -1,5 +1,8 @@ import { NetworkIdentifier } from "../client/api"; +/** + * Maps chain IDs to their corresponding Coinbase network IDs + */ export const CHAIN_ID_TO_NETWORK_ID = { 1: "ethereum-mainnet", 11155111: "ethereum-sepolia", @@ -13,8 +16,14 @@ export const CHAIN_ID_TO_NETWORK_ID = { 11155420: "optimism-sepolia", } as const; +/** + * Supported chain IDs are the keys of the CHAIN_ID_TO_NETWORK_ID object + */ export type SupportedChainId = keyof typeof CHAIN_ID_TO_NETWORK_ID; +/** + * Represents a chainID and the corresponding Coinbase network ID + */ export type Network = { chainId: SupportedChainId; networkId: NetworkIdentifier; diff --git a/src/utils/wait.ts b/src/utils/wait.ts index e3f2767b..c124ca17 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -1,10 +1,30 @@ import { TimeoutError } from "../coinbase/errors"; export type WaitOptions = { + /** Interval between retries in seconds. Defaults to 0.2 */ intervalSeconds?: number; + /** Maximum time to wait before timing out in seconds. Defaults to 10 */ timeoutSeconds?: number; }; +/** + * Polls a resource until a terminal condition is met or timeout occurs. + * + * @param reload - Function that fetches the latest state of the resource + * @param isTerminal - Function that determines if the current state is terminal + * @param transform - Function that transforms the resource into a new type + * @param options - Configuration options for polling behavior + * @returns The resource in its terminal state + * @throws {TimeoutError} If the operation exceeds the timeout duration + * + * @example + * const result = await wait( + * () => fetchOrderStatus(orderId), + * (status) => status === 'completed', + * (status) => status === 'completed' ? { status } : undefined, + * { timeoutSeconds: 30 } + * ); + */ export async function wait( reload: () => Promise, isTerminal: (obj: T) => boolean, diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index 27784368..90174a0f 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,12 +1,40 @@ import { Signer, type SmartWallet } from "./types"; import { Coinbase } from "../index"; import type { Address } from "viem"; -import { toSmartWallet } from "./toSmartWallet."; +import { toSmartWallet } from "./toSmartWallet"; +/** + * Options for creating a smart wallet + */ export type CreateSmartWalletOptions = { + /** The signer object that will own the smart wallet */ signer: Signer; }; +/** + * Creates a new smart wallet using the Coinbase API + * + * See https://viem.sh/docs/accounts/local/privateKeyToAccount for using a Viem LocalAccount with SmartWallet + * + * @example + * ```ts + * import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; + * import { createSmartWallet } from "@coinbase/coinbase-sdk"; + * import { Coinbase } from "@coinbase/coinbase-sdk"; + * + * Coinbase.configureFromJson({filePath: "~/.apikeys/prod.json"}); + * + * const privateKey = generatePrivateKey(); + * const owner = privateKeyToAccount(privateKey); + * const wallet = await createSmartWallet({ + * signer: owner + * }); + * ``` + * + * @param {CreateSmartWalletOptions} options - Configuration options for creating the smart wallet + * @returns {Promise} A promise that resolves to the newly created smart wallet instance + * @throws {Error} If the Coinbase API client is not initialized + */ export async function createSmartWallet(options: CreateSmartWalletOptions): Promise { const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ owner: options.signer.address, diff --git a/src/wallets/toSmartWallet..ts b/src/wallets/toSmartWallet.ts similarity index 56% rename from src/wallets/toSmartWallet..ts rename to src/wallets/toSmartWallet.ts index 34dc981b..bc9b89ad 100644 --- a/src/wallets/toSmartWallet..ts +++ b/src/wallets/toSmartWallet.ts @@ -8,12 +8,33 @@ import { sendUserOperation } from "../actions/sendUserOperation"; import type { Address, LocalAccount } from "viem"; import { createNetwork } from "../utils/chain"; +/** + * Options for converting a smart wallet address and signer to a SmartWallet instance + */ export type ToSmartWalletOptions = { + /** The address of the smart wallet */ smartWalletAddress: Address; + /** The signer that will own the smart wallet */ signer: Signer; }; -export async function toSmartWallet(options: ToSmartWalletOptions): Promise { +/** + * Converts a smart wallet address and signer to a SmartWallet instance + * + * @example + * ```ts + * import { toSmartWallet } from "@coinbase/coinbase-sdk"; + * + * const wallet = toSmartWallet({ + * smartWalletAddress: "0x1234567890123456789012345678901234567890", + * signer: localAccount + * }); + * ``` + * + * @param {ToSmartWalletOptions} options - Options for converting the smart wallet address and signer to a SmartWallet instance + * @returns {SmartWallet} The SmartWallet instance + */ +export function toSmartWallet(options: ToSmartWalletOptions): SmartWallet { const wallet: SmartWallet = { address: options.smartWalletAddress, owners: [options.signer], diff --git a/src/wallets/types.ts b/src/wallets/types.ts index e56a2c34..9ef18361 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,11 +1,11 @@ import type { Address } from "abitype"; import type { Hash, Hex } from "viem"; -import { +import type { SendUserOperationOptions, SendUserOperationReturnType, } from "../actions/sendUserOperation"; -import { Network, SupportedChainId } from "../types/chain"; -import { Prettify } from "viem"; +import type { Network, SupportedChainId } from "../types/chain"; +import type { Prettify } from "viem"; /** * Options for configuring a SmartWallet for a specific network From fef7857739dede8db2992fe622428c5d2ff4f1dd Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 18:01:36 -0500 Subject: [PATCH 32/59] Fix --- src/utils/chain.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utils/chain.ts b/src/utils/chain.ts index a3792d97..50943a06 100644 --- a/src/utils/chain.ts +++ b/src/utils/chain.ts @@ -1,6 +1,11 @@ import { NetworkIdentifier } from "../client/api"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId, Network } from "../types/chain"; +/** + * Creates a network configuration for a given chain ID + * @param chainId - The chain ID to create a network configuration for + * @returns The network configuration + */ export function createNetwork(chainId: SupportedChainId): Network { return { chainId, From f1564266f1134faba98989588ebc7c1aa859237b Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 18:03:00 -0500 Subject: [PATCH 33/59] Changes" --- src/utils/wait.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/wait.ts b/src/utils/wait.ts index c124ca17..38863fd0 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -1,5 +1,8 @@ import { TimeoutError } from "../coinbase/errors"; +/** + * Options for the wait function + */ export type WaitOptions = { /** Interval between retries in seconds. Defaults to 0.2 */ intervalSeconds?: number; From 01613ce8b318f4cb971ea2c20ef42522f849594a Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 18:27:48 -0500 Subject: [PATCH 34/59] changes --- src/actions/sendUserOperation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 45bc72f3..96f38524 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -4,6 +4,7 @@ import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; import type { Calls } from "viem/types/calls"; +import type { SendUserOperationParameters } from "viem/account-abstraction/"; /** * Options for sending a user operation From b87d66d2f47e398aaa27981d8a848362811e73e6 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 18:42:20 -0500 Subject: [PATCH 35/59] Fix --- src/actions/sendUserOperation.ts | 1 + src/client/api.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 96f38524..9eccf33a 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -93,6 +93,7 @@ export async function sendUserOperation( network, { calls: encodedCalls, + paymaster_url: paymasterUrl, }, ); diff --git a/src/client/api.ts b/src/client/api.ts index 64d79f8d..cbf64609 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -1100,6 +1100,12 @@ export interface CreateUserOperationRequest { * @memberof CreateUserOperationRequest */ 'calls': Array; + /** + * The URL of the paymaster to use for the user operation. + * @type {string} + * @memberof CreateUserOperationRequest + */ + 'paymaster_url'?: string; } /** * From 2de5968c01579723b2d7c5f0421af35729e4186e Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 13 Feb 2025 18:54:33 -0500 Subject: [PATCH 36/59] Whitespace --- src/actions/sendUserOperation.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 9eccf33a..f5941a32 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -38,7 +38,6 @@ export type SendUserOperationReturnType = { * ```ts * import { sendUserOperation } from "@coinbase/coinbase-sdk"; * import { parseEther } from "viem"; - * * const result = await sendUserOperation(wallet, { * calls: [ From d3092b59abf17ca6377e0256c09587a18a96d406 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Fri, 14 Feb 2025 11:29:08 -0500 Subject: [PATCH 37/59] Refactor --- src/actions/sendUserOperation.ts | 17 +++++++---------- src/actions/waitForUserOperation.ts | 14 +++++++------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index f5941a32..79df6b20 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -3,7 +3,7 @@ import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; -import type { Calls } from "viem/types/calls"; +import type { Call, Calls } from "viem/types/calls"; import type { SendUserOperationParameters } from "viem/account-abstraction/"; /** @@ -33,12 +33,12 @@ export type SendUserOperationReturnType = { /** * Sends a user operation to the network - * + * * @example * ```ts * import { sendUserOperation } from "@coinbase/coinbase-sdk"; * import { parseEther } from "viem"; - * + * * const result = await sendUserOperation(wallet, { * calls: [ * { @@ -56,7 +56,7 @@ export type SendUserOperationReturnType = { * paymasterUrl: "https://api.developer.coinbase.com/rpc/v1/base/someapikey", * }); * ``` - * + * * @param {SmartWallet} wallet - The smart wallet to send the user operation from * @param {SendUserOperationOptions} options - The options for the user operation * @returns {Promise} The result of the user operation @@ -71,15 +71,12 @@ export async function sendUserOperation( const encodedCalls = calls.map(call => { if ("abi" in call) { return { - data: encodeFunctionData({ - abi: call.abi, - functionName: call.functionName, - args: call.args, - }), + data: encodeFunctionData(call), to: call.to, - value: call.value.toString() || "0", + value: call.value.toString(), }; } + // return call as Call return { data: call.data, to: call.to, diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index ec8da5bb..21568d03 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -78,13 +78,6 @@ export async function waitForUserOperation( return response.data; }; - const isTerminal = (operation: UserOperation): boolean => { - return ( - operation.status === UserOperationStatusEnum.Complete || - operation.status === UserOperationStatusEnum.Failed - ); - }; - const transform = (operation: UserOperation): WaitForUserOperationReturnType => { if (operation.status === UserOperationStatusEnum.Failed) { return { @@ -110,3 +103,10 @@ export async function waitForUserOperation( return await wait(reload, isTerminal, transform, waitOptions); } + +const isTerminal = (operation: UserOperation): boolean => { + return ( + operation.status === UserOperationStatusEnum.Complete || + operation.status === UserOperationStatusEnum.Failed + ); +}; From a6350a3b966102909c34c793c55696c8fe97fca6 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Fri, 14 Feb 2025 12:00:10 -0500 Subject: [PATCH 38/59] Changes --- src/types/chain.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/types/chain.ts b/src/types/chain.ts index 098479b0..3a53cd0e 100644 --- a/src/types/chain.ts +++ b/src/types/chain.ts @@ -1,19 +1,11 @@ import { NetworkIdentifier } from "../client/api"; /** - * Maps chain IDs to their corresponding Coinbase network IDs + * Maps chain IDs to their corresponding Coinbase network IDs. Only SmartWallet related chains are listed here right now. */ export const CHAIN_ID_TO_NETWORK_ID = { - 1: "ethereum-mainnet", - 11155111: "ethereum-sepolia", - 137: "polygon-mainnet", - 80001: "polygon-mumbai", 8453: "base-mainnet", 84532: "base-sepolia", - 42161: "arbitrum-mainnet", - 421614: "arbitrum-sepolia", - 10: "optimism-mainnet", - 11155420: "optimism-sepolia", } as const; /** From 47d507ec2fe6ecf5febfeec3d91217a63d07730e Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Fri, 14 Feb 2025 12:23:00 -0500 Subject: [PATCH 39/59] Improve messaging --- src/utils/wait.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils/wait.ts b/src/utils/wait.ts index 38863fd0..16e2a8ec 100644 --- a/src/utils/wait.ts +++ b/src/utils/wait.ts @@ -46,6 +46,7 @@ export async function wait( await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000)); } - - throw new TimeoutError(`Operation timed out after ${timeoutSeconds} seconds`); + throw new TimeoutError( + `Operation has not reached a terminal state after ${timeoutSeconds} seconds and may still succeed. Retry with a longer timeout using the timeoutSeconds option.`, + ); } From b2fea1a6a135a311b3390dc2c606c8d580c16528 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 18 Feb 2025 20:48:46 -0500 Subject: [PATCH 40/59] Address feedback --- src/actions/sendUserOperation.ts | 3 +-- src/actions/waitForUserOperation.ts | 6 +++--- src/types/chain.ts | 4 ++-- src/utils/chain.ts | 3 +-- src/wallets/toSmartWallet.ts | 25 +++++++++++++++++++------ 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 79df6b20..5e655234 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -23,7 +23,7 @@ export type SendUserOperationOptions = { * Return type for the sendUserOperation function */ export type SendUserOperationReturnType = { - /** The ID of the user operation */ + /** The UUID of the user operation which is server-generated identifier for the operation */ id: string; /** The address of the smart wallet */ smartWalletAddress: Address; @@ -111,6 +111,5 @@ export async function sendUserOperation( id: broadcastResponse.data.id, smartWalletAddress: wallet.address, status: broadcastResponse.data.status, - transactionHash: broadcastResponse.data.transaction_hash, } as SendUserOperationReturnType; } diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 21568d03..0d3e69d6 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -7,7 +7,7 @@ import { UserOperation, UserOperationStatusEnum } from "../client"; * Options for waiting for a user operation */ export type WaitForUserOperationOptions = { - /** The ID of the user operation */ + /** The UUID of the user operation which was returned by the sendUserOperation function */ id: string; /** The address of the smart wallet */ smartWalletAddress: Address; @@ -19,7 +19,7 @@ export type WaitForUserOperationOptions = { * Represents a failed user operation */ export type FailedOperation = { - /** The ID of the user operation */ + /** The UUID of the user operation which was returned by the sendUserOperation function */ id: string; /** The address of the smart wallet */ smartWalletAddress: Address; @@ -31,7 +31,7 @@ export type FailedOperation = { * Represents a completed user operation */ export type CompletedOperation = { - /** The ID of the user operation */ + /** The UUID of the user operation which was returned by the sendUserOperation function */ id: string; /** The address of the smart wallet */ smartWalletAddress: Address; diff --git a/src/types/chain.ts b/src/types/chain.ts index 3a53cd0e..2bfc07fa 100644 --- a/src/types/chain.ts +++ b/src/types/chain.ts @@ -4,8 +4,8 @@ import { NetworkIdentifier } from "../client/api"; * Maps chain IDs to their corresponding Coinbase network IDs. Only SmartWallet related chains are listed here right now. */ export const CHAIN_ID_TO_NETWORK_ID = { - 8453: "base-mainnet", - 84532: "base-sepolia", + 8453: NetworkIdentifier.BaseMainnet, + 84532: NetworkIdentifier.BaseSepolia, } as const; /** diff --git a/src/utils/chain.ts b/src/utils/chain.ts index 50943a06..8e95bbcd 100644 --- a/src/utils/chain.ts +++ b/src/utils/chain.ts @@ -1,4 +1,3 @@ -import { NetworkIdentifier } from "../client/api"; import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId, Network } from "../types/chain"; /** @@ -9,6 +8,6 @@ import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId, Network } from "../types/chai export function createNetwork(chainId: SupportedChainId): Network { return { chainId, - networkId: CHAIN_ID_TO_NETWORK_ID[chainId] as NetworkIdentifier, + networkId: CHAIN_ID_TO_NETWORK_ID[chainId], }; } diff --git a/src/wallets/toSmartWallet.ts b/src/wallets/toSmartWallet.ts index bc9b89ad..8153bba7 100644 --- a/src/wallets/toSmartWallet.ts +++ b/src/wallets/toSmartWallet.ts @@ -5,7 +5,7 @@ import { type SmartWallet, } from "./types"; import { sendUserOperation } from "../actions/sendUserOperation"; -import type { Address, LocalAccount } from "viem"; +import type { Address } from "viem"; import { createNetwork } from "../utils/chain"; /** @@ -19,20 +19,33 @@ export type ToSmartWalletOptions = { }; /** - * Converts a smart wallet address and signer to a SmartWallet instance + * Creates a SmartWallet instance from an existing smart wallet address and signer. + * Use this to interact with previously deployed smart wallets, rather than creating new ones. + * + * The signer must be the original owner of the smart wallet. * * @example - * ```ts + * ```typescript * import { toSmartWallet } from "@coinbase/coinbase-sdk"; - * + * + * // Connect to an existing smart wallet * const wallet = toSmartWallet({ * smartWalletAddress: "0x1234567890123456789012345678901234567890", * signer: localAccount * }); + * + * // Use on a specific network + * const networkWallet = wallet.useNetwork({ + * chainId: 8453, // Base Mainnet + * paymasterUrl: "https://paymaster.example.com" + * }); * ``` * - * @param {ToSmartWalletOptions} options - Options for converting the smart wallet address and signer to a SmartWallet instance - * @returns {SmartWallet} The SmartWallet instance + * @param {ToSmartWalletOptions} options - Configuration options + * @param {string} options.smartWalletAddress - The deployed smart wallet's address + * @param {Signer} options.signer - The owner's signer instance + * @returns {SmartWallet} A configured SmartWallet instance ready for transaction submission + * @throws {Error} If the signer is not an original owner of the wallet */ export function toSmartWallet(options: ToSmartWalletOptions): SmartWallet { const wallet: SmartWallet = { From b76d00098975b3ad5dca9fbdf8e31f30acffbaf9 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 18 Feb 2025 20:58:46 -0500 Subject: [PATCH 41/59] Fix --- src/actions/sendUserOperation.ts | 10 ++++------ src/wallets/toSmartWallet.ts | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 5e655234..5b58ffa6 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -69,18 +69,16 @@ export async function sendUserOperation( const network = CHAIN_ID_TO_NETWORK_ID[chainId]; const encodedCalls = calls.map(call => { - if ("abi" in call) { + if (call.abi) return { data: encodeFunctionData(call), to: call.to, - value: call.value.toString(), + value: call.value, }; - } - // return call as Call return { - data: call.data, + data: call.data ?? "0x", to: call.to, - value: call.value.toString() || "0", + value: call.value, }; }); diff --git a/src/wallets/toSmartWallet.ts b/src/wallets/toSmartWallet.ts index 8153bba7..579817fc 100644 --- a/src/wallets/toSmartWallet.ts +++ b/src/wallets/toSmartWallet.ts @@ -27,13 +27,13 @@ export type ToSmartWalletOptions = { * @example * ```typescript * import { toSmartWallet } from "@coinbase/coinbase-sdk"; - * + * * // Connect to an existing smart wallet * const wallet = toSmartWallet({ * smartWalletAddress: "0x1234567890123456789012345678901234567890", * signer: localAccount * }); - * + * * // Use on a specific network * const networkWallet = wallet.useNetwork({ * chainId: 8453, // Base Mainnet From e35da0d3b5497b7c8feea8e278626fd020e77f6b Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Tue, 18 Feb 2025 21:03:30 -0500 Subject: [PATCH 42/59] Fix --- src/actions/sendUserOperation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 5b58ffa6..f471e15c 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -73,12 +73,12 @@ export async function sendUserOperation( return { data: encodeFunctionData(call), to: call.to, - value: call.value, + value: call.value ?? BigInt(0), }; return { data: call.data ?? "0x", to: call.to, - value: call.value, + value: call.value ?? BigInt(0), }; }); From ba67f6235f7dcedbad9d31ac8d8787b0d251dcca Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 20:32:30 -0500 Subject: [PATCH 43/59] fixes --- package.json | 2 +- src/actions/sendUserOperation.test.ts | 309 +++++++++++++++++++++++ src/actions/sendUserOperation.ts | 22 +- src/actions/waitForUserOperation.test.ts | 136 ++++++++++ src/tests/utils.ts | 8 + src/utils/chain.test.ts | 23 ++ src/utils/wait.test.ts | 97 +++++++ src/wallets/createSmartWallet.test.ts | 132 ++++++++++ src/wallets/toSmartWallet.test.ts | 172 +++++++++++++ tsconfig.json | 2 +- 10 files changed, 896 insertions(+), 7 deletions(-) create mode 100644 src/actions/sendUserOperation.test.ts create mode 100644 src/actions/waitForUserOperation.test.ts create mode 100644 src/utils/chain.test.ts create mode 100644 src/utils/wait.test.ts create mode 100644 src/wallets/createSmartWallet.test.ts create mode 100644 src/wallets/toSmartWallet.test.ts diff --git a/package.json b/package.json index e098d2aa..0aa59125 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format-check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "check": "tsc --noEmit", - "test": "npx jest --no-cache --testMatch=**/*_test.ts", + "test": "npx jest --no-cache --testMatch=\"**/*.(test|_test).ts\"", "test:dry-run": "npm install && npm ci && npm publish --dry-run", "test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'", "test:e2e:stake": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}' -t Stake", diff --git a/src/actions/sendUserOperation.test.ts b/src/actions/sendUserOperation.test.ts new file mode 100644 index 00000000..9a9f1a9d --- /dev/null +++ b/src/actions/sendUserOperation.test.ts @@ -0,0 +1,309 @@ +import { sendUserOperation } from "./sendUserOperation"; +import { Coinbase } from "../coinbase/coinbase"; +import { encodeFunctionData, erc20Abi, Hex, parseEther } from "viem"; +import { UserOperationStatusEnum } from "../client"; +import { smartWalletApiMock, mockReturnValue, mockReturnRejectedValue } from "../tests/utils"; + +describe("sendUserOperation", () => { + const VALID_WALLET = { + address: "0x1234567890123456789012345678901234567890" as const, + owners: [ + { + address: "0x1234567890123456789012345678901234567890" as const, + sign: jest.fn(), + }, + ], + type: "smart" as const, + sendUserOperation: jest.fn(), + useNetwork: jest.fn(), + }; + + const VALID_ABI_FUNCTION_CALL = { + to: "0x2234567890123456789012345678901234567890", + abi: erc20Abi, + functionName: "transfer", + args: ["0x3234567890123456789012345678901234567890", parseEther("1")], + value: 0n, + } as const; + + const VALID_ENCODED_CALL = { + to: "0x4234567890123456789012345678901234567890" as const, + data: "0x123abc", + value: parseEther("0.1"), + } as const; + + const VALID_CREATE_OPERATION_RESPONSE = { + id: "op123", + unsigned_payload: "0x456def" as const, + }; + + const VALID_BROADCAST_RESPONSE = { + id: "op123", + status: UserOperationStatusEnum.Broadcast, + }; + + beforeEach(() => { + jest.clearAllMocks(); + + Coinbase.apiClients.smartWallet = smartWalletApiMock; + + Coinbase.apiClients.smartWallet!.createUserOperation = mockReturnValue( + VALID_CREATE_OPERATION_RESPONSE, + ); + Coinbase.apiClients.smartWallet!.broadcastUserOperation = + mockReturnValue(VALID_BROADCAST_RESPONSE); + VALID_WALLET.owners[0].sign.mockReturnValue("0x789ghi"); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("should successfully send a user operation with an ABI function call", async () => { + const result = await sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL], + chainId: 8453, + }); + + expect(Coinbase.apiClients.smartWallet!.createUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + "base-mainnet", + { + calls: [ + { + to: VALID_ABI_FUNCTION_CALL.to, + data: encodeFunctionData({ + abi: VALID_ABI_FUNCTION_CALL.abi, + functionName: VALID_ABI_FUNCTION_CALL.functionName, + args: VALID_ABI_FUNCTION_CALL.args, + }), + value: "0", + }, + ], + paymaster_url: undefined, + }, + ); + + expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + VALID_CREATE_OPERATION_RESPONSE.id, + { + signature: "0x789ghi", + }, + ); + + expect(result).toEqual({ + id: VALID_BROADCAST_RESPONSE.id, + smartWalletAddress: VALID_WALLET.address, + status: VALID_BROADCAST_RESPONSE.status, + }); + }); + + it("should successfully send a user operation with a encoded function call", async () => { + const result = await sendUserOperation(VALID_WALLET, { + calls: [VALID_ENCODED_CALL], + chainId: 8453, + }); + + expect(Coinbase.apiClients.smartWallet!.createUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + "base-mainnet", + { + calls: [ + { + to: VALID_ENCODED_CALL.to, + data: VALID_ENCODED_CALL.data, + value: VALID_ENCODED_CALL.value.toString(), + }, + ], + paymaster_url: undefined, + }, + ); + + expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + VALID_CREATE_OPERATION_RESPONSE.id, + { + signature: "0x789ghi", + }, + ); + + expect(result).toEqual({ + id: VALID_BROADCAST_RESPONSE.id, + smartWalletAddress: VALID_WALLET.address, + status: VALID_BROADCAST_RESPONSE.status, + }); + }); + + it("should successfully send a user operation with multiple mixed calls", async () => { + const result = await sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL, VALID_ENCODED_CALL], + chainId: 8453, + }); + + expect(Coinbase.apiClients.smartWallet!.createUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + "base-mainnet", + { + calls: [ + { + to: VALID_ABI_FUNCTION_CALL.to, + data: encodeFunctionData({ + abi: VALID_ABI_FUNCTION_CALL.abi, + functionName: VALID_ABI_FUNCTION_CALL.functionName, + args: VALID_ABI_FUNCTION_CALL.args, + }), + value: "0", + }, + { + to: VALID_ENCODED_CALL.to, + data: VALID_ENCODED_CALL.data, + value: VALID_ENCODED_CALL.value.toString(), + }, + ], + paymaster_url: undefined, + }, + ); + + expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + VALID_CREATE_OPERATION_RESPONSE.id, + { + signature: "0x789ghi", + }, + ); + + expect(result).toEqual({ + id: VALID_BROADCAST_RESPONSE.id, + smartWalletAddress: VALID_WALLET.address, + status: VALID_BROADCAST_RESPONSE.status, + }); + }); + + it("should handle calls with undefined value property and set it to 0", async () => { + const result = await sendUserOperation(VALID_WALLET, { + calls: [{ ...VALID_ABI_FUNCTION_CALL, value: undefined }], + chainId: 8453, + }); + + expect(Coinbase.apiClients.smartWallet!.createUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + "base-mainnet", + { + calls: [ + { + to: VALID_ABI_FUNCTION_CALL.to, + data: encodeFunctionData({ + abi: VALID_ABI_FUNCTION_CALL.abi, + functionName: VALID_ABI_FUNCTION_CALL.functionName, + args: VALID_ABI_FUNCTION_CALL.args, + }), + value: "0", + }, + ], + paymaster_url: undefined, + }, + ); + + expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + VALID_CREATE_OPERATION_RESPONSE.id, + { + signature: "0x789ghi", + }, + ); + + expect(result).toEqual({ + id: VALID_BROADCAST_RESPONSE.id, + smartWalletAddress: VALID_WALLET.address, + status: VALID_BROADCAST_RESPONSE.status, + }); + }); + + it("should throw if calls array is empty", async () => { + await expect( + sendUserOperation(VALID_WALLET, { + calls: [], + chainId: 8453, + }), + ).rejects.toThrow("Calls array is empty"); + }); + + it("should include paymaster URL when provided", async () => { + const result = await sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL], + chainId: 8453, + paymasterUrl: "https://paymaster.com", + }); + + expect(Coinbase.apiClients.smartWallet!.createUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + "base-mainnet", + { + calls: [ + { + to: VALID_ABI_FUNCTION_CALL.to, + data: encodeFunctionData({ + abi: VALID_ABI_FUNCTION_CALL.abi, + functionName: VALID_ABI_FUNCTION_CALL.functionName, + args: VALID_ABI_FUNCTION_CALL.args, + }), + value: "0", + }, + ], + paymaster_url: "https://paymaster.com", + }, + ); + + expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( + VALID_WALLET.address, + VALID_CREATE_OPERATION_RESPONSE.id, + { + signature: "0x789ghi", + }, + ); + + expect(result).toEqual({ + id: VALID_BROADCAST_RESPONSE.id, + smartWalletAddress: VALID_WALLET.address, + status: VALID_BROADCAST_RESPONSE.status, + }); + }); + + it("should handle createUserOperation API errors", async () => { + Coinbase.apiClients.smartWallet!.createUserOperation = mockReturnRejectedValue( + new Error("API error"), + ); + + await expect( + sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL], + chainId: 8453, + }), + ).rejects.toThrow("API error"); + }); + + it("should handle broadcastUserOperation API errors", async () => { + Coinbase.apiClients.smartWallet!.broadcastUserOperation = mockReturnRejectedValue( + new Error("API error"), + ); + + await expect( + sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL], + chainId: 8453, + }), + ).rejects.toThrow("API error"); + }); + + it("should handle signature generation errors", async () => { + VALID_WALLET.owners[0].sign.mockRejectedValue(new Error("Signature error")); + + await expect( + sendUserOperation(VALID_WALLET, { + calls: [VALID_ABI_FUNCTION_CALL], + chainId: 8453, + }), + ).rejects.toThrow("Signature error"); + }); +}); diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index f471e15c..4665cf1c 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -68,17 +68,29 @@ export async function sendUserOperation( const { calls, chainId, paymasterUrl } = options; const network = CHAIN_ID_TO_NETWORK_ID[chainId]; + if (calls.length === 0) { + throw new Error("Calls array is empty"); + } + const encodedCalls = calls.map(call => { - if (call.abi) + const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string + + if ("abi" in call && call.abi && "functionName" in call) { return { - data: encodeFunctionData(call), to: call.to, - value: call.value ?? BigInt(0), + data: encodeFunctionData({ + abi: call.abi, + functionName: call.functionName, + args: call.args, + }), + value, }; + } + return { - data: call.data ?? "0x", to: call.to, - value: call.value ?? BigInt(0), + data: call.data ?? "0x", + value, }; }); diff --git a/src/actions/waitForUserOperation.test.ts b/src/actions/waitForUserOperation.test.ts new file mode 100644 index 00000000..271385cf --- /dev/null +++ b/src/actions/waitForUserOperation.test.ts @@ -0,0 +1,136 @@ +import { waitForUserOperation } from "./waitForUserOperation"; +import { Coinbase } from "../coinbase/coinbase"; +import { UserOperationStatusEnum } from "../client"; +import { smartWalletApiMock, mockReturnValue } from "../tests/utils"; +import * as waitUtils from "../utils/wait"; + +describe("waitForUserOperation", () => { + const VALID_WALLET_ADDRESS = "0x1234567890123456789012345678901234567890" as const; + + const VALID_OPERATION_ID = "op123"; + const VALID_OPERATION_RESPONSE = { + id: VALID_OPERATION_ID, + status: UserOperationStatusEnum.Complete, + transaction_hash: "0x1234567890123456789012345678901234567890", + }; + + const FAILED_OPERATION_RESPONSE = { + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + status: UserOperationStatusEnum.Failed, + }; + + beforeEach(() => { + jest.clearAllMocks(); + Coinbase.apiClients.smartWallet = smartWalletApiMock; + Coinbase.apiClients.smartWallet!.getUserOperation = mockReturnValue(VALID_OPERATION_RESPONSE); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("should successfully wait for a completed operation", async () => { + const result = await waitForUserOperation({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + }); + + expect(Coinbase.apiClients.smartWallet!.getUserOperation).toHaveBeenCalledWith( + VALID_WALLET_ADDRESS, + VALID_OPERATION_ID, + ); + + expect(result).toEqual({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + status: UserOperationStatusEnum.Complete, + transactionHash: "0x1234567890123456789012345678901234567890", + }); + }); + + it("should successfully handle a failed operation", async () => { + Coinbase.apiClients.smartWallet!.getUserOperation = mockReturnValue(FAILED_OPERATION_RESPONSE); + + const result = await waitForUserOperation({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + }); + + expect(Coinbase.apiClients.smartWallet!.getUserOperation).toHaveBeenCalledWith( + VALID_WALLET_ADDRESS, + VALID_OPERATION_ID, + ); + + expect(result).toEqual({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + status: UserOperationStatusEnum.Failed, + transactionHash: undefined, + }); + }); + + it("should use default timeout options when none are provided", async () => { + const waitSpy = jest.spyOn(waitUtils, "wait"); + + const result = await waitForUserOperation({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + }); + + expect(waitSpy).toHaveBeenCalledWith( + expect.any(Function), + expect.any(Function), + expect.any(Function), + { timeoutSeconds: 30 }, + ); + + expect(result).toEqual({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + status: UserOperationStatusEnum.Complete, + transactionHash: "0x1234567890123456789012345678901234567890", + }); + }); + + it("should respect custom timeout options", async () => { + const waitSpy = jest.spyOn(waitUtils, "wait"); + + const result = await waitForUserOperation({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + waitOptions: { timeoutSeconds: 1, intervalSeconds: 0.1 }, + }); + + expect(waitSpy).toHaveBeenCalledWith( + expect.any(Function), + expect.any(Function), + expect.any(Function), + { timeoutSeconds: 1, intervalSeconds: 0.1 }, + ); + + expect(result).toEqual({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + status: UserOperationStatusEnum.Complete, + transactionHash: "0x1234567890123456789012345678901234567890", + }); + }); + + it("should throw an error if the operation is not terminal", async () => { + Coinbase.apiClients.smartWallet!.getUserOperation = mockReturnValue({ + id: VALID_OPERATION_ID, + status: UserOperationStatusEnum.Pending, + }); + + await expect( + waitForUserOperation({ + id: VALID_OPERATION_ID, + smartWalletAddress: VALID_WALLET_ADDRESS, + waitOptions: { timeoutSeconds: 1 }, + }), + ).rejects.toThrow( + "Operation has not reached a terminal state after 1 seconds and may still succeed. Retry with a longer timeout using the timeoutSeconds option.", + ); + }); +}); diff --git a/src/tests/utils.ts b/src/tests/utils.ts index f76c5118..f3f5201e 100644 --- a/src/tests/utils.ts +++ b/src/tests/utils.ts @@ -846,6 +846,14 @@ export const reputationApiMock = { getAddressReputation: jest.fn(), }; +export const smartWalletApiMock = { + createSmartWallet: jest.fn(), + getSmartWallet: jest.fn(), + createUserOperation: jest.fn(), + broadcastUserOperation: jest.fn(), + getUserOperation: jest.fn(), +}; + export const testAllReadTypesABI = [ { type: "function", diff --git a/src/utils/chain.test.ts b/src/utils/chain.test.ts new file mode 100644 index 00000000..85a3d613 --- /dev/null +++ b/src/utils/chain.test.ts @@ -0,0 +1,23 @@ +import { createNetwork } from "./chain"; +import { CHAIN_ID_TO_NETWORK_ID, SupportedChainId } from "../types/chain"; + +describe("createNetwork", () => { + it("should handle all supported chain IDs", () => { + const supportedChainIds = Object.keys(CHAIN_ID_TO_NETWORK_ID).map(Number) as SupportedChainId[]; + + supportedChainIds.forEach(chainId => { + const result = createNetwork(chainId); + expect(result).toEqual({ + chainId: chainId, + networkId: CHAIN_ID_TO_NETWORK_ID[chainId], + }); + }); + }); + it("should return undefined networkId for an unsupported chain ID", () => { + const result = createNetwork(1 as SupportedChainId); + expect(result).toEqual({ + chainId: 1, + networkId: undefined, + }); + }); +}); diff --git a/src/utils/wait.test.ts b/src/utils/wait.test.ts new file mode 100644 index 00000000..830d86eb --- /dev/null +++ b/src/utils/wait.test.ts @@ -0,0 +1,97 @@ +import { wait } from "./wait"; +import { TimeoutError } from "../coinbase/errors"; + +describe("wait", () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it("should resolve immediately if initial state is terminal", async () => { + const mockReload = jest.fn().mockResolvedValue("COMPLETED"); + const isTerminal = (status: string) => status === "COMPLETED"; + + const promise = wait(mockReload, isTerminal); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result).toBe("COMPLETED"); + expect(mockReload).toHaveBeenCalledTimes(1); + }); + + it("should poll until terminal state is reached", async () => { + const mockReload = jest + .fn() + .mockResolvedValueOnce("PENDING") + .mockResolvedValueOnce("PROCESSING") + .mockResolvedValue("COMPLETED"); + const isTerminal = (status: string) => status === "COMPLETED"; + + const promise = wait(mockReload, isTerminal, undefined, { + intervalSeconds: 0.01, + }); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result).toBe("COMPLETED"); + expect(mockReload).toHaveBeenCalledTimes(3); + }); + + it("should transform the result using provided transform function", async () => { + const mockReload = jest.fn().mockResolvedValue("COMPLETED"); + const isTerminal = (status: string) => status === "COMPLETED"; + const transform = (status: string) => ({ status }); + + const promise = wait(mockReload, isTerminal, transform); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result).toEqual({ status: "COMPLETED" }); + }); + + it("should respect custom interval", async () => { + const mockReload = jest.fn().mockResolvedValueOnce("PENDING").mockResolvedValue("COMPLETED"); + + const isTerminal = (status: string) => status === "COMPLETED"; + + wait(mockReload, isTerminal, undefined, { intervalSeconds: 0.5 }); + + await jest.advanceTimersByTimeAsync(0); + expect(mockReload).toHaveBeenCalledTimes(1); + + await jest.advanceTimersByTimeAsync(499); + expect(mockReload).toHaveBeenCalledTimes(1); + + await jest.advanceTimersByTimeAsync(1); + expect(mockReload).toHaveBeenCalledTimes(2); + }); + + it("should throw TimeoutError after specified timeout", async () => { + const mockReload = jest.fn().mockResolvedValue("PENDING"); + const isTerminal = (status: string) => status === "COMPLETED"; + + const promise = wait(mockReload, isTerminal, undefined, { + timeoutSeconds: 1, + intervalSeconds: 0.2, + }); + promise.catch(error => { + expect(error).toBeInstanceOf(TimeoutError); + }); + + await jest.runAllTimersAsync(); + + expect(mockReload.mock.calls.length).toBeGreaterThanOrEqual(4); + expect(mockReload.mock.calls.length).toBeLessThanOrEqual(6); + }); + + it("should handle reload function failures", async () => { + const mockReload = jest.fn().mockRejectedValue(new Error("Network error")); + const isTerminal = (status: string) => status === "COMPLETED"; + + const promise = wait(mockReload, isTerminal); + await expect(promise).rejects.toThrow("Network error"); + }); +}); diff --git a/src/wallets/createSmartWallet.test.ts b/src/wallets/createSmartWallet.test.ts new file mode 100644 index 00000000..e4515a45 --- /dev/null +++ b/src/wallets/createSmartWallet.test.ts @@ -0,0 +1,132 @@ +import { createSmartWallet } from "./createSmartWallet"; +import { Coinbase } from "../coinbase/coinbase"; +import { type Address } from "viem"; +import { smartWalletApiMock, mockReturnValue, mockReturnRejectedValue } from "../tests/utils"; +import { sendUserOperation } from "../actions/sendUserOperation"; + +jest.mock("../actions/sendUserOperation", () => ({ + sendUserOperation: jest.fn(), +})); + +describe("createSmartWallet", () => { + const VALID_SIGNER = { + address: "0x1234567890123456789012345678901234567890" as Address, + sign: jest.fn(), + }; + + const VALID_CREATE_RESPONSE = { + address: "0x2234567890123456789012345678901234567890" as Address, + owners: [VALID_SIGNER.address], + }; + + beforeEach(() => { + jest.clearAllMocks(); + + Coinbase.apiClients.smartWallet = smartWalletApiMock; + Coinbase.apiClients.smartWallet!.createSmartWallet = mockReturnValue(VALID_CREATE_RESPONSE); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it("should successfully create a smart wallet", async () => { + const result = await createSmartWallet({ + signer: VALID_SIGNER, + }); + + expect(Coinbase.apiClients.smartWallet!.createSmartWallet).toHaveBeenCalledWith({ + owner: VALID_SIGNER.address, + }); + + expect(result).toEqual({ + address: VALID_CREATE_RESPONSE.address, + owners: [VALID_SIGNER], + type: "smart", + sendUserOperation: expect.any(Function), + useNetwork: expect.any(Function), + }); + }); + + it("should create a wallet that can send user operations", async () => { + const wallet = await createSmartWallet({ + signer: VALID_SIGNER, + }); + + const operationOptions = { + calls: [ + { + to: "0x3234567890123456789012345678901234567890" as Address, + data: "0x123abc", + value: 0n, + }, + ], + chainId: 8453, + } as const; + + await wallet.sendUserOperation(operationOptions); + + expect(sendUserOperation).toHaveBeenCalledWith(wallet, operationOptions); + }); + + it("should create a wallet that can be network-scoped", async () => { + const wallet = await createSmartWallet({ + signer: VALID_SIGNER, + }); + + const networkOptions = { + chainId: 8453, + paymasterUrl: "https://paymaster.example.com", + } as const; + + const networkWallet = wallet.useNetwork(networkOptions); + + expect(networkWallet).toEqual({ + ...wallet, + network: expect.objectContaining({ + chainId: networkOptions.chainId, + }), + paymasterUrl: networkOptions.paymasterUrl, + sendUserOperation: expect.any(Function), + }); + + const operationOptions = { + calls: [ + { + to: "0x3234567890123456789012345678901234567890" as Address, + data: "0x123abc", + value: 0n, + }, + ], + } as const; + + await networkWallet.sendUserOperation(operationOptions); + + expect(sendUserOperation).toHaveBeenCalledWith(wallet, { + ...operationOptions, + chainId: networkOptions.chainId, + }); + }); + + it("should throw if API client is not initialized", async () => { + Coinbase.apiClients.smartWallet = undefined; + + await expect( + createSmartWallet({ + signer: VALID_SIGNER, + }), + ).rejects.toThrow(); + }); + + it("should handle API errors during creation", async () => { + Coinbase.apiClients.smartWallet!.createSmartWallet = mockReturnRejectedValue( + new Error("Failed to create smart wallet"), + ); + + await expect( + createSmartWallet({ + signer: VALID_SIGNER, + }), + ).rejects.toThrow("Failed to create smart wallet"); + }); +}); diff --git a/src/wallets/toSmartWallet.test.ts b/src/wallets/toSmartWallet.test.ts new file mode 100644 index 00000000..fc055abd --- /dev/null +++ b/src/wallets/toSmartWallet.test.ts @@ -0,0 +1,172 @@ +import { sendUserOperation } from "../actions/sendUserOperation"; +import { createNetwork } from "../utils/chain"; +import { toSmartWallet } from "./toSmartWallet"; +import type { Address } from "viem"; + +jest.mock("../actions/sendUserOperation", () => ({ + sendUserOperation: jest.fn(), +})); + +describe("toSmartWallet", () => { + const VALID_SIGNER = { + address: "0x1234567890123456789012345678901234567890" as Address, + sign: jest.fn(), + }; + + const SMART_WALLET_ADDRESS = "0x2234567890123456789012345678901234567890" as Address; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should create a smart wallet instance with correct properties", () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + expect(wallet).toEqual({ + address: SMART_WALLET_ADDRESS, + owners: [VALID_SIGNER], + type: "smart", + sendUserOperation: expect.any(Function), + useNetwork: expect.any(Function), + }); + }); + + it("should properly handle sendUserOperation calls", async () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + const operationOptions = { + calls: [ + { + to: "0x3234567890123456789012345678901234567890" as Address, + data: "0x123abc", + value: 0n, + }, + ], + chainId: 8453, + } as const; + + await wallet.sendUserOperation(operationOptions); + + expect(sendUserOperation).toHaveBeenCalledWith(wallet, operationOptions); + }); + + describe("useNetwork", () => { + const networkOptions = { + chainId: 8453, + paymasterUrl: "https://paymaster.example.com", + } as const; + + it("should create a network-scoped wallet with correct properties", () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + const networkWallet = wallet.useNetwork(networkOptions); + const expectedNetwork = createNetwork(networkOptions.chainId); + + expect(networkWallet).toEqual({ + address: SMART_WALLET_ADDRESS, + owners: [VALID_SIGNER], + type: "smart", + network: expectedNetwork, + paymasterUrl: networkOptions.paymasterUrl, + sendUserOperation: expect.any(Function), + useNetwork: expect.any(Function), + }); + }); + + it("should properly handle sendUserOperation calls with network context", async () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + const networkWallet = wallet.useNetwork(networkOptions); + + const operationOptions = { + calls: [ + { + to: "0x3234567890123456789012345678901234567890" as Address, + data: "0x123abc", + value: 0n, + }, + ], + } as const; + + await networkWallet.sendUserOperation(operationOptions); + + expect(sendUserOperation).toHaveBeenCalledWith(wallet, { + ...operationOptions, + chainId: networkOptions.chainId, + }); + }); + it("should preserve network context when sending multiple operations", async () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + const networkWallet = wallet.useNetwork(networkOptions); + + const operationOptions1 = { + calls: [ + { + to: "0x3234567890123456789012345678901234567890" as Address, + data: "0x123abc", + value: 0n, + }, + ], + } as const; + + const operationOptions2 = { + calls: [ + { + to: "0x4234567890123456789012345678901234567890" as Address, + data: "0x456def", + value: 0n, + }, + ], + } as const; + + await networkWallet.sendUserOperation(operationOptions1); + await networkWallet.sendUserOperation(operationOptions2); + + expect(sendUserOperation).toHaveBeenCalledTimes(2); + expect(sendUserOperation).toHaveBeenNthCalledWith(1, wallet, { + ...operationOptions1, + chainId: networkOptions.chainId, + }); + expect(sendUserOperation).toHaveBeenNthCalledWith(2, wallet, { + ...operationOptions2, + chainId: networkOptions.chainId, + }); + }); + + it("should correctly handle different network chains", () => { + const wallet = toSmartWallet({ + smartWalletAddress: SMART_WALLET_ADDRESS, + signer: VALID_SIGNER, + }); + + const baseMainnet = wallet.useNetwork({ + chainId: 8453, + paymasterUrl: "https://paymaster.example.com", + }); + + const baseSepolia = wallet.useNetwork({ + chainId: 84532, + paymasterUrl: "https://paymaster-goerli.example.com", + }); + + expect(baseMainnet.network).toEqual(createNetwork(8453)); + expect(baseSepolia.network).toEqual(createNetwork(84532)); + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 977e2ff8..12c5dcc6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,5 +15,5 @@ "removeComments": false }, "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist", "**/__tests__/**/**"] + "exclude": ["node_modules", "dist", "src/**/*.test.ts", "**/tests/**"] } From d802c612792496a831c699d3f5f6515b898da6f6 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 20:35:21 -0500 Subject: [PATCH 44/59] Fix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0aa59125..c7e603e9 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format-check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "check": "tsc --noEmit", - "test": "npx jest --no-cache --testMatch=\"**/*.(test|_test).ts\"", + "test": "npx jest --no-cache --testMatch=\"**/*(_test|.test).ts\"", "test:dry-run": "npm install && npm ci && npm publish --dry-run", "test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'", "test:e2e:stake": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}' -t Stake", From db05f6cd160098efae4b514606c1a19ce63a55ca Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 20:51:06 -0500 Subject: [PATCH 45/59] WIP --- jest.config.js | 13 ++++++-- package.json | 2 +- testNewSmartWallet.ts | 77 ------------------------------------------- 3 files changed, 11 insertions(+), 81 deletions(-) delete mode 100644 testNewSmartWallet.ts diff --git a/jest.config.js b/jest.config.js index 40a4c63a..9180aa52 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,14 +2,21 @@ module.exports = { preset: "ts-jest", testEnvironment: "node", extensionsToTreatAsEsm: [".ts"], - coveragePathIgnorePatterns: ["node_modules", "client", "__tests__"], + testMatch: ["**/src/**/*.test.ts", "**/src/tests/**/*.ts"], + testPathIgnorePatterns: [ + "/node_modules/", + "/src/tests/e2e.ts", + "/src/tests/utils.ts", + "/src/tests/types.test-d.ts", + ], + coveragePathIgnorePatterns: ["node_modules", "client", "__tests__", "/src/tests/"], collectCoverage: true, - collectCoverageFrom: ["./src/coinbase/**"], + collectCoverageFrom: ["./src/**/*.ts"], coverageReporters: ["html"], verbose: true, maxWorkers: 1, coverageThreshold: { - "./src/coinbase/**": { + "./src/**/*.ts": { branches: 75, functions: 85, statements: 85, diff --git a/package.json b/package.json index c7e603e9..469959a1 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format-check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "check": "tsc --noEmit", - "test": "npx jest --no-cache --testMatch=\"**/*(_test|.test).ts\"", + "test": "jest --config jest.config.js", "test:dry-run": "npm install && npm ci && npm publish --dry-run", "test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'", "test:e2e:stake": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}' -t Stake", diff --git a/testNewSmartWallet.ts b/testNewSmartWallet.ts deleted file mode 100644 index 118588de..00000000 --- a/testNewSmartWallet.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { parseEther } from "viem"; -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Coinbase, ExternalAddress, Wallet } from "./src/index"; -import { createSmartWallet } from "./src/index"; -import { waitForUserOperation } from "./src/actions/waitForUserOperation"; -import { UserOperationStatusEnum } from "./src/client"; - -Coinbase.configureFromJson({ - filePath: "~/.apikeys/dev.json", - debugging: true, - basePath: "https://cloud-api-dev.cbhq.net/platform/", -}); - -async function main() { - // create a smart wallet with viem wallet owner - const privateKey = generatePrivateKey(); - const owner = privateKeyToAccount(privateKey); - const smartWallet = await createSmartWallet({ signer: owner }); - - // Faucet the smart wallet using an External Address - const externalAdress = new ExternalAddress(Coinbase.networks.BaseSepolia, smartWallet.address); - const faucet = await externalAdress.faucet(); - await faucet.wait(); - - // create a wallet address to send to and check its balance after - const wallet = await Wallet.create(); - const walletAddress = await wallet.getDefaultAddress(); - - const userOperation = await smartWallet.sendUserOperation({ - calls: [ - { - to: walletAddress.getId() as `0x${string}`, - value: parseEther("0.0000005"), - data: "0x", - }, - ], - chainId: 84532, - }); - - const userOperationResult = await waitForUserOperation(userOperation); - - // connect to a network - const networkScopedSmartWallet = smartWallet.useNetwork({ - chainId: 84532, - }); - - const userOperation2 = await networkScopedSmartWallet.sendUserOperation({ - calls: [ - { - to: walletAddress.getId() as `0x${string}`, - value: parseEther("0.0000005"), - data: "0x", - }, - ], - }); - - const userOperationResult2 = await waitForUserOperation({ - ...userOperation2, - waitOptions: { - timeoutSeconds: 10000, - intervalSeconds: 1, - }, - }); - - if (userOperationResult2.status === UserOperationStatusEnum.Failed) { - userOperationResult2; // type is FailedOperation - } else { - userOperationResult2; // type is CompletedOperation - console.log(userOperationResult2.transactionHash); - } - - // get final balance now - const finalBalance = await walletAddress.getBalance("eth"); - console.log("finalBalance", finalBalance); -} - -main(); From 5c2bcd4328fa5721cafad5ab3e69c272164d9a85 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 21:11:07 -0500 Subject: [PATCH 46/59] Changes --- package-lock.json | 2 +- package.json | 4 ++-- src/actions/sendUserOperation.test.ts | 2 +- src/actions/sendUserOperation.ts | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index e37e5641..19477720 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "ethers": "^6.12.1", "node-jose": "^2.2.0", "secp256k1": "^5.0.0", - "viem": "^2.23.2" + "viem": "^2.21.26" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/package.json b/package.json index 469959a1..59c08072 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:types": "tsd --files src/tests/types.test-d.ts", "clean": "rm -rf dist/*", "build": "tsc", - "prepack": "tsc", + "prepack": "tsc --skipLibCheck", "docs": "typedoc --entryPoints ./src --entryPointStrategy expand --exclude ./src/tests/**/*.ts" }, "files": [ @@ -39,7 +39,7 @@ "ethers": "^6.12.1", "node-jose": "^2.2.0", "secp256k1": "^5.0.0", - "viem": "^2.23.2" + "viem": "^2.21.26" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/src/actions/sendUserOperation.test.ts b/src/actions/sendUserOperation.test.ts index 9a9f1a9d..0b0fba55 100644 --- a/src/actions/sendUserOperation.test.ts +++ b/src/actions/sendUserOperation.test.ts @@ -1,6 +1,6 @@ import { sendUserOperation } from "./sendUserOperation"; import { Coinbase } from "../coinbase/coinbase"; -import { encodeFunctionData, erc20Abi, Hex, parseEther } from "viem"; +import { encodeFunctionData, erc20Abi, parseEther } from "viem"; import { UserOperationStatusEnum } from "../client"; import { smartWalletApiMock, mockReturnValue, mockReturnRejectedValue } from "../tests/utils"; diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 4665cf1c..26177147 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -3,8 +3,7 @@ import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; -import type { Call, Calls } from "viem/types/calls"; -import type { SendUserOperationParameters } from "viem/account-abstraction/"; +import type { Calls } from "viem/types/calls" /** * Options for sending a user operation From 44ba29ab58764fc15cd6d694cbce6d3bda562e03 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 22:32:15 -0500 Subject: [PATCH 47/59] Fix --- src/actions/sendUserOperation.ts | 103 +++---- src/types/calls.ts | 64 +++++ src/types/contract.ts | 469 +++++++++++++++++++++++++++++++ src/types/misc.ts | 38 +++ src/types/multicall.ts | 199 +++++++++++++ src/types/utils.ts | 327 +++++++++++++++++++++ 6 files changed, 1151 insertions(+), 49 deletions(-) create mode 100644 src/types/calls.ts create mode 100644 src/types/contract.ts create mode 100644 src/types/misc.ts create mode 100644 src/types/multicall.ts create mode 100644 src/types/utils.ts diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 26177147..6539578b 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -3,7 +3,7 @@ import { UserOperationStatusEnum } from "../client"; import { Address, encodeFunctionData, Hex } from "viem"; import { Coinbase } from "../coinbase/coinbase"; import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; -import type { Calls } from "viem/types/calls" +import { Calls } from '../types/calls' /** * Options for sending a user operation @@ -64,61 +64,66 @@ export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, ): Promise { - const { calls, chainId, paymasterUrl } = options; - const network = CHAIN_ID_TO_NETWORK_ID[chainId]; + return { + id: "123", + smartWalletAddress: "0x123", + status: "broadcast", + }; + // const { calls, chainId, paymasterUrl } = options; + // const network = CHAIN_ID_TO_NETWORK_ID[chainId]; - if (calls.length === 0) { - throw new Error("Calls array is empty"); - } + // if (calls.length === 0) { + // throw new Error("Calls array is empty"); + // } - const encodedCalls = calls.map(call => { - const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string + // const encodedCalls = calls.map(call => { + // const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string - if ("abi" in call && call.abi && "functionName" in call) { - return { - to: call.to, - data: encodeFunctionData({ - abi: call.abi, - functionName: call.functionName, - args: call.args, - }), - value, - }; - } + // if ("abi" in call && call.abi && "functionName" in call) { + // return { + // to: call.to, + // data: encodeFunctionData({ + // abi: call.abi, + // functionName: call.functionName, + // args: call.args, + // }), + // value, + // }; + // } - return { - to: call.to, - data: call.data ?? "0x", - value, - }; - }); + // return { + // to: call.to, + // data: call.data ?? "0x", + // value, + // }; + // }); - const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( - wallet.address, - network, - { - calls: encodedCalls, - paymaster_url: paymasterUrl, - }, - ); + // const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( + // wallet.address, + // network, + // { + // calls: encodedCalls, + // paymaster_url: paymasterUrl, + // }, + // ); - const owner = wallet.owners[0]; + // const owner = wallet.owners[0]; - const signature = await owner.sign({ - hash: createOpResponse.data.unsigned_payload as Hex, - }); + // const signature = await owner.sign({ + // hash: createOpResponse.data.unsigned_payload as Hex, + // }); - const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( - wallet.address, - createOpResponse.data.id, - { - signature, - }, - ); + // const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( + // wallet.address, + // createOpResponse.data.id, + // { + // signature, + // }, + // ); - return { - id: broadcastResponse.data.id, - smartWalletAddress: wallet.address, - status: broadcastResponse.data.status, - } as SendUserOperationReturnType; + // return { + // id: broadcastResponse.data.id, + // smartWalletAddress: wallet.address, + // status: broadcastResponse.data.status, + // } as SendUserOperationReturnType; } diff --git a/src/types/calls.ts b/src/types/calls.ts new file mode 100644 index 00000000..6c616768 --- /dev/null +++ b/src/types/calls.ts @@ -0,0 +1,64 @@ +import type { AbiStateMutability, Address } from 'viem' +import type { GetMulticallContractParameters } from './multicall' +import type { Hex, OneOf, Prettify } from 'viem' + +export type Call< + call = unknown, + extraProperties extends Record = {}, +> = OneOf< + | (extraProperties & { + data?: Hex | undefined + to: Address + value?: bigint | undefined + }) + | (extraProperties & + (Omit< + GetMulticallContractParameters, + 'address' + > & { + to: Address + value?: bigint | undefined + })) +> + +export type Calls< + calls extends readonly unknown[], + extraProperties extends Record = {}, + /// + result extends readonly any[] = [], +> = calls extends readonly [] // no calls, return empty + ? readonly [] + : calls extends readonly [infer call] // one call left before returning `result` + ? readonly [...result, Prettify>] + : calls extends readonly [infer call, ...infer rest] // grab first call and recurse through `rest` + ? Calls< + [...rest], + extraProperties, + [...result, Prettify>] + > + : readonly unknown[] extends calls + ? calls + : // If `calls` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + calls extends readonly (infer call extends OneOf)[] + ? readonly Prettify[] + : // Fallback + readonly OneOf[] + +export type Batches< + batches extends readonly { calls: readonly unknown[] }[], + properties extends Record = {}, + /// + result extends readonly any[] = [], +> = batches extends readonly [infer batch extends { calls: readonly unknown[] }] + ? [...result, { calls: Calls } & properties] + : batches extends readonly [ + infer batch extends { calls: readonly unknown[] }, + ...infer rest extends readonly { calls: readonly unknown[] }[], + ] + ? Batches< + [...rest], + properties, + [...result, { calls: Calls } & properties] + > + : batches \ No newline at end of file diff --git a/src/types/contract.ts b/src/types/contract.ts new file mode 100644 index 00000000..59a113fc --- /dev/null +++ b/src/types/contract.ts @@ -0,0 +1,469 @@ +import type { + Abi, + AbiEvent, + AbiFunction, + AbiParameter, + AbiParameterToPrimitiveType, + AbiParametersToPrimitiveTypes, + AbiStateMutability, + Address, + ExtractAbiError, + ExtractAbiErrorNames, + ExtractAbiEvent, + ExtractAbiEventNames, + ExtractAbiFunction, + ExtractAbiFunctionNames, + ResolvedRegister, +} from 'abitype' + +import type { Hex, LogTopic } from './misc' +import type { TransactionRequest } from 'viem' +import type { + Filter, + IsNarrowable, + IsUnion, + MaybeRequired, + NoInfer, + Prettify, + UnionToTuple, +} from './utils' + +export type ContractFunctionName< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, +> = ExtractAbiFunctionNames< + abi extends Abi ? abi : Abi, + mutability +> extends infer functionName extends string + ? [functionName] extends [never] + ? string + : functionName + : string + +export type ContractErrorName = + ExtractAbiErrorNames< + abi extends Abi ? abi : Abi + > extends infer errorName extends string + ? [errorName] extends [never] + ? string + : errorName + : string + +export type ContractEventName = + ExtractAbiEventNames< + abi extends Abi ? abi : Abi + > extends infer eventName extends string + ? [eventName] extends [never] + ? string + : eventName + : string + +export type ContractFunctionArgs< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, + functionName extends ContractFunctionName< + abi, + mutability + > = ContractFunctionName, +> = AbiParametersToPrimitiveTypes< + ExtractAbiFunction< + abi extends Abi ? abi : Abi, + functionName, + mutability + >['inputs'], + 'inputs' +> extends infer args + ? [args] extends [never] + ? readonly unknown[] + : args + : readonly unknown[] + +export type ContractConstructorArgs< + abi extends Abi | readonly unknown[] = Abi, +> = AbiParametersToPrimitiveTypes< + Extract< + (abi extends Abi ? abi : Abi)[number], + { type: 'constructor' } + >['inputs'], + 'inputs' +> extends infer args + ? [args] extends [never] + ? readonly unknown[] + : args + : readonly unknown[] + +export type ContractErrorArgs< + abi extends Abi | readonly unknown[] = Abi, + errorName extends ContractErrorName = ContractErrorName, +> = AbiParametersToPrimitiveTypes< + ExtractAbiError['inputs'], + 'inputs' +> extends infer args + ? [args] extends [never] + ? readonly unknown[] + : args + : readonly unknown[] + +export type ContractEventArgs< + abi extends Abi | readonly unknown[] = Abi, + eventName extends ContractEventName = ContractEventName, +> = AbiEventParametersToPrimitiveTypes< + ExtractAbiEvent['inputs'] +> extends infer args + ? [args] extends [never] + ? readonly unknown[] | Record + : args + : readonly unknown[] | Record + +export type ContractEventArgsFromTopics< + abi extends Abi | readonly unknown[] = Abi, + eventName extends ContractEventName = ContractEventName, + strict extends boolean = true, +> = AbiEventParametersToPrimitiveTypes< + ExtractAbiEvent['inputs'], + { EnableUnion: false; IndexedOnly: false; Required: strict } +> extends infer args + ? [args] extends [never] + ? readonly unknown[] | Record + : args + : readonly unknown[] | Record + +export type Widen = + | ([unknown] extends [type] ? unknown : never) + | (type extends Function ? type : never) + | (type extends ResolvedRegister['BigIntType'] ? bigint : never) + | (type extends boolean ? boolean : never) + | (type extends ResolvedRegister['IntType'] ? number : never) + | (type extends string + ? type extends ResolvedRegister['AddressType'] + ? ResolvedRegister['AddressType'] + : type extends ResolvedRegister['BytesType']['inputs'] + ? ResolvedRegister['BytesType'] + : string + : never) + | (type extends readonly [] ? readonly [] : never) + | (type extends Record + ? { [K in keyof type]: Widen } + : never) + | (type extends { length: number } + ? { + [K in keyof type]: Widen + } extends infer Val extends readonly unknown[] + ? readonly [...Val] + : never + : never) + +export type UnionWiden = type extends any ? Widen : never + +export type ExtractAbiFunctionForArgs< + abi extends Abi, + mutability extends AbiStateMutability, + functionName extends ContractFunctionName, + args extends ContractFunctionArgs, +> = ExtractAbiFunction< + abi, + functionName, + mutability +> extends infer abiFunction extends AbiFunction + ? IsUnion extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match + ? UnionToTuple extends infer abiFunctions extends + readonly AbiFunction[] + ? // convert back to union (removes `never` tuple entries) + { [k in keyof abiFunctions]: CheckArgs }[number] + : never + : abiFunction + : never +type CheckArgs< + abiFunction extends AbiFunction, + args, + /// + targetArgs extends AbiParametersToPrimitiveTypes< + abiFunction['inputs'], + 'inputs' + > = AbiParametersToPrimitiveTypes, +> = (readonly [] extends args ? readonly [] : args) extends targetArgs // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided) + ? abiFunction + : never + +export type ContractFunctionParameters< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, + functionName extends ContractFunctionName< + abi, + mutability + > = ContractFunctionName, + args extends ContractFunctionArgs< + abi, + mutability, + functionName + > = ContractFunctionArgs, + deployless extends boolean = false, + /// + allFunctionNames = ContractFunctionName, + allArgs = ContractFunctionArgs, + // when `args` is inferred to `readonly []` ("inputs": []) or `never` (`abi` declared as `Abi` or not inferrable), allow `args` to be optional. + // important that both branches return same structural type +> = { + abi: abi + functionName: + | allFunctionNames // show all options + | (functionName extends allFunctionNames ? functionName : never) // infer value + args?: (abi extends Abi ? UnionWiden : never) | allArgs | undefined +} & (readonly [] extends allArgs ? {} : { args: Widen }) & + (deployless extends true + ? { address?: undefined; code: Hex } + : { address: Address }) + +export type ContractFunctionReturnType< + abi extends Abi | readonly unknown[] = Abi, + mutability extends AbiStateMutability = AbiStateMutability, + functionName extends ContractFunctionName< + abi, + mutability + > = ContractFunctionName, + args extends ContractFunctionArgs< + abi, + mutability, + functionName + > = ContractFunctionArgs, +> = abi extends Abi + ? Abi extends abi + ? unknown + : AbiParametersToPrimitiveTypes< + ExtractAbiFunctionForArgs< + abi, + mutability, + functionName, + args + >['outputs'] + > extends infer types + ? types extends readonly [] + ? void + : types extends readonly [infer type] + ? type + : types + : never + : unknown + +export type AbiItem = Abi[number] + +export type ExtractAbiItemNames = Extract< + abi[number], + { name: string } +>['name'] + +export type ExtractAbiItem< + abi extends Abi, + name extends ExtractAbiItemNames, +> = Extract + +export type AbiItemName = + abi extends Abi ? ExtractAbiItemNames : string + +export type AbiItemArgs< + abi extends Abi | readonly unknown[] = Abi, + name extends AbiItemName = AbiItemName, +> = AbiParametersToPrimitiveTypes< + ExtractAbiItem['inputs'], + 'inputs' +> extends infer args + ? [args] extends [never] + ? readonly unknown[] + : args + : readonly unknown[] + +export type ExtractAbiItemForArgs< + abi extends Abi, + name extends AbiItemName, + args extends AbiItemArgs, +> = ExtractAbiItem extends infer abiItem extends AbiItem & { + inputs: readonly AbiParameter[] +} + ? IsUnion extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match + ? UnionToTuple extends infer abiItems extends readonly (AbiItem & { + inputs: readonly AbiParameter[] + })[] + ? { + [k in keyof abiItems]: ( + readonly [] extends args + ? readonly [] // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided) + : args + ) extends AbiParametersToPrimitiveTypes< + abiItems[k]['inputs'], + 'inputs' + > + ? abiItems[k] + : never + }[number] // convert back to union (removes `never` tuple entries: `['foo', never, 'bar'][number]` => `'foo' | 'bar'`) + : never + : abiItem + : never + +export type EventDefinition = `${string}(${string})` + +export type GetValue< + abi extends Abi | readonly unknown[], + functionName extends string, + valueType = TransactionRequest['value'], + abiFunction extends AbiFunction = abi extends Abi + ? ExtractAbiFunction + : AbiFunction, + _Narrowable extends boolean = IsNarrowable, +> = _Narrowable extends true + ? abiFunction['stateMutability'] extends 'payable' + ? { value?: NoInfer | undefined } + : abiFunction['payable'] extends true + ? { value?: NoInfer | undefined } + : { value?: undefined } + : { value?: NoInfer | undefined } + +////////////////////////////////////////////////////////////////////////////////////////////////// + +export type MaybeAbiEventName = + abiEvent extends AbiEvent ? abiEvent['name'] : undefined + +export type MaybeExtractEventArgsFromAbi< + abi extends Abi | readonly unknown[] | undefined, + eventName extends string | undefined, +> = abi extends Abi | readonly unknown[] + ? eventName extends string + ? GetEventArgs + : undefined + : undefined + +////////////////////////////////////////////////////////////////////// +// ABI item args + +export type GetEventArgs< + abi extends Abi | readonly unknown[], + eventName extends string, + config extends EventParameterOptions = DefaultEventParameterOptions, + abiEvent extends AbiEvent & { type: 'event' } = abi extends Abi + ? ExtractAbiEvent + : AbiEvent & { type: 'event' }, + args = AbiEventParametersToPrimitiveTypes, + FailedToParseArgs = + | ([args] extends [never] ? true : false) + | (readonly unknown[] extends args ? true : false), +> = true extends FailedToParseArgs + ? readonly unknown[] | Record + : args + +////////////////////////////////////////////////////////////////////// +// ABI event types + +type EventParameterOptions = { + EnableUnion?: boolean + IndexedOnly?: boolean + Required?: boolean +} +type DefaultEventParameterOptions = { + EnableUnion: true + IndexedOnly: true + Required: false +} + +export type AbiEventParametersToPrimitiveTypes< + abiParameters extends readonly AbiParameter[], + // + _options extends EventParameterOptions = DefaultEventParameterOptions, + // Remove non-indexed parameters based on `Options['IndexedOnly']` +> = abiParameters extends readonly [] + ? readonly [] + : Filter< + abiParameters, + _options['IndexedOnly'] extends true ? { indexed: true } : object + > extends infer Filtered extends readonly AbiParameter[] + ? _HasUnnamedAbiParameter extends true + ? // Has unnamed tuple parameters so return as array + | readonly [ + ...{ + [K in keyof Filtered]: AbiEventParameterToPrimitiveType< + Filtered[K], + _options + > + }, + ] + // Distribute over tuple to represent optional parameters + | (_options['Required'] extends true + ? never + : // Distribute over tuple to represent optional parameters + Filtered extends readonly [ + ...infer Head extends readonly AbiParameter[], + infer _, + ] + ? AbiEventParametersToPrimitiveTypes< + readonly [...{ [K in keyof Head]: Omit }], + _options + > + : never) + : // All tuple parameters are named so return as object + { + [Parameter in Filtered[number] as Parameter extends { + name: infer Name extends string + } + ? Name + : never]?: + | AbiEventParameterToPrimitiveType + | undefined + } extends infer Mapped + ? Prettify< + MaybeRequired< + Mapped, + _options['Required'] extends boolean + ? _options['Required'] + : false + > + > + : never + : never + +// TODO: Speed up by returning immediately as soon as named parameter is found. +type _HasUnnamedAbiParameter = + abiParameters extends readonly [ + infer Head extends AbiParameter, + ...infer Tail extends readonly AbiParameter[], + ] + ? Head extends { name: string } + ? Head['name'] extends '' + ? true + : _HasUnnamedAbiParameter + : true + : false + +/** + * @internal + */ +export type LogTopicType< + primitiveType = Hex, + topic extends LogTopic = LogTopic, +> = topic extends Hex + ? primitiveType + : topic extends Hex[] + ? primitiveType[] + : topic extends null + ? null + : never + +/** + * @internal + */ +export type AbiEventParameterToPrimitiveType< + abiParameter extends AbiParameter, + // + _options extends EventParameterOptions = DefaultEventParameterOptions, + _type = AbiParameterToPrimitiveType, +> = _options['EnableUnion'] extends true ? LogTopicType<_type> : _type + +type HashedEventTypes = 'bytes' | 'string' | 'tuple' | `${string}[${string}]` + +/** + * @internal + */ +export type AbiEventTopicToPrimitiveType< + abiParameter extends AbiParameter, + topic extends LogTopic, + primitiveType = abiParameter['type'] extends HashedEventTypes + ? topic + : AbiParameterToPrimitiveType, +> = LogTopicType \ No newline at end of file diff --git a/src/types/misc.ts b/src/types/misc.ts new file mode 100644 index 00000000..3986976e --- /dev/null +++ b/src/types/misc.ts @@ -0,0 +1,38 @@ +import type { OneOf } from './utils' + +export type ByteArray = Uint8Array +export type Hex = `0x${string}` +export type Hash = `0x${string}` +export type LogTopic = Hex | Hex[] | null +export type SignableMessage = + | string + | { + /** Raw data representation of the message. */ + raw: Hex | ByteArray + } +export type SignatureLegacy = { + r: Hex + s: Hex + v: bigint +} +export type Signature = OneOf< + | SignatureLegacy + | { + r: Hex + s: Hex + /** @deprecated use `yParity`. */ + v: bigint + yParity?: number | undefined + } + | { + r: Hex + s: Hex + /** @deprecated use `yParity`. */ + v?: bigint | undefined + yParity: number + } +> +export type CompactSignature = { + r: Hex + yParityAndS: Hex +} \ No newline at end of file diff --git a/src/types/multicall.ts b/src/types/multicall.ts new file mode 100644 index 00000000..70a59f7a --- /dev/null +++ b/src/types/multicall.ts @@ -0,0 +1,199 @@ +import type { Abi, AbiStateMutability } from 'abitype' + +import type { + ContractFunctionArgs, + ContractFunctionName, + ContractFunctionParameters, + ContractFunctionReturnType, +} from './contract' +import type { MaybePartial, Prettify } from './utils' + +export type MulticallContracts< + contracts extends readonly unknown[], + options extends { + mutability: AbiStateMutability + optional?: boolean + properties?: Record + } = { mutability: AbiStateMutability }, + /// + result extends readonly any[] = [], +> = contracts extends readonly [] // no contracts, return empty + ? readonly [] + : contracts extends readonly [infer contract] // one contract left before returning `result` + ? readonly [ + ...result, + MaybePartial< + Prettify< + GetMulticallContractParameters & + options['properties'] + >, + options['optional'] + >, + ] + : contracts extends readonly [infer contract, ...infer rest] // grab first contract and recurse through `rest` + ? MulticallContracts< + [...rest], + options, + [ + ...result, + MaybePartial< + Prettify< + GetMulticallContractParameters< + contract, + options['mutability'] + > & + options['properties'] + >, + options['optional'] + >, + ] + > + : readonly unknown[] extends contracts + ? contracts + : // If `contracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + contracts extends readonly (infer contract extends + ContractFunctionParameters)[] + ? readonly MaybePartial< + Prettify, + options['optional'] + >[] + : // Fallback + readonly MaybePartial< + Prettify, + options['optional'] + >[] + +export type MulticallResults< + contracts extends readonly unknown[] = readonly ContractFunctionParameters[], + allowFailure extends boolean = true, + options extends { + error?: Error | undefined + extraProperties?: Record | undefined + mutability: AbiStateMutability + } = { error: Error; extraProperties: {}; mutability: AbiStateMutability }, + /// + result extends any[] = [], +> = contracts extends readonly [] // no contracts, return empty + ? readonly [] + : contracts extends readonly [infer contract] // one contract left before returning `result` + ? [ + ...result, + MulticallResponse< + GetMulticallContractReturnType, + options['error'], + allowFailure, + options['extraProperties'] + >, + ] + : contracts extends readonly [infer contract, ...infer rest] // grab first contract and recurse through `rest` + ? MulticallResults< + [...rest], + allowFailure, + options, + [ + ...result, + MulticallResponse< + GetMulticallContractReturnType, + options['error'], + allowFailure, + options['extraProperties'] + >, + ] + > + : readonly unknown[] extends contracts + ? MulticallResponse< + unknown, + options['error'], + allowFailure, + options['extraProperties'] + >[] + : // If `contracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + contracts extends readonly (infer contract extends + ContractFunctionParameters)[] + ? MulticallResponse< + GetMulticallContractReturnType, + options['error'], + allowFailure, + options['extraProperties'] + >[] + : // Fallback + MulticallResponse< + unknown, + options['error'], + allowFailure, + options['extraProperties'] + >[] + +export type MulticallResponse< + result = unknown, + error = unknown, + allowFailure extends boolean = true, + extraProperties extends Record | undefined = {}, +> = allowFailure extends true + ? + | (extraProperties & { + error?: undefined + result: result + status: 'success' + }) + | (extraProperties & { + error: unknown extends error ? Error : error + result?: undefined + status: 'failure' + }) + : result + +// infer contract parameters from `unknown` +export type GetMulticallContractParameters< + contract, + mutability extends AbiStateMutability, +> = contract extends { abi: infer abi extends Abi } // 1. Check if `abi` is const-asserted or defined inline + ? // 1a. Check if `functionName` is valid for `abi` + contract extends { + functionName: infer functionName extends ContractFunctionName< + abi, + mutability + > + } + ? // 1aa. Check if `args` is valid for `abi` and `functionName` + contract extends { + args: infer args extends ContractFunctionArgs< + abi, + mutability, + functionName + > + } + ? ContractFunctionParameters // `args` valid, pass through + : ContractFunctionParameters // invalid `args` + : // 1b. `functionName` is invalid, check if `abi` is declared as `Abi` + Abi extends abi + ? ContractFunctionParameters // `abi` declared as `Abi`, unable to infer types further + : // `abi` is const-asserted or defined inline, infer types for `functionName` and `args` + ContractFunctionParameters + : ContractFunctionParameters // invalid `contract['abi']`, set to `readonly unknown[]` + +type GetMulticallContractReturnType< + contract, + mutability extends AbiStateMutability, +> = contract extends { abi: infer abi extends Abi } // 1. Check if `abi` is const-asserted or defined inline + ? // Check if `functionName` is valid for `abi` + contract extends { + functionName: infer functionName extends ContractFunctionName< + abi, + mutability + > + } + ? // Check if `args` is valid for `abi` and `functionName` + contract extends { + args: infer args extends ContractFunctionArgs< + abi, + mutability, + functionName + > + } + ? ContractFunctionReturnType // `args` valid, pass through + : ContractFunctionReturnType // invalid `args` + : ContractFunctionReturnType // Invalid `functionName` + : ContractFunctionReturnType // invalid `contract['abi']` (not const-asserted or declared as `Abi`) \ No newline at end of file diff --git a/src/types/utils.ts b/src/types/utils.ts new file mode 100644 index 00000000..9c81c4e9 --- /dev/null +++ b/src/types/utils.ts @@ -0,0 +1,327 @@ +declare const symbol: unique symbol + +/** + * Creates a branded type of {@link T} with the brand {@link U}. + * + * @param T - Type to brand + * @param U - Label + * @returns Branded type + * + * @example + * type Result = Branded + * // ^? type Result = string & { [symbol]: 'foo' } + */ +export type Branded = T & { [symbol]: U } + +/** + * Filters out all members of {@link T} that are not {@link P} + * + * @param T - Items to filter + * @param P - Type to filter out + * @returns Filtered items + * + * @example + * type Result = Filter<['a', 'b', 'c'], 'b'> + * // ^? type Result = ['a', 'c'] + */ +export type Filter< + T extends readonly unknown[], + P, + Acc extends readonly unknown[] = [], +> = T extends readonly [infer F, ...infer Rest extends readonly unknown[]] + ? [F] extends [P] + ? Filter + : Filter + : readonly [...Acc] + +/** + * @description Checks if {@link T} can be narrowed further than {@link U} + * @param T - Type to check + * @param U - Type to against + * @example + * type Result = IsNarrowable<'foo', string> + * // ^? true + */ +export type IsNarrowable = IsNever< + (T extends U ? true : false) & (U extends T ? false : true) +> extends true + ? false + : true + +/** + * @description Checks if {@link T} is `never` + * @param T - Type to check + * @example + * type Result = IsNever + * // ^? type Result = true + */ +export type IsNever = [T] extends [never] ? true : false + +/** Removes `readonly` from all properties of an object. */ +export type Mutable = { + -readonly [key in keyof type]: type[key] +} + +/** + * @description Evaluates boolean "or" condition for {@link T} properties. + * @param T - Type to check + * + * * @example + * type Result = Or<[false, true, false]> + * // ^? type Result = true + * + * @example + * type Result = Or<[false, false, false]> + * // ^? type Result = false + */ +export type Or = T extends readonly [ + infer Head, + ...infer Tail, +] + ? Head extends true + ? true + : Or + : false + +/** + * @description Checks if {@link T} is `undefined` + * @param T - Type to check + * @example + * type Result = IsUndefined + * // ^? type Result = true + */ +export type IsUndefined = [undefined] extends [T] ? true : false + +export type MaybePromise = T | Promise + +/** + * @description Makes attributes on the type T required if required is true. + * + * @example + * MaybeRequired<{ a: string, b?: number }, true> + * => { a: string, b: number } + * + * MaybeRequired<{ a: string, b?: number }, false> + * => { a: string, b?: number } + */ +export type MaybeRequired = required extends true + ? ExactRequired + : T + +/** + * @description Assigns the properties of U onto T. + * + * @example + * Assign<{ a: string, b: number }, { a: undefined, c: boolean }> + * => { a: undefined, b: number, c: boolean } + */ +export type Assign = Assign_ & U +type Assign_ = { + [K in keyof T as K extends keyof U + ? U[K] extends void + ? never + : K + : K]: K extends keyof U ? U[K] : T[K] +} + +// TODO: Remove when peer dep `typescript@>=4.5` (NoInfer is native) +export type NoInfer = [type][type extends any ? 0 : never] + +/** + * @description Constructs a type by excluding `undefined` from `T`. + * + * @example + * NoUndefined + * => string + * + * @internal + */ +export type NoUndefined = T extends undefined ? never : T + +/** Strict version of built-in Omit type */ +export type Omit = Pick< + type, + Exclude +> + +/** + * @description Creates a type that is a partial of T, but with the required keys K. + * + * @example + * PartialBy<{ a: string, b: number }, 'a'> + * => { a?: string, b: number } + */ +export type PartialBy = Omit & + ExactPartial> + +/** + * @description Combines members of an intersection into a readable type. + * + * @see {@link https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg} + * @example + * Prettify<{ a: string } & { b: string } & { c: number, d: bigint }> + * => { a: string, b: string, c: number, d: bigint } + */ +export type Prettify = { + [K in keyof T]: T[K] +} & {} + +/** @internal */ +export type Evaluate = { + [key in keyof type]: type[key] +} & {} + +/** + * @description Creates a type that is T with the required keys K. + * + * @example + * RequiredBy<{ a?: string, b: number }, 'a'> + * => { a: string, b: number } + */ +export type RequiredBy = Omit & + ExactRequired> + +/** + * @description Returns truthy if `array` contains `value`. + * + * @example + * Some<[1, 2, 3], 2> + * => true + */ +export type Some< + array extends readonly unknown[], + value, +> = array extends readonly [value, ...unknown[]] + ? true + : array extends readonly [unknown, ...infer rest] + ? Some + : false + +/** + * @description Creates a type that extracts the values of T. + * + * @example + * ValueOf<{ a: string, b: number }> + * => string | number + * + * @internal + */ +export type ValueOf = T[keyof T] + +export type UnionToTuple< + union, + /// + last = LastInUnion, +> = [union] extends [never] ? [] : [...UnionToTuple>, last] +type LastInUnion = UnionToIntersection< + U extends unknown ? (x: U) => 0 : never +> extends (x: infer l) => 0 + ? l + : never +type UnionToIntersection = ( + union extends unknown + ? (arg: union) => 0 + : never +) extends (arg: infer i) => 0 + ? i + : never + +export type IsUnion< + union, + /// + union2 = union, +> = union extends union2 ? ([union2] extends [union] ? false : true) : never + +export type MaybePartial< + type, + enabled extends boolean | undefined, +> = enabled extends true ? Prettify> : type + +export type ExactPartial = { + [key in keyof type]?: type[key] | undefined +} + +export type ExactRequired = { + [P in keyof type]-?: Exclude +} + +export type OneOf< + union extends object, + fallback extends object | undefined = undefined, + /// + keys extends KeyofUnion = KeyofUnion, +> = union extends infer item + ? Prettify< + item & { + [key in Exclude]?: fallback extends object + ? key extends keyof fallback + ? fallback[key] + : undefined + : undefined + } + > + : never +type KeyofUnion = type extends type ? keyof type : never + +/////////////////////////////////////////////////////////////////////////// +// Loose types + +/** + * Loose version of {@link Omit} + * @internal + */ +export type LooseOmit = Pick< + type, + Exclude +> + +/////////////////////////////////////////////////////////////////////////// +// Union types + +export type UnionEvaluate = type extends object ? Prettify : type + +export type UnionLooseOmit = type extends any + ? LooseOmit + : never + +/** + * @description Construct a type with the properties of union type T except for those in type K. + * @example + * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> + * => { b: number } | { b: undefined, c: number } + */ +export type UnionOmit = type extends any + ? Omit + : never + +/** + * @description Construct a type with the properties of union type T except for those in type K. + * @example + * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> + * => { b: number } | { b: undefined, c: number } + */ +export type UnionPick = type extends any + ? Pick + : never + +/** + * @description Creates a type that is a partial of T, but with the required keys K. + * + * @example + * PartialBy<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> + * => { a?: string, b: number } | { a?: string, b: undefined, c: number } + */ +export type UnionPartialBy = T extends any + ? PartialBy + : never + +/** + * @description Creates a type that is T with the required keys K. + * + * @example + * RequiredBy<{ a?: string, b: number } | { a?: string, c?: number }, 'a'> + * => { a: string, b: number } | { a: string, c?: number } + */ +export type UnionRequiredBy = T extends any + ? RequiredBy + : never \ No newline at end of file From 9d9873e67a08e594f46e9a8fef7561ac3a9436b9 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 22:34:15 -0500 Subject: [PATCH 48/59] Latest package lock --- package-lock.json | 2050 +++++++++++++++++++++++++++++---------------- 1 file changed, 1351 insertions(+), 699 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19477720..7185788a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,13 +47,15 @@ "node_modules/@adraffy/ens-normalize": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -63,12 +65,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -76,30 +80,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", + "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.9", + "@babel/types": "^7.26.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -119,34 +125,38 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.5", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -159,67 +169,35 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -229,170 +207,68 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", - "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", - "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, - "dependencies": { - "@babel/types": "^7.24.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", - "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", + "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.26.9" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -405,6 +281,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -417,6 +294,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -429,6 +307,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -436,11 +315,44 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -453,6 +365,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -461,12 +374,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -480,6 +394,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -492,6 +407,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -504,6 +420,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -516,6 +433,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -528,6 +446,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -540,6 +459,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -547,11 +467,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -563,12 +500,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -578,33 +516,32 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -617,19 +554,20 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -639,13 +577,15 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -658,22 +598,21 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.0.tgz", - "integrity": "sha512-Q1CnsQrytI3TlCB1IVWXWeqUIPGVEKGaE7IbVdt13Nq/3i0JESAkQQERrfiQkmlpijl+++qyqPgaS31Bvc1jRQ==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", + "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.5", - "@types/estree": "^1.0.5", - "@typescript-eslint/types": "^7.2.0", "comment-parser": "1.4.1", - "esquery": "^1.5.0", + "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { @@ -681,25 +620,30 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -709,6 +653,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -732,6 +677,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -742,6 +688,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -750,21 +697,24 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -777,6 +727,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -787,6 +738,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -799,6 +751,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -811,13 +764,16 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -834,6 +790,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -843,6 +800,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -856,6 +814,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -869,6 +828,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -881,6 +841,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -896,6 +857,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -908,6 +870,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -917,6 +880,7 @@ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -926,6 +890,7 @@ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -943,6 +908,7 @@ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -990,6 +956,7 @@ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", @@ -1005,6 +972,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -1018,6 +986,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -1030,6 +999,7 @@ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", @@ -1047,6 +1017,7 @@ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -1062,6 +1033,7 @@ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -1105,6 +1077,7 @@ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -1117,6 +1090,7 @@ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -1131,6 +1105,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -1146,6 +1121,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -1161,6 +1137,7 @@ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -1187,6 +1164,7 @@ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -1200,10 +1178,11 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1218,6 +1197,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1227,21 +1207,24 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1279,6 +1262,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1292,6 +1276,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1301,6 +1286,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1314,6 +1300,7 @@ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -1361,13 +1348,15 @@ "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -1377,6 +1366,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } @@ -1385,25 +1375,29 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@tsd/typescript": { "version": "5.4.5", @@ -1420,6 +1414,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -1433,6 +1428,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -1442,41 +1438,48 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1485,13 +1488,15 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -1501,15 +1506,17 @@ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -1519,7 +1526,8 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/minimist": { "version": "1.2.5", @@ -1529,12 +1537,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", - "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "version": "20.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz", + "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-jose": { @@ -1542,6 +1551,7 @@ "resolved": "https://registry.npmjs.org/@types/node-jose/-/node-jose-1.1.13.tgz", "integrity": "sha512-QjMd4yhwy1EvSToQn0YI3cD29YhyfxFwj7NecuymjLys2/P0FwxWnkgBlFxCai6Y3aBCe7rbwmqwJJawxlgcXw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1558,27 +1568,24 @@ "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } @@ -1587,24 +1594,24 @@ "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", - "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/type-utils": "7.8.0", - "@typescript-eslint/utils": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", - "debug": "^4.3.4", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { @@ -1625,15 +1632,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", - "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { @@ -1653,13 +1661,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", - "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1670,13 +1679,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", - "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.8.0", - "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1697,10 +1707,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", - "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1710,13 +1721,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", - "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/visitor-keys": "7.8.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1738,18 +1750,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", - "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.15", - "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.8.0", - "@typescript-eslint/types": "7.8.0", - "@typescript-eslint/typescript-estree": "7.8.0", - "semver": "^7.6.0" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1763,12 +1773,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", - "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1780,10 +1791,11 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" }, "node_modules/abitype": { "version": "1.0.8", @@ -1807,10 +1819,11 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1823,15 +1836,20 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -1839,13 +1857,15 @@ "node_modules/aes-js": { "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1862,6 +1882,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -1877,6 +1898,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -1889,21 +1911,24 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-sequence-parser": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", - "dev": true + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.3.tgz", + "integrity": "sha512-+fksAx9eG3Ab6LDnLs3ZqZa8KVJ/jYnX+D4Qe1azX+LFGFAXqynCQLOdLpNYN/l9e7l6hMWwZbrnctqr6eSQSw==", + "dev": true, + "license": "MIT" }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1919,6 +1944,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1932,6 +1958,7 @@ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } @@ -1940,19 +1967,22 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1967,15 +1997,24 @@ "node": ">=0.10.0" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1986,6 +2025,7 @@ "version": "1.22.0", "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.22.0.tgz", "integrity": "sha512-dmI0KbkyAhntUR05YY96qg2H6gg0XMl2+qTW0xmYg6Up+BFBAJYRLROMXRdDEL06/Wqwa0TJThAYvFtSFdRCZw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "is-buffer": "^2.0.5" @@ -1998,6 +2038,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", "dependencies": { "is-retry-allowed": "^2.2.0" }, @@ -2010,6 +2051,7 @@ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -2031,6 +2073,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -2047,6 +2090,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -2063,6 +2107,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2072,6 +2117,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -2083,23 +2129,27 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -2110,6 +2160,7 @@ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -2125,7 +2176,17 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/base-x": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -2144,12 +2205,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/base64url": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -2158,6 +2221,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz", "integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==", + "license": "MIT", "dependencies": { "@noble/hashes": "^1.2.0", "@scure/base": "^1.1.1", @@ -2172,20 +2236,23 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "license": "ISC", "dependencies": { "@noble/hashes": "^1.2.0" } }, "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2195,6 +2262,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -2205,12 +2273,13 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -2226,11 +2295,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2244,6 +2314,7 @@ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, + "license": "MIT", "dependencies": { "fast-json-stable-stringify": "2.x" }, @@ -2251,39 +2322,32 @@ "node": ">= 6" } }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, "node_modules/bs58check": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "license": "MIT", "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", "safe-buffer": "^5.1.2" } }, - "node_modules/bs58check/node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bs58check/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.2" - } - }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } @@ -2306,6 +2370,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -2315,18 +2380,20 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "engines": { - "node": ">=6" + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 0.4" } }, "node_modules/callsites": { @@ -2334,6 +2401,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2343,6 +2411,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2366,9 +2435,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001617", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz", - "integrity": "sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==", + "version": "1.0.30001700", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", + "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", "dev": true, "funding": [ { @@ -2383,13 +2452,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2406,6 +2477,7 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -2421,30 +2493,37 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -2459,6 +2538,7 @@ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -2468,13 +2548,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2486,12 +2568,14 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2504,6 +2588,7 @@ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.0.0" } @@ -2512,18 +2597,21 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -2537,6 +2625,7 @@ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -2557,13 +2646,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2574,12 +2665,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2628,15 +2720,17 @@ } }, "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "license": "MIT" }, "node_modules/dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, + "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -2650,13 +2744,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2665,6 +2761,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -2674,6 +2771,7 @@ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2683,6 +2781,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -2692,6 +2791,7 @@ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -2701,6 +2801,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -2713,6 +2814,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -2721,9 +2823,10 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -2731,16 +2834,48 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { - "version": "1.4.763", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.763.tgz", - "integrity": "sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==", - "dev": true + "version": "1.5.102", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz", + "integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==", + "dev": true, + "license": "ISC" }, "node_modules/elliptic": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", - "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -2756,6 +2891,7 @@ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2767,27 +2903,83 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2797,6 +2989,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2805,16 +2998,18 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -2864,6 +3059,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -2906,20 +3102,23 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.5.tgz", - "integrity": "sha512-ZeTfKV474W1N9niWfawpwsXGu+ZoMXu4417eBROX31d7ZuOk8zyG66SO77DpJ2+A9Wa2scw/jRqBPnnQo7VbcQ==", + "version": "48.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.11.0.tgz", + "integrity": "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.43.0", + "@es-joy/jsdoccomment": "~0.46.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.4", + "debug": "^4.3.5", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.6.1", - "spdx-expression-parse": "^4.0.0" + "espree": "^10.1.0", + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.1" }, "engines": { "node": ">=18" @@ -2928,14 +3127,46 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -2970,6 +3201,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -2986,6 +3218,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2998,6 +3231,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3008,6 +3242,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3020,6 +3255,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -3037,6 +3273,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3046,10 +3283,11 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -3062,6 +3300,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3074,6 +3313,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -3083,14 +3323,15 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/ethers": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", - "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", "funding": [ { "type": "individual", @@ -3101,13 +3342,14 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", + "tslib": "2.7.0", "ws": "8.17.1" }, "engines": { @@ -3118,6 +3360,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", "dependencies": { "@noble/hashes": "1.3.2" }, @@ -3129,6 +3372,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", "engines": { "node": ">= 16" }, @@ -3137,9 +3381,13 @@ } }, "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } }, "node_modules/eventemitter3": { "version": "5.0.1", @@ -3152,6 +3400,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3184,6 +3433,7 @@ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", @@ -3198,25 +3448,28 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -3227,6 +3480,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3238,19 +3492,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -3260,6 +3517,7 @@ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } @@ -3269,6 +3527,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -3276,11 +3535,35 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3293,6 +3576,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3309,6 +3593,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -3319,21 +3604,23 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -3344,12 +3631,14 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -3360,7 +3649,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -3368,6 +3658,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -3380,7 +3671,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3390,6 +3681,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -3399,24 +3691,64 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3428,7 +3760,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3449,6 +3783,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -3461,6 +3796,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3471,6 +3807,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3483,6 +3820,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -3498,6 +3836,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3513,17 +3852,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hard-rejection": { "version": "2.1.0", @@ -3540,14 +3893,43 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -3561,6 +3943,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -3570,7 +3953,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3582,6 +3965,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -3625,13 +4009,15 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -3653,22 +4039,25 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3681,10 +4070,11 @@ } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -3704,6 +4094,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -3722,7 +4113,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3731,7 +4124,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/irregular-plurals": { "version": "3.5.0", @@ -3747,7 +4141,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-buffer": { "version": "2.0.5", @@ -3767,32 +4162,22 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { - "builtin-modules": "^3.3.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3803,6 +4188,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3812,6 +4198,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3821,6 +4208,7 @@ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3830,6 +4218,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -3842,6 +4231,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3851,6 +4241,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3869,6 +4260,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -3881,6 +4273,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3905,7 +4298,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isows": { "version": "1.0.6", @@ -3927,15 +4321,17 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -3952,6 +4348,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -3966,6 +4363,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -3980,6 +4378,7 @@ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -3988,11 +4387,55 @@ "node": ">=8" } }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -4019,6 +4462,7 @@ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -4033,6 +4477,7 @@ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -4064,6 +4509,7 @@ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -4097,6 +4543,7 @@ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -4142,6 +4589,7 @@ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -4157,6 +4605,7 @@ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -4169,6 +4618,7 @@ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -4185,6 +4635,7 @@ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -4202,6 +4653,7 @@ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -4211,6 +4663,7 @@ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -4236,6 +4689,7 @@ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" @@ -4249,6 +4703,7 @@ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -4264,6 +4719,7 @@ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", @@ -4284,6 +4740,7 @@ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -4298,6 +4755,7 @@ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -4315,6 +4773,7 @@ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -4324,6 +4783,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -4344,6 +4804,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -4357,6 +4818,7 @@ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -4389,6 +4851,7 @@ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -4422,6 +4885,7 @@ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -4453,6 +4917,7 @@ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -4470,6 +4935,7 @@ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -4487,6 +4953,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4499,6 +4966,7 @@ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -4518,6 +4986,7 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -4533,6 +5002,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -4547,13 +5017,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4566,51 +5038,58 @@ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -4619,16 +5098,18 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -4648,6 +5129,7 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4657,6 +5139,7 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4666,6 +5149,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -4678,13 +5162,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -4698,19 +5184,22 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -4730,15 +5219,17 @@ } }, "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "license": "Apache-2.0" }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -4747,13 +5238,15 @@ "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -4768,13 +5261,15 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } @@ -4797,6 +5292,7 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, + "license": "MIT", "bin": { "marked": "bin/marked.js" }, @@ -4804,10 +5300,20 @@ "node": ">= 12" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -4868,24 +5374,27 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -4896,6 +5405,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4904,6 +5414,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -4916,6 +5427,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4933,18 +5445,21 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" }, "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4971,43 +5486,49 @@ } }, "node_modules/mock-fs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.2.0.tgz", - "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz", + "integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -5018,12 +5539,14 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-jose": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-2.2.0.tgz", "integrity": "sha512-XPCvJRr94SjLrSIm4pbYHKLEaOsDvJCpyFw/6V/KK/IXmyZ6SFBzAUDO9HQf4DB/nTEFcRGH87mNciOP23kFjw==", + "license": "Apache-2.0", "dependencies": { "base64url": "^3.0.1", "buffer": "^6.0.3", @@ -5037,10 +5560,11 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "3.0.3", @@ -5063,6 +5587,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5072,6 +5597,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -5084,6 +5610,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -5093,6 +5620,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -5108,6 +5636,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -5154,6 +5683,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5169,6 +5699,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -5184,6 +5715,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5191,13 +5723,15 @@ "node_modules/pako": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -5205,11 +5739,26 @@ "node": ">=6" } }, + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "license": "Apache-2.0 AND MIT", + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -5228,6 +5777,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5237,6 +5787,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5246,6 +5797,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5254,28 +5806,32 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -5288,6 +5844,7 @@ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -5297,6 +5854,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -5309,6 +5867,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -5322,6 +5881,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -5334,6 +5894,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -5349,6 +5910,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -5377,15 +5939,17 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz", + "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -5401,6 +5965,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -5413,6 +5978,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -5427,6 +5993,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -5438,6 +6005,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -5447,6 +6015,7 @@ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -5458,13 +6027,15 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5483,7 +6054,8 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -5503,7 +6075,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "4.0.1", @@ -5519,7 +6092,8 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/read-pkg": { "version": "5.2.0", @@ -5665,6 +6239,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5693,23 +6268,28 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5719,6 +6299,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -5731,6 +6312,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5740,15 +6322,17 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -5758,6 +6342,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5767,7 +6352,9 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -5782,6 +6369,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -5806,6 +6394,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -5827,27 +6416,30 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/secp256k1": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.0.tgz", - "integrity": "sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.1.tgz", + "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==", "hasInstallScript": true, + "license": "MIT", "dependencies": { - "elliptic": "^6.5.4", + "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5859,6 +6451,7 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5872,6 +6465,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5884,6 +6478,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5893,6 +6488,7 @@ "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -5904,28 +6500,39 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -5935,6 +6542,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -5966,35 +6574,40 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", - "dev": true + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -6007,6 +6620,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6015,6 +6629,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -6024,6 +6639,7 @@ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -6037,6 +6653,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6051,6 +6668,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6063,6 +6681,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6072,6 +6691,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6094,6 +6714,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -6106,6 +6727,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -6132,6 +6754,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6140,10 +6763,11 @@ } }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, + "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -6155,17 +6779,12 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -6180,6 +6799,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6190,6 +6810,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6201,28 +6822,22 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "BSD-3-Clause" }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -6241,10 +6856,11 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -6253,28 +6869,31 @@ } }, "node_modules/ts-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", - "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, + "license": "MIT", "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -6284,6 +6903,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, @@ -6300,6 +6922,7 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -6361,15 +6984,17 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -6382,6 +7007,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -6391,6 +7017,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -6403,6 +7030,7 @@ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", @@ -6422,13 +7050,15 @@ "node_modules/typeforce": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", + "license": "MIT" }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "devOptional": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6438,15 +7068,15 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/update-browserslist-db": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", - "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -6462,9 +7092,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -6478,6 +7109,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -6485,7 +7117,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/uuid": { "version": "9.0.1", @@ -6495,6 +7128,7 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -6503,13 +7137,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -6542,9 +7178,9 @@ } }, "node_modules/viem": { - "version": "2.23.2", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", - "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "version": "2.23.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.3.tgz", + "integrity": "sha512-ON/Uybteajqxn3iFyhV/6Ybm+QKhcrsVyTZf/9v2w0CvYQIoyJYCfHSsQR9zpsbOGrR7d2p62w6jzb6fqzzacg==", "funding": [ { "type": "github", @@ -6596,19 +7232,22 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vscode-textmate": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } @@ -6618,6 +7257,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6632,6 +7272,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", + "license": "MIT", "dependencies": { "bs58check": "<3.0.0" } @@ -6641,6 +7282,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6650,6 +7292,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6666,13 +7309,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -6685,6 +7330,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -6706,6 +7352,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -6714,13 +7361,15 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -6739,6 +7388,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -6748,6 +7398,7 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6757,6 +7408,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, From 858e8814a69510abe005284bab85c8074fbcb8cb Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Wed, 19 Feb 2025 22:43:43 -0500 Subject: [PATCH 49/59] fix import --- src/types/calls.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types/calls.ts b/src/types/calls.ts index 6c616768..a2d6c84b 100644 --- a/src/types/calls.ts +++ b/src/types/calls.ts @@ -1,6 +1,7 @@ import type { AbiStateMutability, Address } from 'viem' import type { GetMulticallContractParameters } from './multicall' -import type { Hex, OneOf, Prettify } from 'viem' +import type { OneOf, Prettify } from './utils' +import type { Hex } from './misc' export type Call< call = unknown, From 9939e95cdef4ab56db8a043581cdca17a1415999 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 12:31:17 -0500 Subject: [PATCH 50/59] Changes --- NOTICE.md | 3 + README.md | 5 +- src/actions/sendUserOperation.ts | 7 +- src/actions/waitForUserOperation.ts | 2 +- src/coinbase/types.ts | 8 +- src/types/calls.ts | 58 +--- src/types/contract.ts | 456 ++++---------------------- src/types/misc.ts | 41 +-- src/types/multicall.ts | 181 +--------- src/types/utils.ts | 157 ++++----- src/wallets/createSmartWallet.test.ts | 2 +- src/wallets/createSmartWallet.ts | 2 +- src/wallets/toSmartWallet.test.ts | 2 +- src/wallets/toSmartWallet.ts | 2 +- src/wallets/types.ts | 5 +- 15 files changed, 160 insertions(+), 771 deletions(-) create mode 100644 NOTICE.md diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 00000000..939fb190 --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,3 @@ +This project includes software from https://github.com/wevm/viem/ + * Copyright (c) 2023-present weth, LLC + * Licensed under MIT License \ No newline at end of file diff --git a/README.md b/README.md index 8500530c..59f5305f 100644 --- a/README.md +++ b/README.md @@ -232,4 +232,7 @@ To import Wallets that were persisted to your local file system using `saveSeed` ```typescript const userWallet = await Wallet.fetch(wallet.getId()); await userWallet.loadSeedFromFile(seedFilePath); -``` \ No newline at end of file +``` + +## Acknowledgments +This project includes code from [viem](https://github.com/wevm/viem) licensed under MIT. \ No newline at end of file diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 6539578b..58f399a7 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,9 +1,8 @@ import type { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; -import { Address, encodeFunctionData, Hex } from "viem"; -import { Coinbase } from "../coinbase/coinbase"; -import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; -import { Calls } from '../types/calls' +import type { SupportedChainId } from "../types/chain"; +import type { Address } from "../types/misc"; +import type { Calls } from "../types/calls"; /** * Options for sending a user operation diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 0d3e69d6..3dcd0ac8 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -1,4 +1,4 @@ -import { Address } from "viem"; +import type { Address } from "../types/misc"; import { Coinbase } from "../coinbase/coinbase"; import { wait, WaitOptions } from "../utils/wait"; import { UserOperation, UserOperationStatusEnum } from "../client"; diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 623aad91..27134336 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -407,13 +407,13 @@ export type AddressAPIClient = { * * @param walletId - The ID of the wallet the address belongs to. * @param addressId - The onchain address of the address to sign the payload with. - * @param CreatePayloadSignatureRequest - The payload signature creation request. + * @param createPayloadSignatureRequest - The payload signature creation request. * @param options - Axios request options. * @throws {APIError} If the request fails. */ createPayloadSignature( walletId: string, - addressid: string, + addressId: string, createPayloadSignatureRequest?: CreatePayloadSignatureRequest, options?: AxiosRequestConfig, ): AxiosPromise; @@ -429,7 +429,7 @@ export type AddressAPIClient = { */ getPayloadSignature( walletId: string, - addressid: string, + addressId: string, payloadSignatureId: string, options?: AxiosRequestConfig, ): AxiosPromise; @@ -446,7 +446,7 @@ export type AddressAPIClient = { */ listPayloadSignatures( walletId: string, - addressid: string, + addressId: string, limit?: number, page?: string, options?: AxiosRequestConfig, diff --git a/src/types/calls.ts b/src/types/calls.ts index a2d6c84b..5ec2afc3 100644 --- a/src/types/calls.ts +++ b/src/types/calls.ts @@ -1,26 +1,22 @@ -import type { AbiStateMutability, Address } from 'viem' -import type { GetMulticallContractParameters } from './multicall' -import type { OneOf, Prettify } from './utils' -import type { Hex } from './misc' +// Adapted from viem (https://github.com/wevm/viem) -export type Call< - call = unknown, - extraProperties extends Record = {}, -> = OneOf< +import type { AbiStateMutability, Address } from "viem"; +import type { GetMulticallContractParameters } from "./multicall"; +import type { OneOf, Prettify } from "./utils"; +import type { Hex } from "./misc"; + +export type Call = {}> = OneOf< | (extraProperties & { - data?: Hex | undefined - to: Address - value?: bigint | undefined + data?: Hex | undefined; + to: Address; + value?: bigint | undefined; }) | (extraProperties & - (Omit< - GetMulticallContractParameters, - 'address' - > & { - to: Address - value?: bigint | undefined + (Omit, "address"> & { + to: Address; + value?: bigint | undefined; })) -> +>; export type Calls< calls extends readonly unknown[], @@ -32,11 +28,7 @@ export type Calls< : calls extends readonly [infer call] // one call left before returning `result` ? readonly [...result, Prettify>] : calls extends readonly [infer call, ...infer rest] // grab first call and recurse through `rest` - ? Calls< - [...rest], - extraProperties, - [...result, Prettify>] - > + ? Calls<[...rest], extraProperties, [...result, Prettify>]> : readonly unknown[] extends calls ? calls : // If `calls` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! @@ -44,22 +36,4 @@ export type Calls< calls extends readonly (infer call extends OneOf)[] ? readonly Prettify[] : // Fallback - readonly OneOf[] - -export type Batches< - batches extends readonly { calls: readonly unknown[] }[], - properties extends Record = {}, - /// - result extends readonly any[] = [], -> = batches extends readonly [infer batch extends { calls: readonly unknown[] }] - ? [...result, { calls: Calls } & properties] - : batches extends readonly [ - infer batch extends { calls: readonly unknown[] }, - ...infer rest extends readonly { calls: readonly unknown[] }[], - ] - ? Batches< - [...rest], - properties, - [...result, { calls: Calls } & properties] - > - : batches \ No newline at end of file + readonly OneOf[]; diff --git a/src/types/contract.ts b/src/types/contract.ts index 59a113fc..2e668b50 100644 --- a/src/types/contract.ts +++ b/src/types/contract.ts @@ -1,202 +1,112 @@ +// Adapted from viem (https://github.com/wevm/viem) + import type { Abi, - AbiEvent, AbiFunction, - AbiParameter, - AbiParameterToPrimitiveType, AbiParametersToPrimitiveTypes, AbiStateMutability, Address, - ExtractAbiError, - ExtractAbiErrorNames, - ExtractAbiEvent, - ExtractAbiEventNames, ExtractAbiFunction, ExtractAbiFunctionNames, ResolvedRegister, -} from 'abitype' +} from "abitype"; -import type { Hex, LogTopic } from './misc' -import type { TransactionRequest } from 'viem' -import type { - Filter, - IsNarrowable, - IsUnion, - MaybeRequired, - NoInfer, - Prettify, - UnionToTuple, -} from './utils' +import type { Hex } from "./misc"; +import type { IsUnion, UnionToTuple } from "./utils"; export type ContractFunctionName< abi extends Abi | readonly unknown[] = Abi, mutability extends AbiStateMutability = AbiStateMutability, -> = ExtractAbiFunctionNames< - abi extends Abi ? abi : Abi, - mutability -> extends infer functionName extends string - ? [functionName] extends [never] - ? string - : functionName - : string - -export type ContractErrorName = - ExtractAbiErrorNames< - abi extends Abi ? abi : Abi - > extends infer errorName extends string - ? [errorName] extends [never] - ? string - : errorName - : string - -export type ContractEventName = - ExtractAbiEventNames< - abi extends Abi ? abi : Abi - > extends infer eventName extends string - ? [eventName] extends [never] +> = + ExtractAbiFunctionNames< + abi extends Abi ? abi : Abi, + mutability + > extends infer functionName extends string + ? [functionName] extends [never] ? string - : eventName - : string + : functionName + : string; export type ContractFunctionArgs< abi extends Abi | readonly unknown[] = Abi, mutability extends AbiStateMutability = AbiStateMutability, - functionName extends ContractFunctionName< + functionName extends ContractFunctionName = ContractFunctionName< abi, mutability - > = ContractFunctionName, -> = AbiParametersToPrimitiveTypes< - ExtractAbiFunction< - abi extends Abi ? abi : Abi, - functionName, - mutability - >['inputs'], - 'inputs' -> extends infer args - ? [args] extends [never] - ? readonly unknown[] - : args - : readonly unknown[] - -export type ContractConstructorArgs< - abi extends Abi | readonly unknown[] = Abi, -> = AbiParametersToPrimitiveTypes< - Extract< - (abi extends Abi ? abi : Abi)[number], - { type: 'constructor' } - >['inputs'], - 'inputs' -> extends infer args - ? [args] extends [never] - ? readonly unknown[] - : args - : readonly unknown[] - -export type ContractErrorArgs< - abi extends Abi | readonly unknown[] = Abi, - errorName extends ContractErrorName = ContractErrorName, -> = AbiParametersToPrimitiveTypes< - ExtractAbiError['inputs'], - 'inputs' -> extends infer args - ? [args] extends [never] - ? readonly unknown[] - : args - : readonly unknown[] - -export type ContractEventArgs< - abi extends Abi | readonly unknown[] = Abi, - eventName extends ContractEventName = ContractEventName, -> = AbiEventParametersToPrimitiveTypes< - ExtractAbiEvent['inputs'] -> extends infer args - ? [args] extends [never] - ? readonly unknown[] | Record - : args - : readonly unknown[] | Record - -export type ContractEventArgsFromTopics< - abi extends Abi | readonly unknown[] = Abi, - eventName extends ContractEventName = ContractEventName, - strict extends boolean = true, -> = AbiEventParametersToPrimitiveTypes< - ExtractAbiEvent['inputs'], - { EnableUnion: false; IndexedOnly: false; Required: strict } -> extends infer args - ? [args] extends [never] - ? readonly unknown[] | Record - : args - : readonly unknown[] | Record + >, +> = + AbiParametersToPrimitiveTypes< + ExtractAbiFunction["inputs"], + "inputs" + > extends infer args + ? [args] extends [never] + ? readonly unknown[] + : args + : readonly unknown[]; export type Widen = | ([unknown] extends [type] ? unknown : never) | (type extends Function ? type : never) - | (type extends ResolvedRegister['BigIntType'] ? bigint : never) + | (type extends ResolvedRegister["BigIntType"] ? bigint : never) | (type extends boolean ? boolean : never) - | (type extends ResolvedRegister['IntType'] ? number : never) + | (type extends ResolvedRegister["IntType"] ? number : never) | (type extends string - ? type extends ResolvedRegister['AddressType'] - ? ResolvedRegister['AddressType'] - : type extends ResolvedRegister['BytesType']['inputs'] - ? ResolvedRegister['BytesType'] + ? type extends ResolvedRegister["AddressType"] + ? ResolvedRegister["AddressType"] + : type extends ResolvedRegister["BytesType"]["inputs"] + ? ResolvedRegister["BytesType"] : string : never) | (type extends readonly [] ? readonly [] : never) - | (type extends Record - ? { [K in keyof type]: Widen } - : never) + | (type extends Record ? { [K in keyof type]: Widen } : never) | (type extends { length: number } ? { - [K in keyof type]: Widen + [K in keyof type]: Widen; } extends infer Val extends readonly unknown[] ? readonly [...Val] : never - : never) + : never); -export type UnionWiden = type extends any ? Widen : never +export type UnionWiden = type extends any ? Widen : never; export type ExtractAbiFunctionForArgs< abi extends Abi, mutability extends AbiStateMutability, functionName extends ContractFunctionName, args extends ContractFunctionArgs, -> = ExtractAbiFunction< - abi, - functionName, - mutability -> extends infer abiFunction extends AbiFunction - ? IsUnion extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match - ? UnionToTuple extends infer abiFunctions extends - readonly AbiFunction[] - ? // convert back to union (removes `never` tuple entries) - { [k in keyof abiFunctions]: CheckArgs }[number] - : never - : abiFunction - : never +> = + ExtractAbiFunction extends infer abiFunction extends AbiFunction + ? IsUnion extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match + ? UnionToTuple extends infer abiFunctions extends readonly AbiFunction[] + ? // convert back to union (removes `never` tuple entries) + { [k in keyof abiFunctions]: CheckArgs }[number] + : never + : abiFunction + : never; type CheckArgs< abiFunction extends AbiFunction, args, /// targetArgs extends AbiParametersToPrimitiveTypes< - abiFunction['inputs'], - 'inputs' - > = AbiParametersToPrimitiveTypes, + abiFunction["inputs"], + "inputs" + > = AbiParametersToPrimitiveTypes, > = (readonly [] extends args ? readonly [] : args) extends targetArgs // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided) ? abiFunction - : never + : never; export type ContractFunctionParameters< abi extends Abi | readonly unknown[] = Abi, mutability extends AbiStateMutability = AbiStateMutability, - functionName extends ContractFunctionName< + functionName extends ContractFunctionName = ContractFunctionName< abi, mutability - > = ContractFunctionName, - args extends ContractFunctionArgs< + >, + args extends ContractFunctionArgs = ContractFunctionArgs< abi, mutability, functionName - > = ContractFunctionArgs, + >, deployless extends boolean = false, /// allFunctionNames = ContractFunctionName, @@ -204,266 +114,10 @@ export type ContractFunctionParameters< // when `args` is inferred to `readonly []` ("inputs": []) or `never` (`abi` declared as `Abi` or not inferrable), allow `args` to be optional. // important that both branches return same structural type > = { - abi: abi + abi: abi; functionName: | allFunctionNames // show all options - | (functionName extends allFunctionNames ? functionName : never) // infer value - args?: (abi extends Abi ? UnionWiden : never) | allArgs | undefined + | (functionName extends allFunctionNames ? functionName : never); // infer value + args?: (abi extends Abi ? UnionWiden : never) | allArgs | undefined; } & (readonly [] extends allArgs ? {} : { args: Widen }) & - (deployless extends true - ? { address?: undefined; code: Hex } - : { address: Address }) - -export type ContractFunctionReturnType< - abi extends Abi | readonly unknown[] = Abi, - mutability extends AbiStateMutability = AbiStateMutability, - functionName extends ContractFunctionName< - abi, - mutability - > = ContractFunctionName, - args extends ContractFunctionArgs< - abi, - mutability, - functionName - > = ContractFunctionArgs, -> = abi extends Abi - ? Abi extends abi - ? unknown - : AbiParametersToPrimitiveTypes< - ExtractAbiFunctionForArgs< - abi, - mutability, - functionName, - args - >['outputs'] - > extends infer types - ? types extends readonly [] - ? void - : types extends readonly [infer type] - ? type - : types - : never - : unknown - -export type AbiItem = Abi[number] - -export type ExtractAbiItemNames = Extract< - abi[number], - { name: string } ->['name'] - -export type ExtractAbiItem< - abi extends Abi, - name extends ExtractAbiItemNames, -> = Extract - -export type AbiItemName = - abi extends Abi ? ExtractAbiItemNames : string - -export type AbiItemArgs< - abi extends Abi | readonly unknown[] = Abi, - name extends AbiItemName = AbiItemName, -> = AbiParametersToPrimitiveTypes< - ExtractAbiItem['inputs'], - 'inputs' -> extends infer args - ? [args] extends [never] - ? readonly unknown[] - : args - : readonly unknown[] - -export type ExtractAbiItemForArgs< - abi extends Abi, - name extends AbiItemName, - args extends AbiItemArgs, -> = ExtractAbiItem extends infer abiItem extends AbiItem & { - inputs: readonly AbiParameter[] -} - ? IsUnion extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match - ? UnionToTuple extends infer abiItems extends readonly (AbiItem & { - inputs: readonly AbiParameter[] - })[] - ? { - [k in keyof abiItems]: ( - readonly [] extends args - ? readonly [] // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided) - : args - ) extends AbiParametersToPrimitiveTypes< - abiItems[k]['inputs'], - 'inputs' - > - ? abiItems[k] - : never - }[number] // convert back to union (removes `never` tuple entries: `['foo', never, 'bar'][number]` => `'foo' | 'bar'`) - : never - : abiItem - : never - -export type EventDefinition = `${string}(${string})` - -export type GetValue< - abi extends Abi | readonly unknown[], - functionName extends string, - valueType = TransactionRequest['value'], - abiFunction extends AbiFunction = abi extends Abi - ? ExtractAbiFunction - : AbiFunction, - _Narrowable extends boolean = IsNarrowable, -> = _Narrowable extends true - ? abiFunction['stateMutability'] extends 'payable' - ? { value?: NoInfer | undefined } - : abiFunction['payable'] extends true - ? { value?: NoInfer | undefined } - : { value?: undefined } - : { value?: NoInfer | undefined } - -////////////////////////////////////////////////////////////////////////////////////////////////// - -export type MaybeAbiEventName = - abiEvent extends AbiEvent ? abiEvent['name'] : undefined - -export type MaybeExtractEventArgsFromAbi< - abi extends Abi | readonly unknown[] | undefined, - eventName extends string | undefined, -> = abi extends Abi | readonly unknown[] - ? eventName extends string - ? GetEventArgs - : undefined - : undefined - -////////////////////////////////////////////////////////////////////// -// ABI item args - -export type GetEventArgs< - abi extends Abi | readonly unknown[], - eventName extends string, - config extends EventParameterOptions = DefaultEventParameterOptions, - abiEvent extends AbiEvent & { type: 'event' } = abi extends Abi - ? ExtractAbiEvent - : AbiEvent & { type: 'event' }, - args = AbiEventParametersToPrimitiveTypes, - FailedToParseArgs = - | ([args] extends [never] ? true : false) - | (readonly unknown[] extends args ? true : false), -> = true extends FailedToParseArgs - ? readonly unknown[] | Record - : args - -////////////////////////////////////////////////////////////////////// -// ABI event types - -type EventParameterOptions = { - EnableUnion?: boolean - IndexedOnly?: boolean - Required?: boolean -} -type DefaultEventParameterOptions = { - EnableUnion: true - IndexedOnly: true - Required: false -} - -export type AbiEventParametersToPrimitiveTypes< - abiParameters extends readonly AbiParameter[], - // - _options extends EventParameterOptions = DefaultEventParameterOptions, - // Remove non-indexed parameters based on `Options['IndexedOnly']` -> = abiParameters extends readonly [] - ? readonly [] - : Filter< - abiParameters, - _options['IndexedOnly'] extends true ? { indexed: true } : object - > extends infer Filtered extends readonly AbiParameter[] - ? _HasUnnamedAbiParameter extends true - ? // Has unnamed tuple parameters so return as array - | readonly [ - ...{ - [K in keyof Filtered]: AbiEventParameterToPrimitiveType< - Filtered[K], - _options - > - }, - ] - // Distribute over tuple to represent optional parameters - | (_options['Required'] extends true - ? never - : // Distribute over tuple to represent optional parameters - Filtered extends readonly [ - ...infer Head extends readonly AbiParameter[], - infer _, - ] - ? AbiEventParametersToPrimitiveTypes< - readonly [...{ [K in keyof Head]: Omit }], - _options - > - : never) - : // All tuple parameters are named so return as object - { - [Parameter in Filtered[number] as Parameter extends { - name: infer Name extends string - } - ? Name - : never]?: - | AbiEventParameterToPrimitiveType - | undefined - } extends infer Mapped - ? Prettify< - MaybeRequired< - Mapped, - _options['Required'] extends boolean - ? _options['Required'] - : false - > - > - : never - : never - -// TODO: Speed up by returning immediately as soon as named parameter is found. -type _HasUnnamedAbiParameter = - abiParameters extends readonly [ - infer Head extends AbiParameter, - ...infer Tail extends readonly AbiParameter[], - ] - ? Head extends { name: string } - ? Head['name'] extends '' - ? true - : _HasUnnamedAbiParameter - : true - : false - -/** - * @internal - */ -export type LogTopicType< - primitiveType = Hex, - topic extends LogTopic = LogTopic, -> = topic extends Hex - ? primitiveType - : topic extends Hex[] - ? primitiveType[] - : topic extends null - ? null - : never - -/** - * @internal - */ -export type AbiEventParameterToPrimitiveType< - abiParameter extends AbiParameter, - // - _options extends EventParameterOptions = DefaultEventParameterOptions, - _type = AbiParameterToPrimitiveType, -> = _options['EnableUnion'] extends true ? LogTopicType<_type> : _type - -type HashedEventTypes = 'bytes' | 'string' | 'tuple' | `${string}[${string}]` - -/** - * @internal - */ -export type AbiEventTopicToPrimitiveType< - abiParameter extends AbiParameter, - topic extends LogTopic, - primitiveType = abiParameter['type'] extends HashedEventTypes - ? topic - : AbiParameterToPrimitiveType, -> = LogTopicType \ No newline at end of file + (deployless extends true ? { address?: undefined; code: Hex } : { address: Address }); diff --git a/src/types/misc.ts b/src/types/misc.ts index 3986976e..0331005a 100644 --- a/src/types/misc.ts +++ b/src/types/misc.ts @@ -1,38 +1,5 @@ -import type { OneOf } from './utils' +// Adapted from viem (https://github.com/wevm/viem) -export type ByteArray = Uint8Array -export type Hex = `0x${string}` -export type Hash = `0x${string}` -export type LogTopic = Hex | Hex[] | null -export type SignableMessage = - | string - | { - /** Raw data representation of the message. */ - raw: Hex | ByteArray - } -export type SignatureLegacy = { - r: Hex - s: Hex - v: bigint -} -export type Signature = OneOf< - | SignatureLegacy - | { - r: Hex - s: Hex - /** @deprecated use `yParity`. */ - v: bigint - yParity?: number | undefined - } - | { - r: Hex - s: Hex - /** @deprecated use `yParity`. */ - v?: bigint | undefined - yParity: number - } -> -export type CompactSignature = { - r: Hex - yParityAndS: Hex -} \ No newline at end of file +export type Hex = `0x${string}`; +export type Hash = `0x${string}`; +export type Address = `0x${string}`; diff --git a/src/types/multicall.ts b/src/types/multicall.ts index 70a59f7a..b92449bf 100644 --- a/src/types/multicall.ts +++ b/src/types/multicall.ts @@ -1,149 +1,11 @@ -import type { Abi, AbiStateMutability } from 'abitype' +// Adapted from viem (https://github.com/wevm/viem) +import type { Abi, AbiStateMutability } from "abitype"; import type { ContractFunctionArgs, ContractFunctionName, ContractFunctionParameters, - ContractFunctionReturnType, -} from './contract' -import type { MaybePartial, Prettify } from './utils' - -export type MulticallContracts< - contracts extends readonly unknown[], - options extends { - mutability: AbiStateMutability - optional?: boolean - properties?: Record - } = { mutability: AbiStateMutability }, - /// - result extends readonly any[] = [], -> = contracts extends readonly [] // no contracts, return empty - ? readonly [] - : contracts extends readonly [infer contract] // one contract left before returning `result` - ? readonly [ - ...result, - MaybePartial< - Prettify< - GetMulticallContractParameters & - options['properties'] - >, - options['optional'] - >, - ] - : contracts extends readonly [infer contract, ...infer rest] // grab first contract and recurse through `rest` - ? MulticallContracts< - [...rest], - options, - [ - ...result, - MaybePartial< - Prettify< - GetMulticallContractParameters< - contract, - options['mutability'] - > & - options['properties'] - >, - options['optional'] - >, - ] - > - : readonly unknown[] extends contracts - ? contracts - : // If `contracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! - // use this to infer the param types in the case of Array.map() argument - contracts extends readonly (infer contract extends - ContractFunctionParameters)[] - ? readonly MaybePartial< - Prettify, - options['optional'] - >[] - : // Fallback - readonly MaybePartial< - Prettify, - options['optional'] - >[] - -export type MulticallResults< - contracts extends readonly unknown[] = readonly ContractFunctionParameters[], - allowFailure extends boolean = true, - options extends { - error?: Error | undefined - extraProperties?: Record | undefined - mutability: AbiStateMutability - } = { error: Error; extraProperties: {}; mutability: AbiStateMutability }, - /// - result extends any[] = [], -> = contracts extends readonly [] // no contracts, return empty - ? readonly [] - : contracts extends readonly [infer contract] // one contract left before returning `result` - ? [ - ...result, - MulticallResponse< - GetMulticallContractReturnType, - options['error'], - allowFailure, - options['extraProperties'] - >, - ] - : contracts extends readonly [infer contract, ...infer rest] // grab first contract and recurse through `rest` - ? MulticallResults< - [...rest], - allowFailure, - options, - [ - ...result, - MulticallResponse< - GetMulticallContractReturnType, - options['error'], - allowFailure, - options['extraProperties'] - >, - ] - > - : readonly unknown[] extends contracts - ? MulticallResponse< - unknown, - options['error'], - allowFailure, - options['extraProperties'] - >[] - : // If `contracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! - // use this to infer the param types in the case of Array.map() argument - contracts extends readonly (infer contract extends - ContractFunctionParameters)[] - ? MulticallResponse< - GetMulticallContractReturnType, - options['error'], - allowFailure, - options['extraProperties'] - >[] - : // Fallback - MulticallResponse< - unknown, - options['error'], - allowFailure, - options['extraProperties'] - >[] - -export type MulticallResponse< - result = unknown, - error = unknown, - allowFailure extends boolean = true, - extraProperties extends Record | undefined = {}, -> = allowFailure extends true - ? - | (extraProperties & { - error?: undefined - result: result - status: 'success' - }) - | (extraProperties & { - error: unknown extends error ? Error : error - result?: undefined - status: 'failure' - }) - : result +} from "./contract"; // infer contract parameters from `unknown` export type GetMulticallContractParameters< @@ -152,18 +14,11 @@ export type GetMulticallContractParameters< > = contract extends { abi: infer abi extends Abi } // 1. Check if `abi` is const-asserted or defined inline ? // 1a. Check if `functionName` is valid for `abi` contract extends { - functionName: infer functionName extends ContractFunctionName< - abi, - mutability - > + functionName: infer functionName extends ContractFunctionName; } ? // 1aa. Check if `args` is valid for `abi` and `functionName` contract extends { - args: infer args extends ContractFunctionArgs< - abi, - mutability, - functionName - > + args: infer args extends ContractFunctionArgs; } ? ContractFunctionParameters // `args` valid, pass through : ContractFunctionParameters // invalid `args` @@ -172,28 +27,4 @@ export type GetMulticallContractParameters< ? ContractFunctionParameters // `abi` declared as `Abi`, unable to infer types further : // `abi` is const-asserted or defined inline, infer types for `functionName` and `args` ContractFunctionParameters - : ContractFunctionParameters // invalid `contract['abi']`, set to `readonly unknown[]` - -type GetMulticallContractReturnType< - contract, - mutability extends AbiStateMutability, -> = contract extends { abi: infer abi extends Abi } // 1. Check if `abi` is const-asserted or defined inline - ? // Check if `functionName` is valid for `abi` - contract extends { - functionName: infer functionName extends ContractFunctionName< - abi, - mutability - > - } - ? // Check if `args` is valid for `abi` and `functionName` - contract extends { - args: infer args extends ContractFunctionArgs< - abi, - mutability, - functionName - > - } - ? ContractFunctionReturnType // `args` valid, pass through - : ContractFunctionReturnType // invalid `args` - : ContractFunctionReturnType // Invalid `functionName` - : ContractFunctionReturnType // invalid `contract['abi']` (not const-asserted or declared as `Abi`) \ No newline at end of file + : ContractFunctionParameters; // invalid `contract['abi']`, set to `readonly unknown[]` diff --git a/src/types/utils.ts b/src/types/utils.ts index 9c81c4e9..9e02c30a 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -1,17 +1,4 @@ -declare const symbol: unique symbol - -/** - * Creates a branded type of {@link T} with the brand {@link U}. - * - * @param T - Type to brand - * @param U - Label - * @returns Branded type - * - * @example - * type Result = Branded - * // ^? type Result = string & { [symbol]: 'foo' } - */ -export type Branded = T & { [symbol]: U } +// Adapted from viem (https://github.com/wevm/viem) /** * Filters out all members of {@link T} that are not {@link P} @@ -32,7 +19,7 @@ export type Filter< ? [F] extends [P] ? Filter : Filter - : readonly [...Acc] + : readonly [...Acc]; /** * @description Checks if {@link T} can be narrowed further than {@link U} @@ -42,11 +29,8 @@ export type Filter< * type Result = IsNarrowable<'foo', string> * // ^? true */ -export type IsNarrowable = IsNever< - (T extends U ? true : false) & (U extends T ? false : true) -> extends true - ? false - : true +export type IsNarrowable = + IsNever<(T extends U ? true : false) & (U extends T ? false : true)> extends true ? false : true; /** * @description Checks if {@link T} is `never` @@ -55,12 +39,12 @@ export type IsNarrowable = IsNever< * type Result = IsNever * // ^? type Result = true */ -export type IsNever = [T] extends [never] ? true : false +export type IsNever = [T] extends [never] ? true : false; /** Removes `readonly` from all properties of an object. */ export type Mutable = { - -readonly [key in keyof type]: type[key] -} + -readonly [key in keyof type]: type[key]; +}; /** * @description Evaluates boolean "or" condition for {@link T} properties. @@ -74,14 +58,11 @@ export type Mutable = { * type Result = Or<[false, false, false]> * // ^? type Result = false */ -export type Or = T extends readonly [ - infer Head, - ...infer Tail, -] +export type Or = T extends readonly [infer Head, ...infer Tail] ? Head extends true ? true : Or - : false + : false; /** * @description Checks if {@link T} is `undefined` @@ -90,9 +71,9 @@ export type Or = T extends readonly [ * type Result = IsUndefined * // ^? type Result = true */ -export type IsUndefined = [undefined] extends [T] ? true : false +export type IsUndefined = [undefined] extends [T] ? true : false; -export type MaybePromise = T | Promise +export type MaybePromise = T | Promise; /** * @description Makes attributes on the type T required if required is true. @@ -106,7 +87,7 @@ export type MaybePromise = T | Promise */ export type MaybeRequired = required extends true ? ExactRequired - : T + : T; /** * @description Assigns the properties of U onto T. @@ -115,17 +96,15 @@ export type MaybeRequired = required extends true * Assign<{ a: string, b: number }, { a: undefined, c: boolean }> * => { a: undefined, b: number, c: boolean } */ -export type Assign = Assign_ & U +export type Assign = Assign_ & U; type Assign_ = { - [K in keyof T as K extends keyof U - ? U[K] extends void - ? never - : K - : K]: K extends keyof U ? U[K] : T[K] -} + [K in keyof T as K extends keyof U ? (U[K] extends void ? never : K) : K]: K extends keyof U + ? U[K] + : T[K]; +}; // TODO: Remove when peer dep `typescript@>=4.5` (NoInfer is native) -export type NoInfer = [type][type extends any ? 0 : never] +export type NoInfer = [type][type extends any ? 0 : never]; /** * @description Constructs a type by excluding `undefined` from `T`. @@ -136,13 +115,10 @@ export type NoInfer = [type][type extends any ? 0 : never] * * @internal */ -export type NoUndefined = T extends undefined ? never : T +export type NoUndefined = T extends undefined ? never : T; /** Strict version of built-in Omit type */ -export type Omit = Pick< - type, - Exclude -> +export type Omit = Pick>; /** * @description Creates a type that is a partial of T, but with the required keys K. @@ -151,8 +127,7 @@ export type Omit = Pick< * PartialBy<{ a: string, b: number }, 'a'> * => { a?: string, b: number } */ -export type PartialBy = Omit & - ExactPartial> +export type PartialBy = Omit & ExactPartial>; /** * @description Combines members of an intersection into a readable type. @@ -163,13 +138,13 @@ export type PartialBy = Omit & * => { a: string, b: string, c: number, d: bigint } */ export type Prettify = { - [K in keyof T]: T[K] -} & {} + [K in keyof T]: T[K]; +} & {}; /** @internal */ export type Evaluate = { - [key in keyof type]: type[key] -} & {} + [key in keyof type]: type[key]; +} & {}; /** * @description Creates a type that is T with the required keys K. @@ -178,8 +153,7 @@ export type Evaluate = { * RequiredBy<{ a?: string, b: number }, 'a'> * => { a: string, b: number } */ -export type RequiredBy = Omit & - ExactRequired> +export type RequiredBy = Omit & ExactRequired>; /** * @description Returns truthy if `array` contains `value`. @@ -188,14 +162,14 @@ export type RequiredBy = Omit & * Some<[1, 2, 3], 2> * => true */ -export type Some< - array extends readonly unknown[], +export type Some = array extends readonly [ value, -> = array extends readonly [value, ...unknown[]] + ...unknown[], +] ? true : array extends readonly [unknown, ...infer rest] ? Some - : false + : false; /** * @description Creates a type that extracts the values of T. @@ -206,44 +180,40 @@ export type Some< * * @internal */ -export type ValueOf = T[keyof T] +export type ValueOf = T[keyof T]; export type UnionToTuple< union, /// last = LastInUnion, -> = [union] extends [never] ? [] : [...UnionToTuple>, last] -type LastInUnion = UnionToIntersection< - U extends unknown ? (x: U) => 0 : never -> extends (x: infer l) => 0 - ? l - : never -type UnionToIntersection = ( - union extends unknown - ? (arg: union) => 0 - : never -) extends (arg: infer i) => 0 +> = [union] extends [never] ? [] : [...UnionToTuple>, last]; +type LastInUnion = + UnionToIntersection 0 : never> extends (x: infer l) => 0 + ? l + : never; +type UnionToIntersection = (union extends unknown ? (arg: union) => 0 : never) extends ( + arg: infer i, +) => 0 ? i - : never + : never; export type IsUnion< union, /// union2 = union, -> = union extends union2 ? ([union2] extends [union] ? false : true) : never +> = union extends union2 ? ([union2] extends [union] ? false : true) : never; -export type MaybePartial< - type, - enabled extends boolean | undefined, -> = enabled extends true ? Prettify> : type +export type MaybePartial = enabled extends true + ? Prettify> + : type; export type ExactPartial = { - [key in keyof type]?: type[key] | undefined -} + [key in keyof type]?: type[key] | undefined; +}; export type ExactRequired = { - [P in keyof type]-?: Exclude -} + [P in keyof type]-?: Exclude; +}; export type OneOf< union extends object, @@ -257,11 +227,11 @@ export type OneOf< ? key extends keyof fallback ? fallback[key] : undefined - : undefined + : undefined; } > - : never -type KeyofUnion = type extends type ? keyof type : never + : never; +type KeyofUnion = type extends type ? keyof type : never; /////////////////////////////////////////////////////////////////////////// // Loose types @@ -270,19 +240,16 @@ type KeyofUnion = type extends type ? keyof type : never * Loose version of {@link Omit} * @internal */ -export type LooseOmit = Pick< - type, - Exclude -> +export type LooseOmit = Pick>; /////////////////////////////////////////////////////////////////////////// // Union types -export type UnionEvaluate = type extends object ? Prettify : type +export type UnionEvaluate = type extends object ? Prettify : type; export type UnionLooseOmit = type extends any ? LooseOmit - : never + : never; /** * @description Construct a type with the properties of union type T except for those in type K. @@ -290,9 +257,7 @@ export type UnionLooseOmit = type extends any * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * => { b: number } | { b: undefined, c: number } */ -export type UnionOmit = type extends any - ? Omit - : never +export type UnionOmit = type extends any ? Omit : never; /** * @description Construct a type with the properties of union type T except for those in type K. @@ -300,9 +265,7 @@ export type UnionOmit = type extends any * type Result = UnionOmit<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * => { b: number } | { b: undefined, c: number } */ -export type UnionPick = type extends any - ? Pick - : never +export type UnionPick = type extends any ? Pick : never; /** * @description Creates a type that is a partial of T, but with the required keys K. @@ -311,9 +274,7 @@ export type UnionPick = type extends any * PartialBy<{ a: string, b: number } | { a: string, b: undefined, c: number }, 'a'> * => { a?: string, b: number } | { a?: string, b: undefined, c: number } */ -export type UnionPartialBy = T extends any - ? PartialBy - : never +export type UnionPartialBy = T extends any ? PartialBy : never; /** * @description Creates a type that is T with the required keys K. @@ -322,6 +283,4 @@ export type UnionPartialBy = T extends any * RequiredBy<{ a?: string, b: number } | { a?: string, c?: number }, 'a'> * => { a: string, b: number } | { a: string, c?: number } */ -export type UnionRequiredBy = T extends any - ? RequiredBy - : never \ No newline at end of file +export type UnionRequiredBy = T extends any ? RequiredBy : never; diff --git a/src/wallets/createSmartWallet.test.ts b/src/wallets/createSmartWallet.test.ts index e4515a45..329d8265 100644 --- a/src/wallets/createSmartWallet.test.ts +++ b/src/wallets/createSmartWallet.test.ts @@ -1,6 +1,6 @@ import { createSmartWallet } from "./createSmartWallet"; import { Coinbase } from "../coinbase/coinbase"; -import { type Address } from "viem"; +import type { Address } from "../types/misc"; import { smartWalletApiMock, mockReturnValue, mockReturnRejectedValue } from "../tests/utils"; import { sendUserOperation } from "../actions/sendUserOperation"; diff --git a/src/wallets/createSmartWallet.ts b/src/wallets/createSmartWallet.ts index 90174a0f..07264137 100644 --- a/src/wallets/createSmartWallet.ts +++ b/src/wallets/createSmartWallet.ts @@ -1,6 +1,6 @@ import { Signer, type SmartWallet } from "./types"; import { Coinbase } from "../index"; -import type { Address } from "viem"; +import type { Address } from "../types/misc"; import { toSmartWallet } from "./toSmartWallet"; /** diff --git a/src/wallets/toSmartWallet.test.ts b/src/wallets/toSmartWallet.test.ts index fc055abd..2d88c344 100644 --- a/src/wallets/toSmartWallet.test.ts +++ b/src/wallets/toSmartWallet.test.ts @@ -1,7 +1,7 @@ import { sendUserOperation } from "../actions/sendUserOperation"; import { createNetwork } from "../utils/chain"; import { toSmartWallet } from "./toSmartWallet"; -import type { Address } from "viem"; +import type { Address } from "../types/misc"; jest.mock("../actions/sendUserOperation", () => ({ sendUserOperation: jest.fn(), diff --git a/src/wallets/toSmartWallet.ts b/src/wallets/toSmartWallet.ts index 579817fc..98dcddb4 100644 --- a/src/wallets/toSmartWallet.ts +++ b/src/wallets/toSmartWallet.ts @@ -5,7 +5,7 @@ import { type SmartWallet, } from "./types"; import { sendUserOperation } from "../actions/sendUserOperation"; -import type { Address } from "viem"; +import type { Address } from "../types/misc"; import { createNetwork } from "../utils/chain"; /** diff --git a/src/wallets/types.ts b/src/wallets/types.ts index 9ef18361..7a90d2a5 100644 --- a/src/wallets/types.ts +++ b/src/wallets/types.ts @@ -1,11 +1,10 @@ -import type { Address } from "abitype"; -import type { Hash, Hex } from "viem"; +import type { Hash, Hex, Address } from "../types/misc"; import type { SendUserOperationOptions, SendUserOperationReturnType, } from "../actions/sendUserOperation"; import type { Network, SupportedChainId } from "../types/chain"; -import type { Prettify } from "viem"; +import type { Prettify } from "../types/utils"; /** * Options for configuring a SmartWallet for a specific network From cdb25adc8203340bf7dedbf72f81dbb3bb9bb499 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 12:34:30 -0500 Subject: [PATCH 51/59] Fix --- src/actions/sendUserOperation.ts | 107 +++++++++++++++---------------- 1 file changed, 52 insertions(+), 55 deletions(-) diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 58f399a7..210be790 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -1,8 +1,10 @@ import type { SmartWallet } from "../wallets/types"; import { UserOperationStatusEnum } from "../client"; -import type { SupportedChainId } from "../types/chain"; -import type { Address } from "../types/misc"; +import { CHAIN_ID_TO_NETWORK_ID, type SupportedChainId } from "../types/chain"; +import type { Address, Hex } from "../types/misc"; import type { Calls } from "../types/calls"; +import { encodeFunctionData } from "viem"; +import { Coinbase } from "../coinbase/coinbase"; /** * Options for sending a user operation @@ -63,66 +65,61 @@ export async function sendUserOperation( wallet: SmartWallet, options: SendUserOperationOptions, ): Promise { - return { - id: "123", - smartWalletAddress: "0x123", - status: "broadcast", - }; - // const { calls, chainId, paymasterUrl } = options; - // const network = CHAIN_ID_TO_NETWORK_ID[chainId]; + const { calls, chainId, paymasterUrl } = options; + const network = CHAIN_ID_TO_NETWORK_ID[chainId]; - // if (calls.length === 0) { - // throw new Error("Calls array is empty"); - // } + if (calls.length === 0) { + throw new Error("Calls array is empty"); + } - // const encodedCalls = calls.map(call => { - // const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string + const encodedCalls = calls.map(call => { + const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string - // if ("abi" in call && call.abi && "functionName" in call) { - // return { - // to: call.to, - // data: encodeFunctionData({ - // abi: call.abi, - // functionName: call.functionName, - // args: call.args, - // }), - // value, - // }; - // } + if ("abi" in call && call.abi && "functionName" in call) { + return { + to: call.to, + data: encodeFunctionData({ + abi: call.abi, + functionName: call.functionName, + args: call.args, + }), + value, + }; + } - // return { - // to: call.to, - // data: call.data ?? "0x", - // value, - // }; - // }); + return { + to: call.to, + data: call.data ?? "0x", + value, + }; + }); - // const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( - // wallet.address, - // network, - // { - // calls: encodedCalls, - // paymaster_url: paymasterUrl, - // }, - // ); + const createOpResponse = await Coinbase.apiClients.smartWallet!.createUserOperation( + wallet.address, + network, + { + calls: encodedCalls, + paymaster_url: paymasterUrl, + }, + ); - // const owner = wallet.owners[0]; + const owner = wallet.owners[0]; - // const signature = await owner.sign({ - // hash: createOpResponse.data.unsigned_payload as Hex, - // }); + const signature = await owner.sign({ + hash: createOpResponse.data.unsigned_payload as Hex, + }); - // const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( - // wallet.address, - // createOpResponse.data.id, - // { - // signature, - // }, - // ); + const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( + wallet.address, + createOpResponse.data.id, + { + signature, + }, + ); - // return { - // id: broadcastResponse.data.id, - // smartWalletAddress: wallet.address, - // status: broadcastResponse.data.status, - // } as SendUserOperationReturnType; + return { + id: broadcastResponse.data.id, + smartWalletAddress: wallet.address, + status: broadcastResponse.data.status, + } as SendUserOperationReturnType; } From f91b84a566e0cf3077092448d1943fa443fac568 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 12:36:42 -0500 Subject: [PATCH 52/59] Fix --- src/tests/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/utils.ts b/src/tests/utils.ts index 275de083..e87fc324 100644 --- a/src/tests/utils.ts +++ b/src/tests/utils.ts @@ -129,7 +129,7 @@ export const newAddressModelsFromWallet = async ( const address2 = getAddressFromHDKey(wallet.derive("m/44'/60'/0'/0/1")); const publicKey1 = convertStringToHex(wallet.derive("m/44'/60'/0'/0/0").publicKey!); const publicKey2 = convertStringToHex(wallet.derive("m/44'/60'/0'/0/1").publicKey!); - + return [ { address_id: address1, @@ -144,7 +144,7 @@ export const newAddressModelsFromWallet = async ( public_key: publicKey2, wallet_id: walletId, index: 1, - } + }, ]; }; From f5093d7586419b01e18d04712b2c3fb6e9617010 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 12:51:46 -0500 Subject: [PATCH 53/59] fix test configuration --- jest.config.js | 6 ------ package.json | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/jest.config.js b/jest.config.js index 9180aa52..d594a723 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,12 +3,6 @@ module.exports = { testEnvironment: "node", extensionsToTreatAsEsm: [".ts"], testMatch: ["**/src/**/*.test.ts", "**/src/tests/**/*.ts"], - testPathIgnorePatterns: [ - "/node_modules/", - "/src/tests/e2e.ts", - "/src/tests/utils.ts", - "/src/tests/types.test-d.ts", - ], coveragePathIgnorePatterns: ["node_modules", "client", "__tests__", "/src/tests/"], collectCoverage: true, collectCoverageFrom: ["./src/**/*.ts"], diff --git a/package.json b/package.json index 96a54ec7..68966d47 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"", "format-check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"", "check": "tsc --noEmit", - "test": "jest --config jest.config.js", + "test": "jest --config jest.config.js --testPathIgnorePatterns src/tests/e2e.ts src/tests/utils.ts src/tests/types.test-d.ts", "test:dry-run": "npm install && npm ci && npm publish --dry-run", "test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'", "test:e2e:stake": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}' -t Stake", From 1b6a054ee88ad903cc96bd3edae6824c0cfb9f52 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 12:55:39 -0500 Subject: [PATCH 54/59] Changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8af86b07..47a068d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Coinbase Node.js SDK Changelog +## Unreleased + +### Added +- Ability to create a SmartWallet and send a user operation. + ## [0.18.1] - 2025-02-13 ### Fixed From 2fd6d4755d6b3b90a2d46c739d9897b9df02f393 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 13:07:41 -0500 Subject: [PATCH 55/59] Fix --- src/actions/sendUserOperation.test.ts | 8 +++++++- src/actions/sendUserOperation.ts | 5 ++++- src/client/api.ts | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/actions/sendUserOperation.test.ts b/src/actions/sendUserOperation.test.ts index 0b0fba55..baeb1650 100644 --- a/src/actions/sendUserOperation.test.ts +++ b/src/actions/sendUserOperation.test.ts @@ -34,12 +34,13 @@ describe("sendUserOperation", () => { const VALID_CREATE_OPERATION_RESPONSE = { id: "op123", - unsigned_payload: "0x456def" as const, + user_op_hash: "0x456def" as const, }; const VALID_BROADCAST_RESPONSE = { id: "op123", status: UserOperationStatusEnum.Broadcast, + user_op_hash: "0x456def" as const, }; beforeEach(() => { @@ -96,6 +97,7 @@ describe("sendUserOperation", () => { id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, + userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, }); }); @@ -132,6 +134,7 @@ describe("sendUserOperation", () => { id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, + userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, }); }); @@ -177,6 +180,7 @@ describe("sendUserOperation", () => { id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, + userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, }); }); @@ -217,6 +221,7 @@ describe("sendUserOperation", () => { id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, + userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, }); }); @@ -267,6 +272,7 @@ describe("sendUserOperation", () => { id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, + userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, }); }); diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index 210be790..eaded48f 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -29,6 +29,8 @@ export type SendUserOperationReturnType = { smartWalletAddress: Address; /** The status of the user operation */ status: typeof UserOperationStatusEnum.Broadcast; + /** The hash of the user operation */ + userOpHash: Hex; }; /** @@ -106,7 +108,7 @@ export async function sendUserOperation( const owner = wallet.owners[0]; const signature = await owner.sign({ - hash: createOpResponse.data.unsigned_payload as Hex, + hash: createOpResponse.data.user_op_hash as Hex, }); const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( @@ -121,5 +123,6 @@ export async function sendUserOperation( id: broadcastResponse.data.id, smartWalletAddress: wallet.address, status: broadcastResponse.data.status, + userOpHash: createOpResponse.data.user_op_hash, } as SendUserOperationReturnType; } diff --git a/src/client/api.ts b/src/client/api.ts index cbf64609..55614be9 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -4094,10 +4094,17 @@ export interface UserOperation { * @memberof UserOperation */ 'calls': Array; + /** + * The unique identifier for the user operation onchain. This is the payload that must be signed by one of the owners of the smart wallet to send the user operation. + * @type {string} + * @memberof UserOperation + */ + 'user_op_hash': string; /** * The hex-encoded hash that must be signed by the user. * @type {string} * @memberof UserOperation + * @deprecated */ 'unsigned_payload': string; /** From 3fc946a6ea966da736ebc6ed2414f8f44116dfa1 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 13:11:51 -0500 Subject: [PATCH 56/59] Expose userOpHash --- src/actions/waitForUserOperation.test.ts | 6 ++++++ src/actions/waitForUserOperation.ts | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/actions/waitForUserOperation.test.ts b/src/actions/waitForUserOperation.test.ts index 271385cf..322777a0 100644 --- a/src/actions/waitForUserOperation.test.ts +++ b/src/actions/waitForUserOperation.test.ts @@ -12,12 +12,14 @@ describe("waitForUserOperation", () => { id: VALID_OPERATION_ID, status: UserOperationStatusEnum.Complete, transaction_hash: "0x1234567890123456789012345678901234567890", + user_op_hash: "0x1234567890123456789012345678901234567890", }; const FAILED_OPERATION_RESPONSE = { id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Failed, + user_op_hash: "0x1234567890123456789012345678901234567890", }; beforeEach(() => { @@ -46,6 +48,7 @@ describe("waitForUserOperation", () => { smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", + userOpHash: "0x1234567890123456789012345678901234567890", }); }); @@ -67,6 +70,7 @@ describe("waitForUserOperation", () => { smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Failed, transactionHash: undefined, + userOpHash: "0x1234567890123456789012345678901234567890", }); }); @@ -90,6 +94,7 @@ describe("waitForUserOperation", () => { smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", + userOpHash: "0x1234567890123456789012345678901234567890", }); }); @@ -114,6 +119,7 @@ describe("waitForUserOperation", () => { smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", + userOpHash: "0x1234567890123456789012345678901234567890", }); }); diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 3dcd0ac8..6aa43988 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -1,4 +1,4 @@ -import type { Address } from "../types/misc"; +import type { Address, Hex } from "../types/misc"; import { Coinbase } from "../coinbase/coinbase"; import { wait, WaitOptions } from "../utils/wait"; import { UserOperation, UserOperationStatusEnum } from "../client"; @@ -25,6 +25,8 @@ export type FailedOperation = { smartWalletAddress: Address; /** The status of the user operation */ status: typeof UserOperationStatusEnum.Failed; + /** The hash of the user operation */ + userOpHash: Hex; }; /** @@ -39,6 +41,8 @@ export type CompletedOperation = { transactionHash: string; /** The status of the user operation */ status: typeof UserOperationStatusEnum.Complete; + /** The hash of the user operation */ + userOpHash: Hex; }; /** @@ -84,6 +88,7 @@ export async function waitForUserOperation( id: operation.id, smartWalletAddress: smartWalletAddress, status: UserOperationStatusEnum.Failed, + userOpHash: operation.user_op_hash as Hex, } satisfies FailedOperation; } else if (operation.status === UserOperationStatusEnum.Complete) { return { @@ -91,6 +96,7 @@ export async function waitForUserOperation( smartWalletAddress: smartWalletAddress, transactionHash: operation.transaction_hash!, status: UserOperationStatusEnum.Complete, + userOpHash: operation.user_op_hash as Hex, } satisfies CompletedOperation; } else { throw new Error("User operation is not terminal"); From e87c629af20cd17116db1e9ce04a1eb4f9dcbdce Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Thu, 20 Feb 2025 20:30:35 -0500 Subject: [PATCH 57/59] Updated SDK for userOpHash --- src/actions/sendUserOperation.test.ts | 17 ++---- src/actions/sendUserOperation.ts | 7 +-- src/actions/waitForUserOperation.test.ts | 36 ++++++------- src/actions/waitForUserOperation.ts | 14 ++--- src/client/api.ts | 68 ++++++++++++------------ src/coinbase/types.ts | 2 +- 6 files changed, 61 insertions(+), 83 deletions(-) diff --git a/src/actions/sendUserOperation.test.ts b/src/actions/sendUserOperation.test.ts index baeb1650..5af47d54 100644 --- a/src/actions/sendUserOperation.test.ts +++ b/src/actions/sendUserOperation.test.ts @@ -33,12 +33,10 @@ describe("sendUserOperation", () => { } as const; const VALID_CREATE_OPERATION_RESPONSE = { - id: "op123", user_op_hash: "0x456def" as const, }; const VALID_BROADCAST_RESPONSE = { - id: "op123", status: UserOperationStatusEnum.Broadcast, user_op_hash: "0x456def" as const, }; @@ -87,14 +85,13 @@ describe("sendUserOperation", () => { expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( VALID_WALLET.address, - VALID_CREATE_OPERATION_RESPONSE.id, + VALID_CREATE_OPERATION_RESPONSE.user_op_hash, { signature: "0x789ghi", }, ); expect(result).toEqual({ - id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, @@ -124,14 +121,13 @@ describe("sendUserOperation", () => { expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( VALID_WALLET.address, - VALID_CREATE_OPERATION_RESPONSE.id, + VALID_CREATE_OPERATION_RESPONSE.user_op_hash, { signature: "0x789ghi", }, ); expect(result).toEqual({ - id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, @@ -170,14 +166,13 @@ describe("sendUserOperation", () => { expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( VALID_WALLET.address, - VALID_CREATE_OPERATION_RESPONSE.id, + VALID_CREATE_OPERATION_RESPONSE.user_op_hash, { signature: "0x789ghi", }, ); expect(result).toEqual({ - id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, @@ -211,14 +206,13 @@ describe("sendUserOperation", () => { expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( VALID_WALLET.address, - VALID_CREATE_OPERATION_RESPONSE.id, + VALID_CREATE_OPERATION_RESPONSE.user_op_hash, { signature: "0x789ghi", }, ); expect(result).toEqual({ - id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, @@ -262,14 +256,13 @@ describe("sendUserOperation", () => { expect(Coinbase.apiClients.smartWallet!.broadcastUserOperation).toHaveBeenCalledWith( VALID_WALLET.address, - VALID_CREATE_OPERATION_RESPONSE.id, + VALID_CREATE_OPERATION_RESPONSE.user_op_hash, { signature: "0x789ghi", }, ); expect(result).toEqual({ - id: VALID_BROADCAST_RESPONSE.id, smartWalletAddress: VALID_WALLET.address, status: VALID_BROADCAST_RESPONSE.status, userOpHash: VALID_BROADCAST_RESPONSE.user_op_hash, diff --git a/src/actions/sendUserOperation.ts b/src/actions/sendUserOperation.ts index eaded48f..176a660c 100644 --- a/src/actions/sendUserOperation.ts +++ b/src/actions/sendUserOperation.ts @@ -23,8 +23,6 @@ export type SendUserOperationOptions = { * Return type for the sendUserOperation function */ export type SendUserOperationReturnType = { - /** The UUID of the user operation which is server-generated identifier for the operation */ - id: string; /** The address of the smart wallet */ smartWalletAddress: Address; /** The status of the user operation */ @@ -75,7 +73,7 @@ export async function sendUserOperation( } const encodedCalls = calls.map(call => { - const value = (call.value ?? BigInt(0)).toString(); // Convert BigInt to string + const value = (call.value ?? BigInt(0)).toString(); if ("abi" in call && call.abi && "functionName" in call) { return { @@ -113,14 +111,13 @@ export async function sendUserOperation( const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( wallet.address, - createOpResponse.data.id, + createOpResponse.data.user_op_hash, { signature, }, ); return { - id: broadcastResponse.data.id, smartWalletAddress: wallet.address, status: broadcastResponse.data.status, userOpHash: createOpResponse.data.user_op_hash, diff --git a/src/actions/waitForUserOperation.test.ts b/src/actions/waitForUserOperation.test.ts index 322777a0..6ec79426 100644 --- a/src/actions/waitForUserOperation.test.ts +++ b/src/actions/waitForUserOperation.test.ts @@ -7,19 +7,17 @@ import * as waitUtils from "../utils/wait"; describe("waitForUserOperation", () => { const VALID_WALLET_ADDRESS = "0x1234567890123456789012345678901234567890" as const; - const VALID_OPERATION_ID = "op123"; + const VALID_OPERATION_HASH = "0x1234567890123456789012345678901234567890" as const; const VALID_OPERATION_RESPONSE = { - id: VALID_OPERATION_ID, status: UserOperationStatusEnum.Complete, transaction_hash: "0x1234567890123456789012345678901234567890", - user_op_hash: "0x1234567890123456789012345678901234567890", + user_op_hash: VALID_OPERATION_HASH, }; const FAILED_OPERATION_RESPONSE = { - id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Failed, - user_op_hash: "0x1234567890123456789012345678901234567890", + user_op_hash: VALID_OPERATION_HASH, }; beforeEach(() => { @@ -34,21 +32,20 @@ describe("waitForUserOperation", () => { it("should successfully wait for a completed operation", async () => { const result = await waitForUserOperation({ - id: VALID_OPERATION_ID, + userOpHash: VALID_OPERATION_HASH, smartWalletAddress: VALID_WALLET_ADDRESS, }); expect(Coinbase.apiClients.smartWallet!.getUserOperation).toHaveBeenCalledWith( VALID_WALLET_ADDRESS, - VALID_OPERATION_ID, + VALID_OPERATION_HASH, ); expect(result).toEqual({ - id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", - userOpHash: "0x1234567890123456789012345678901234567890", + userOpHash: VALID_OPERATION_HASH, }); }); @@ -56,21 +53,20 @@ describe("waitForUserOperation", () => { Coinbase.apiClients.smartWallet!.getUserOperation = mockReturnValue(FAILED_OPERATION_RESPONSE); const result = await waitForUserOperation({ - id: VALID_OPERATION_ID, + userOpHash: VALID_OPERATION_HASH, smartWalletAddress: VALID_WALLET_ADDRESS, }); expect(Coinbase.apiClients.smartWallet!.getUserOperation).toHaveBeenCalledWith( VALID_WALLET_ADDRESS, - VALID_OPERATION_ID, + VALID_OPERATION_HASH, ); expect(result).toEqual({ - id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Failed, transactionHash: undefined, - userOpHash: "0x1234567890123456789012345678901234567890", + userOpHash: VALID_OPERATION_HASH, }); }); @@ -78,7 +74,7 @@ describe("waitForUserOperation", () => { const waitSpy = jest.spyOn(waitUtils, "wait"); const result = await waitForUserOperation({ - id: VALID_OPERATION_ID, + userOpHash: VALID_OPERATION_HASH, smartWalletAddress: VALID_WALLET_ADDRESS, }); @@ -90,11 +86,10 @@ describe("waitForUserOperation", () => { ); expect(result).toEqual({ - id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", - userOpHash: "0x1234567890123456789012345678901234567890", + userOpHash: VALID_OPERATION_HASH, }); }); @@ -102,7 +97,7 @@ describe("waitForUserOperation", () => { const waitSpy = jest.spyOn(waitUtils, "wait"); const result = await waitForUserOperation({ - id: VALID_OPERATION_ID, + userOpHash: VALID_OPERATION_HASH, smartWalletAddress: VALID_WALLET_ADDRESS, waitOptions: { timeoutSeconds: 1, intervalSeconds: 0.1 }, }); @@ -115,23 +110,22 @@ describe("waitForUserOperation", () => { ); expect(result).toEqual({ - id: VALID_OPERATION_ID, smartWalletAddress: VALID_WALLET_ADDRESS, status: UserOperationStatusEnum.Complete, transactionHash: "0x1234567890123456789012345678901234567890", - userOpHash: "0x1234567890123456789012345678901234567890", + userOpHash: VALID_OPERATION_HASH, }); }); it("should throw an error if the operation is not terminal", async () => { Coinbase.apiClients.smartWallet!.getUserOperation = mockReturnValue({ - id: VALID_OPERATION_ID, + user_op_hash: VALID_OPERATION_HASH, status: UserOperationStatusEnum.Pending, }); await expect( waitForUserOperation({ - id: VALID_OPERATION_ID, + userOpHash: VALID_OPERATION_HASH, smartWalletAddress: VALID_WALLET_ADDRESS, waitOptions: { timeoutSeconds: 1 }, }), diff --git a/src/actions/waitForUserOperation.ts b/src/actions/waitForUserOperation.ts index 6aa43988..34181cf6 100644 --- a/src/actions/waitForUserOperation.ts +++ b/src/actions/waitForUserOperation.ts @@ -7,8 +7,8 @@ import { UserOperation, UserOperationStatusEnum } from "../client"; * Options for waiting for a user operation */ export type WaitForUserOperationOptions = { - /** The UUID of the user operation which was returned by the sendUserOperation function */ - id: string; + /** The hash of the user operation */ + userOpHash: Hex; /** The address of the smart wallet */ smartWalletAddress: Address; /** Optional options for the wait operation */ @@ -19,8 +19,6 @@ export type WaitForUserOperationOptions = { * Represents a failed user operation */ export type FailedOperation = { - /** The UUID of the user operation which was returned by the sendUserOperation function */ - id: string; /** The address of the smart wallet */ smartWalletAddress: Address; /** The status of the user operation */ @@ -33,8 +31,6 @@ export type FailedOperation = { * Represents a completed user operation */ export type CompletedOperation = { - /** The UUID of the user operation which was returned by the sendUserOperation function */ - id: string; /** The address of the smart wallet */ smartWalletAddress: Address; /** The transaction hash of the user operation */ @@ -72,12 +68,12 @@ export type WaitForUserOperationReturnType = FailedOperation | CompletedOperatio export async function waitForUserOperation( options: WaitForUserOperationOptions, ): Promise { - const { id, smartWalletAddress } = options; + const { userOpHash, smartWalletAddress } = options; const reload = async () => { const response = await Coinbase.apiClients.smartWallet!.getUserOperation( smartWalletAddress, - id, + userOpHash, ); return response.data; }; @@ -85,14 +81,12 @@ export async function waitForUserOperation( const transform = (operation: UserOperation): WaitForUserOperationReturnType => { if (operation.status === UserOperationStatusEnum.Failed) { return { - id: operation.id, smartWalletAddress: smartWalletAddress, status: UserOperationStatusEnum.Failed, userOpHash: operation.user_op_hash as Hex, } satisfies FailedOperation; } else if (operation.status === UserOperationStatusEnum.Complete) { return { - id: operation.id, smartWalletAddress: smartWalletAddress, transactionHash: operation.transaction_hash!, status: UserOperationStatusEnum.Complete, diff --git a/src/client/api.ts b/src/client/api.ts index 55614be9..c5c56209 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -9993,19 +9993,19 @@ export const SmartWalletsApiAxiosParamCreator = function (configuration?: Config * Broadcast a user operation * @summary Broadcast a user operation * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. - * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {string} userOpHash The hash of the user operation to broadcast * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - broadcastUserOperation: async (smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options: RawAxiosRequestConfig = {}): Promise => { + broadcastUserOperation: async (smartWalletAddress: string, userOpHash: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'smartWalletAddress' is not null or undefined assertParamExists('broadcastUserOperation', 'smartWalletAddress', smartWalletAddress) - // verify required parameter 'userOperationId' is not null or undefined - assertParamExists('broadcastUserOperation', 'userOperationId', userOperationId) - const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}/broadcast` + // verify required parameter 'userOpHash' is not null or undefined + assertParamExists('broadcastUserOperation', 'userOpHash', userOpHash) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_op_hash}/broadcast` .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))) - .replace(`{${"user_operation_id"}}`, encodeURIComponent(String(userOperationId))); + .replace(`{${"user_op_hash"}}`, encodeURIComponent(String(userOpHash))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10160,18 +10160,18 @@ export const SmartWalletsApiAxiosParamCreator = function (configuration?: Config * Get user operation * @summary Get user operation * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. - * @param {string} userOperationId The ID of the user operation to fetch. + * @param {string} userOpHash The hash of the user operation to fetch * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getUserOperation: async (smartWalletAddress: string, userOperationId: string, options: RawAxiosRequestConfig = {}): Promise => { + getUserOperation: async (smartWalletAddress: string, userOpHash: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'smartWalletAddress' is not null or undefined assertParamExists('getUserOperation', 'smartWalletAddress', smartWalletAddress) - // verify required parameter 'userOperationId' is not null or undefined - assertParamExists('getUserOperation', 'userOperationId', userOperationId) - const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}` + // verify required parameter 'userOpHash' is not null or undefined + assertParamExists('getUserOperation', 'userOpHash', userOpHash) + const localVarPath = `/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_op_hash}` .replace(`{${"smart_wallet_address"}}`, encodeURIComponent(String(smartWalletAddress))) - .replace(`{${"user_operation_id"}}`, encodeURIComponent(String(userOperationId))); + .replace(`{${"user_op_hash"}}`, encodeURIComponent(String(userOpHash))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -10260,13 +10260,13 @@ export const SmartWalletsApiFp = function(configuration?: Configuration) { * Broadcast a user operation * @summary Broadcast a user operation * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. - * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {string} userOpHash The hash of the user operation to broadcast * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options); + async broadcastUserOperation(smartWalletAddress: string, userOpHash: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.broadcastUserOperation(smartWalletAddress, userOpHash, broadcastUserOperationRequest, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.broadcastUserOperation']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -10316,12 +10316,12 @@ export const SmartWalletsApiFp = function(configuration?: Configuration) { * Get user operation * @summary Get user operation * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. - * @param {string} userOperationId The ID of the user operation to fetch. + * @param {string} userOpHash The hash of the user operation to fetch * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getUserOperation(smartWalletAddress, userOperationId, options); + async getUserOperation(smartWalletAddress: string, userOpHash: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getUserOperation(smartWalletAddress, userOpHash, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['SmartWalletsApi.getUserOperation']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -10354,13 +10354,13 @@ export const SmartWalletsApiFactory = function (configuration?: Configuration, b * Broadcast a user operation * @summary Broadcast a user operation * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. - * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {string} userOpHash The hash of the user operation to broadcast * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options).then((request) => request(axios, basePath)); + broadcastUserOperation(smartWalletAddress: string, userOpHash: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.broadcastUserOperation(smartWalletAddress, userOpHash, broadcastUserOperationRequest, options).then((request) => request(axios, basePath)); }, /** * Create a new smart wallet, not scoped to a given network. @@ -10398,12 +10398,12 @@ export const SmartWalletsApiFactory = function (configuration?: Configuration, b * Get user operation * @summary Get user operation * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. - * @param {string} userOperationId The ID of the user operation to fetch. + * @param {string} userOpHash The hash of the user operation to fetch * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getUserOperation(smartWalletAddress, userOperationId, options).then((request) => request(axios, basePath)); + getUserOperation(smartWalletAddress: string, userOpHash: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getUserOperation(smartWalletAddress, userOpHash, options).then((request) => request(axios, basePath)); }, /** * List smart wallets @@ -10429,13 +10429,13 @@ export interface SmartWalletsApiInterface { * Broadcast a user operation * @summary Broadcast a user operation * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. - * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {string} userOpHash The hash of the user operation to broadcast * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartWalletsApiInterface */ - broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise; + broadcastUserOperation(smartWalletAddress: string, userOpHash: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig): AxiosPromise; /** * Create a new smart wallet, not scoped to a given network. @@ -10473,12 +10473,12 @@ export interface SmartWalletsApiInterface { * Get user operation * @summary Get user operation * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. - * @param {string} userOperationId The ID of the user operation to fetch. + * @param {string} userOpHash The hash of the user operation to fetch * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartWalletsApiInterface */ - getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig): AxiosPromise; + getUserOperation(smartWalletAddress: string, userOpHash: string, options?: RawAxiosRequestConfig): AxiosPromise; /** * List smart wallets @@ -10504,14 +10504,14 @@ export class SmartWalletsApi extends BaseAPI implements SmartWalletsApiInterface * Broadcast a user operation * @summary Broadcast a user operation * @param {string} smartWalletAddress The address of the smart wallet to broadcast the user operation from. - * @param {string} userOperationId The ID of the user operation to broadcast. + * @param {string} userOpHash The hash of the user operation to broadcast * @param {BroadcastUserOperationRequest} [broadcastUserOperationRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartWalletsApi */ - public broadcastUserOperation(smartWalletAddress: string, userOperationId: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig) { - return SmartWalletsApiFp(this.configuration).broadcastUserOperation(smartWalletAddress, userOperationId, broadcastUserOperationRequest, options).then((request) => request(this.axios, this.basePath)); + public broadcastUserOperation(smartWalletAddress: string, userOpHash: string, broadcastUserOperationRequest?: BroadcastUserOperationRequest, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).broadcastUserOperation(smartWalletAddress, userOpHash, broadcastUserOperationRequest, options).then((request) => request(this.axios, this.basePath)); } /** @@ -10556,13 +10556,13 @@ export class SmartWalletsApi extends BaseAPI implements SmartWalletsApiInterface * Get user operation * @summary Get user operation * @param {string} smartWalletAddress The address of the smart wallet the user operation belongs to. - * @param {string} userOperationId The ID of the user operation to fetch. + * @param {string} userOpHash The hash of the user operation to fetch * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartWalletsApi */ - public getUserOperation(smartWalletAddress: string, userOperationId: string, options?: RawAxiosRequestConfig) { - return SmartWalletsApiFp(this.configuration).getUserOperation(smartWalletAddress, userOperationId, options).then((request) => request(this.axios, this.basePath)); + public getUserOperation(smartWalletAddress: string, userOpHash: string, options?: RawAxiosRequestConfig) { + return SmartWalletsApiFp(this.configuration).getUserOperation(smartWalletAddress, userOpHash, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 27134336..72670dc2 100644 --- a/src/coinbase/types.ts +++ b/src/coinbase/types.ts @@ -315,7 +315,7 @@ export type SmartWalletAPIClient = { */ getUserOperation: ( smartWalletAddress: string, - userOperationId: string, + userOpHash: string, options?: RawAxiosRequestConfig, ) => AxiosPromise; }; From 5887f8b714faa76227134c790ec386b048107f34 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Fri, 21 Feb 2025 00:29:59 -0500 Subject: [PATCH 58/59] Fix tests --- src/tests/external_address_test.ts | 9 --------- src/tests/wallet_address_test.ts | 9 --------- src/tests/wallet_test.ts | 9 --------- 3 files changed, 27 deletions(-) diff --git a/src/tests/external_address_test.ts b/src/tests/external_address_test.ts index e84055fb..81e2b4d3 100644 --- a/src/tests/external_address_test.ts +++ b/src/tests/external_address_test.ts @@ -70,15 +70,6 @@ describe("ExternalAddress", () => { contract_address: "0x", }, }, - pending_claimable_balance: { - amount: "1000000000000000000", - asset: { - asset_id: Coinbase.assets.Eth, - network_id: Coinbase.networks.EthereumHolesky, - decimals: 18, - contract_address: "0x", - }, - }, }, }; const STAKING_OPERATION_MODEL: StakingOperationModel = { diff --git a/src/tests/wallet_address_test.ts b/src/tests/wallet_address_test.ts index cf005ca4..20593e62 100644 --- a/src/tests/wallet_address_test.ts +++ b/src/tests/wallet_address_test.ts @@ -406,15 +406,6 @@ describe("WalletAddress", () => { contract_address: "0x", }, }, - pending_claimable_balance: { - amount: "1000000000000000000", - asset: { - asset_id: Coinbase.assets.Eth, - network_id: Coinbase.networks.EthereumHolesky, - decimals: 18, - contract_address: "0x", - }, - }, }, }; diff --git a/src/tests/wallet_test.ts b/src/tests/wallet_test.ts index 04ef7617..cebde65d 100644 --- a/src/tests/wallet_test.ts +++ b/src/tests/wallet_test.ts @@ -186,15 +186,6 @@ describe("Wallet Class", () => { contract_address: "0x", }, }, - pending_claimable_balance: { - amount: "1000000000000000000", - asset: { - asset_id: Coinbase.assets.Eth, - network_id: Coinbase.networks.EthereumHolesky, - decimals: 18, - contract_address: "0x", - }, - }, }, }; From f27914dcfd34e1f803f40d9ab3e8718122e82033 Mon Sep 17 00:00:00 2001 From: Rohan Agarwal Date: Fri, 21 Feb 2025 11:43:25 -0500 Subject: [PATCH 59/59] Flaky tests --- src/tests/e2e.ts | 295 ++++++++++++++++++++++++----------------------- 1 file changed, 149 insertions(+), 146 deletions(-) diff --git a/src/tests/e2e.ts b/src/tests/e2e.ts index 8ac0146d..2bb5b69a 100644 --- a/src/tests/e2e.ts +++ b/src/tests/e2e.ts @@ -39,117 +39,118 @@ describe("Coinbase SDK E2E Test", () => { expect(fs.existsSync("./dist/coinbase/coinbase.js")).toBe(true); }); - it("should be able to interact with the Coinbase SDK", async () => { - console.log("Creating new wallet..."); - const wallet = await Wallet.create(); - - expect(wallet.toString()).toBeDefined(); - expect(wallet?.getId()).toBeDefined(); - console.log( - `Created new wallet with ID: ${wallet.getId()}, default address: ${wallet.getDefaultAddress()}`, - ); - - console.log("Importing wallet with balance..."); - const seedFile = JSON.parse(process.env.WALLET_DATA || ""); - const walletId = Object.keys(seedFile)[0]; - const seed = seedFile[walletId].seed; - - const importedWallet = await Wallet.import({ - seed, - walletId, - networkId: Coinbase.networks.BaseSepolia, - }); - expect(importedWallet).toBeDefined(); - expect(importedWallet.getId()).toBe(walletId); - console.log( - `Imported wallet with ID: ${importedWallet.getId()}, default address: ${importedWallet.getDefaultAddress()}`, - ); - await importedWallet.saveSeedToFile("test_seed.json"); - - try { - const transaction = await importedWallet.faucet(); - expect(transaction.toString()).toBeDefined(); - } catch { - console.log("Faucet request failed. Skipping..."); - } - console.log("Listing wallet addresses..."); - const addresses = await importedWallet.listAddresses(); - expect(addresses.length).toBeGreaterThan(0); - console.log(`Listed addresses: ${addresses.join(", ")}`); - - console.log("Fetching wallet balances..."); - const balances = await importedWallet.listBalances(); - expect(Array.from([...balances.keys()]).length).toBeGreaterThan(0); - console.log(`Fetched balances: ${balances.toString()}`); - - console.log("Exporting wallet..."); - const exportedWallet = await wallet.export(); - expect(exportedWallet.walletId).toBeDefined(); - expect(exportedWallet.seed).toBeDefined(); - - console.log("Saving seed to file..."); - await wallet.saveSeedToFile("test_seed.json"); - expect(fs.existsSync("test_seed.json")).toBe(true); - console.log("Saved seed to test_seed.json"); - - const unhydratedWallet = await Wallet.fetch(walletId); - expect(unhydratedWallet.canSign()).toBe(false); - await unhydratedWallet.loadSeedFromFile("test_seed.json"); - expect(unhydratedWallet.canSign()).toBe(true); - expect(unhydratedWallet.getId()).toBe(walletId); - - console.log("Transfering 0.000000001 ETH from default address to second address..."); - const transfer = await unhydratedWallet.createTransfer({ - amount: 0.000000001, - assetId: Coinbase.assets.Eth, - destination: wallet, - }); - - await transfer.wait(); - - expect(transfer.toString()).toBeDefined(); - expect(await transfer.getStatus()).toBe(TransferStatus.COMPLETE); - console.log(`Transferred 1 Gwei from ${unhydratedWallet} to ${wallet}`); - - console.log("Fetching updated balances..."); - const firstBalance = await unhydratedWallet.listBalances(); - const secondBalance = await wallet.listBalances(); - expect(firstBalance.get(Coinbase.assets.Eth)).not.toEqual("0"); - expect(secondBalance.get(Coinbase.assets.Eth)).not.toEqual("0"); - console.log(`First address balances: ${firstBalance}`); - console.log(`Second address balances: ${secondBalance}`); - - console.log("Fetching address transactions..."); - let result; - for (let i = 0; i < 5; i++) { - // Try up to 5 times - result = await (await unhydratedWallet.getDefaultAddress()).listTransactions({ limit: 1 }); - if (result?.data.length > 0) break; - // Wait 2 seconds between attempts - console.log(`Waiting for transaction to be processed... (${i + 1} attempts)`); - await new Promise(resolve => setTimeout(resolve, 2000)); - } - expect(result?.data.length).toBeGreaterThan(0); - - console.log("Fetching address historical balances..."); - const balance_result = await ( - await unhydratedWallet.getDefaultAddress() - ).listHistoricalBalances(Coinbase.assets.Eth, { limit: 2 }); - expect(balance_result?.data.length).toBeGreaterThan(0); - console.log(`First eth historical balance: ${balance_result?.data[0].amount.toString()}`); - - const savedSeed = JSON.parse(fs.readFileSync("test_seed.json", "utf-8")); - fs.unlinkSync("test_seed.json"); - - expect(exportedWallet.seed.length).toBe(64); - expect(savedSeed[exportedWallet.walletId!]).toEqual({ - seed: exportedWallet.seed, - encrypted: false, - authTag: "", - iv: "", - networkId: exportedWallet.networkId, - }); - }, 60000); + // CDP-266 Flaky test + // it("should be able to interact with the Coinbase SDK", async () => { + // console.log("Creating new wallet..."); + // const wallet = await Wallet.create(); + + // expect(wallet.toString()).toBeDefined(); + // expect(wallet?.getId()).toBeDefined(); + // console.log( + // `Created new wallet with ID: ${wallet.getId()}, default address: ${wallet.getDefaultAddress()}`, + // ); + + // console.log("Importing wallet with balance..."); + // const seedFile = JSON.parse(process.env.WALLET_DATA || ""); + // const walletId = Object.keys(seedFile)[0]; + // const seed = seedFile[walletId].seed; + + // const importedWallet = await Wallet.import({ + // seed, + // walletId, + // networkId: Coinbase.networks.BaseSepolia, + // }); + // expect(importedWallet).toBeDefined(); + // expect(importedWallet.getId()).toBe(walletId); + // console.log( + // `Imported wallet with ID: ${importedWallet.getId()}, default address: ${importedWallet.getDefaultAddress()}`, + // ); + // await importedWallet.saveSeedToFile("test_seed.json"); + + // try { + // const transaction = await importedWallet.faucet(); + // expect(transaction.toString()).toBeDefined(); + // } catch { + // console.log("Faucet request failed. Skipping..."); + // } + // console.log("Listing wallet addresses..."); + // const addresses = await importedWallet.listAddresses(); + // expect(addresses.length).toBeGreaterThan(0); + // console.log(`Listed addresses: ${addresses.join(", ")}`); + + // console.log("Fetching wallet balances..."); + // const balances = await importedWallet.listBalances(); + // expect(Array.from([...balances.keys()]).length).toBeGreaterThan(0); + // console.log(`Fetched balances: ${balances.toString()}`); + + // console.log("Exporting wallet..."); + // const exportedWallet = await wallet.export(); + // expect(exportedWallet.walletId).toBeDefined(); + // expect(exportedWallet.seed).toBeDefined(); + + // console.log("Saving seed to file..."); + // await wallet.saveSeedToFile("test_seed.json"); + // expect(fs.existsSync("test_seed.json")).toBe(true); + // console.log("Saved seed to test_seed.json"); + + // const unhydratedWallet = await Wallet.fetch(walletId); + // expect(unhydratedWallet.canSign()).toBe(false); + // await unhydratedWallet.loadSeedFromFile("test_seed.json"); + // expect(unhydratedWallet.canSign()).toBe(true); + // expect(unhydratedWallet.getId()).toBe(walletId); + + // console.log("Transfering 0.000000001 ETH from default address to second address..."); + // const transfer = await unhydratedWallet.createTransfer({ + // amount: 0.000000001, + // assetId: Coinbase.assets.Eth, + // destination: wallet, + // }); + + // await transfer.wait(); + + // expect(transfer.toString()).toBeDefined(); + // expect(await transfer.getStatus()).toBe(TransferStatus.COMPLETE); + // console.log(`Transferred 1 Gwei from ${unhydratedWallet} to ${wallet}`); + + // console.log("Fetching updated balances..."); + // const firstBalance = await unhydratedWallet.listBalances(); + // const secondBalance = await wallet.listBalances(); + // expect(firstBalance.get(Coinbase.assets.Eth)).not.toEqual("0"); + // expect(secondBalance.get(Coinbase.assets.Eth)).not.toEqual("0"); + // console.log(`First address balances: ${firstBalance}`); + // console.log(`Second address balances: ${secondBalance}`); + + // console.log("Fetching address transactions..."); + // let result; + // for (let i = 0; i < 5; i++) { + // // Try up to 5 times + // result = await (await unhydratedWallet.getDefaultAddress()).listTransactions({ limit: 1 }); + // if (result?.data.length > 0) break; + // // Wait 2 seconds between attempts + // console.log(`Waiting for transaction to be processed... (${i + 1} attempts)`); + // await new Promise(resolve => setTimeout(resolve, 2000)); + // } + // expect(result?.data.length).toBeGreaterThan(0); + + // console.log("Fetching address historical balances..."); + // const balance_result = await ( + // await unhydratedWallet.getDefaultAddress() + // ).listHistoricalBalances(Coinbase.assets.Eth, { limit: 2 }); + // expect(balance_result?.data.length).toBeGreaterThan(0); + // console.log(`First eth historical balance: ${balance_result?.data[0].amount.toString()}`); + + // const savedSeed = JSON.parse(fs.readFileSync("test_seed.json", "utf-8")); + // fs.unlinkSync("test_seed.json"); + + // expect(exportedWallet.seed.length).toBe(64); + // expect(savedSeed[exportedWallet.walletId!]).toEqual({ + // seed: exportedWallet.seed, + // encrypted: false, + // authTag: "", + // iv: "", + // networkId: exportedWallet.networkId, + // }); + // }, 60000); it("Should be able to invoke a contract and retrieve the transaction receipt", async () => { const seedFile = JSON.parse(process.env.WALLET_DATA || ""); @@ -328,33 +329,34 @@ describe("Coinbase SDK Stake E2E Test", () => { }); }); - describe("Stake: Validator Tests", () => { - it("should list validators", async () => { - const networkId = Coinbase.networks.EthereumMainnet; - const assetId = Coinbase.assets.Eth; - const status = ValidatorStatus.ACTIVE; + // CDP-266 Flaky tests + // describe("Stake: Validator Tests", () => { + // it("should list validators", async () => { + // const networkId = Coinbase.networks.EthereumMainnet; + // const assetId = Coinbase.assets.Eth; + // const status = ValidatorStatus.ACTIVE; - const validators = await Validator.list(networkId, assetId, status); + // const validators = await Validator.list(networkId, assetId, status); - expect(validators).toBeDefined(); - expect(validators.length).toEqual(1); - const validator = validators[0]; - expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE); - expect(validator.getValidatorId()).toEqual(process.env.STAKE_VALIDATOR_ADDRESS_1 as string); - }); + // expect(validators).toBeDefined(); + // expect(validators.length).toEqual(1); + // const validator = validators[0]; + // expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE); + // expect(validator.getValidatorId()).toEqual(process.env.STAKE_VALIDATOR_ADDRESS_1 as string); + // }); - it("should fetch a validator", async () => { - const networkId = Coinbase.networks.EthereumMainnet; - const assetId = Coinbase.assets.Eth; - const validatorId = process.env.STAKE_VALIDATOR_ADDRESS_1 as string; + // it("should fetch a validator", async () => { + // const networkId = Coinbase.networks.EthereumMainnet; + // const assetId = Coinbase.assets.Eth; + // const validatorId = process.env.STAKE_VALIDATOR_ADDRESS_1 as string; - const validator = await Validator.fetch(networkId, assetId, validatorId); + // const validator = await Validator.fetch(networkId, assetId, validatorId); - expect(validator).toBeDefined(); - expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE); - expect(validator.getValidatorId()).toEqual(validatorId); - }); - }); + // expect(validator).toBeDefined(); + // expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE); + // expect(validator.getValidatorId()).toEqual(validatorId); + // }); + // }); describe("Stake: Context Tests", () => { it("should return stakeable balances for shared ETH staking", async () => { @@ -402,22 +404,23 @@ describe("Coinbase SDK Stake E2E Test", () => { expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(0); }); - it("should return unstakeable balances for Dedicated ETH staking", async () => { - // This address is expected to have 1 validator associated with it, thus returning a 32 unstake balance. + // CDP-266 Flaky test + // it("should return unstakeable balances for Dedicated ETH staking", async () => { + // // This address is expected to have 1 validator associated with it, thus returning a 32 unstake balance. - const address = new ExternalAddress( - Coinbase.networks.EthereumMainnet, - process.env.STAKE_ADDRESS_ID_2 as string, - ); + // const address = new ExternalAddress( + // Coinbase.networks.EthereumMainnet, + // process.env.STAKE_ADDRESS_ID_2 as string, + // ); - const stakeableBalance = await address.unstakeableBalance( - Coinbase.assets.Eth, - StakeOptionsMode.NATIVE, - ); + // const stakeableBalance = await address.unstakeableBalance( + // Coinbase.assets.Eth, + // StakeOptionsMode.NATIVE, + // ); - expect(stakeableBalance).toBeDefined(); - expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(32); - }); + // expect(stakeableBalance).toBeDefined(); + // expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(32); + // }); }); describe("Stake: Build Tests", () => {