UNPKG

@thirdweb-dev/wallets

Version:

<p align="center"> <br /> <a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/packages/sdk/logo.svg?raw=true" width="200" alt=""/></a> <br /> </p> <h1 align="center">thirdweb Wallet SDK</h1> <p align="center"> <a href="ht

1,430 lines (1,404 loc) • 82.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var chains = require('@thirdweb-dev/chains'); var connector = require('../../../../dist/connector-a63dd9e7.cjs.dev.js'); var sdk = require('@account-abstraction/sdk'); var ethers = require('ethers'); var url = require('../../../../dist/url-f53b640f.cjs.dev.js'); var contracts = require('@account-abstraction/contracts'); var defineProperty = require('../../../../dist/defineProperty-21d22449.cjs.dev.js'); var utils = require('@account-abstraction/utils'); var sdk$1 = require('@thirdweb-dev/sdk'); require('eventemitter3'); function toJSON(op) { return ethers.ethers.utils.resolveProperties(op).then(userOp => Object.keys(userOp).map(key => { let val = userOp[key]; if (typeof val !== "string" || !val.startsWith("0x")) { val = ethers.ethers.utils.hexValue(val); } return [key, val]; }).reduce((set, _ref) => { let [k, v] = _ref; return { ...set, [k]: v }; }, {})); } // v0.6 userOpHash calculation async function getUserOpHashV06(userOp, entryPoint, chainId) { const op = await ethers.utils.resolveProperties(userOp); const hashedUserOp = { sender: op.sender, nonce: op.nonce, initCodeHash: ethers.utils.keccak256(op.initCode), callDataHash: ethers.utils.keccak256(op.callData), callGasLimit: op.callGasLimit, verificationGasLimit: op.verificationGasLimit, preVerificationGas: op.preVerificationGas, maxFeePerGas: op.maxFeePerGas, maxPriorityFeePerGas: op.maxPriorityFeePerGas, paymasterAndDataHash: ethers.utils.keccak256(op.paymasterAndData) }; const userOpType = { components: [{ type: "address", name: "sender" }, { type: "uint256", name: "nonce" }, { type: "bytes32", name: "initCodeHash" }, { type: "bytes32", name: "callDataHash" }, { type: "uint256", name: "callGasLimit" }, { type: "uint256", name: "verificationGasLimit" }, { type: "uint256", name: "preVerificationGas" }, { type: "uint256", name: "maxFeePerGas" }, { type: "uint256", name: "maxPriorityFeePerGas" }, { type: "bytes32", name: "paymasterAndDataHash" }], name: "hashedUserOp", type: "tuple" }; const encoded = ethers.utils.defaultAbiCoder.encode([userOpType], [{ ...hashedUserOp }]); // remove leading word (total length) and trailing word (zero-length signature) const userOpHash = ethers.utils.keccak256(encoded); const enc = ethers.utils.defaultAbiCoder.encode(["bytes32", "address", "uint256"], [userOpHash, entryPoint, chainId]); return ethers.utils.keccak256(enc); } const SIG_SIZE = 65; const DUMMY_PAYMASTER_AND_DATA = "0x0101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000001010101010100000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; class VerifyingPaymasterAPI extends sdk.PaymasterAPI { constructor(paymasterUrl, entryPoint, clientId, secretKey) { super(); this.paymasterUrl = paymasterUrl; this.entryPoint = entryPoint; this.clientId = clientId; this.secretKey = secretKey; } async getPaymasterAndData(userOp) { const headers = { "Content-Type": "application/json" }; if (url.isTwUrl(this.paymasterUrl)) { if (this.secretKey && this.clientId) { throw new Error("Cannot use both secret key and client ID. Please use secretKey for server-side applications and clientId for client-side applications."); } if (this.secretKey) { headers["x-secret-key"] = this.secretKey; } else if (this.clientId) { headers["x-client-id"] = this.clientId; if (typeof globalThis !== "undefined" && "APP_BUNDLE_ID" in globalThis) { headers["x-bundle-id"] = globalThis.APP_BUNDLE_ID; } } // Dashboard token. if (typeof globalThis !== "undefined" && "TW_AUTH_TOKEN" in globalThis && typeof globalThis.TW_AUTH_TOKEN === "string") { headers["authorization"] = `Bearer ${globalThis.TW_AUTH_TOKEN}`; } // CLI token. if (typeof globalThis !== "undefined" && "TW_CLI_AUTH_TOKEN" in globalThis && typeof globalThis.TW_CLI_AUTH_TOKEN === "string") { headers["authorization"] = `Bearer ${globalThis.TW_CLI_AUTH_TOKEN}`; headers["x-authorize-wallet"] = "true"; } } // Ask the paymaster to sign the transaction and return a valid paymasterAndData value. const response = await fetch(this.paymasterUrl, { method: "POST", headers, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "pm_sponsorUserOperation", params: [await toJSON(userOp), { entryPoint: this.entryPoint }] }) }); const res = await response.json(); if (!response.ok) { const error = res.error || response.statusText; const code = res.code || "UNKNOWN"; throw new Error(`Paymaster error: ${error} Status: ${response.status} Code: ${code}`); } if (res.result) { const result = res.result.paymasterAndData || res.result; return result.toString(); } else { throw new Error(`Paymaster returned no result from ${this.paymasterUrl}`); } } } const getVerifyingPaymaster = (paymasterUrl, entryPoint, clientId, secretKey) => new VerifyingPaymasterAPI(paymasterUrl, entryPoint, clientId, secretKey); /** * This class encapsulates Ethers.js listener function and necessary UserOperation details to * discover a TransactionReceipt for the operation. * * TODO refactor this to a simple event listener on the entry point */ class UserOperationEventListener { constructor(resolve, reject, entryPoint, sender, userOpHash, nonce, timeout) { this.resolve = resolve; this.reject = reject; this.entryPoint = entryPoint; this.sender = sender; this.userOpHash = userOpHash; this.nonce = nonce; this.timeout = timeout; defineProperty._defineProperty(this, "resolved", false); // eslint-disable-next-line @typescript-eslint/no-misused-promises this.boundLisener = this.listenerCallback.bind(this); } start() { // eslint-disable-next-line @typescript-eslint/no-misused-promises const filter = this.entryPoint.filters.UserOperationEvent(this.userOpHash); // listener takes time... first query directly: // eslint-disable-next-line @typescript-eslint/no-misused-promises setTimeout(async () => { const res = await this.entryPoint.queryFilter(filter, "latest"); if (res.length > 0) { void this.listenerCallback(res[0]); } else { this.entryPoint.once(filter, this.boundLisener); } }, 100); } stop() { // eslint-disable-next-line @typescript-eslint/no-misused-promises this.entryPoint.off("UserOperationEvent", this.boundLisener); } // eslint-disable-next-line @typescript-eslint/no-unused-vars async listenerCallback() { for (var _len = arguments.length, param = new Array(_len), _key = 0; _key < _len; _key++) { param[_key] = arguments[_key]; } // TODO clean this up.. // eslint-disable-next-line prefer-rest-params const event = arguments[arguments.length - 1]; if (!event.args) { console.error("got event without args", event); return; } // TODO: can this happen? we register to event by userOpHash.. if (event.args.userOpHash !== this.userOpHash) { console.log(`== event with wrong userOpHash: sender/nonce: event.${event.args.sender}@${event.args.nonce.toString()}!= userOp.${this.sender}@${parseInt(this.nonce?.toString())}`); return; } const transactionReceipt = await event.getTransactionReceipt(); // before returning the receipt, update the status from the event. // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!event.args.success) { await this.extractFailureReason(transactionReceipt); } this.stop(); this.resolve(transactionReceipt); this.resolved = true; } async extractFailureReason(receipt) { receipt.status = 0; const revertReasonEvents = await this.entryPoint.queryFilter(this.entryPoint.filters.UserOperationRevertReason(this.userOpHash, this.sender), receipt.blockHash); if (revertReasonEvents[0]) { let message = revertReasonEvents[0].args.revertReason; if (message.startsWith("0x08c379a0")) { // Error(string) message = ethers.utils.defaultAbiCoder.decode(["string"], "0x" + message.substring(10)).toString(); } this.reject(new Error(`UserOp failed with reason: ${message}`)); } } } class ERC4337EthersSigner extends ethers.Signer { // TODO: we have 'erc4337provider', remove shared dependencies or avoid two-way reference constructor(config, originalSigner, erc4337provider, httpRpcClient, smartAccountAPI) { super(); ethers.utils.defineReadOnly(this, "provider", erc4337provider); this.config = config; this.originalSigner = originalSigner; this.erc4337provider = erc4337provider; this.httpRpcClient = httpRpcClient; this.smartAccountAPI = smartAccountAPI; } // This one is called by Contract. It signs the request and passes in to Provider to be sent. async sendTransaction(transaction) { let batched = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; const tx = await ethers.ethers.utils.resolveProperties(transaction); await this.verifyAllNecessaryFields(tx); const userOperation = await this.smartAccountAPI.createSignedUserOp({ target: tx.to || "", data: tx.data?.toString() || "0x", value: tx.value, gasLimit: tx.gasLimit }, batched); const transactionResponse = await this.erc4337provider.constructUserOpTransactionResponse(userOperation); try { await this.httpRpcClient.sendUserOpToBundler(userOperation); } catch (error) { throw this.unwrapError(error); } // TODO: handle errors - transaction that is "rejected" by bundler is _not likely_ to ever resolve its "wait()" return transactionResponse; } unwrapError(errorIn) { try { let errorMsg = "Unknown Error"; if (errorIn.error) { errorMsg = `The bundler has failed to include UserOperation in a batch: ${errorIn.error}`; } else if (errorIn.body && typeof errorIn.body === "string") { const errorBody = JSON.parse(errorIn.body); const errorStatus = errorIn.status || "UNKNOWN"; const errorCode = errorBody?.code || "UNKNOWN"; let failedOpMessage = errorBody?.error?.message || errorBody?.error?.data || errorBody?.error || errorIn.reason; if (failedOpMessage?.includes("FailedOp")) { let paymasterInfo = ""; // TODO: better error extraction methods will be needed const matched = failedOpMessage.match(/FailedOp\((.*)\)/); if (matched) { const split = matched[1].split(","); paymasterInfo = `(paymaster address: ${split[1]})`; failedOpMessage = split[2]; } errorMsg = `The bundler has failed to include UserOperation in a batch: ${failedOpMessage} ${paymasterInfo}`; } else { errorMsg = `RPC error: ${failedOpMessage} Status: ${errorStatus} Code: ${errorCode}`; } } const error = new Error(errorMsg); error.stack = errorIn.stack; return error; } catch (error) {} return errorIn; } async verifyAllNecessaryFields(transactionRequest) { if (!transactionRequest.to) { throw new Error("Missing call target"); } if (!transactionRequest.data && !transactionRequest.value) { // TBD: banning no-op UserOps seems to make sense on provider level throw new Error("Missing call data or value"); } } // eslint-disable-next-line @typescript-eslint/no-unused-vars connect(provider) { throw new Error("changing providers is not supported"); } async getAddress() { if (!this.address) { this.address = await this.erc4337provider.getSenderAccountAddress(); } return this.address; } async signMessage(message) { const isNotDeployed = await this.smartAccountAPI.checkAccountPhantom(); if (isNotDeployed) { console.log("Account contract not deployed yet. Deploying account before signing message"); const tx = await this.sendTransaction({ to: await this.getAddress(), data: "0x" }); await tx.wait(); } return await this.originalSigner.signMessage(message); } async signTransaction( // eslint-disable-next-line @typescript-eslint/no-unused-vars transaction) { throw new Error("not implemented"); } } class ERC4337EthersProvider extends ethers.providers.BaseProvider { constructor(chainId, config, originalSigner, originalProvider, httpRpcClient, entryPoint, smartAccountAPI) { super({ name: "ERC-4337 Custom Network", chainId }); this.chainId = chainId; this.config = config; this.originalSigner = originalSigner; this.originalProvider = originalProvider; this.httpRpcClient = httpRpcClient; this.entryPoint = entryPoint; this.smartAccountAPI = smartAccountAPI; this.signer = new ERC4337EthersSigner(config, originalSigner, this, httpRpcClient, smartAccountAPI); } /** * finish intializing the provider. * MUST be called after construction, before using the provider. */ async init() { // await this.httpRpcClient.validateChainId() this.initializedBlockNumber = await this.originalProvider.getBlockNumber(); await this.smartAccountAPI.init(); // await this.signer.init() return this; } getSigner() { return this.signer; } async perform(method, params) { if (method === "sendTransaction" || method === "getTransactionReceipt") { // TODO: do we need 'perform' method to be available at all? // there is nobody out there to use it for ERC-4337 methods yet, we have nothing to override in fact. throw new Error("Should not get here. Investigate."); } if (method === "estimateGas") { // hijack this to estimate gas from the entrypoint instead const { callGasLimit } = await this.smartAccountAPI.encodeUserOpCallDataAndGasLimit({ target: params.transaction.to, data: params.transaction.data, value: params.transaction.value, gasLimit: params.transaction.gasLimit }, false // TODO check this ); return callGasLimit; } return await this.originalProvider.perform(method, params); } async getTransaction(transactionHash) { // TODO return await super.getTransaction(transactionHash); } async getTransactionReceipt(transactionHash) { const userOpHash = await transactionHash; const sender = await this.getSenderAccountAddress(); return await new Promise((resolve, reject) => { new UserOperationEventListener(resolve, reject, this.entryPoint, sender, userOpHash).start(); }); } async getSenderAccountAddress() { return await this.smartAccountAPI.getAccountAddress(); } async waitForTransaction(transactionHash, confirmations, timeout) { const sender = await this.getSenderAccountAddress(); return await new Promise((resolve, reject) => { const listener = new UserOperationEventListener(resolve, reject, this.entryPoint, sender, transactionHash, undefined, timeout); listener.start(); }); } // fabricate a response in a format usable by ethers users... async constructUserOpTransactionResponse(userOp1) { const userOp = await ethers.utils.resolveProperties(userOp1); const userOpHash = await this.smartAccountAPI.getUserOpHash(userOp); const waitForUserOp = async () => await new Promise((resolve, reject) => { new UserOperationEventListener(resolve, reject, this.entryPoint, userOp.sender, userOpHash, userOp.nonce).start(); }); return { hash: userOpHash, confirmations: 0, from: userOp.sender, nonce: ethers.BigNumber.from(userOp.nonce).toNumber(), gasLimit: ethers.BigNumber.from(userOp.callGasLimit), // ?? value: ethers.BigNumber.from(0), data: ethers.utils.hexValue(userOp.callData), // should extract the actual called method from this "execFromEntryPoint()" call chainId: this.chainId, wait: async confirmations => { const transactionReceipt = await waitForUserOp(); if (userOp.initCode.length !== 0) { // checking if the wallet has been deployed by the transaction; it must be if we are here await this.smartAccountAPI.checkAccountPhantom(); } return transactionReceipt; } }; } async detectNetwork() { return this.originalProvider.detectNetwork(); } } var pkg = { name: "@thirdweb-dev/wallets", version: "2.0.7", main: "dist/thirdweb-dev-wallets.cjs.js", module: "dist/thirdweb-dev-wallets.esm.js", types: "dist/thirdweb-dev-wallets.cjs.d.ts", browser: { "./dist/thirdweb-dev-wallets.esm.js": "./dist/thirdweb-dev-wallets.browser.esm.js" }, exports: { ".": { module: { browser: "./dist/thirdweb-dev-wallets.browser.esm.js", "default": "./dist/thirdweb-dev-wallets.esm.js" }, "default": "./dist/thirdweb-dev-wallets.cjs.js" }, "./evm": { module: { browser: "./evm/dist/thirdweb-dev-wallets-evm.browser.esm.js", "default": "./evm/dist/thirdweb-dev-wallets-evm.esm.js" }, "default": "./evm/dist/thirdweb-dev-wallets-evm.cjs.js" }, "./evm/wallets/base": { module: { browser: "./evm/wallets/base/dist/thirdweb-dev-wallets-evm-wallets-base.browser.esm.js", "default": "./evm/wallets/base/dist/thirdweb-dev-wallets-evm-wallets-base.esm.js" }, "default": "./evm/wallets/base/dist/thirdweb-dev-wallets-evm-wallets-base.cjs.js" }, "./evm/wallets/safe": { module: { browser: "./evm/wallets/safe/dist/thirdweb-dev-wallets-evm-wallets-safe.browser.esm.js", "default": "./evm/wallets/safe/dist/thirdweb-dev-wallets-evm-wallets-safe.esm.js" }, "default": "./evm/wallets/safe/dist/thirdweb-dev-wallets-evm-wallets-safe.cjs.js" }, "./evm/wallets/frame": { module: { browser: "./evm/wallets/frame/dist/thirdweb-dev-wallets-evm-wallets-frame.browser.esm.js", "default": "./evm/wallets/frame/dist/thirdweb-dev-wallets-evm-wallets-frame.esm.js" }, "default": "./evm/wallets/frame/dist/thirdweb-dev-wallets-evm-wallets-frame.cjs.js" }, "./evm/wallets/magic": { module: { browser: "./evm/wallets/magic/dist/thirdweb-dev-wallets-evm-wallets-magic.browser.esm.js", "default": "./evm/wallets/magic/dist/thirdweb-dev-wallets-evm-wallets-magic.esm.js" }, "default": "./evm/wallets/magic/dist/thirdweb-dev-wallets-evm-wallets-magic.cjs.js" }, "./evm/wallets/trust": { module: { browser: "./evm/wallets/trust/dist/thirdweb-dev-wallets-evm-wallets-trust.browser.esm.js", "default": "./evm/wallets/trust/dist/thirdweb-dev-wallets-evm-wallets-trust.esm.js" }, "default": "./evm/wallets/trust/dist/thirdweb-dev-wallets-evm-wallets-trust.cjs.js" }, "./evm/wallets/blocto": { module: { browser: "./evm/wallets/blocto/dist/thirdweb-dev-wallets-evm-wallets-blocto.browser.esm.js", "default": "./evm/wallets/blocto/dist/thirdweb-dev-wallets-evm-wallets-blocto.esm.js" }, "default": "./evm/wallets/blocto/dist/thirdweb-dev-wallets-evm-wallets-blocto.cjs.js" }, "./evm/wallets/ethers": { module: { browser: "./evm/wallets/ethers/dist/thirdweb-dev-wallets-evm-wallets-ethers.browser.esm.js", "default": "./evm/wallets/ethers/dist/thirdweb-dev-wallets-evm-wallets-ethers.esm.js" }, "default": "./evm/wallets/ethers/dist/thirdweb-dev-wallets-evm-wallets-ethers.cjs.js" }, "./evm/wallets/signer": { module: { browser: "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.browser.esm.js", "default": "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.esm.js" }, "default": "./evm/wallets/signer/dist/thirdweb-dev-wallets-evm-wallets-signer.cjs.js" }, "./evm/wallets/zerion": { module: { browser: "./evm/wallets/zerion/dist/thirdweb-dev-wallets-evm-wallets-zerion.browser.esm.js", "default": "./evm/wallets/zerion/dist/thirdweb-dev-wallets-evm-wallets-zerion.esm.js" }, "default": "./evm/wallets/zerion/dist/thirdweb-dev-wallets-evm-wallets-zerion.cjs.js" }, "./evm/wallets/aws-kms": { module: { browser: "./evm/wallets/aws-kms/dist/thirdweb-dev-wallets-evm-wallets-aws-kms.browser.esm.js", "default": "./evm/wallets/aws-kms/dist/thirdweb-dev-wallets-evm-wallets-aws-kms.esm.js" }, "default": "./evm/wallets/aws-kms/dist/thirdweb-dev-wallets-evm-wallets-aws-kms.cjs.js" }, "./evm/wallets/gcp-kms": { module: { browser: "./evm/wallets/gcp-kms/dist/thirdweb-dev-wallets-evm-wallets-gcp-kms.browser.esm.js", "default": "./evm/wallets/gcp-kms/dist/thirdweb-dev-wallets-evm-wallets-gcp-kms.esm.js" }, "default": "./evm/wallets/gcp-kms/dist/thirdweb-dev-wallets-evm-wallets-gcp-kms.cjs.js" }, "./evm/wallets/phantom": { module: { browser: "./evm/wallets/phantom/dist/thirdweb-dev-wallets-evm-wallets-phantom.browser.esm.js", "default": "./evm/wallets/phantom/dist/thirdweb-dev-wallets-evm-wallets-phantom.esm.js" }, "default": "./evm/wallets/phantom/dist/thirdweb-dev-wallets-evm-wallets-phantom.cjs.js" }, "./evm/wallets/abstract": { module: { browser: "./evm/wallets/abstract/dist/thirdweb-dev-wallets-evm-wallets-abstract.browser.esm.js", "default": "./evm/wallets/abstract/dist/thirdweb-dev-wallets-evm-wallets-abstract.esm.js" }, "default": "./evm/wallets/abstract/dist/thirdweb-dev-wallets-evm-wallets-abstract.cjs.js" }, "./evm/wallets/injected": { module: { browser: "./evm/wallets/injected/dist/thirdweb-dev-wallets-evm-wallets-injected.browser.esm.js", "default": "./evm/wallets/injected/dist/thirdweb-dev-wallets-evm-wallets-injected.esm.js" }, "default": "./evm/wallets/injected/dist/thirdweb-dev-wallets-evm-wallets-injected.cjs.js" }, "./evm/wallets/metamask": { module: { browser: "./evm/wallets/metamask/dist/thirdweb-dev-wallets-evm-wallets-metamask.browser.esm.js", "default": "./evm/wallets/metamask/dist/thirdweb-dev-wallets-evm-wallets-metamask.esm.js" }, "default": "./evm/wallets/metamask/dist/thirdweb-dev-wallets-evm-wallets-metamask.cjs.js" }, "./evm/wallets/private-key": { module: { browser: "./evm/wallets/private-key/dist/thirdweb-dev-wallets-evm-wallets-private-key.browser.esm.js", "default": "./evm/wallets/private-key/dist/thirdweb-dev-wallets-evm-wallets-private-key.esm.js" }, "default": "./evm/wallets/private-key/dist/thirdweb-dev-wallets-evm-wallets-private-key.cjs.js" }, "./evm/wallets/local-wallet": { module: { browser: "./evm/wallets/local-wallet/dist/thirdweb-dev-wallets-evm-wallets-local-wallet.browser.esm.js", "default": "./evm/wallets/local-wallet/dist/thirdweb-dev-wallets-evm-wallets-local-wallet.esm.js" }, "default": "./evm/wallets/local-wallet/dist/thirdweb-dev-wallets-evm-wallets-local-wallet.cjs.js" }, "./evm/wallets/paper-wallet": { module: { browser: "./evm/wallets/paper-wallet/dist/thirdweb-dev-wallets-evm-wallets-paper-wallet.browser.esm.js", "default": "./evm/wallets/paper-wallet/dist/thirdweb-dev-wallets-evm-wallets-paper-wallet.esm.js" }, "default": "./evm/wallets/paper-wallet/dist/thirdweb-dev-wallets-evm-wallets-paper-wallet.cjs.js" }, "./evm/wallets/smart-wallet": { module: { browser: "./evm/wallets/smart-wallet/dist/thirdweb-dev-wallets-evm-wallets-smart-wallet.browser.esm.js", "default": "./evm/wallets/smart-wallet/dist/thirdweb-dev-wallets-evm-wallets-smart-wallet.esm.js" }, "default": "./evm/wallets/smart-wallet/dist/thirdweb-dev-wallets-evm-wallets-smart-wallet.cjs.js" }, "./evm/connectors/safe": { module: { browser: "./evm/connectors/safe/dist/thirdweb-dev-wallets-evm-connectors-safe.browser.esm.js", "default": "./evm/connectors/safe/dist/thirdweb-dev-wallets-evm-connectors-safe.esm.js" }, "default": "./evm/connectors/safe/dist/thirdweb-dev-wallets-evm-connectors-safe.cjs.js" }, "./evm/connectors/frame": { module: { browser: "./evm/connectors/frame/dist/thirdweb-dev-wallets-evm-connectors-frame.browser.esm.js", "default": "./evm/connectors/frame/dist/thirdweb-dev-wallets-evm-connectors-frame.esm.js" }, "default": "./evm/connectors/frame/dist/thirdweb-dev-wallets-evm-connectors-frame.cjs.js" }, "./evm/connectors/magic": { module: { browser: "./evm/connectors/magic/dist/thirdweb-dev-wallets-evm-connectors-magic.browser.esm.js", "default": "./evm/connectors/magic/dist/thirdweb-dev-wallets-evm-connectors-magic.esm.js" }, "default": "./evm/connectors/magic/dist/thirdweb-dev-wallets-evm-connectors-magic.cjs.js" }, "./evm/connectors/paper": { module: { browser: "./evm/connectors/paper/dist/thirdweb-dev-wallets-evm-connectors-paper.browser.esm.js", "default": "./evm/connectors/paper/dist/thirdweb-dev-wallets-evm-connectors-paper.esm.js" }, "default": "./evm/connectors/paper/dist/thirdweb-dev-wallets-evm-connectors-paper.cjs.js" }, "./evm/connectors/trust": { module: { browser: "./evm/connectors/trust/dist/thirdweb-dev-wallets-evm-connectors-trust.browser.esm.js", "default": "./evm/connectors/trust/dist/thirdweb-dev-wallets-evm-connectors-trust.esm.js" }, "default": "./evm/connectors/trust/dist/thirdweb-dev-wallets-evm-connectors-trust.cjs.js" }, "./evm/wallets/rainbow-wallet": { module: { browser: "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.browser.esm.js", "default": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.esm.js" }, "default": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.cjs.js" }, "./evm/wallets/wallet-connect": { module: { browser: "./evm/wallets/wallet-connect/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect.browser.esm.js", "default": "./evm/wallets/wallet-connect/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect.esm.js" }, "default": "./evm/wallets/wallet-connect/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect.cjs.js" }, "./evm/connectors/blocto": { module: { browser: "./evm/connectors/blocto/dist/thirdweb-dev-wallets-evm-connectors-blocto.browser.esm.js", "default": "./evm/connectors/blocto/dist/thirdweb-dev-wallets-evm-connectors-blocto.esm.js" }, "default": "./evm/connectors/blocto/dist/thirdweb-dev-wallets-evm-connectors-blocto.cjs.js" }, "./evm/connectors/signer": { module: { browser: "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.browser.esm.js", "default": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.esm.js" }, "default": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.cjs.js" }, "./evm/connectors/zerion": { module: { browser: "./evm/connectors/zerion/dist/thirdweb-dev-wallets-evm-connectors-zerion.browser.esm.js", "default": "./evm/connectors/zerion/dist/thirdweb-dev-wallets-evm-connectors-zerion.esm.js" }, "default": "./evm/connectors/zerion/dist/thirdweb-dev-wallets-evm-connectors-zerion.cjs.js" }, "./evm/wallets/coinbase-wallet": { module: { browser: "./evm/wallets/coinbase-wallet/dist/thirdweb-dev-wallets-evm-wallets-coinbase-wallet.browser.esm.js", "default": "./evm/wallets/coinbase-wallet/dist/thirdweb-dev-wallets-evm-wallets-coinbase-wallet.esm.js" }, "default": "./evm/wallets/coinbase-wallet/dist/thirdweb-dev-wallets-evm-wallets-coinbase-wallet.cjs.js" }, "./evm/wallets/embedded-wallet": { module: { browser: "./evm/wallets/embedded-wallet/dist/thirdweb-dev-wallets-evm-wallets-embedded-wallet.browser.esm.js", "default": "./evm/wallets/embedded-wallet/dist/thirdweb-dev-wallets-evm-wallets-embedded-wallet.esm.js" }, "default": "./evm/wallets/embedded-wallet/dist/thirdweb-dev-wallets-evm-wallets-embedded-wallet.cjs.js" }, "./evm/connectors/phantom": { module: { browser: "./evm/connectors/phantom/dist/thirdweb-dev-wallets-evm-connectors-phantom.browser.esm.js", "default": "./evm/connectors/phantom/dist/thirdweb-dev-wallets-evm-connectors-phantom.esm.js" }, "default": "./evm/connectors/phantom/dist/thirdweb-dev-wallets-evm-connectors-phantom.cjs.js" }, "./evm/connectors/rainbow": { module: { browser: "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.browser.esm.js", "default": "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.esm.js" }, "default": "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.cjs.js" }, "./evm/connectors/injected": { module: { browser: "./evm/connectors/injected/dist/thirdweb-dev-wallets-evm-connectors-injected.browser.esm.js", "default": "./evm/connectors/injected/dist/thirdweb-dev-wallets-evm-connectors-injected.esm.js" }, "default": "./evm/connectors/injected/dist/thirdweb-dev-wallets-evm-connectors-injected.cjs.js" }, "./evm/connectors/metamask": { module: { browser: "./evm/connectors/metamask/dist/thirdweb-dev-wallets-evm-connectors-metamask.browser.esm.js", "default": "./evm/connectors/metamask/dist/thirdweb-dev-wallets-evm-connectors-metamask.esm.js" }, "default": "./evm/connectors/metamask/dist/thirdweb-dev-wallets-evm-connectors-metamask.cjs.js" }, "./evm/wallets/local-wallet-node": { module: { browser: "./evm/wallets/local-wallet-node/dist/thirdweb-dev-wallets-evm-wallets-local-wallet-node.browser.esm.js", "default": "./evm/wallets/local-wallet-node/dist/thirdweb-dev-wallets-evm-wallets-local-wallet-node.esm.js" }, "default": "./evm/wallets/local-wallet-node/dist/thirdweb-dev-wallets-evm-wallets-local-wallet-node.cjs.js" }, "./evm/wallets/wallet-connect-v1": { module: { browser: "./evm/wallets/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect-v1.browser.esm.js", "default": "./evm/wallets/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect-v1.esm.js" }, "default": "./evm/wallets/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect-v1.cjs.js" }, "./evm/wallets/aws-secrets-manager": { module: { browser: "./evm/wallets/aws-secrets-manager/dist/thirdweb-dev-wallets-evm-wallets-aws-secrets-manager.browser.esm.js", "default": "./evm/wallets/aws-secrets-manager/dist/thirdweb-dev-wallets-evm-wallets-aws-secrets-manager.esm.js" }, "default": "./evm/wallets/aws-secrets-manager/dist/thirdweb-dev-wallets-evm-wallets-aws-secrets-manager.cjs.js" }, "./evm/connectors/local-wallet": { module: { browser: "./evm/connectors/local-wallet/dist/thirdweb-dev-wallets-evm-connectors-local-wallet.browser.esm.js", "default": "./evm/connectors/local-wallet/dist/thirdweb-dev-wallets-evm-connectors-local-wallet.esm.js" }, "default": "./evm/connectors/local-wallet/dist/thirdweb-dev-wallets-evm-connectors-local-wallet.cjs.js" }, "./evm/connectors/smart-wallet": { module: { browser: "./evm/connectors/smart-wallet/dist/thirdweb-dev-wallets-evm-connectors-smart-wallet.browser.esm.js", "default": "./evm/connectors/smart-wallet/dist/thirdweb-dev-wallets-evm-connectors-smart-wallet.esm.js" }, "default": "./evm/connectors/smart-wallet/dist/thirdweb-dev-wallets-evm-connectors-smart-wallet.cjs.js" }, "./evm/connectors/wallet-connect": { module: { browser: "./evm/connectors/wallet-connect/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect.browser.esm.js", "default": "./evm/connectors/wallet-connect/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect.esm.js" }, "default": "./evm/connectors/wallet-connect/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect.cjs.js" }, "./evm/connectors/coinbase-wallet": { module: { browser: "./evm/connectors/coinbase-wallet/dist/thirdweb-dev-wallets-evm-connectors-coinbase-wallet.browser.esm.js", "default": "./evm/connectors/coinbase-wallet/dist/thirdweb-dev-wallets-evm-connectors-coinbase-wallet.esm.js" }, "default": "./evm/connectors/coinbase-wallet/dist/thirdweb-dev-wallets-evm-connectors-coinbase-wallet.cjs.js" }, "./evm/connectors/embedded-wallet": { module: { browser: "./evm/connectors/embedded-wallet/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet.browser.esm.js", "default": "./evm/connectors/embedded-wallet/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet.esm.js" }, "default": "./evm/connectors/embedded-wallet/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet.cjs.js" }, "./evm/connectors/wallet-connect-v1": { module: { browser: "./evm/connectors/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect-v1.browser.esm.js", "default": "./evm/connectors/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect-v1.esm.js" }, "default": "./evm/connectors/wallet-connect-v1/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect-v1.cjs.js" }, "./evm/connectors/embedded-wallet/implementations": { module: { browser: "./evm/connectors/embedded-wallet/implementations/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet-implementations.browser.esm.js", "default": "./evm/connectors/embedded-wallet/implementations/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet-implementations.esm.js" }, "default": "./evm/connectors/embedded-wallet/implementations/dist/thirdweb-dev-wallets-evm-connectors-embedded-wallet-implementations.cjs.js" }, "./package.json": "./package.json" }, repository: "https://github.com/thirdweb-dev/js/tree/main/packages/wallets", license: "Apache-2.0", bugs: { url: "https://github.com/thirdweb-dev/js/issues" }, author: "thirdweb eng <eng@thirdweb.com>", files: [ "dist/", "evm/" ], preconstruct: { entrypoints: [ "index.ts", "evm/index.ts", "evm/connectors/*/index.ts", "evm/connectors/embedded-wallet/implementations/index.ts", "evm/wallets/**" ], exports: { envConditions: [ "browser" ] } }, sideEffects: false, dependencies: { "@account-abstraction/contracts": "^0.5.0", "@account-abstraction/sdk": "^0.5.0", "@account-abstraction/utils": "^0.5.0", "@blocto/sdk": "^0.5.4", "@coinbase/wallet-sdk": "^3.7.1", "@magic-ext/connect": "^6.7.2", "@magic-ext/oauth": "^7.6.2", "@magic-sdk/provider": "^13.6.2", "@paperxyz/embedded-wallet-service-sdk": "^1.2.4", "@paperxyz/sdk-common-utilities": "^0.1.0", "@safe-global/safe-core-sdk": "^3.3.4", "@safe-global/safe-ethers-adapters": "0.1.0-alpha.17", "@safe-global/safe-ethers-lib": "^1.9.4", "@thirdweb-dev/chains": "workspace:*", "@thirdweb-dev/contracts-js": "workspace:*", "@thirdweb-dev/sdk": "workspace:*", "@walletconnect/core": "^2.9.1", "@walletconnect/ethereum-provider": "^2.9.1", "@walletconnect/jsonrpc-utils": "^1.0.8", "@walletconnect/modal": "^2.6.1", "@walletconnect/types": "^2.9.1", "@walletconnect/utils": "^2.10.2", "@walletconnect/web3wallet": "^1.8.7", buffer: "^6.0.3", "crypto-js": "^4.1.1", "eth-provider": "^0.13.6", eventemitter3: "^5.0.1", "magic-sdk": "^13.6.2", "web3-core": "1.5.2" }, peerDependencies: { "@aws-sdk/client-secrets-manager": "^3.256.0", "@noble/ed25519": "^1.7.1", bs58: "^5.0.0", ethers: "^5.7.2", "ethers-aws-kms-signer": "^1.3.2", "ethers-gcp-kms-signer": "^1.1.6", tweetnacl: "^1.0.3" }, peerDependenciesMeta: { tweetnacl: { optional: true }, "@aws-sdk/client-secrets-manager": { optional: true }, "ethers-aws-kms-signer": { optional: true }, "@noble/ed25519": { optional: true }, bs58: { optional: true }, ethers: { optional: true } }, devDependencies: { "@aws-sdk/client-secrets-manager": "^3.378.0", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-transform-flow-strip-types": "^7.22.5", "@babel/plugin-transform-private-methods": "7.22.5", "@noble/ed25519": "^1.7.1", "@preconstruct/cli": "2.7.0", "@thirdweb-dev/tsconfig": "workspace:*", "@types/crypto-js": "^4.1.1", abitype: "^0.2.5", "babel-plugin-transform-inline-environment-variables": "^0.4.4", bs58: "^5.0.0", "cross-env": "^7.0.3", "eslint-config-thirdweb": "workspace:*", "eslint-plugin-better-tree-shaking": "0.0.4", "ethereum-provider": "^0.7.7", ethers: "^5.7.2", "ethers-aws-kms-signer": "^1.3.2", "ethers-gcp-kms-signer": "^1.1.6", tweetnacl: "^1.0.3", typescript: "^5.1.6" }, scripts: { format: "prettier --write 'src/**/*'", lint: "eslint src/", fix: "eslint src/ --fix", clean: "rm -rf dist/", build: "tsc && cross-env THIRDWEB_EWS_SDK_VERSION=$npm_package_version preconstruct build", "preconstruct:fix": "preconstruct fix", push: "yalc push" } }; function isBrowser() { return typeof window !== "undefined"; } class HttpRpcClient { constructor(bundlerUrl, entryPointAddress, chainId, clientId, secretKey) { this.bundlerUrl = bundlerUrl; this.entryPointAddress = entryPointAddress; this.chainId = chainId; const headers = {}; if (url.isTwUrl(this.bundlerUrl)) { const bundleId = typeof globalThis !== "undefined" && "APP_BUNDLE_ID" in globalThis ? globalThis.APP_BUNDLE_ID : undefined; if (secretKey) { headers["x-secret-key"] = secretKey; } else if (clientId) { headers["x-client-id"] = clientId; if (bundleId) { headers["x-bundle-id"] = bundleId; } } // Dashboard token if (typeof globalThis !== "undefined" && "TW_AUTH_TOKEN" in globalThis && typeof globalThis.TW_AUTH_TOKEN === "string") { headers["authorization"] = `Bearer ${globalThis.TW_AUTH_TOKEN}`; } // CLI token if (typeof globalThis !== "undefined" && "TW_CLI_AUTH_TOKEN" in globalThis && typeof globalThis.TW_CLI_AUTH_TOKEN === "string") { headers["authorization"] = `Bearer ${globalThis.TW_CLI_AUTH_TOKEN}`; headers["x-authorize-wallet"] = "true"; } headers["x-sdk-version"] = pkg.version; headers["x-sdk-name"] = pkg.name; headers["x-sdk-platform"] = bundleId ? "react-native" : isBrowser() ? window.bridge !== undefined ? "webGL" : "browser" : "node"; } this.userOpJsonRpcProvider = new ethers.providers.JsonRpcProvider({ url: this.bundlerUrl, headers }, { name: "Connected bundler network", chainId }); this.initializing = this.validateChainId(); } async validateChainId() { // validate chainId is in sync with expected chainid const chain = await this.userOpJsonRpcProvider.send("eth_chainId", []); const bundlerChain = parseInt(chain); if (bundlerChain !== this.chainId) { throw new Error(`bundler ${this.bundlerUrl} is on chainId ${bundlerChain}, but provider is on chainId ${this.chainId}`); } } /** * send a UserOperation to the bundler * @param userOp1 * @return userOpHash the id of this operation, for getUserOperationTransaction */ async sendUserOpToBundler(userOp1) { await this.initializing; const hexifiedUserOp = utils.deepHexlify(await ethers.utils.resolveProperties(userOp1)); const jsonRequestData = [hexifiedUserOp, this.entryPointAddress]; await this.printUserOperation("eth_sendUserOperation", jsonRequestData); return await this.userOpJsonRpcProvider.send("eth_sendUserOperation", [hexifiedUserOp, this.entryPointAddress]); } async estimateUserOpGas(userOp1) { await this.initializing; const hexifiedUserOp = utils.deepHexlify(await ethers.utils.resolveProperties(userOp1)); const jsonRequestData = [hexifiedUserOp, this.entryPointAddress]; await this.printUserOperation("eth_estimateUserOperationGas", jsonRequestData); return await this.userOpJsonRpcProvider.send("eth_estimateUserOperationGas", [hexifiedUserOp, this.entryPointAddress]); } async printUserOperation(method, _ref) { { return; } } } /** * wrap an existing provider to tunnel requests through Account Abstraction. * @param originalProvider the normal provider * @param config see ClientConfig for more info * @param originalSigner use this signer as the owner. of this wallet. By default, use the provider's signer */ async function create4337Provider(config, accountApi, originalProvider) { const entryPoint = contracts.EntryPoint__factory.connect(config.entryPointAddress, originalProvider); const chainId = (await originalProvider.getNetwork()).chainId; const httpRpcClient = new HttpRpcClient(config.bundlerUrl, config.entryPointAddress, chainId, config.clientId, config.secretKey); return await new ERC4337EthersProvider(chainId, config, config.localSigner, originalProvider, httpRpcClient, entryPoint, accountApi).init(); } const ENTRYPOINT_ADDRESS = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"; // v0.6 const ACCOUNT_CORE_ABI = [{ type: "constructor", name: "", inputs: [{ type: "address", name: "_entrypoint", internalType: "contract IEntryPoint" }, { type: "address", name: "_factory", internalType: "address" }], outputs: [], stateMutability: "nonpayable" }, { type: "event", name: "AdminUpdated", inputs: [{ type: "address", name: "signer", indexed: true, internalType: "address" }, { type: "bool", name: "isAdmin", indexed: false, internalType: "bool" }], outputs: [], anonymous: false }, { type: "event", name: "ContractURIUpdated", inputs: [{ type: "string", name: "prevURI", indexed: false, internalType: "string" }, { type: "string", name: "newURI", indexed: false, internalType: "string" }], outputs: [], anonymous: false }, { type: "event", name: "Initialized", inputs: [{ type: "uint8", name: "version", indexed: false, internalType: "uint8" }], outputs: [], anonymous: false }, { type: "event", name: "SignerPermissionsUpdated", inputs: [{ type: "address", name: "authorizingSigner", indexed: true, internalType: "address" }, { type: "address", name: "targetSigner", indexed: true, internalType: "address" }, { type: "tuple", name: "permissions", components: [{ type: "address", name: "signer", internalType: "address" }, { type: "address[]", name: "approvedTargets", internalType: "address[]" }, { type: "uint256", name: "nativeTokenLimitPerTransaction", internalType: "uint256" }, { type: "uint128", name: "permissionStartTimestamp", internalType: "uint128" }, { type: "uint128", name: "permissionEndTimestamp", internalType: "uint128" }, { type: "uint128", name: "reqValidityStartTimestamp", internalType: "uint128" }, { type: "uint128", name: "reqValidityEndTimestamp", internalType: "uint128" }, { type: "bytes32", name: "uid", internalType: "bytes32" }], indexed: false, internalType: "struct IAccountPermissions.SignerPermissionRequest" }], outputs: [], anonymous: false }, { type: "function", name: "addDeposit", inputs: [], outputs: [], stateMutability: "payable" }, { type: "function", name: "contractURI", inputs: [], outputs: [{ type: "string", name: "", internalType: "string" }], stateMutability: "view" }, { type: "function", name: "entryPoint", inputs: [], outputs: [{ type: "address", name: "", internalType: "contract IEntryPoint" }], stateMutability: "view" }, { type: "function", name: "execute", inputs: [{ type: "address", name: "_target", internalType: "address" }, { type: "uint256", name: "_value", internalType: "uint256" }, { type: "bytes", name: "_calldata", internalType: "bytes" }], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "executeBatch", inputs: [{ type: "address[]", name: "_target", internalType: "address[]" }, { type: "uint256[]", name: "_value", internalType: "uint256[]" }, { type: "bytes[]", name: "_calldata", internalType: "bytes[]" }], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "factory", inputs: [], outputs: [{ type: "address", name: "", internalType: "address" }], stateMutability: "view" }, { type: "function", name: "getAllActiveSigners", inputs: [], outputs: [{ type: "tuple[]", name: "signers", components: [{ type: "address", name: "signer", internalType: "address" }, { type: "address[]", name: "approvedTargets", internalType: "address[]" }, { type: "uint256", name: "nativeTokenLimitPerTransaction", internalType: "uint256" }, { type: "uint128", name: "startTimestamp", internalType: "uint128" }, { type: "uint128", name: "endTimestamp", internalType: "uint128" }], internalType: "struct IAccountPermissions.SignerPermissions[]" }], stateMutability: "view" }, { type: "function", name: "getAllAdmins", inputs: [], outputs: [{ type: "address[]", name: "", internalType: "address[]" }], stateMutability: "view" }, { type: "function", name: "getAllSigners", inputs: [], outputs: [{ type: "tuple[]", name: "signers", components: [{ type: "address", name: "signer", internalType: "address" }, { type: "address[]", name: "approvedTargets", internalType: "address[]" }, { type: "uint256", name: "nativeTokenLimitPerTransaction", internalType: "uint256" }, { type: "uint128", name: "startTimestamp", internalType: "uint128" }, { type: "uint128", name: "endTimestamp", internalType: "uint128" }], internalType: "struct IAccountPermissions.SignerPermissions[]" }], stateMutability: "view" }, { type: "function", name: "getDeposit", inputs: [], outputs: [{ type: "uint256", name: "", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "getNonce", inputs: [], outputs: [{ type: "uint256", name: "", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "getPermissionsForSigner", inputs: [{ type: "address", name: "signer", internalType: "address" }], outputs: [{ type: "tuple", name: "", components: [{ type: "address", name: "signer", internalType: "address" }, { type: "address[]", name: "approvedTargets", internalType: "address[]" }, { type: "uint256", name: "nativeTokenLimitPerTransaction", internalType: "uint256" }, { type: "uint128", name: "startTimestamp", internalType: "uint128" }, { type: "uint128", name: "endTimestamp", internalType: "uint128" }], internalType: "struct IAccountPermissions.SignerPermissions" }], stateMutability: "view" }, { type: "function", name: "initialize", inputs: [{ type: "address", name: "_defaultAdmin", internalType: "address" }, { type: "bytes", name: "", internalType: "bytes" }], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "isActiveSigner", inputs: [{ type: "address", name: "signer", internalType: "address" }], outputs: [{ type: "bool", name: "", internalType: "bool" }], stateMutability: "view" }, { type: "function", name: "isAdmin", inputs: [{ type: "address", name: "_account", internalType: "address" }], outputs: [{ type: "bool", name: "", internalType: "bool" }], stateMutability: "view" }, { type: "function", name: "isValidSignature", inputs: [{ type: "bytes32", name: "_hash", internalType: "bytes32" }, { type: "bytes", name: "_signature", internalType: "bytes" }], outputs: [{ type: "bytes4", name: "magicValue", internalType: "bytes4" }], stateMutability: "view" }, { type: "function", name: "isValidSigner", inputs: [{ type: "address", name: "_signer", internalType: "address" }, { type: "tuple", name: "_userOp", components: [{ type: "address", name: "sender", internalType: "address" }, { type: "uint256", name: "nonce", internalType: "uint256" }, { type: "bytes", name: "initCode", internalType: "bytes" }, { type: "bytes", name: "callData", internalType: "bytes" }, { type: "uint256", name: "callGasLimit", internalType: "uint256" }, { type: "uint256", name: "verificationGasLimit", internalType: "uint256" }, { type: "uint256", name: "preVerificationGas", internalType: "uint256" }, { type: "uint256", name: "maxFeePerGas", internalType: "uint256" }, { type: "uint256", name: "maxPriorityFeePerGas", internalType: "uint256" }, { type: "bytes", name: "paymasterAndData", internalType: "bytes" }, { type: "bytes", name: "signature", internalType: "bytes" }], internalType: "struct UserOperation" }], outputs: