diff --git a/.gitignore b/.gitignore index bea3c097..08803af8 100644 --- a/.gitignore +++ b/.gitignore @@ -132,7 +132,6 @@ dist .yarn/install-state.gz .pnp.* .DS_Store -**/*_local* .idea 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/accounts/to_local_account.ts b/src/coinbase/accounts/to_local_account.ts new file mode 100644 index 00000000..a335d2ef --- /dev/null +++ b/src/coinbase/accounts/to_local_account.ts @@ -0,0 +1,83 @@ +import { hashTypedData, keccak256, serializeTransaction } from "viem"; +import { toAccount } from "viem/accounts"; +import type { + HashTypedDataParameters, + Hex, LocalAccount, + SerializeTransactionFn, + SignableMessage, + TransactionSerializable, + TypedData +} from "viem"; +import { WalletAddress } from "../address/wallet_address"; +import { hashMessage } from "viem"; + +export function toLocalAccount(address: WalletAddress): LocalAccount { + return toAccount({ + address: address.getId() as `0x${string}`, + signMessage: function ({ + message, + }: { + message: SignableMessage; + }): Promise { + return signMessage(address, message); + }, + signTransaction: function < + TTransactionSerializable extends TransactionSerializable, + >( + transaction: TTransactionSerializable, + args?: + | { serializer?: SerializeTransactionFn } + | undefined, + ): Promise { + const serializer = !args?.serializer + ? serializeTransaction + : args.serializer; + + return signTransaction( + address, + transaction, + serializer, + ); + }, + signTypedData: function ( + typedData: TypedData | { [key: string]: unknown }, + ): Promise { + return signTypedData(address, typedData); + }, + }); + + +} + +export async function signMessage( + address: WalletAddress, + message: SignableMessage +): Promise { + const hashedMessage = hashMessage(message); + const payloadSignature = await address.createPayloadSignature( + hashedMessage + ); + return `${payloadSignature.getSignature()}` as Hex; +} + +export async function signTransaction< + TTransactionSerializable extends TransactionSerializable, +>( + address: WalletAddress, + transaction: TTransactionSerializable, + serializer: SerializeTransactionFn, +): Promise { + const serializedTx = serializer(transaction); + const transactionHash = keccak256(serializedTx); + const payload = await address.createPayloadSignature(transactionHash); + return `${payload}` as Hex; +} + +export async function signTypedData( + address: WalletAddress, + data: TypedData | { [key: string]: unknown }, +): Promise { + const hashToSign = hashTypedData(data as HashTypedDataParameters); + const payloadSignature = await address.createPayloadSignature(hashToSign); + return `${payloadSignature.getSignature()}` as Hex; +} 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); diff --git a/src/coinbase/smart_wallet.ts b/src/coinbase/smart_wallet.ts new file mode 100644 index 00000000..b5aa4a33 --- /dev/null +++ b/src/coinbase/smart_wallet.ts @@ -0,0 +1,110 @@ +import { NetworkIdentifier, SmartWallet as SmartWalletModel } from "../client"; + +import { Coinbase } from "./coinbase"; + +import type { Hex } from 'viem'; +import type { + UserOperationCalls +} from 'viem/account-abstraction'; + +import { encodeFunctionData, LocalAccount } from "viem"; +import { UserOperation } from "./user_operation"; + +export class SmartWallet { + private model: SmartWalletModel; + private account: LocalAccount; + private networkId?: NetworkIdentifier; + + public constructor(model: SmartWalletModel, account: LocalAccount) { + this.model = model; + this.account = account; + } + + public static async create({account}: {account: LocalAccount}): Promise { + const result = await Coinbase.apiClients.smartWallet!.createSmartWallet({ + owner: account.address, + }); + + const smartWallet = new SmartWallet(result.data!, account); + return smartWallet; + } + + public static async connect({smartWalletAddress, account}: {smartWalletAddress: string, account: LocalAccount}): Promise { + const result = await Coinbase.apiClients.smartWallet!.getSmartWallet(smartWalletAddress); + + if (!result.data?.owners.some(owner => owner.toLowerCase() === account.address.toLowerCase())) { + throw new Error('Account is not an owner of the smart wallet'); + } + + const smartWallet = new SmartWallet(result.data!, account); + return smartWallet; + } + + public async use({networkId}: {networkId: NetworkIdentifier}) { + this.networkId = networkId; + } + + public getAddress() { + return this.model.address; + } + + public async sendUserOperation( + params: { calls: UserOperationCalls } + ): Promise { + if (!this.networkId) { + throw new Error('Network not set - call use({networkId}) first'); + } + + const encodedCalls = params.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( + this.getAddress(), + this.networkId, + { + calls: encodedCalls + } + ) + + if (!createOpResponse.data) { + throw new Error('Failed to create user operation') + } + + if (!this.account.sign) { + throw new Error('Account does not support signing') + } + + const signature = await this.account.sign({ hash: createOpResponse.data.unsigned_payload as `0x${string}` }) + + const broadcastResponse = await Coinbase.apiClients.smartWallet!.broadcastUserOperation( + this.getAddress(), + createOpResponse.data.id, + { + signature, + } + ) + + if (!broadcastResponse.data) { + throw new Error('Failed to broadcast user operation') + } + + return new UserOperation(broadcastResponse.data, this.getAddress()); + } + +} diff --git a/src/coinbase/types.ts b/src/coinbase/types.ts index 8aef4db2..89d8c45c 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; }; /** diff --git a/src/coinbase/user_operation.ts b/src/coinbase/user_operation.ts new file mode 100644 index 00000000..d6c44570 --- /dev/null +++ b/src/coinbase/user_operation.ts @@ -0,0 +1,124 @@ +import { Coinbase } from "./coinbase"; +import { UserOperation as UserOperationModel, UserOperationStatusEnum } from "../client/api"; +import { delay } from "./utils"; +import { TimeoutError } from "./errors"; + +/** + * A representation of a UserOperation, which calls a smart contract method + * onchain. + */ +export class UserOperation { + private model: UserOperationModel; + private smartWalletAddress: string; + /** + * Private constructor to prevent direct instantiation outside of the factory methods. + * + * @ignore + * @param userOperationModel - The UserOperation model. + * @hideconstructor + */ + public constructor(userOperationModel: UserOperationModel, smartWalletAddress: string) { + this.model = userOperationModel; + this.smartWalletAddress = smartWalletAddress; + } + + /** + * Returns the ID of the UserOperation. + * + * @returns The UserOperation ID. + */ + public getId(): string { + return this.model.id; + } + + /** + * Returns the Network ID of the UserOperation. + * + * @returns The Network ID. + */ + public getNetworkId(): string { + return this.model.network_id; + } + + public getSmartWalletAddress(): string { + return this.smartWalletAddress; + } + + + /** + * TODO + * + * Returns the Transaction Hash of the ContractInvocation. + * + * @returns The Transaction Hash as a Hex string, or undefined if not yet available. + */ + // public getTransactionHash(): string | undefined { + // return this.getTransaction().getTransactionHash(); + // } + + /** + * Returns the Status of the ContractInvocation. + * + * @returns The Status of the ContractInvocation. + */ + public getStatus(): UserOperationStatusEnum | undefined { + return this.model.status; + } + + /** + * TODO + * + * Returns the link to the Transaction on the blockchain explorer. + * + * @returns The link to the Transaction on the blockchain explorer. + */ + // public getTransactionLink(): string { + // return this.getTransaction().getTransactionLink(); + // } + + /** + * Waits for the ContractInvocation to be confirmed on the Network or fail on chain. + * Waits until the ContractInvocation is completed or failed on-chain by polling at the given interval. + * Raises an error if the ContractInvocation takes longer than the given timeout. + * + * @param options - The options to configure the wait function. + * @param options.intervalSeconds - The interval to check the status of the ContractInvocation. + * @param options.timeoutSeconds - The maximum time to wait for the ContractInvocation to be confirmed. + * + * @returns The ContractInvocation object in a terminal state. + * @throws {Error} if the ContractInvocation times out. + */ + public async wait({ + intervalSeconds = 0.2, + timeoutSeconds = 10, + } = {}): Promise { + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutSeconds * 1000) { + await this.reload(); + + // If the UserOperation is in a terminal state, return the UserOperation. + const status = this.getStatus(); + if (status === UserOperationStatusEnum.Complete || status === UserOperationStatusEnum.Failed) { + return this; + } + + await delay(intervalSeconds); + } + + throw new TimeoutError("UserOperation timed out"); + } + + /** + * Reloads the ContractInvocation model with the latest data from the server. + * + * @throws {APIError} if the API request to get a ContractInvocation fails. + */ + public async reload(): Promise { + const result = await Coinbase.apiClients.smartWallet!.getUserOperation( + this.getSmartWalletAddress(), + this.getId(), + ); + this.model = result?.data; + } +} diff --git a/src/index.ts b/src/index.ts index d5412e89..2ec7f652 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,3 +32,8 @@ export * from "./coinbase/crypto_amount"; export * from "./coinbase/fiat_amount"; export * from "./coinbase/fund_operation"; export * from "./coinbase/fund_quote"; +export * from "./coinbase/smart_wallet"; +export * from "./coinbase/user_operation"; +export { + toLocalAccount, +} from './coinbase/accounts/to_local_account' \ No newline at end of file diff --git a/test_smart_wallet.ts b/test_smart_wallet.ts new file mode 100644 index 00000000..0c8488ae --- /dev/null +++ b/test_smart_wallet.ts @@ -0,0 +1,71 @@ +import { createWalletClient, http, parseEther } from 'viem' +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts' +import { SmartWallet } from './src/coinbase/smart_wallet' +import { Coinbase, Wallet } from './src' +import { mainnet } from 'viem/chains'; + +Coinbase.configureFromJson({ + filePath: "~/.apikeys/dev.json", + debugging: true, + basePath: "http://localhost:8002" +}); + +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 SmartWallet.create({account: owner}) + + // const client = createWalletClient({ + // chain: mainnet + // transport: http() + // }) + // client.getAddresses() + + // 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.getAddress(), + }) + await transfer.wait() + + 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(); diff --git a/test_viem_account.ts b/test_viem_account.ts new file mode 100644 index 00000000..c25a2876 --- /dev/null +++ b/test_viem_account.ts @@ -0,0 +1,93 @@ +import { createWalletClient, http, parseEther } from 'viem'; +import { Coinbase, hashMessage, hashTypedDataMessage, PayloadSignature, toLocalAccount, Wallet } from './src'; +import { mainnet } from 'viem/chains'; + +Coinbase.configureFromJson({ + filePath: "~/.apikeys/prod.json", +}); + +const myAbi = [ + { + inputs: [ + { + name: "amount", + type: "uint256", + }, + ], + name: "transfer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + } +] as const; + +async function main() { + const wallet = await Wallet.create(); + const walletAddress = await wallet.getDefaultAddress(); + + const localAccount = toLocalAccount(walletAddress); + const msg = "Hey Team" + const signature = await localAccount.signMessage({message: msg}); + console.log(signature); + + const walletClient = await createWalletClient({ + account: localAccount, + chain: mainnet, + transport: http(), + }); + + walletClient.writeContract({ + address: walletAddress.getId() as `0x${string}`, + abi: myAbi, + functionName: "transfer", + args: [123n] + }) + + + + // sign with normal wallet address way + const hashedMsg = hashMessage(msg); + // sign with normal wallet address way + const hashedMsg = hashMessage(msg); + const signature2 = await walletAddress.createPayloadSignature(hashedMsg); + console.log(signature2.getSignature()); + + const domain = { + name: "MyDapp", + version: "1", + chainId: 1, + verifyingContract: walletAddress.getId() as `0x${string}`, + } as const; + + const types = { + MyType: [ + { name: "sender", type: "address" }, + { name: "amount", type: "uint256" }, + ], + }; + + const typedDataMessage = { + sender: walletAddress.getId(), + amount: 1000, + }; + + const signatureTypedData = await localAccount.signTypedData({ + domain, + types, + primaryType: "MyType", + message: typedDataMessage, + }); + console.log(signatureTypedData); + + const hashedTypedData = hashTypedDataMessage( + domain, + types, + typedDataMessage, + ); + + let payloadSignature: PayloadSignature = await walletAddress.createPayloadSignature(hashedTypedData); + payloadSignature = await payloadSignature.wait(); + console.log(payloadSignature.getSignature()); +} + +main();