UNPKG

@web3auth/no-modal

Version:
188 lines (184 loc) 8.09 kB
'use strict'; var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var _defineProperty = require('@babel/runtime/helpers/defineProperty'); var kit = require('@solana/kit'); var walletStandardFeatures = require('@solana/wallet-standard-features'); var features = require('@wallet-standard/features'); var wsEmbed = require('@web3auth/ws-embed'); require('@segment/analytics-next'); require('../../base/loglevel.js'); require('@toruslabs/base-controllers'); require('@toruslabs/session-manager'); require('@web3auth/auth'); var index$1 = require('../../base/errors/index.js'); require('@toruslabs/constants'); require('@toruslabs/http-helpers'); var constants = require('../../base/constants.js'); var index = require('../../base/wallet/index.js'); require('../../base/connector/connectorStatus.js'); require('../../base/connector/constants.js'); require('jwt-decode'); require('../../base/plugin/errors.js'); require('../../base/plugin/IPlugin.js'); var solana = require('../../base/wallet/solana.js'); const base58Encoder = kit.getBase58Encoder(); const base64Decoder = kit.getBase64Decoder(); const base64Encoder = kit.getBase64Encoder(); const transactionDecoder = kit.getTransactionDecoder(); const ACCOUNT_FEATURES = [walletStandardFeatures.SolanaSignAndSendTransaction, walletStandardFeatures.SolanaSignMessage, walletStandardFeatures.SolanaSignTransaction]; function solanaWalletChainsFromConfigs(solanaChainConfigs) { const ids = solanaChainConfigs.map(solana.getSolanaChainByChainConfig).filter(id => id != null); const unique = [...new Set(ids)]; return unique; } const SOLANA_PROVIDER_HEX_CHAIN_IDS = new Set(Object.keys(constants.SOLANA_CAIP_CHAIN_MAP).map(id => id.toLowerCase())); /** * AuthSolanaWallet implements the Wallet Standard interface, wrapping a JRPC provider. * Used by AuthConnector so consumers get a standards-compliant Wallet from `connection.solanaWallet`. * * {@link Wallet.accounts} is synchronous in the Wallet Standard; it returns `[]` until accounts have been loaded * (`null` internally). The first async operation ({@link StandardConnect}, sign, etc.) calls `ensureAccountsLoaded`, which * requires {@link IProvider.chainId} to be a configured Solana network (see {@link SOLANA_CAIP_CHAIN_MAP}) before {@link SOLANA_METHOD_TYPES.GET_ACCOUNTS}. */ class AuthSolanaWallet { /** * @param solanaChainConfigs - All configured Solana {@link CustomChainConfig} entries (same namespace). */ constructor(_provider, solanaChainConfigs) { _defineProperty(this, "_provider", void 0); _defineProperty(this, "version", "1.0.0"); _defineProperty(this, "name", "Web3Auth"); _defineProperty(this, "icon", index.WEB3AUTH_ICON); _defineProperty(this, "chains", void 0); _defineProperty(this, "features", void 0); _defineProperty(this, "_accounts", null); _defineProperty(this, "_listeners", {}); this._provider = _provider; this.chains = solanaWalletChainsFromConfigs(solanaChainConfigs); this.features = { [features.StandardConnect]: { version: "1.0.0", connect: async () => { await this.ensureAccountsLoaded(); return { accounts: this.accounts }; } }, [features.StandardDisconnect]: { version: "1.0.0", disconnect: async () => {} }, [features.StandardEvents]: { version: "1.0.0", on: (event, listener) => { var _this$_listeners, _this$_listeners$even; ((_this$_listeners$even = (_this$_listeners = this._listeners)[event]) !== null && _this$_listeners$even !== void 0 ? _this$_listeners$even : _this$_listeners[event] = new Set()).add(listener); return () => this._listeners[event].delete(listener); } }, [walletStandardFeatures.SolanaSignAndSendTransaction]: { version: "1.0.0", supportedTransactionVersions: ["legacy", 0], signAndSendTransaction: async (...inputs) => { await this.ensureAccountsLoaded(); return Promise.all(inputs.map(async input => { const base64Tx = base64Decoder.decode(input.transaction); const signature = await this._provider.request({ method: wsEmbed.SOLANA_METHOD_TYPES.SEND_TRANSACTION, params: { message: base64Tx } }); return { signature: new Uint8Array(base58Encoder.encode(signature)) }; })); } }, [walletStandardFeatures.SolanaSignMessage]: { version: "1.0.0", signMessage: async (...inputs) => { await this.ensureAccountsLoaded(); return Promise.all(inputs.map(async input => { const message = new TextDecoder().decode(input.message); const signature = await this._provider.request({ method: wsEmbed.SOLANA_METHOD_TYPES.SIGN_MESSAGE, params: { data: message, from: input.account.address } }); return { signedMessage: new Uint8Array(input.message), signature: new Uint8Array(base58Encoder.encode(signature)) }; })); } }, [walletStandardFeatures.SolanaSignTransaction]: { version: "1.0.0", supportedTransactionVersions: ["legacy", 0], signTransaction: async (...inputs) => { await this.ensureAccountsLoaded(); return Promise.all(inputs.map(async input => { const base64Tx = base64Decoder.decode(input.transaction); const signatureBase58 = await this._provider.request({ method: wsEmbed.SOLANA_METHOD_TYPES.SIGN_TRANSACTION, params: { message: base64Tx } }); const sigBytes = new Uint8Array(base58Encoder.encode(signatureBase58)); const decodedTx = transactionDecoder.decode(input.transaction); const signedTx = _objectSpread(_objectSpread({}, decodedTx), {}, { signatures: _objectSpread(_objectSpread({}, decodedTx.signatures), {}, { [input.account.address]: sigBytes }) }); const signedBase64 = kit.getBase64EncodedWireTransaction(signedTx); return { signedTransaction: new Uint8Array(base64Encoder.encode(signedBase64)) }; })); } } }; } /** * Wallet Standard requires a synchronous getter; RPC runs on first async wallet operation instead. */ get accounts() { var _this$_accounts; return (_this$_accounts = this._accounts) !== null && _this$_accounts !== void 0 ? _this$_accounts : []; } /** Throws if the embed is not on Solana; otherwise loads accounts once via {@link SOLANA_METHOD_TYPES.GET_ACCOUNTS}. */ async ensureAccountsLoaded() { var _await$this$_provider; // assert solana chain const chainId = this._provider.chainId; if (!SOLANA_PROVIDER_HEX_CHAIN_IDS.has(chainId.toLowerCase())) throw index$1.WalletLoginError.unsupportedOperation(`Solana wallet operations require the embedded provider to be on a Solana network (current chainId: ${chainId}). Switch chain first.`); if (this._accounts !== null) return; const addresses = (_await$this$_provider = await this._provider.request({ method: wsEmbed.SOLANA_METHOD_TYPES.GET_ACCOUNTS })) !== null && _await$this$_provider !== void 0 ? _await$this$_provider : []; const accountChains = this.chains; this._accounts = addresses.map(address => ({ address, publicKey: new Uint8Array(base58Encoder.encode(address)), chains: accountChains.length ? accountChains : [], features: ACCOUNT_FEATURES })); this.emitChange({ accounts: this.accounts }); } emitChange(properties) { const listeners = this._listeners.change; if (!listeners) return; listeners.forEach(listener => { listener(properties); }); } } exports.AuthSolanaWallet = AuthSolanaWallet;