UNPKG

@simplepay-ai/widget

Version:

SimplePay Payment Widget

1,493 lines 129 kB
import { B as Buffer, b as getAugmentedNamespace, s as sha3, g as getDefaultExportFromCjs, d as bytesToHex, e as sha256 } from "./main-oDQ_krE7.js"; import { D, _, c as clsx, d, y } from "./clsx.m-yJycXJN4.js"; class ScopedLocalStorage { constructor(scope, module) { this.scope = scope; this.module = module; } storeObject(key, item) { this.setItem(key, JSON.stringify(item)); } loadObject(key) { const item = this.getItem(key); return item ? JSON.parse(item) : void 0; } setItem(key, value) { localStorage.setItem(this.scopedKey(key), value); } getItem(key) { return localStorage.getItem(this.scopedKey(key)); } removeItem(key) { localStorage.removeItem(this.scopedKey(key)); } clear() { const prefix = this.scopedKey(""); const keysToRemove = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (typeof key === "string" && key.startsWith(prefix)) { keysToRemove.push(key); } } keysToRemove.forEach((key) => localStorage.removeItem(key)); } scopedKey(key) { return `-${this.scope}${this.module ? `:${this.module}` : ""}:${key}`; } static clearAll() { new ScopedLocalStorage("CBWSDK").clear(); new ScopedLocalStorage("walletlink").clear(); } } const standardErrorCodes = { rpc: { invalidInput: -32e3, resourceNotFound: -32001, resourceUnavailable: -32002, transactionRejected: -32003, methodNotSupported: -32004, limitExceeded: -32005, parse: -32700, invalidRequest: -32600, methodNotFound: -32601, invalidParams: -32602, internal: -32603 }, provider: { userRejectedRequest: 4001, unauthorized: 4100, unsupportedMethod: 4200, disconnected: 4900, chainDisconnected: 4901, unsupportedChain: 4902 } }; const errorValues = { "-32700": { standard: "JSON RPC 2.0", message: "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text." }, "-32600": { standard: "JSON RPC 2.0", message: "The JSON sent is not a valid Request object." }, "-32601": { standard: "JSON RPC 2.0", message: "The method does not exist / is not available." }, "-32602": { standard: "JSON RPC 2.0", message: "Invalid method parameter(s)." }, "-32603": { standard: "JSON RPC 2.0", message: "Internal JSON-RPC error." }, "-32000": { standard: "EIP-1474", message: "Invalid input." }, "-32001": { standard: "EIP-1474", message: "Resource not found." }, "-32002": { standard: "EIP-1474", message: "Resource unavailable." }, "-32003": { standard: "EIP-1474", message: "Transaction rejected." }, "-32004": { standard: "EIP-1474", message: "Method not supported." }, "-32005": { standard: "EIP-1474", message: "Request limit exceeded." }, "4001": { standard: "EIP-1193", message: "User rejected the request." }, "4100": { standard: "EIP-1193", message: "The requested account and/or method has not been authorized by the user." }, "4200": { standard: "EIP-1193", message: "The requested method is not supported by this Ethereum provider." }, "4900": { standard: "EIP-1193", message: "The provider is disconnected from all chains." }, "4901": { standard: "EIP-1193", message: "The provider is disconnected from the specified chain." }, "4902": { standard: "EIP-3085", message: "Unrecognized chain ID." } }; const FALLBACK_MESSAGE = "Unspecified error message."; const JSON_RPC_SERVER_ERROR_MESSAGE = "Unspecified server error."; function getMessageFromCode(code, fallbackMessage = FALLBACK_MESSAGE) { if (code && Number.isInteger(code)) { const codeString = code.toString(); if (hasKey(errorValues, codeString)) { return errorValues[codeString].message; } if (isJsonRpcServerError(code)) { return JSON_RPC_SERVER_ERROR_MESSAGE; } } return fallbackMessage; } function isValidCode(code) { if (!Number.isInteger(code)) { return false; } const codeString = code.toString(); if (errorValues[codeString]) { return true; } if (isJsonRpcServerError(code)) { return true; } return false; } function serialize(error, { shouldIncludeStack = false } = {}) { const serialized = {}; if (error && typeof error === "object" && !Array.isArray(error) && hasKey(error, "code") && isValidCode(error.code)) { const _error = error; serialized.code = _error.code; if (_error.message && typeof _error.message === "string") { serialized.message = _error.message; if (hasKey(_error, "data")) { serialized.data = _error.data; } } else { serialized.message = getMessageFromCode(serialized.code); serialized.data = { originalError: assignOriginalError(error) }; } } else { serialized.code = standardErrorCodes.rpc.internal; serialized.message = hasStringProperty(error, "message") ? error.message : FALLBACK_MESSAGE; serialized.data = { originalError: assignOriginalError(error) }; } if (shouldIncludeStack) { serialized.stack = hasStringProperty(error, "stack") ? error.stack : void 0; } return serialized; } function isJsonRpcServerError(code) { return code >= -32099 && code <= -32e3; } function assignOriginalError(error) { if (error && typeof error === "object" && !Array.isArray(error)) { return Object.assign({}, error); } return error; } function hasKey(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } function hasStringProperty(obj, prop) { return typeof obj === "object" && obj !== null && prop in obj && typeof obj[prop] === "string"; } const standardErrors = { rpc: { parse: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.parse, arg), invalidRequest: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.invalidRequest, arg), invalidParams: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.invalidParams, arg), methodNotFound: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.methodNotFound, arg), internal: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.internal, arg), server: (opts) => { if (!opts || typeof opts !== "object" || Array.isArray(opts)) { throw new Error("Ethereum RPC Server errors must provide single object argument."); } const { code } = opts; if (!Number.isInteger(code) || code > -32005 || code < -32099) { throw new Error('"code" must be an integer such that: -32099 <= code <= -32005'); } return getEthJsonRpcError(code, opts); }, invalidInput: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.invalidInput, arg), resourceNotFound: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.resourceNotFound, arg), resourceUnavailable: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.resourceUnavailable, arg), transactionRejected: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.transactionRejected, arg), methodNotSupported: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.methodNotSupported, arg), limitExceeded: (arg) => getEthJsonRpcError(standardErrorCodes.rpc.limitExceeded, arg) }, provider: { userRejectedRequest: (arg) => { return getEthProviderError(standardErrorCodes.provider.userRejectedRequest, arg); }, unauthorized: (arg) => { return getEthProviderError(standardErrorCodes.provider.unauthorized, arg); }, unsupportedMethod: (arg) => { return getEthProviderError(standardErrorCodes.provider.unsupportedMethod, arg); }, disconnected: (arg) => { return getEthProviderError(standardErrorCodes.provider.disconnected, arg); }, chainDisconnected: (arg) => { return getEthProviderError(standardErrorCodes.provider.chainDisconnected, arg); }, unsupportedChain: (arg) => { return getEthProviderError(standardErrorCodes.provider.unsupportedChain, arg); }, custom: (opts) => { if (!opts || typeof opts !== "object" || Array.isArray(opts)) { throw new Error("Ethereum Provider custom errors must provide single object argument."); } const { code, message, data } = opts; if (!message || typeof message !== "string") { throw new Error('"message" must be a nonempty string'); } return new EthereumProviderError(code, message, data); } } }; function getEthJsonRpcError(code, arg) { const [message, data] = parseOpts(arg); return new EthereumRpcError(code, message || getMessageFromCode(code), data); } function getEthProviderError(code, arg) { const [message, data] = parseOpts(arg); return new EthereumProviderError(code, message || getMessageFromCode(code), data); } function parseOpts(arg) { if (arg) { if (typeof arg === "string") { return [arg]; } else if (typeof arg === "object" && !Array.isArray(arg)) { const { message, data } = arg; if (message && typeof message !== "string") { throw new Error("Must specify string message."); } return [message || void 0, data]; } } return []; } class EthereumRpcError extends Error { constructor(code, message, data) { if (!Number.isInteger(code)) { throw new Error('"code" must be an integer.'); } if (!message || typeof message !== "string") { throw new Error('"message" must be a nonempty string.'); } super(message); this.code = code; if (data !== void 0) { this.data = data; } } } class EthereumProviderError extends EthereumRpcError { /** * Create an Ethereum Provider JSON-RPC error. * `code` must be an integer in the 1000 <= 4999 range. */ constructor(code, message, data) { if (!isValidEthProviderCode(code)) { throw new Error('"code" must be an integer such that: 1000 <= code <= 4999'); } super(code, message, data); } } function isValidEthProviderCode(code) { return Number.isInteger(code) && code >= 1e3 && code <= 4999; } function OpaqueType() { return (value) => value; } const HexString = OpaqueType(); const AddressString = OpaqueType(); const BigIntString = OpaqueType(); function IntNumber(num) { return Math.floor(num); } const INT_STRING_REGEX = /^[0-9]*$/; const HEXADECIMAL_STRING_REGEX = /^[a-f0-9]*$/; function randomBytesHex(length) { return uint8ArrayToHex(crypto.getRandomValues(new Uint8Array(length))); } function uint8ArrayToHex(value) { return [...value].map((b) => b.toString(16).padStart(2, "0")).join(""); } function hexStringToUint8Array(hexString) { return new Uint8Array(hexString.match(/.{1,2}/g).map((byte) => Number.parseInt(byte, 16))); } function hexStringFromBuffer(buf, includePrefix = false) { const hex = buf.toString("hex"); return HexString(includePrefix ? `0x${hex}` : hex); } function encodeToHexString(str) { return hexStringFromBuffer(ensureBuffer(str), true); } function bigIntStringFromBigInt(bi) { return BigIntString(bi.toString(10)); } function hexStringFromNumber(num) { return HexString(`0x${BigInt(num).toString(16)}`); } function has0xPrefix(str) { return str.startsWith("0x") || str.startsWith("0X"); } function strip0x(hex) { if (has0xPrefix(hex)) { return hex.slice(2); } return hex; } function prepend0x(hex) { if (has0xPrefix(hex)) { return `0x${hex.slice(2)}`; } return `0x${hex}`; } function isHexString$1(hex) { if (typeof hex !== "string") { return false; } const s = strip0x(hex).toLowerCase(); return HEXADECIMAL_STRING_REGEX.test(s); } function ensureHexString(hex, includePrefix = false) { if (typeof hex === "string") { const s = strip0x(hex).toLowerCase(); if (HEXADECIMAL_STRING_REGEX.test(s)) { return HexString(includePrefix ? `0x${s}` : s); } } throw standardErrors.rpc.invalidParams(`"${String(hex)}" is not a hexadecimal string`); } function ensureEvenLengthHexString(hex, includePrefix = false) { let h = ensureHexString(hex, false); if (h.length % 2 === 1) { h = HexString(`0${h}`); } return includePrefix ? HexString(`0x${h}`) : h; } function ensureAddressString(str) { if (typeof str === "string") { const s = strip0x(str).toLowerCase(); if (isHexString$1(s) && s.length === 40) { return AddressString(prepend0x(s)); } } throw standardErrors.rpc.invalidParams(`Invalid Ethereum address: ${String(str)}`); } function ensureBuffer(str) { if (Buffer.isBuffer(str)) { return str; } if (typeof str === "string") { if (isHexString$1(str)) { const s = ensureEvenLengthHexString(str, false); return Buffer.from(s, "hex"); } return Buffer.from(str, "utf8"); } throw standardErrors.rpc.invalidParams(`Not binary data: ${String(str)}`); } function ensureIntNumber(num) { if (typeof num === "number" && Number.isInteger(num)) { return IntNumber(num); } if (typeof num === "string") { if (INT_STRING_REGEX.test(num)) { return IntNumber(Number(num)); } if (isHexString$1(num)) { return IntNumber(Number(BigInt(ensureEvenLengthHexString(num, true)))); } } throw standardErrors.rpc.invalidParams(`Not an integer: ${String(num)}`); } function ensureBigInt(val) { if (val !== null && (typeof val === "bigint" || isBigNumber(val))) { return BigInt(val.toString(10)); } if (typeof val === "number") { return BigInt(ensureIntNumber(val)); } if (typeof val === "string") { if (INT_STRING_REGEX.test(val)) { return BigInt(val); } if (isHexString$1(val)) { return BigInt(ensureEvenLengthHexString(val, true)); } } throw standardErrors.rpc.invalidParams(`Not an integer: ${String(val)}`); } function ensureParsedJSONObject(val) { if (typeof val === "string") { return JSON.parse(val); } if (typeof val === "object") { return val; } throw standardErrors.rpc.invalidParams(`Not a JSON string or an object: ${String(val)}`); } function isBigNumber(val) { if (val == null || typeof val.constructor !== "function") { return false; } const { constructor } = val; return typeof constructor.config === "function" && typeof constructor.EUCLID === "number"; } async function generateKeyPair() { return crypto.subtle.generateKey({ name: "ECDH", namedCurve: "P-256" }, true, ["deriveKey"]); } async function deriveSharedSecret(ownPrivateKey, peerPublicKey) { return crypto.subtle.deriveKey({ name: "ECDH", public: peerPublicKey }, ownPrivateKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]); } async function encrypt(sharedSecret, plainText) { const iv = crypto.getRandomValues(new Uint8Array(12)); const cipherText = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, sharedSecret, new TextEncoder().encode(plainText)); return { iv, cipherText }; } async function decrypt(sharedSecret, { iv, cipherText }) { const plainText = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, sharedSecret, cipherText); return new TextDecoder().decode(plainText); } function getFormat(keyType) { switch (keyType) { case "public": return "spki"; case "private": return "pkcs8"; } } async function exportKeyToHexString(type, key) { const format = getFormat(type); const exported = await crypto.subtle.exportKey(format, key); return uint8ArrayToHex(new Uint8Array(exported)); } async function importKeyFromHexString(type, hexString) { const format = getFormat(type); const arrayBuffer = hexStringToUint8Array(hexString).buffer; return await crypto.subtle.importKey(format, new Uint8Array(arrayBuffer), { name: "ECDH", namedCurve: "P-256" }, true, type === "private" ? ["deriveKey"] : []); } async function encryptContent(content, sharedSecret) { const serialized = JSON.stringify(content, (_2, value) => { if (!(value instanceof Error)) return value; const error = value; return Object.assign(Object.assign({}, error.code ? { code: error.code } : {}), { message: error.message }); }); return encrypt(sharedSecret, serialized); } async function decryptContent(encryptedData, sharedSecret) { return JSON.parse(await decrypt(sharedSecret, encryptedData)); } const OWN_PRIVATE_KEY = { storageKey: "ownPrivateKey", keyType: "private" }; const OWN_PUBLIC_KEY = { storageKey: "ownPublicKey", keyType: "public" }; const PEER_PUBLIC_KEY = { storageKey: "peerPublicKey", keyType: "public" }; class SCWKeyManager { constructor() { this.storage = new ScopedLocalStorage("CBWSDK", "SCWKeyManager"); this.ownPrivateKey = null; this.ownPublicKey = null; this.peerPublicKey = null; this.sharedSecret = null; } async getOwnPublicKey() { await this.loadKeysIfNeeded(); return this.ownPublicKey; } // returns null if the shared secret is not yet derived async getSharedSecret() { await this.loadKeysIfNeeded(); return this.sharedSecret; } async setPeerPublicKey(key) { this.sharedSecret = null; this.peerPublicKey = key; await this.storeKey(PEER_PUBLIC_KEY, key); await this.loadKeysIfNeeded(); } async clear() { this.ownPrivateKey = null; this.ownPublicKey = null; this.peerPublicKey = null; this.sharedSecret = null; this.storage.removeItem(OWN_PUBLIC_KEY.storageKey); this.storage.removeItem(OWN_PRIVATE_KEY.storageKey); this.storage.removeItem(PEER_PUBLIC_KEY.storageKey); } async generateKeyPair() { const newKeyPair = await generateKeyPair(); this.ownPrivateKey = newKeyPair.privateKey; this.ownPublicKey = newKeyPair.publicKey; await this.storeKey(OWN_PRIVATE_KEY, newKeyPair.privateKey); await this.storeKey(OWN_PUBLIC_KEY, newKeyPair.publicKey); } async loadKeysIfNeeded() { if (this.ownPrivateKey === null) { this.ownPrivateKey = await this.loadKey(OWN_PRIVATE_KEY); } if (this.ownPublicKey === null) { this.ownPublicKey = await this.loadKey(OWN_PUBLIC_KEY); } if (this.ownPrivateKey === null || this.ownPublicKey === null) { await this.generateKeyPair(); } if (this.peerPublicKey === null) { this.peerPublicKey = await this.loadKey(PEER_PUBLIC_KEY); } if (this.sharedSecret === null) { if (this.ownPrivateKey === null || this.peerPublicKey === null) return; this.sharedSecret = await deriveSharedSecret(this.ownPrivateKey, this.peerPublicKey); } } // storage methods async loadKey(item) { const key = this.storage.getItem(item.storageKey); if (!key) return null; return importKeyFromHexString(item.keyType, key); } async storeKey(item, key) { const hexString = await exportKeyToHexString(item.keyType, key); this.storage.setItem(item.storageKey, hexString); } } const VERSION = "4.3.0"; const NAME = "@coinbase/wallet-sdk"; async function fetchRPCRequest(request, rpcUrl) { const requestBody = Object.assign(Object.assign({}, request), { jsonrpc: "2.0", id: crypto.randomUUID() }); const res = await window.fetch(rpcUrl, { method: "POST", body: JSON.stringify(requestBody), mode: "cors", headers: { "Content-Type": "application/json", "X-Cbw-Sdk-Version": VERSION, "X-Cbw-Sdk-Platform": NAME } }); const { result, error } = await res.json(); if (error) throw error; return result; } function getCoinbaseInjectedLegacyProvider() { const window2 = globalThis; return window2.coinbaseWalletExtension; } function getInjectedEthereum() { var _a, _b; try { const window2 = globalThis; return (_a = window2.ethereum) !== null && _a !== void 0 ? _a : (_b = window2.top) === null || _b === void 0 ? void 0 : _b.ethereum; } catch (_c) { return void 0; } } function getCoinbaseInjectedProvider({ metadata, preference }) { var _a, _b; const { appName, appLogoUrl, appChainIds } = metadata; if (preference.options !== "smartWalletOnly") { const extension = getCoinbaseInjectedLegacyProvider(); if (extension) { (_a = extension.setAppInfo) === null || _a === void 0 ? void 0 : _a.call(extension, appName, appLogoUrl, appChainIds, preference); return extension; } } const ethereum = getInjectedEthereum(); if (ethereum === null || ethereum === void 0 ? void 0 : ethereum.isCoinbaseBrowser) { (_b = ethereum.setAppInfo) === null || _b === void 0 ? void 0 : _b.call(ethereum, appName, appLogoUrl, appChainIds, preference); return ethereum; } return void 0; } function checkErrorForInvalidRequestArgs(args) { if (!args || typeof args !== "object" || Array.isArray(args)) { throw standardErrors.rpc.invalidParams({ message: "Expected a single, non-array, object argument.", data: args }); } const { method, params } = args; if (typeof method !== "string" || method.length === 0) { throw standardErrors.rpc.invalidParams({ message: "'args.method' must be a non-empty string.", data: args }); } if (params !== void 0 && !Array.isArray(params) && (typeof params !== "object" || params === null)) { throw standardErrors.rpc.invalidParams({ message: "'args.params' must be an object or array if provided.", data: args }); } switch (method) { case "eth_sign": case "eth_signTypedData_v2": case "eth_subscribe": case "eth_unsubscribe": throw standardErrors.provider.unsupportedMethod(); } } const ACCOUNTS_KEY = "accounts"; const ACTIVE_CHAIN_STORAGE_KEY = "activeChain"; const AVAILABLE_CHAINS_STORAGE_KEY = "availableChains"; const WALLET_CAPABILITIES_STORAGE_KEY = "walletCapabilities"; class SCWSigner { constructor(params) { var _a, _b, _c; this.metadata = params.metadata; this.communicator = params.communicator; this.callback = params.callback; this.keyManager = new SCWKeyManager(); this.storage = new ScopedLocalStorage("CBWSDK", "SCWStateManager"); this.accounts = (_a = this.storage.loadObject(ACCOUNTS_KEY)) !== null && _a !== void 0 ? _a : []; this.chain = this.storage.loadObject(ACTIVE_CHAIN_STORAGE_KEY) || { id: (_c = (_b = params.metadata.appChainIds) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : 1 }; this.handshake = this.handshake.bind(this); this.request = this.request.bind(this); this.createRequestMessage = this.createRequestMessage.bind(this); this.decryptResponseMessage = this.decryptResponseMessage.bind(this); } async handshake(args) { var _a, _b, _c, _d; await ((_b = (_a = this.communicator).waitForPopupLoaded) === null || _b === void 0 ? void 0 : _b.call(_a)); const handshakeMessage = await this.createRequestMessage({ handshake: { method: args.method, params: Object.assign({}, this.metadata, (_c = args.params) !== null && _c !== void 0 ? _c : {}) } }); const response = await this.communicator.postRequestAndWaitForResponse(handshakeMessage); if ("failure" in response.content) throw response.content.failure; const peerPublicKey = await importKeyFromHexString("public", response.sender); await this.keyManager.setPeerPublicKey(peerPublicKey); const decrypted = await this.decryptResponseMessage(response); const result = decrypted.result; if ("error" in result) throw result.error; switch (args.method) { case "eth_requestAccounts": { const accounts = result.value; this.accounts = accounts; this.storage.storeObject(ACCOUNTS_KEY, accounts); (_d = this.callback) === null || _d === void 0 ? void 0 : _d.call(this, "accountsChanged", accounts); break; } } } async request(request) { var _a; if (this.accounts.length === 0) { switch (request.method) { case "wallet_sendCalls": return this.sendRequestToPopup(request); default: throw standardErrors.provider.unauthorized(); } } switch (request.method) { case "eth_requestAccounts": (_a = this.callback) === null || _a === void 0 ? void 0 : _a.call(this, "connect", { chainId: hexStringFromNumber(this.chain.id) }); return this.accounts; case "eth_accounts": return this.accounts; case "eth_coinbase": return this.accounts[0]; case "net_version": return this.chain.id; case "eth_chainId": return hexStringFromNumber(this.chain.id); case "wallet_getCapabilities": return this.storage.loadObject(WALLET_CAPABILITIES_STORAGE_KEY); case "wallet_switchEthereumChain": return this.handleSwitchChainRequest(request); case "eth_ecRecover": case "personal_sign": case "wallet_sign": case "personal_ecRecover": case "eth_signTransaction": case "eth_sendTransaction": case "eth_signTypedData_v1": case "eth_signTypedData_v3": case "eth_signTypedData_v4": case "eth_signTypedData": case "wallet_addEthereumChain": case "wallet_watchAsset": case "wallet_sendCalls": case "wallet_showCallsStatus": case "wallet_grantPermissions": return this.sendRequestToPopup(request); default: if (!this.chain.rpcUrl) throw standardErrors.rpc.internal("No RPC URL set for chain"); return fetchRPCRequest(request, this.chain.rpcUrl); } } async sendRequestToPopup(request) { var _a, _b; await ((_b = (_a = this.communicator).waitForPopupLoaded) === null || _b === void 0 ? void 0 : _b.call(_a)); const response = await this.sendEncryptedRequest(request); const decrypted = await this.decryptResponseMessage(response); const result = decrypted.result; if ("error" in result) throw result.error; return result.value; } async cleanup() { var _a, _b; this.storage.clear(); await this.keyManager.clear(); this.accounts = []; this.chain = { id: (_b = (_a = this.metadata.appChainIds) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 1 }; } /** * @returns `null` if the request was successful. * https://eips.ethereum.org/EIPS/eip-3326#wallet_switchethereumchain */ async handleSwitchChainRequest(request) { var _a; const params = request.params; if (!params || !((_a = params[0]) === null || _a === void 0 ? void 0 : _a.chainId)) { throw standardErrors.rpc.invalidParams(); } const chainId = ensureIntNumber(params[0].chainId); const localResult = this.updateChain(chainId); if (localResult) return null; const popupResult = await this.sendRequestToPopup(request); if (popupResult === null) { this.updateChain(chainId); } return popupResult; } async sendEncryptedRequest(request) { const sharedSecret = await this.keyManager.getSharedSecret(); if (!sharedSecret) { throw standardErrors.provider.unauthorized("No valid session found, try requestAccounts before other methods"); } const encrypted = await encryptContent({ action: request, chainId: this.chain.id }, sharedSecret); const message = await this.createRequestMessage({ encrypted }); return this.communicator.postRequestAndWaitForResponse(message); } async createRequestMessage(content) { const publicKey = await exportKeyToHexString("public", await this.keyManager.getOwnPublicKey()); return { id: crypto.randomUUID(), sender: publicKey, content, timestamp: /* @__PURE__ */ new Date() }; } async decryptResponseMessage(message) { var _a, _b; const content = message.content; if ("failure" in content) { throw content.failure; } const sharedSecret = await this.keyManager.getSharedSecret(); if (!sharedSecret) { throw standardErrors.provider.unauthorized("Invalid session"); } const response = await decryptContent(content.encrypted, sharedSecret); const availableChains = (_a = response.data) === null || _a === void 0 ? void 0 : _a.chains; if (availableChains) { const chains = Object.entries(availableChains).map(([id, rpcUrl]) => ({ id: Number(id), rpcUrl })); this.storage.storeObject(AVAILABLE_CHAINS_STORAGE_KEY, chains); this.updateChain(this.chain.id, chains); } const walletCapabilities = (_b = response.data) === null || _b === void 0 ? void 0 : _b.capabilities; if (walletCapabilities) { this.storage.storeObject(WALLET_CAPABILITIES_STORAGE_KEY, walletCapabilities); } return response; } updateChain(chainId, newAvailableChains) { var _a; const chains = newAvailableChains !== null && newAvailableChains !== void 0 ? newAvailableChains : this.storage.loadObject(AVAILABLE_CHAINS_STORAGE_KEY); const chain = chains === null || chains === void 0 ? void 0 : chains.find((chain2) => chain2.id === chainId); if (!chain) return false; if (chain !== this.chain) { this.chain = chain; this.storage.storeObject(ACTIVE_CHAIN_STORAGE_KEY, chain); (_a = this.callback) === null || _a === void 0 ? void 0 : _a.call(this, "chainChanged", hexStringFromNumber(chain.id)); } return true; } } const require$$0 = /* @__PURE__ */ getAugmentedNamespace(sha3); const { keccak_256 } = require$$0; function zeros(bytes) { return Buffer.allocUnsafe(bytes).fill(0); } function bitLengthFromBigInt(num) { return num.toString(2).length; } function bufferBEFromBigInt(num, length) { let hex = num.toString(16); if (hex.length % 2 !== 0) hex = "0" + hex; const byteArray = hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)); while (byteArray.length < length) { byteArray.unshift(0); } return Buffer.from(byteArray); } function twosFromBigInt(value, width) { const isNegative = value < 0n; let result; if (isNegative) { const mask = (1n << BigInt(width)) - 1n; result = (~value & mask) + 1n; } else { result = value; } result &= (1n << BigInt(width)) - 1n; return result; } function setLength(msg, length, right) { const buf = zeros(length); msg = toBuffer(msg); if (right) { if (msg.length < length) { msg.copy(buf); return buf; } return msg.slice(0, length); } else { if (msg.length < length) { msg.copy(buf, length - msg.length); return buf; } return msg.slice(-length); } } function setLengthRight(msg, length) { return setLength(msg, length, true); } function toBuffer(v) { if (!Buffer.isBuffer(v)) { if (Array.isArray(v)) { v = Buffer.from(v); } else if (typeof v === "string") { if (isHexString(v)) { v = Buffer.from(padToEven(stripHexPrefix(v)), "hex"); } else { v = Buffer.from(v); } } else if (typeof v === "number") { v = intToBuffer(v); } else if (v === null || v === void 0) { v = Buffer.allocUnsafe(0); } else if (typeof v === "bigint") { v = bufferBEFromBigInt(v); } else if (v.toArray) { v = Buffer.from(v.toArray()); } else { throw new Error("invalid type"); } } return v; } function bufferToHex(buf) { buf = toBuffer(buf); return "0x" + buf.toString("hex"); } function keccak(a, bits) { a = toBuffer(a); if (!bits) bits = 256; if (bits !== 256) { throw new Error("unsupported"); } return Buffer.from(keccak_256(new Uint8Array(a))); } function padToEven(str) { return str.length % 2 ? "0" + str : str; } function isHexString(str) { return typeof str === "string" && str.match(/^0x[0-9A-Fa-f]*$/); } function stripHexPrefix(str) { if (typeof str === "string" && str.startsWith("0x")) { return str.slice(2); } return str; } var util$2 = { zeros, setLength, setLengthRight, isHexString, stripHexPrefix, toBuffer, bufferToHex, keccak, bitLengthFromBigInt, bufferBEFromBigInt, twosFromBigInt }; const util$1 = util$2; function elementaryName(name) { if (name.startsWith("int[")) { return "int256" + name.slice(3); } else if (name === "int") { return "int256"; } else if (name.startsWith("uint[")) { return "uint256" + name.slice(4); } else if (name === "uint") { return "uint256"; } else if (name.startsWith("fixed[")) { return "fixed128x128" + name.slice(5); } else if (name === "fixed") { return "fixed128x128"; } else if (name.startsWith("ufixed[")) { return "ufixed128x128" + name.slice(6); } else if (name === "ufixed") { return "ufixed128x128"; } return name; } function parseTypeN(type) { return Number.parseInt(/^\D+(\d+)$/.exec(type)[1], 10); } function parseTypeNxM(type) { var tmp = /^\D+(\d+)x(\d+)$/.exec(type); return [Number.parseInt(tmp[1], 10), Number.parseInt(tmp[2], 10)]; } function parseTypeArray(type) { var tmp = type.match(/(.*)\[(.*?)\]$/); if (tmp) { return tmp[2] === "" ? "dynamic" : Number.parseInt(tmp[2], 10); } return null; } function parseNumber(arg) { var type = typeof arg; if (type === "string" || type === "number") { return BigInt(arg); } else if (type === "bigint") { return arg; } else { throw new Error("Argument is not a number"); } } function encodeSingle(type, arg) { var size, num, ret, i; if (type === "address") { return encodeSingle("uint160", parseNumber(arg)); } else if (type === "bool") { return encodeSingle("uint8", arg ? 1 : 0); } else if (type === "string") { return encodeSingle("bytes", new Buffer(arg, "utf8")); } else if (isArray(type)) { if (typeof arg.length === "undefined") { throw new Error("Not an array?"); } size = parseTypeArray(type); if (size !== "dynamic" && size !== 0 && arg.length > size) { throw new Error("Elements exceed array size: " + size); } ret = []; type = type.slice(0, type.lastIndexOf("[")); if (typeof arg === "string") { arg = JSON.parse(arg); } for (i in arg) { ret.push(encodeSingle(type, arg[i])); } if (size === "dynamic") { var length = encodeSingle("uint256", arg.length); ret.unshift(length); } return Buffer.concat(ret); } else if (type === "bytes") { arg = new Buffer(arg); ret = Buffer.concat([encodeSingle("uint256", arg.length), arg]); if (arg.length % 32 !== 0) { ret = Buffer.concat([ret, util$1.zeros(32 - arg.length % 32)]); } return ret; } else if (type.startsWith("bytes")) { size = parseTypeN(type); if (size < 1 || size > 32) { throw new Error("Invalid bytes<N> width: " + size); } return util$1.setLengthRight(arg, 32); } else if (type.startsWith("uint")) { size = parseTypeN(type); if (size % 8 || size < 8 || size > 256) { throw new Error("Invalid uint<N> width: " + size); } num = parseNumber(arg); const bitLength = util$1.bitLengthFromBigInt(num); if (bitLength > size) { throw new Error("Supplied uint exceeds width: " + size + " vs " + bitLength); } if (num < 0) { throw new Error("Supplied uint is negative"); } return util$1.bufferBEFromBigInt(num, 32); } else if (type.startsWith("int")) { size = parseTypeN(type); if (size % 8 || size < 8 || size > 256) { throw new Error("Invalid int<N> width: " + size); } num = parseNumber(arg); const bitLength = util$1.bitLengthFromBigInt(num); if (bitLength > size) { throw new Error("Supplied int exceeds width: " + size + " vs " + bitLength); } const twos = util$1.twosFromBigInt(num, 256); return util$1.bufferBEFromBigInt(twos, 32); } else if (type.startsWith("ufixed")) { size = parseTypeNxM(type); num = parseNumber(arg); if (num < 0) { throw new Error("Supplied ufixed is negative"); } return encodeSingle("uint256", num * BigInt(2) ** BigInt(size[1])); } else if (type.startsWith("fixed")) { size = parseTypeNxM(type); return encodeSingle("int256", parseNumber(arg) * BigInt(2) ** BigInt(size[1])); } throw new Error("Unsupported or invalid type: " + type); } function isDynamic(type) { return type === "string" || type === "bytes" || parseTypeArray(type) === "dynamic"; } function isArray(type) { return type.lastIndexOf("]") === type.length - 1; } function rawEncode(types, values) { var output = []; var data = []; var headLength = 32 * types.length; for (var i in types) { var type = elementaryName(types[i]); var value = values[i]; var cur = encodeSingle(type, value); if (isDynamic(type)) { output.push(encodeSingle("uint256", headLength)); data.push(cur); headLength += cur.length; } else { output.push(cur); } } return Buffer.concat(output.concat(data)); } function solidityPack(types, values) { if (types.length !== values.length) { throw new Error("Number of types are not matching the values"); } var size, num; var ret = []; for (var i = 0; i < types.length; i++) { var type = elementaryName(types[i]); var value = values[i]; if (type === "bytes") { ret.push(value); } else if (type === "string") { ret.push(new Buffer(value, "utf8")); } else if (type === "bool") { ret.push(new Buffer(value ? "01" : "00", "hex")); } else if (type === "address") { ret.push(util$1.setLength(value, 20)); } else if (type.startsWith("bytes")) { size = parseTypeN(type); if (size < 1 || size > 32) { throw new Error("Invalid bytes<N> width: " + size); } ret.push(util$1.setLengthRight(value, size)); } else if (type.startsWith("uint")) { size = parseTypeN(type); if (size % 8 || size < 8 || size > 256) { throw new Error("Invalid uint<N> width: " + size); } num = parseNumber(value); const bitLength = util$1.bitLengthFromBigInt(num); if (bitLength > size) { throw new Error("Supplied uint exceeds width: " + size + " vs " + bitLength); } ret.push(util$1.bufferBEFromBigInt(num, size / 8)); } else if (type.startsWith("int")) { size = parseTypeN(type); if (size % 8 || size < 8 || size > 256) { throw new Error("Invalid int<N> width: " + size); } num = parseNumber(value); const bitLength = util$1.bitLengthFromBigInt(num); if (bitLength > size) { throw new Error("Supplied int exceeds width: " + size + " vs " + bitLength); } const twos = util$1.twosFromBigInt(num, size); ret.push(util$1.bufferBEFromBigInt(twos, size / 8)); } else { throw new Error("Unsupported or invalid type: " + type); } } return Buffer.concat(ret); } function soliditySHA3(types, values) { return util$1.keccak(solidityPack(types, values)); } var abi$1 = { rawEncode, solidityPack, soliditySHA3 }; const util = util$2; const abi = abi$1; const TYPED_MESSAGE_SCHEMA = { type: "object", properties: { types: { type: "object", additionalProperties: { type: "array", items: { type: "object", properties: { name: { type: "string" }, type: { type: "string" } }, required: ["name", "type"] } } }, primaryType: { type: "string" }, domain: { type: "object" }, message: { type: "object" } }, required: ["types", "primaryType", "domain", "message"] }; const TypedDataUtils = { /** * Encodes an object by encoding and concatenating each of its members * * @param {string} primaryType - Root type * @param {Object} data - Object to encode * @param {Object} types - Type definitions * @returns {string} - Encoded representation of an object */ encodeData(primaryType, data, types, useV4 = true) { const encodedTypes = ["bytes32"]; const encodedValues = [this.hashType(primaryType, types)]; if (useV4) { const encodeField = (name, type, value) => { if (types[type] !== void 0) { return ["bytes32", value == null ? "0x0000000000000000000000000000000000000000000000000000000000000000" : util.keccak(this.encodeData(type, value, types, useV4))]; } if (value === void 0) throw new Error(`missing value for field ${name} of type ${type}`); if (type === "bytes") { return ["bytes32", util.keccak(value)]; } if (type === "string") { if (typeof value === "string") { value = Buffer.from(value, "utf8"); } return ["bytes32", util.keccak(value)]; } if (type.lastIndexOf("]") === type.length - 1) { const parsedType = type.slice(0, type.lastIndexOf("[")); const typeValuePairs = value.map((item) => encodeField(name, parsedType, item)); return ["bytes32", util.keccak(abi.rawEncode( typeValuePairs.map(([type2]) => type2), typeValuePairs.map(([, value2]) => value2) ))]; } return [type, value]; }; for (const field of types[primaryType]) { const [type, value] = encodeField(field.name, field.type, data[field.name]); encodedTypes.push(type); encodedValues.push(value); } } else { for (const field of types[primaryType]) { let value = data[field.name]; if (value !== void 0) { if (field.type === "bytes") { encodedTypes.push("bytes32"); value = util.keccak(value); encodedValues.push(value); } else if (field.type === "string") { encodedTypes.push("bytes32"); if (typeof value === "string") { value = Buffer.from(value, "utf8"); } value = util.keccak(value); encodedValues.push(value); } else if (types[field.type] !== void 0) { encodedTypes.push("bytes32"); value = util.keccak(this.encodeData(field.type, value, types, useV4)); encodedValues.push(value); } else if (field.type.lastIndexOf("]") === field.type.length - 1) { throw new Error("Arrays currently unimplemented in encodeData"); } else { encodedTypes.push(field.type); encodedValues.push(value); } } } } return abi.rawEncode(encodedTypes, encodedValues); }, /** * Encodes the type of an object by encoding a comma delimited list of its members * * @param {string} primaryType - Root type to encode * @param {Object} types - Type definitions * @returns {string} - Encoded representation of the type of an object */ encodeType(primaryType, types) { let result = ""; let deps = this.findTypeDependencies(primaryType, types).filter((dep) => dep !== primaryType); deps = [primaryType].concat(deps.sort()); for (const type of deps) { const children = types[type]; if (!children) { throw new Error("No type definition specified: " + type); } result += type + "(" + types[type].map(({ name, type: type2 }) => type2 + " " + name).join(",") + ")"; } return result; }, /** * Finds all types within a type definition object * * @param {string} primaryType - Root type * @param {Object} types - Type definitions * @param {Array} results - current set of accumulated types * @returns {Array} - Set of all types found in the type definition */ findTypeDependencies(primaryType, types, results = []) { primaryType = primaryType.match(/^\w*/)[0]; if (results.includes(primaryType) || types[primaryType] === void 0) { return results; } results.push(primaryType); for (const field of types[primaryType]) { for (const dep of this.findTypeDependencies(field.type, types, results)) { !results.includes(dep) && results.push(dep); } } return results; }, /** * Hashes an object * * @param {string} primaryType - Root type * @param {Object} data - Object to hash * @param {Object} types - Type definitions * @returns {Buffer} - Hash of an object */ hashStruct(primaryType, data, types, useV4 = true) { return util.keccak(this.encodeData(primaryType, data, types, useV4)); }, /** * Hashes the type of an object * * @param {string} primaryType - Root type to hash * @param {Object} types - Type definitions * @returns {string} - Hash of an object */ hashType(primaryType, types) { return util.keccak(this.encodeType(primaryType, types)); }, /** * Removes properties from a message object that are not defined per EIP-712 * * @param {Object} data - typed message object * @returns {Object} - typed message object with only allowed fields */ sanitizeData(data) { const sanitizedData = {}; for (const key in TYPED_MESSAGE_SCHEMA.properties) { data[key] && (sanitizedData[key] = data[key]); } if (sanitizedData.types) { sanitizedData.types = Object.assign({ EIP712Domain: [] }, sanitizedData.types); } return sanitizedData; }, /** * Returns the hash of a typed message as per EIP-712 for signing * * @param {Object} typedData - Types message data to sign * @returns {string} - sha3 hash for signing */ hash(typedData, useV4 = true) { const sanitizedData = this.sanitizeData(typedData); const parts = [Buffer.from("1901", "hex")]; parts.push(this.hashStruct("EIP712Domain", sanitizedData.domain, sanitizedData.types, useV4)); if (sanitizedData.primaryType !== "EIP712Domain") { parts.push(this.hashStruct(sanitizedData.primaryType, sanitizedData.message, sanitizedData.types, useV4)); } return util.keccak(Buffer.concat(parts)); } }; var ethEip712Util = { TYPED_MESSAGE_SCHEMA, TypedDataUtils, hashForSignTypedDataLegacy: function(msgParams) { return typedSignatureHashLegacy(msgParams.data); }, hashForSignTypedData_v3: function(msgParams) { return TypedDataUtils.hash(msgParams.data, false); }, hashForSignTypedData_v4: function(msgParams) { return TypedDataUtils.hash(msgParams.data); } }; function typedSignatureHashLegacy(typedData) { const error = new Error("Expect argument to be non-empty array"); if (typeof typedData !== "object" || !typedData.length) throw error; const data = typedData.map(function(e) { return e.type === "bytes" ? util.toBuffer(e.value) : e.value; }); const types = typedData.map(function(e) { return e.type; }); const schema = typedData.map(function(e) { if (!e.name) throw error; return e.type + " " + e.name; }); return abi.soliditySHA3( ["bytes32", "bytes32"], [ abi.soliditySHA3(new Array(typedData.length).fill("string"), schema), abi.soliditySHA3(types, data) ] ); } const eip712 = /* @__PURE__ */ getDefaultExportFromCjs(ethEip712Util); const WALLET_USER_NAME_KEY = "walletUsername"; const LOCAL_STORAGE_ADDRESSES_KEY = "Addresses"; const APP_VERSION_KEY = "AppVersion"; function isErrorResponse(response) { return response.errorMessage !== void 0; } class WalletLinkCipher { // @param secret hex representation of 32-byte secret constructor(secret) { this.secret = secret; } /** * * @param plainText string to be encrypted * returns hex string representation of bytes in the order: initialization vector (iv), * auth tag, encrypted plaintext. IV is 12 bytes. Auth tag is 16 bytes. Remaining bytes are the * encrypted plainText. */ async encrypt(plainText) { const secret = this.secret; if (secret.length !== 64) throw Error(`secret must be 256 bits`); const ivBytes = crypto.getRandomValues(new Uint8Array(12)); const secretKey = await crypto.subtle.importKey("raw", hexStringToUint8Array(secret), { name: "aes-gcm" }, false, ["encrypt", "decrypt"]); const enc = new TextEncoder(); const encryptedResult = await window.crypto.subtle.encrypt({ name: "AES-GCM", iv: ivBytes }, secretKey, enc.encode(plainText)); const tagLength = 16; const authTag = encryptedResult.slice(encryptedResult.byteLength - tagLength); const encryptedPlaintext = encryptedResult.slice(0, encryptedResult.byteLength - tagLength); const authTagBytes = new Uint8Array(authTag); const encryptedPlaintextBytes = new Uint8Array(encryptedPlaintext); const concatted = new Uint8Array([...ivBytes, ...authTagBytes, ...encryptedPlaintextBytes]); return uint8ArrayToHex(concatted); } /** * * @param cipherText hex string representation of bytes in the order: initialization vector (iv), * auth tag, encrypted plaintext. IV is 12 bytes. Auth tag is 16 bytes. */ async decrypt(cipherText) { const secret = this.secret; if (secret.length !== 64) throw Error(`secret must be 256 bits`); return new Promise((resolve, reject) => { void async function() { const secretKey = await crypto.subtle.importKey("raw", hexStringToUint8Array(secret), { name: "aes-gcm" }, false, ["encrypt", "decrypt"]); const encrypted = hexStringToUint8Array(cipherText); const ivBytes = encrypted.slice(0, 12); const authTagBytes = encrypted.slice(12, 28); const encryptedPlaintextBytes = encrypted.slice(28); const concattedBytes = new Uint8Array([...encryptedPlaintextBytes, ...authTagBytes]); const algo = { name: "AES-GCM", iv: new Uint8Array(ivBytes) }; try { const decrypted = await window.crypto.subtle.decrypt(algo, secretKey, concattedBytes); const decoder = new TextDecoder(); resolve(decoder.decode(decrypted)); } catch (err) { reject(err); } }(); }); } } class WalletLinkHTTP { constructor(linkAPIUrl, sessionId, sessionKey) { this.linkAPIUrl = linkAPIUrl; this.sessionId = sessionId; const credentials = `${sessionId}:${sessionKey}`; this.auth = `Basic ${btoa(credentials)}`; } // mark unseen events as seen async markUnseenEventsAsSeen(events) { return Pro