@d13co/use-wallet 4.5.3 → 4.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -33,10 +33,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
33
  ));
34
34
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
 
36
- // ../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs
36
+ // ../../../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs
37
37
  var m, v, u, _, f, g, Z, E, y, x, A, R, I, N, h, T, O, S, b, C, F, U, k, L, w, D, G, V, H, q, W, J, Y, B, P, j, Q, X, z;
38
38
  var init_es = __esm({
39
- "../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs"() {
39
+ "../../../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs"() {
40
40
  "use strict";
41
41
  m = ((o) => (o.MissingApiKey = "MISSING_API_KEY", o.ModalNotReady = "MODAL_NOT_READY", o.ConnectionLost = "CONNECTION_WAS_LOST", o.MalformedResponse = "MALFORMED_RESPONSE", o.InvalidArgument = "INVALID_ARGUMENT", o.ExtensionNotInitialized = "EXTENSION_NOT_INITIALIZED", o.IncompatibleExtensions = "INCOMPATIBLE_EXTENSIONS", o))(m || {});
42
42
  v = ((s) => (s.SyncWeb3Method = "SYNC_WEB3_METHOD", s.DuplicateIframe = "DUPLICATE_IFRAME", s.ReactNativeEndpointConfiguration = "REACT_NATIVE_ENDPOINT_CONFIGURATION", s.DeprecationNotice = "DEPRECATION_NOTICE", s.ProductAnnouncement = "ANNOUNCEMENT", s))(v || {});
@@ -80,7 +80,7 @@ var init_es = __esm({
80
80
  }
81
81
  });
82
82
 
83
- // ../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs
83
+ // ../../../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs
84
84
  function ir(r10) {
85
85
  let e = { exports: {} };
86
86
  return r10(e, e.exports), e.exports;
@@ -383,7 +383,7 @@ function On(r10) {
383
383
  }
384
384
  var Yt, Ne, Qt, Zt, er, tr, rr, nr, sr, or, Nt, ar, $e, cr, h2, Z2, ze, ot, lr, dr, Ye, oe, Qe, Ze, X2, M, ur, J2, pr, mr, hr, Er, fr, gr, yr, Rr, vr, Tr, Ir, br, Pr, Ae, z2, Y2, et, tt, Q2, y2, E2, wr, xr, Sr, rt, Mr, T2, Cr, Nr, Ar, $r, Lr, Or, _r, kr, Dr, qr, it, Ur, nt, st, Fr, Wr, ie, ae, at, m2, ut, $, U2, L2, de, te, Qr, me, pe, R2, x2, A2, Zr, en, tn, rn, Oe, _e, he, bt, nn, sn, St, K, At, De, $t, f2, Tn, ye, Ue, Fe, We, Je, In, Te, Ie, Pe, we, H2, xe, Me, je, An, Ht, Bt, $n, Ve, Xt, Be, Ce, He;
385
385
  var init_es2 = __esm({
386
- "../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs"() {
386
+ "../../../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs"() {
387
387
  "use strict";
388
388
  init_es();
389
389
  init_es();
@@ -1503,16 +1503,16 @@ var init_es2 = __esm({
1503
1503
  }
1504
1504
  });
1505
1505
 
1506
- // ../../node_modules/.pnpm/@magic-sdk+commons@25.4.2_@magic-sdk+provider@29.5.0_localforage@1.10.0__@magic-sdk+types@24.22.0/node_modules/@magic-sdk/commons/dist/es/index.mjs
1506
+ // ../../../../node_modules/.pnpm/@magic-sdk+commons@25.4.2_@magic-sdk+provider@29.5.0_localforage@1.10.0__@magic-sdk+types@24.22.0/node_modules/@magic-sdk/commons/dist/es/index.mjs
1507
1507
  var init_es3 = __esm({
1508
- "../../node_modules/.pnpm/@magic-sdk+commons@25.4.2_@magic-sdk+provider@29.5.0_localforage@1.10.0__@magic-sdk+types@24.22.0/node_modules/@magic-sdk/commons/dist/es/index.mjs"() {
1508
+ "../../../../node_modules/.pnpm/@magic-sdk+commons@25.4.2_@magic-sdk+provider@29.5.0_localforage@1.10.0__@magic-sdk+types@24.22.0/node_modules/@magic-sdk/commons/dist/es/index.mjs"() {
1509
1509
  "use strict";
1510
1510
  init_es2();
1511
1511
  init_es();
1512
1512
  }
1513
1513
  });
1514
1514
 
1515
- // ../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs
1515
+ // ../../../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs
1516
1516
  var es_exports = {};
1517
1517
  __export(es_exports, {
1518
1518
  AuthEventOnReceived: () => k,
@@ -1571,7 +1571,7 @@ function st2(_2) {
1571
1571
  }
1572
1572
  var $r2, Qe2, Zr2, qr2, kr2, et2, de2, Je2, rt2, $e2, qe2, er2, pe2, Te2, at2, ye2, wt2;
1573
1573
  var init_es4 = __esm({
1574
- "../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs"() {
1574
+ "../../../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs"() {
1575
1575
  "use strict";
1576
1576
  init_es2();
1577
1577
  init_es2();
@@ -3195,14 +3195,14 @@ var init_es4 = __esm({
3195
3195
  }
3196
3196
  });
3197
3197
 
3198
- // ../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs
3198
+ // ../../../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs
3199
3199
  var es_exports2 = {};
3200
3200
  __export(es_exports2, {
3201
3201
  AlgorandExtension: () => r9
3202
3202
  });
3203
3203
  var r9;
3204
3204
  var init_es5 = __esm({
3205
- "../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs"() {
3205
+ "../../../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs"() {
3206
3206
  "use strict";
3207
3207
  init_es3();
3208
3208
  r9 = class extends He.Internal {
@@ -3232,9 +3232,9 @@ var init_es5 = __esm({
3232
3232
  }
3233
3233
  });
3234
3234
 
3235
- // ../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js
3235
+ // ../../../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js
3236
3236
  var require_nacl_fast = __commonJS({
3237
- "../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js"(exports2, module2) {
3237
+ "../../../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js"(exports2, module2) {
3238
3238
  "use strict";
3239
3239
  (function(nacl) {
3240
3240
  "use strict";
@@ -5479,12 +5479,11 @@ __export(index_exports, {
5479
5479
  LogLevel: () => LogLevel,
5480
5480
  LuteWallet: () => LuteWallet,
5481
5481
  MagicAuth: () => MagicAuth,
5482
- MetaMaskWallet: () => MetaMaskWallet,
5483
5482
  MnemonicWallet: () => MnemonicWallet,
5484
5483
  NetworkConfigBuilder: () => NetworkConfigBuilder,
5485
5484
  NetworkId: () => NetworkId,
5486
5485
  PeraWallet: () => PeraWallet,
5487
- RainbowWallet: () => RainbowWallet,
5486
+ RainbowKitWallet: () => RainbowKitWallet,
5488
5487
  ScopeType: () => ScopeType,
5489
5488
  SecureKeyContainer: () => SecureKeyContainer,
5490
5489
  SessionError: () => SessionError,
@@ -5577,7 +5576,7 @@ var Logger = class _Logger {
5577
5576
  var logger = Logger.getInstance();
5578
5577
 
5579
5578
  // src/manager.ts
5580
- var import_store16 = require("@tanstack/store");
5579
+ var import_store15 = require("@tanstack/store");
5581
5580
  var import_algosdk15 = __toESM(require("algosdk"), 1);
5582
5581
 
5583
5582
  // src/network.ts
@@ -5782,10 +5781,9 @@ var WalletId = /* @__PURE__ */ ((WalletId2) => {
5782
5781
  WalletId2["KMD"] = "kmd";
5783
5782
  WalletId2["LUTE"] = "lute";
5784
5783
  WalletId2["MAGIC"] = "magic";
5785
- WalletId2["METAMASK"] = "metamask";
5786
5784
  WalletId2["MNEMONIC"] = "mnemonic";
5787
5785
  WalletId2["PERA"] = "pera";
5788
- WalletId2["RAINBOW"] = "rainbow";
5786
+ WalletId2["RAINBOWKIT"] = "rainbowkit";
5789
5787
  WalletId2["WALLETCONNECT"] = "walletconnect";
5790
5788
  WalletId2["WEB3AUTH"] = "web3auth";
5791
5789
  WalletId2["W3_WALLET"] = "w3-wallet";
@@ -6027,6 +6025,14 @@ var BaseWallet = class {
6027
6025
  return networkConfig[activeNetwork];
6028
6026
  }
6029
6027
  // ---------- Protected Methods ------------------------------------- //
6028
+ /**
6029
+ * Dynamically update wallet metadata (e.g., after learning the actual
6030
+ * connector name/icon during connect).
6031
+ */
6032
+ updateMetadata(updates) {
6033
+ ;
6034
+ this.metadata = { ...this.metadata, ...updates };
6035
+ }
6030
6036
  onDisconnect = () => {
6031
6037
  this.logger.debug(`Removing wallet from store...`);
6032
6038
  removeWallet(this.store, { walletId: this.walletKey });
@@ -8240,115 +8246,146 @@ var MagicAuth = class extends BaseWallet {
8240
8246
  };
8241
8247
  };
8242
8248
 
8243
- // src/wallets/liquid-evm-base.ts
8249
+ // src/wallets/mnemonic.ts
8244
8250
  var import_algosdk9 = __toESM(require("algosdk"), 1);
8245
- var LiquidEvmBaseWallet = class extends BaseWallet {
8246
- liquidEvmSdk = null;
8247
- algorandClient = null;
8248
- evmAddressMap = /* @__PURE__ */ new Map();
8249
- // algorandAddress -> evmAddress
8251
+ var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
8252
+ var ICON11 = `data:image/svg+xml;base64,${btoa(`
8253
+ <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
8254
+ <rect fill="#525252" width="400" height="400" />
8255
+ <path fill="#FFFFFF" d="M309.2,309.3H275l-22.2-82.7l-47.9,82.7h-38.3l73.9-128l-11.9-44.5l-99.6,172.6H90.8L217.1,90.6 h33.5l14.7,54.3h34.6l-23.6,41L309.2,309.3z" />
8256
+ </svg>
8257
+ `)}`;
8258
+ var MnemonicWallet = class extends BaseWallet {
8259
+ account = null;
8250
8260
  options;
8251
8261
  store;
8252
- constructor(params) {
8253
- super(params);
8254
- this.options = params.options || {};
8255
- this.store = params.store;
8256
- }
8257
- /**
8258
- * Default metadata for Liquid EVM wallets.
8259
- * Subclasses MUST override this with their own metadata including isLiquid: "EVM"
8260
- */
8261
- static defaultMetadata;
8262
- /**
8263
- * Ensure the wallet is on the Algorand chain (4160).
8264
- * Queries the current chain first, and only switches/adds if needed.
8265
- */
8266
- async ensureAlgorandChain() {
8267
- const provider = await this.getEvmProvider();
8268
- const { ALGORAND_CHAIN_ID_HEX, ALGORAND_EVM_CHAIN_CONFIG } = await import("liquid-accounts-evm");
8269
- const currentChainId = await provider.request({ method: "eth_chainId" });
8270
- if (currentChainId === ALGORAND_CHAIN_ID_HEX) {
8271
- return;
8262
+ constructor({
8263
+ id,
8264
+ store,
8265
+ subscribe,
8266
+ getAlgodClient,
8267
+ options,
8268
+ metadata = {}
8269
+ }) {
8270
+ super({ id, metadata, getAlgodClient, store, subscribe });
8271
+ const {
8272
+ persistToStorage = false,
8273
+ promptForMnemonic = () => Promise.resolve(prompt("Enter 25-word mnemonic passphrase:"))
8274
+ } = options || {};
8275
+ this.options = { persistToStorage, promptForMnemonic };
8276
+ this.store = store;
8277
+ if (this.options.persistToStorage) {
8278
+ this.logger.warn(
8279
+ "Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!"
8280
+ );
8272
8281
  }
8273
- this.logger.info(`Wrong chain (${currentChainId}), switching to Algorand (${ALGORAND_CHAIN_ID_HEX})...`);
8282
+ }
8283
+ static defaultMetadata = {
8284
+ name: "Mnemonic",
8285
+ icon: ICON11
8286
+ };
8287
+ loadMnemonicFromStorage() {
8288
+ return StorageAdapter.getItem(LOCAL_STORAGE_MNEMONIC_KEY);
8289
+ }
8290
+ saveMnemonicToStorage(mnemonic) {
8291
+ StorageAdapter.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic);
8292
+ }
8293
+ removeMnemonicFromStorage() {
8294
+ StorageAdapter.removeItem(LOCAL_STORAGE_MNEMONIC_KEY);
8295
+ }
8296
+ checkMainnet() {
8274
8297
  try {
8275
- await provider.request({
8276
- method: "wallet_switchEthereumChain",
8277
- params: [{ chainId: ALGORAND_CHAIN_ID_HEX }]
8278
- });
8279
- } catch (switchError) {
8280
- if (switchError.code === 4902) {
8281
- this.logger.info("Algorand chain not found, adding it...");
8282
- await provider.request({
8283
- method: "wallet_addEthereumChain",
8284
- params: [ALGORAND_EVM_CHAIN_CONFIG]
8285
- });
8286
- } else {
8287
- throw switchError;
8298
+ const network = this.activeNetworkConfig;
8299
+ if (!network.isTestnet) {
8300
+ this.logger.warn(
8301
+ "The Mnemonic wallet provider is insecure and intended for testing only. Any private key mnemonics used should never hold real Algos (i.e., on MainNet)."
8302
+ );
8303
+ throw new Error("Production network detected. Aborting.");
8288
8304
  }
8305
+ } catch (error) {
8306
+ this.disconnect();
8307
+ throw error;
8289
8308
  }
8290
8309
  }
8291
- /**
8292
- * Initialize the Liquid EVM SDK for deriving Algorand addresses
8293
- */
8294
- async initializeEvmSdk() {
8295
- if (!this.liquidEvmSdk) {
8296
- this.logger.info("Initializing Liquid EVM SDK...");
8297
- if (!this.algorandClient) {
8298
- const { AlgorandClient } = await import("@algorandfoundation/algokit-utils");
8299
- const algodClient = this.getAlgodClient();
8300
- this.algorandClient = AlgorandClient.fromClients({
8301
- algod: algodClient
8302
- });
8310
+ async initializeAccount() {
8311
+ let mnemonic = this.loadMnemonicFromStorage();
8312
+ if (!mnemonic) {
8313
+ mnemonic = await this.options.promptForMnemonic();
8314
+ if (!mnemonic) {
8315
+ this.account = null;
8316
+ this.logger.error("No mnemonic provided");
8317
+ throw new Error("No mnemonic provided");
8318
+ }
8319
+ if (this.options.persistToStorage) {
8320
+ this.logger.warn("Mnemonic saved to localStorage.");
8321
+ this.saveMnemonicToStorage(mnemonic);
8303
8322
  }
8304
- const { LiquidEvmSdk } = await import("liquid-accounts-evm");
8305
- this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
8306
- this.logger.info("Liquid EVM SDK initialized");
8307
8323
  }
8308
- return this.liquidEvmSdk;
8324
+ const account = import_algosdk9.default.mnemonicToSecretKey(mnemonic);
8325
+ this.account = account;
8326
+ return account;
8309
8327
  }
8310
- /**
8311
- * Derive Algorand accounts from EVM addresses
8312
- */
8313
- async deriveAlgorandAccounts(evmAddresses) {
8314
- const liquidEvmSdk = await this.initializeEvmSdk();
8315
- const walletAccounts = [];
8316
- for (let i = 0; i < evmAddresses.length; i++) {
8317
- const evmAddress = evmAddresses[i];
8318
- const algorandAddress = await liquidEvmSdk.getAddress({ evmAddress });
8319
- this.evmAddressMap.set(algorandAddress, evmAddress);
8320
- walletAccounts.push({
8321
- name: `${this.metadata.name} ${evmAddress}`,
8322
- address: algorandAddress,
8323
- metadata: { evmAddress }
8324
- });
8328
+ connect = async () => {
8329
+ this.checkMainnet();
8330
+ this.logger.info("Connecting...");
8331
+ const account = await this.initializeAccount();
8332
+ const walletAccount = {
8333
+ name: `${this.metadata.name} Account`,
8334
+ address: account.addr.toString()
8335
+ };
8336
+ const walletState = {
8337
+ accounts: [walletAccount],
8338
+ activeAccount: walletAccount
8339
+ };
8340
+ addWallet(this.store, {
8341
+ walletId: this.id,
8342
+ wallet: walletState
8343
+ });
8344
+ this.logger.info("Connected successfully", walletState);
8345
+ return [walletAccount];
8346
+ };
8347
+ disconnect = async () => {
8348
+ this.logger.info("Disconnecting...");
8349
+ this.onDisconnect();
8350
+ this.account = null;
8351
+ this.removeMnemonicFromStorage();
8352
+ this.logger.info("Disconnected");
8353
+ };
8354
+ resumeSession = async () => {
8355
+ this.checkMainnet();
8356
+ const state = this.store.state;
8357
+ const walletState = state.wallets[this.id];
8358
+ if (!walletState) {
8359
+ this.logger.info("No session to resume");
8360
+ return;
8325
8361
  }
8326
- return walletAccounts;
8327
- }
8328
- /**
8329
- * Convert bytes to hex string with 0x prefix
8330
- */
8331
- bytesToHex(bytes) {
8332
- return "0x" + Array.from(bytes).map((b3) => b3.toString(16).padStart(2, "0")).join("");
8333
- }
8334
- /**
8335
- * Process transaction group to extract transactions that need signing
8336
- */
8362
+ this.logger.info("Resuming session...");
8363
+ if (this.options.persistToStorage) {
8364
+ try {
8365
+ await this.initializeAccount();
8366
+ this.logger.info("Session resumed successfully");
8367
+ } catch (error) {
8368
+ this.logger.error("Error resuming session:", error.message);
8369
+ this.disconnect();
8370
+ throw error;
8371
+ }
8372
+ } else {
8373
+ this.logger.info("No session to resume, disconnecting...");
8374
+ this.disconnect();
8375
+ }
8376
+ };
8337
8377
  processTxns(txnGroup, indexesToSign) {
8338
8378
  const txnsToSign = [];
8339
8379
  txnGroup.forEach((txn, index) => {
8340
8380
  const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8341
8381
  const signer = txn.sender.toString();
8342
- const canSignTxn = this.addresses.includes(signer);
8382
+ const canSignTxn = signer === this.account.addr.toString();
8343
8383
  if (isIndexMatch && canSignTxn) {
8344
8384
  txnsToSign.push(txn);
8345
8385
  }
8346
8386
  });
8347
8387
  return txnsToSign;
8348
8388
  }
8349
- /**
8350
- * Process encoded transaction group to extract transactions that need signing
8351
- */
8352
8389
  processEncodedTxns(txnGroup, indexesToSign) {
8353
8390
  const txnsToSign = [];
8354
8391
  txnGroup.forEach((txnBuffer, index) => {
@@ -8357,424 +8394,24 @@ var LiquidEvmBaseWallet = class extends BaseWallet {
8357
8394
  const txn = isSigned ? import_algosdk9.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk9.default.decodeUnsignedTransaction(txnBuffer);
8358
8395
  const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8359
8396
  const signer = txn.sender.toString();
8360
- const canSignTxn = !isSigned && this.addresses.includes(signer);
8397
+ const canSignTxn = !isSigned && signer === this.account.addr.toString();
8361
8398
  if (isIndexMatch && canSignTxn) {
8362
8399
  txnsToSign.push(txn);
8363
8400
  }
8364
8401
  });
8365
8402
  return txnsToSign;
8366
8403
  }
8367
- /**
8368
- * Sign Algorand transactions using EVM wallet signatures
8369
- */
8370
8404
  signTransactions = async (txnGroup, indexesToSign) => {
8405
+ this.checkMainnet();
8371
8406
  try {
8372
8407
  this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8373
- const evmSdk = await this.initializeEvmSdk();
8374
- let flatTxns = [];
8408
+ let txnsToSign = [];
8375
8409
  if (isTransactionArray(txnGroup)) {
8376
- flatTxns = flattenTxnGroup(txnGroup);
8410
+ const flatTxns = flattenTxnGroup(txnGroup);
8411
+ txnsToSign = this.processTxns(flatTxns, indexesToSign);
8377
8412
  } else {
8378
- const flatEncoded = flattenTxnGroup(txnGroup);
8379
- flatTxns = flatEncoded.map((txnBuffer) => {
8380
- const decodedObj = import_algosdk9.default.msgpackRawDecode(txnBuffer);
8381
- const isSigned = isSignedTxn(decodedObj);
8382
- return isSigned ? import_algosdk9.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk9.default.decodeUnsignedTransaction(txnBuffer);
8383
- });
8384
- }
8385
- const txnsToSign = isTransactionArray(txnGroup) ? this.processTxns(flatTxns, indexesToSign) : this.processEncodedTxns(flattenTxnGroup(txnGroup), indexesToSign);
8386
- if (txnsToSign.length === 0) {
8387
- this.logger.debug("No transactions to sign");
8388
- return flatTxns.map(() => null);
8389
- }
8390
- const firstTxn = txnsToSign[0];
8391
- const algorandAddress = firstTxn.sender.toString();
8392
- const evmAddress = this.evmAddressMap.get(algorandAddress);
8393
- if (!evmAddress) {
8394
- throw new Error(`No EVM address found for Algorand address: ${algorandAddress}`);
8395
- }
8396
- const onBeforeSign = this.options.uiHooks?.onBeforeSign ?? this.managerUIHooks?.onBeforeSign;
8397
- if (onBeforeSign) {
8398
- this.logger.debug("Running onBeforeSign hook", { txnGroup, indexesToSign });
8399
- await onBeforeSign(txnGroup, indexesToSign);
8400
- }
8401
- await this.ensureAlgorandChain();
8402
- const signedBlobs = await evmSdk.signTxn({
8403
- evmAddress,
8404
- txns: flatTxns,
8405
- signMessage: (typedData) => this.signWithProvider(typedData, evmAddress)
8406
- });
8407
- const onAfterSign = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8408
- if (onAfterSign) {
8409
- this.logger.debug("Running onAfterSign hook");
8410
- try {
8411
- onAfterSign(true);
8412
- } catch (e) {
8413
- }
8414
- }
8415
- const result = flatTxns.map((txn, index) => {
8416
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8417
- const signer = txn.sender.toString();
8418
- const canSignTxn = this.addresses.includes(signer);
8419
- if (isIndexMatch && canSignTxn) {
8420
- return signedBlobs[index];
8421
- }
8422
- return null;
8423
- });
8424
- this.logger.debug("Transactions signed successfully", result);
8425
- return result;
8426
- } catch (error) {
8427
- try {
8428
- const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8429
- onAfterSignCleanup?.(false, error.message);
8430
- } catch (e) {
8431
- }
8432
- this.logger.error("Error signing transactions:", error.message);
8433
- throw error;
8434
- }
8435
- };
8436
- /**
8437
- * Helper to compare and update accounts if needed during session resume
8438
- */
8439
- async resumeWithAccounts(evmAddresses, setAccountsFn) {
8440
- const state = this.store.state;
8441
- const walletState = state.wallets[this.id];
8442
- if (!walletState) {
8443
- this.logger.info("No session to resume");
8444
- return;
8445
- }
8446
- for (const account of walletState.accounts) {
8447
- const evmAddr = account.metadata?.evmAddress;
8448
- if (evmAddr) {
8449
- this.evmAddressMap.set(account.address, evmAddr);
8450
- }
8451
- }
8452
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
8453
- const match = compareAccounts(walletAccounts, walletState.accounts);
8454
- if (!match) {
8455
- this.logger.warn("Session accounts mismatch, updating accounts", {
8456
- prev: walletState.accounts,
8457
- current: walletAccounts
8458
- });
8459
- setAccountsFn(walletAccounts);
8460
- }
8461
- this.logger.info("Session resumed");
8462
- }
8463
- notifyConnect(evmAddress, algorandAddress) {
8464
- const onConnect = this.options.uiHooks?.onConnect ?? this.managerUIHooks?.onConnect;
8465
- if (onConnect) {
8466
- onConnect({ evmAddress, algorandAddress });
8467
- }
8468
- }
8469
- };
8470
-
8471
- // src/wallets/metamask.ts
8472
- var ICON11 = `data:image/svg+xml;base64,${btoa(`
8473
- <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
8474
- viewBox="0 0 142 136.878" style="enable-background:new 0 0 142 136.878;" xml:space="preserve">
8475
- <path style="fill:#FF5C16;" d="M132.682,132.192l-30.583-9.106l-23.063,13.787l-16.092-0.007l-23.077-13.78l-30.569,9.106L0,100.801
8476
- l9.299-34.839L0,36.507L9.299,0l47.766,28.538h27.85L132.682,0l9.299,36.507l-9.299,29.455l9.299,34.839L132.682,132.192
8477
- L132.682,132.192z"/>
8478
- <path style="fill:#FF5C16;" d="M9.305,0l47.767,28.558l-1.899,19.599L9.305,0z M39.875,100.814l21.017,16.01l-21.017,6.261
8479
- C39.875,123.085,39.875,100.814,39.875,100.814z M59.212,74.345l-4.039-26.174L29.317,65.97l-0.014-0.007v0.013l0.08,18.321
8480
- l10.485-9.951L59.212,74.345L59.212,74.345z M132.682,0L84.915,28.558l1.893,19.599L132.682,0z M102.113,100.814l-21.018,16.01
8481
- l21.018,6.261V100.814z M112.678,65.975h0.007H112.678v-0.013l-0.006,0.007L86.815,48.171l-4.039,26.174h19.336l10.492,9.95
8482
- C112.604,84.295,112.678,65.975,112.678,65.975z"/>
8483
- <path style="fill:#E34807;" d="M39.868,123.085l-30.569,9.106L0,100.814h39.868C39.868,100.814,39.868,123.085,39.868,123.085z
8484
- M59.205,74.338l5.839,37.84l-8.093-21.04L29.37,84.295l10.491-9.956h19.344L59.205,74.338z M102.112,123.085l30.57,9.106
8485
- l9.299-31.378h-39.869C102.112,100.814,102.112,123.085,102.112,123.085z M82.776,74.338l-5.839,37.84l8.092-21.04l27.583-6.843
8486
- l-10.498-9.956H82.776V74.338z"/>
8487
- <path style="fill:#FF8D5D;" d="M0,100.801l9.299-34.839h19.997l0.073,18.327l27.584,6.843l8.092,21.039l-4.16,4.633l-21.017-16.01H0
8488
- V100.801z M141.981,100.801l-9.299-34.839h-19.998l-0.073,18.327l-27.582,6.843l-8.093,21.039l4.159,4.633l21.018-16.01h39.868
8489
- V100.801z M84.915,28.538h-27.85l-1.891,19.599l9.872,64.013h11.891l9.878-64.013L84.915,28.538z"/>
8490
- <path style="fill:#661800;" d="M9.299,0L0,36.507l9.299,29.455h19.997l25.87-17.804L9.299,0z M53.426,81.938h-9.059l-4.932,4.835
8491
- l17.524,4.344l-3.533-9.186V81.938z M132.682,0l9.299,36.507l-9.299,29.455h-19.998L86.815,48.158L132.682,0z M88.568,81.938h9.072
8492
- l4.932,4.841l-17.544,4.353l3.54-9.201V81.938z M79.029,124.385l2.067-7.567l-4.16-4.633h-11.9l-4.159,4.633l2.066,7.567"/>
8493
- <path style="fill:#C0C4CD;" d="M79.029,124.384v12.495H62.945v-12.495L79.029,124.384L79.029,124.384z"/>
8494
- <path style="fill:#E7EBF6;" d="M39.875,123.072l23.083,13.8v-12.495l-2.067-7.566C60.891,116.811,39.875,123.072,39.875,123.072z
8495
- M102.113,123.072l-23.084,13.8v-12.495l2.067-7.566C81.096,116.811,102.113,123.072,102.113,123.072z"/>
8496
- </svg>
8497
- `)}`;
8498
- var MetaMaskWallet = class extends LiquidEvmBaseWallet {
8499
- metamaskSdk = null;
8500
- provider = null;
8501
- options;
8502
- constructor(params) {
8503
- super(params);
8504
- this.options = params.options || {};
8505
- }
8506
- static defaultMetadata = {
8507
- name: "MetaMask",
8508
- icon: ICON11,
8509
- isLiquid: "EVM"
8510
- };
8511
- async initializeProvider() {
8512
- if (!this.metamaskSdk) {
8513
- this.logger.info("Initializing MetaMask SDK...");
8514
- const { MetaMaskSDK } = await import("@metamask/sdk");
8515
- this.metamaskSdk = new MetaMaskSDK({
8516
- dappMetadata: {
8517
- name: this.options.dappMetadata?.name || "Algorand dApp",
8518
- url: this.options.dappMetadata?.url || (typeof window !== "undefined" ? window.location.href : ""),
8519
- ...this.options.dappMetadata?.iconUrl && { iconUrl: this.options.dappMetadata.iconUrl }
8520
- }
8521
- });
8522
- this.logger.info("MetaMask SDK initialized");
8523
- }
8524
- }
8525
- async getEvmProvider() {
8526
- if (!this.provider) {
8527
- await this.initializeProvider();
8528
- this.provider = this.metamaskSdk.getProvider() || null;
8529
- if (!this.provider) {
8530
- throw new Error("MetaMask provider not available. Please install MetaMask.");
8531
- }
8532
- }
8533
- return this.provider;
8534
- }
8535
- async signWithProvider(typedData, evmAddress) {
8536
- const provider = await this.getEvmProvider();
8537
- return await provider.request({
8538
- method: "eth_signTypedData_v4",
8539
- params: [evmAddress, JSON.stringify(typedData)]
8540
- });
8541
- }
8542
- connect = async () => {
8543
- this.logger.info("Connecting...");
8544
- await this.initializeProvider();
8545
- await this.initializeEvmSdk();
8546
- const provider = await this.getEvmProvider();
8547
- const evmAddresses = await provider.request({
8548
- method: "eth_requestAccounts"
8549
- });
8550
- if (evmAddresses.length === 0) {
8551
- this.logger.error("No accounts found!");
8552
- throw new Error("No accounts found!");
8553
- }
8554
- this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
8555
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
8556
- const activeAccount = walletAccounts[0];
8557
- const walletState = {
8558
- accounts: walletAccounts,
8559
- activeAccount
8560
- };
8561
- addWallet(this.store, {
8562
- walletId: this.id,
8563
- wallet: walletState
8564
- });
8565
- this.logger.info("\u2705 Connected.", walletState);
8566
- this.notifyConnect(evmAddresses[0], activeAccount.address);
8567
- return walletAccounts;
8568
- };
8569
- disconnect = async () => {
8570
- this.logger.info("Disconnecting...");
8571
- if (this.metamaskSdk) {
8572
- await this.metamaskSdk.terminate();
8573
- }
8574
- this.provider = null;
8575
- this.evmAddressMap.clear();
8576
- this.onDisconnect();
8577
- this.logger.info("Disconnected");
8578
- };
8579
- resumeSession = async () => {
8580
- try {
8581
- const state = this.store.state;
8582
- const walletState = state.wallets[this.id];
8583
- if (!walletState) {
8584
- this.logger.info("No session to resume");
8585
- return;
8586
- }
8587
- this.logger.info("Resuming session...");
8588
- await this.initializeProvider();
8589
- await this.initializeEvmSdk();
8590
- const provider = await this.getEvmProvider();
8591
- const evmAddresses = await provider.request({
8592
- method: "eth_accounts"
8593
- });
8594
- if (evmAddresses.length === 0) {
8595
- this.logger.error("No accounts found!");
8596
- throw new Error("No accounts found!");
8597
- }
8598
- await this.resumeWithAccounts(evmAddresses, (accounts) => {
8599
- setAccounts(this.store, {
8600
- walletId: this.id,
8601
- accounts
8602
- });
8603
- });
8604
- } catch (error) {
8605
- this.logger.error("Error resuming session:", error.message);
8606
- this.onDisconnect();
8607
- throw error;
8608
- }
8609
- };
8610
- };
8611
-
8612
- // src/wallets/mnemonic.ts
8613
- var import_algosdk10 = __toESM(require("algosdk"), 1);
8614
- var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
8615
- var ICON12 = `data:image/svg+xml;base64,${btoa(`
8616
- <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
8617
- <rect fill="#525252" width="400" height="400" />
8618
- <path fill="#FFFFFF" d="M309.2,309.3H275l-22.2-82.7l-47.9,82.7h-38.3l73.9-128l-11.9-44.5l-99.6,172.6H90.8L217.1,90.6 h33.5l14.7,54.3h34.6l-23.6,41L309.2,309.3z" />
8619
- </svg>
8620
- `)}`;
8621
- var MnemonicWallet = class extends BaseWallet {
8622
- account = null;
8623
- options;
8624
- store;
8625
- constructor({
8626
- id,
8627
- store,
8628
- subscribe,
8629
- getAlgodClient,
8630
- options,
8631
- metadata = {}
8632
- }) {
8633
- super({ id, metadata, getAlgodClient, store, subscribe });
8634
- const {
8635
- persistToStorage = false,
8636
- promptForMnemonic = () => Promise.resolve(prompt("Enter 25-word mnemonic passphrase:"))
8637
- } = options || {};
8638
- this.options = { persistToStorage, promptForMnemonic };
8639
- this.store = store;
8640
- if (this.options.persistToStorage) {
8641
- this.logger.warn(
8642
- "Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!"
8643
- );
8644
- }
8645
- }
8646
- static defaultMetadata = {
8647
- name: "Mnemonic",
8648
- icon: ICON12
8649
- };
8650
- loadMnemonicFromStorage() {
8651
- return StorageAdapter.getItem(LOCAL_STORAGE_MNEMONIC_KEY);
8652
- }
8653
- saveMnemonicToStorage(mnemonic) {
8654
- StorageAdapter.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic);
8655
- }
8656
- removeMnemonicFromStorage() {
8657
- StorageAdapter.removeItem(LOCAL_STORAGE_MNEMONIC_KEY);
8658
- }
8659
- checkMainnet() {
8660
- try {
8661
- const network = this.activeNetworkConfig;
8662
- if (!network.isTestnet) {
8663
- this.logger.warn(
8664
- "The Mnemonic wallet provider is insecure and intended for testing only. Any private key mnemonics used should never hold real Algos (i.e., on MainNet)."
8665
- );
8666
- throw new Error("Production network detected. Aborting.");
8667
- }
8668
- } catch (error) {
8669
- this.disconnect();
8670
- throw error;
8671
- }
8672
- }
8673
- async initializeAccount() {
8674
- let mnemonic = this.loadMnemonicFromStorage();
8675
- if (!mnemonic) {
8676
- mnemonic = await this.options.promptForMnemonic();
8677
- if (!mnemonic) {
8678
- this.account = null;
8679
- this.logger.error("No mnemonic provided");
8680
- throw new Error("No mnemonic provided");
8681
- }
8682
- if (this.options.persistToStorage) {
8683
- this.logger.warn("Mnemonic saved to localStorage.");
8684
- this.saveMnemonicToStorage(mnemonic);
8685
- }
8686
- }
8687
- const account = import_algosdk10.default.mnemonicToSecretKey(mnemonic);
8688
- this.account = account;
8689
- return account;
8690
- }
8691
- connect = async () => {
8692
- this.checkMainnet();
8693
- this.logger.info("Connecting...");
8694
- const account = await this.initializeAccount();
8695
- const walletAccount = {
8696
- name: `${this.metadata.name} Account`,
8697
- address: account.addr.toString()
8698
- };
8699
- const walletState = {
8700
- accounts: [walletAccount],
8701
- activeAccount: walletAccount
8702
- };
8703
- addWallet(this.store, {
8704
- walletId: this.id,
8705
- wallet: walletState
8706
- });
8707
- this.logger.info("Connected successfully", walletState);
8708
- return [walletAccount];
8709
- };
8710
- disconnect = async () => {
8711
- this.logger.info("Disconnecting...");
8712
- this.onDisconnect();
8713
- this.account = null;
8714
- this.removeMnemonicFromStorage();
8715
- this.logger.info("Disconnected");
8716
- };
8717
- resumeSession = async () => {
8718
- this.checkMainnet();
8719
- const state = this.store.state;
8720
- const walletState = state.wallets[this.id];
8721
- if (!walletState) {
8722
- this.logger.info("No session to resume");
8723
- return;
8724
- }
8725
- this.logger.info("Resuming session...");
8726
- if (this.options.persistToStorage) {
8727
- try {
8728
- await this.initializeAccount();
8729
- this.logger.info("Session resumed successfully");
8730
- } catch (error) {
8731
- this.logger.error("Error resuming session:", error.message);
8732
- this.disconnect();
8733
- throw error;
8734
- }
8735
- } else {
8736
- this.logger.info("No session to resume, disconnecting...");
8737
- this.disconnect();
8738
- }
8739
- };
8740
- processTxns(txnGroup, indexesToSign) {
8741
- const txnsToSign = [];
8742
- txnGroup.forEach((txn, index) => {
8743
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8744
- const signer = txn.sender.toString();
8745
- const canSignTxn = signer === this.account.addr.toString();
8746
- if (isIndexMatch && canSignTxn) {
8747
- txnsToSign.push(txn);
8748
- }
8749
- });
8750
- return txnsToSign;
8751
- }
8752
- processEncodedTxns(txnGroup, indexesToSign) {
8753
- const txnsToSign = [];
8754
- txnGroup.forEach((txnBuffer, index) => {
8755
- const decodedObj = import_algosdk10.default.msgpackRawDecode(txnBuffer);
8756
- const isSigned = isSignedTxn(decodedObj);
8757
- const txn = isSigned ? import_algosdk10.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk10.default.decodeUnsignedTransaction(txnBuffer);
8758
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8759
- const signer = txn.sender.toString();
8760
- const canSignTxn = !isSigned && signer === this.account.addr.toString();
8761
- if (isIndexMatch && canSignTxn) {
8762
- txnsToSign.push(txn);
8763
- }
8764
- });
8765
- return txnsToSign;
8766
- }
8767
- signTransactions = async (txnGroup, indexesToSign) => {
8768
- this.checkMainnet();
8769
- try {
8770
- this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8771
- let txnsToSign = [];
8772
- if (isTransactionArray(txnGroup)) {
8773
- const flatTxns = flattenTxnGroup(txnGroup);
8774
- txnsToSign = this.processTxns(flatTxns, indexesToSign);
8775
- } else {
8776
- const flatTxns = flattenTxnGroup(txnGroup);
8777
- txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8413
+ const flatTxns = flattenTxnGroup(txnGroup);
8414
+ txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8778
8415
  }
8779
8416
  const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account.sk));
8780
8417
  this.logger.debug("Transactions signed successfully", { signedTxns });
@@ -8787,8 +8424,8 @@ var MnemonicWallet = class extends BaseWallet {
8787
8424
  };
8788
8425
 
8789
8426
  // src/wallets/pera.ts
8790
- var import_algosdk11 = __toESM(require("algosdk"), 1);
8791
- var ICON13 = `data:image/svg+xml;base64,${btoa(`
8427
+ var import_algosdk10 = __toESM(require("algosdk"), 1);
8428
+ var ICON12 = `data:image/svg+xml;base64,${btoa(`
8792
8429
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
8793
8430
  <rect fill="#FFEE55" width="200" height="200" />
8794
8431
  <path fill="#1C1C1C" d="M106.1,64.3c2.2,9.1,1.5,17-1.7,17.8c-3.1,0.8-7.4-6-9.6-15c-2.2-9.1-1.5-17,1.7-17.8 C99.6,48.5,103.9,55.2,106.1,64.3z" />
@@ -8817,7 +8454,7 @@ var PeraWallet = class extends BaseWallet {
8817
8454
  }
8818
8455
  static defaultMetadata = {
8819
8456
  name: "Pera",
8820
- icon: ICON13
8457
+ icon: ICON12
8821
8458
  };
8822
8459
  async initializeClient() {
8823
8460
  this.logger.info("Initializing client...");
@@ -8928,13 +8565,173 @@ var PeraWallet = class extends BaseWallet {
8928
8565
  accounts: walletAccounts
8929
8566
  });
8930
8567
  }
8931
- this.logger.info("Session resumed successfully");
8932
- } catch (error) {
8933
- this.logger.error("Error resuming session:", error.message);
8934
- this.onDisconnect();
8935
- throw error;
8568
+ this.logger.info("Session resumed successfully");
8569
+ } catch (error) {
8570
+ this.logger.error("Error resuming session:", error.message);
8571
+ this.onDisconnect();
8572
+ throw error;
8573
+ }
8574
+ };
8575
+ processTxns(txnGroup, indexesToSign) {
8576
+ const txnsToSign = [];
8577
+ txnGroup.forEach((txn, index) => {
8578
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8579
+ const signer = txn.sender.toString();
8580
+ const canSignTxn = this.addresses.includes(signer);
8581
+ if (isIndexMatch && canSignTxn) {
8582
+ txnsToSign.push({ txn });
8583
+ } else {
8584
+ txnsToSign.push({ txn, signers: [] });
8585
+ }
8586
+ });
8587
+ return txnsToSign;
8588
+ }
8589
+ processEncodedTxns(txnGroup, indexesToSign) {
8590
+ const txnsToSign = [];
8591
+ txnGroup.forEach((txnBuffer, index) => {
8592
+ const decodedObj = import_algosdk10.default.msgpackRawDecode(txnBuffer);
8593
+ const isSigned = isSignedTxn(decodedObj);
8594
+ const txn = isSigned ? import_algosdk10.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk10.default.decodeUnsignedTransaction(txnBuffer);
8595
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8596
+ const signer = txn.sender.toString();
8597
+ const canSignTxn = !isSigned && this.addresses.includes(signer);
8598
+ if (isIndexMatch && canSignTxn) {
8599
+ txnsToSign.push({ txn });
8600
+ } else {
8601
+ txnsToSign.push({ txn, signers: [] });
8602
+ }
8603
+ });
8604
+ return txnsToSign;
8605
+ }
8606
+ signTransactions = async (txnGroup, indexesToSign) => {
8607
+ try {
8608
+ this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8609
+ let txnsToSign = [];
8610
+ if (isTransactionArray(txnGroup)) {
8611
+ const flatTxns = flattenTxnGroup(txnGroup);
8612
+ txnsToSign = this.processTxns(flatTxns, indexesToSign);
8613
+ } else {
8614
+ const flatTxns = flattenTxnGroup(txnGroup);
8615
+ txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8616
+ }
8617
+ const client = this.client || await this.initializeClient();
8618
+ this.logger.debug("Sending processed transactions to wallet...", [txnsToSign]);
8619
+ const signedTxns = await client.signTransaction([txnsToSign]);
8620
+ this.logger.debug("Received signed transactions from wallet", signedTxns);
8621
+ const result = txnsToSign.reduce((acc, txn) => {
8622
+ if (txn.signers && txn.signers.length == 0) {
8623
+ acc.push(null);
8624
+ } else {
8625
+ const signedTxn = signedTxns.shift();
8626
+ if (signedTxn) {
8627
+ acc.push(signedTxn);
8628
+ }
8629
+ }
8630
+ return acc;
8631
+ }, []);
8632
+ this.logger.debug("Transactions signed successfully", result);
8633
+ return result;
8634
+ } catch (error) {
8635
+ this.logger.error("Error signing transactions:", error.message);
8636
+ throw error;
8637
+ }
8638
+ };
8639
+ };
8640
+
8641
+ // src/wallets/liquid-evm-base.ts
8642
+ var import_algosdk11 = __toESM(require("algosdk"), 1);
8643
+ var LiquidEvmBaseWallet = class extends BaseWallet {
8644
+ liquidEvmSdk = null;
8645
+ algorandClient = null;
8646
+ evmAddressMap = /* @__PURE__ */ new Map();
8647
+ // algorandAddress -> evmAddress
8648
+ options;
8649
+ store;
8650
+ constructor(params) {
8651
+ super(params);
8652
+ this.options = params.options || {};
8653
+ this.store = params.store;
8654
+ }
8655
+ /**
8656
+ * Default metadata for Liquid EVM wallets.
8657
+ * Subclasses MUST override this with their own metadata including isLiquid: "EVM"
8658
+ */
8659
+ static defaultMetadata;
8660
+ /**
8661
+ * Ensure the wallet is on the Algorand chain (4160).
8662
+ * Queries the current chain first, and only switches/adds if needed.
8663
+ */
8664
+ async ensureAlgorandChain() {
8665
+ const provider = await this.getEvmProvider();
8666
+ const { ALGORAND_CHAIN_ID_HEX, ALGORAND_EVM_CHAIN_CONFIG } = await import("liquid-accounts-evm");
8667
+ const currentChainId = await provider.request({ method: "eth_chainId" });
8668
+ if (currentChainId.toLowerCase() === ALGORAND_CHAIN_ID_HEX.toLowerCase()) {
8669
+ return;
8670
+ }
8671
+ this.logger.info(`Wrong chain (${currentChainId}), switching to Algorand (${ALGORAND_CHAIN_ID_HEX})...`);
8672
+ try {
8673
+ await provider.request({
8674
+ method: "wallet_switchEthereumChain",
8675
+ params: [{ chainId: ALGORAND_CHAIN_ID_HEX }]
8676
+ });
8677
+ } catch (switchError) {
8678
+ const chainUnknown = [4902, -32600, -32603].includes(switchError.code);
8679
+ if (chainUnknown) {
8680
+ this.logger.info("Algorand chain not found, adding it...");
8681
+ await provider.request({
8682
+ method: "wallet_addEthereumChain",
8683
+ params: [ALGORAND_EVM_CHAIN_CONFIG]
8684
+ });
8685
+ } else {
8686
+ throw switchError;
8687
+ }
8688
+ }
8689
+ }
8690
+ /**
8691
+ * Initialize the Liquid EVM SDK for deriving Algorand addresses
8692
+ */
8693
+ async initializeEvmSdk() {
8694
+ if (!this.liquidEvmSdk) {
8695
+ this.logger.info("Initializing Liquid EVM SDK...");
8696
+ if (!this.algorandClient) {
8697
+ const { AlgorandClient } = await import("@algorandfoundation/algokit-utils");
8698
+ const algodClient = this.getAlgodClient();
8699
+ this.algorandClient = AlgorandClient.fromClients({
8700
+ algod: algodClient
8701
+ });
8702
+ }
8703
+ const { LiquidEvmSdk } = await import("liquid-accounts-evm");
8704
+ this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
8705
+ this.logger.info("Liquid EVM SDK initialized");
8936
8706
  }
8937
- };
8707
+ return this.liquidEvmSdk;
8708
+ }
8709
+ /**
8710
+ * Derive Algorand accounts from EVM addresses.
8711
+ * @param evmAddresses - EVM addresses to derive Algorand accounts from
8712
+ * @param connectorInfo - Optional connector name/icon to include in account metadata
8713
+ */
8714
+ async deriveAlgorandAccounts(evmAddresses, connectorInfo) {
8715
+ const liquidEvmSdk = await this.initializeEvmSdk();
8716
+ const walletAccounts = [];
8717
+ for (let i = 0; i < evmAddresses.length; i++) {
8718
+ const evmAddress = evmAddresses[i];
8719
+ const algorandAddress = await liquidEvmSdk.getAddress({ evmAddress });
8720
+ this.evmAddressMap.set(algorandAddress, evmAddress);
8721
+ const metadata = { evmAddress };
8722
+ if (connectorInfo?.name) metadata.connectorName = connectorInfo.name;
8723
+ if (connectorInfo?.icon) metadata.connectorIcon = connectorInfo.icon;
8724
+ walletAccounts.push({
8725
+ name: `${this.metadata.name} ${evmAddress}`,
8726
+ address: algorandAddress,
8727
+ metadata
8728
+ });
8729
+ }
8730
+ return walletAccounts;
8731
+ }
8732
+ /**
8733
+ * Process transaction group to extract transactions that need signing
8734
+ */
8938
8735
  processTxns(txnGroup, indexesToSign) {
8939
8736
  const txnsToSign = [];
8940
8737
  txnGroup.forEach((txn, index) => {
@@ -8942,13 +8739,14 @@ var PeraWallet = class extends BaseWallet {
8942
8739
  const signer = txn.sender.toString();
8943
8740
  const canSignTxn = this.addresses.includes(signer);
8944
8741
  if (isIndexMatch && canSignTxn) {
8945
- txnsToSign.push({ txn });
8946
- } else {
8947
- txnsToSign.push({ txn, signers: [] });
8742
+ txnsToSign.push(txn);
8948
8743
  }
8949
8744
  });
8950
8745
  return txnsToSign;
8951
8746
  }
8747
+ /**
8748
+ * Process encoded transaction group to extract transactions that need signing
8749
+ */
8952
8750
  processEncodedTxns(txnGroup, indexesToSign) {
8953
8751
  const txnsToSign = [];
8954
8752
  txnGroup.forEach((txnBuffer, index) => {
@@ -8959,154 +8757,316 @@ var PeraWallet = class extends BaseWallet {
8959
8757
  const signer = txn.sender.toString();
8960
8758
  const canSignTxn = !isSigned && this.addresses.includes(signer);
8961
8759
  if (isIndexMatch && canSignTxn) {
8962
- txnsToSign.push({ txn });
8963
- } else {
8964
- txnsToSign.push({ txn, signers: [] });
8760
+ txnsToSign.push(txn);
8965
8761
  }
8966
8762
  });
8967
8763
  return txnsToSign;
8968
8764
  }
8765
+ /**
8766
+ * Sign Algorand transactions using EVM wallet signatures
8767
+ */
8969
8768
  signTransactions = async (txnGroup, indexesToSign) => {
8970
8769
  try {
8971
8770
  this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8972
- let txnsToSign = [];
8771
+ const evmSdk = await this.initializeEvmSdk();
8772
+ let flatTxns = [];
8973
8773
  if (isTransactionArray(txnGroup)) {
8974
- const flatTxns = flattenTxnGroup(txnGroup);
8975
- txnsToSign = this.processTxns(flatTxns, indexesToSign);
8774
+ flatTxns = flattenTxnGroup(txnGroup);
8976
8775
  } else {
8977
- const flatTxns = flattenTxnGroup(txnGroup);
8978
- txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8776
+ const flatEncoded = flattenTxnGroup(txnGroup);
8777
+ flatTxns = flatEncoded.map((txnBuffer) => {
8778
+ const decodedObj = import_algosdk11.default.msgpackRawDecode(txnBuffer);
8779
+ const isSigned = isSignedTxn(decodedObj);
8780
+ return isSigned ? import_algosdk11.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk11.default.decodeUnsignedTransaction(txnBuffer);
8781
+ });
8979
8782
  }
8980
- const client = this.client || await this.initializeClient();
8981
- this.logger.debug("Sending processed transactions to wallet...", [txnsToSign]);
8982
- const signedTxns = await client.signTransaction([txnsToSign]);
8983
- this.logger.debug("Received signed transactions from wallet", signedTxns);
8984
- const result = txnsToSign.reduce((acc, txn) => {
8985
- if (txn.signers && txn.signers.length == 0) {
8986
- acc.push(null);
8987
- } else {
8988
- const signedTxn = signedTxns.shift();
8989
- if (signedTxn) {
8990
- acc.push(signedTxn);
8783
+ const txnsToSign = isTransactionArray(txnGroup) ? this.processTxns(flatTxns, indexesToSign) : this.processEncodedTxns(flattenTxnGroup(txnGroup), indexesToSign);
8784
+ if (txnsToSign.length === 0) {
8785
+ this.logger.debug("No transactions to sign");
8786
+ return flatTxns.map(() => null);
8787
+ }
8788
+ const firstTxn = txnsToSign[0];
8789
+ const algorandAddress = firstTxn.sender.toString();
8790
+ let evmAddress = this.evmAddressMap.get(algorandAddress);
8791
+ if (!evmAddress) {
8792
+ const walletState = this.store.state.wallets[this.id];
8793
+ if (walletState) {
8794
+ for (const account of walletState.accounts) {
8795
+ const addr = account.metadata?.evmAddress;
8796
+ if (addr) {
8797
+ this.evmAddressMap.set(account.address, addr);
8798
+ }
8991
8799
  }
8800
+ evmAddress = this.evmAddressMap.get(algorandAddress);
8992
8801
  }
8993
- return acc;
8994
- }, []);
8802
+ }
8803
+ if (!evmAddress) {
8804
+ throw new Error(`No EVM address found for Algorand address: ${algorandAddress}`);
8805
+ }
8806
+ const onBeforeSign = this.options.uiHooks?.onBeforeSign ?? this.managerUIHooks?.onBeforeSign;
8807
+ if (onBeforeSign) {
8808
+ this.logger.debug("Running onBeforeSign hook", { txnGroup, indexesToSign });
8809
+ await onBeforeSign(txnGroup, indexesToSign);
8810
+ }
8811
+ await this.ensureAlgorandChain();
8812
+ const signedBlobs = await evmSdk.signTxn({
8813
+ evmAddress,
8814
+ txns: flatTxns,
8815
+ signMessage: (typedData) => this.signWithProvider(typedData, evmAddress)
8816
+ });
8817
+ const onAfterSign = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8818
+ if (onAfterSign) {
8819
+ this.logger.debug("Running onAfterSign hook");
8820
+ try {
8821
+ onAfterSign(true);
8822
+ } catch (e) {
8823
+ }
8824
+ }
8825
+ const result = flatTxns.map((txn, index) => {
8826
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8827
+ const signer = txn.sender.toString();
8828
+ const canSignTxn = this.addresses.includes(signer);
8829
+ if (isIndexMatch && canSignTxn) {
8830
+ return signedBlobs[index];
8831
+ }
8832
+ return null;
8833
+ });
8995
8834
  this.logger.debug("Transactions signed successfully", result);
8996
8835
  return result;
8997
8836
  } catch (error) {
8837
+ try {
8838
+ const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8839
+ onAfterSignCleanup?.(false, error.message);
8840
+ } catch (e) {
8841
+ }
8998
8842
  this.logger.error("Error signing transactions:", error.message);
8999
8843
  throw error;
9000
8844
  }
9001
8845
  };
8846
+ /**
8847
+ * Helper to compare and update accounts if needed during session resume
8848
+ */
8849
+ async resumeWithAccounts(evmAddresses, setAccountsFn, connectorInfo) {
8850
+ const state = this.store.state;
8851
+ const walletState = state.wallets[this.id];
8852
+ if (!walletState) {
8853
+ this.logger.info("No session to resume");
8854
+ return;
8855
+ }
8856
+ for (const account of walletState.accounts) {
8857
+ const evmAddr = account.metadata?.evmAddress;
8858
+ if (evmAddr) {
8859
+ this.evmAddressMap.set(account.address, evmAddr);
8860
+ }
8861
+ }
8862
+ const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses, connectorInfo);
8863
+ const match = compareAccounts(walletAccounts, walletState.accounts);
8864
+ if (!match) {
8865
+ this.logger.warn("Session accounts mismatch, updating accounts", {
8866
+ prev: walletState.accounts,
8867
+ current: walletAccounts
8868
+ });
8869
+ }
8870
+ setAccountsFn(walletAccounts);
8871
+ this.logger.info("Session resumed");
8872
+ }
8873
+ notifyConnect(evmAddress, algorandAddress) {
8874
+ const onConnect = this.options.uiHooks?.onConnect ?? this.managerUIHooks?.onConnect;
8875
+ if (onConnect) {
8876
+ onConnect({ evmAddress, algorandAddress });
8877
+ }
8878
+ }
9002
8879
  };
9003
8880
 
9004
- // src/wallets/rainbow.ts
9005
- var ICON14 = `data:image/svg+xml;base64,${btoa(`
8881
+ // src/wallets/rainbowkit.ts
8882
+ var import_liquid_accounts_evm = require("liquid-accounts-evm");
8883
+ var ICON13 = `data:image/svg+xml;base64,${btoa(`
9006
8884
  <svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
9007
- <rect width="120" height="120" rx="60" fill="url(#paint0_linear)"/>
9008
- <path d="M60 85C74.9117 85 87 72.9117 87 58C87 43.0883 74.9117 31 60 31C45.0883 31 33 43.0883 33 58C33 72.9117 45.0883 85 60 85Z" fill="white"/>
9009
- <path d="M60 77C70.4934 77 79 68.4934 79 58C79 47.5066 70.4934 39 60 39C49.5066 39 41 47.5066 41 58C41 68.4934 49.5066 77 60 77Z" fill="url(#paint1_linear)"/>
8885
+ <rect width="120" height="120" rx="24" fill="url(#rk_bg)"/>
8886
+ <path d="M24 86V76.8C24 55.9 40.9 39 61.8 39H66C70.418 39 74 42.582 74 47V86" stroke="#FF4000" stroke-width="8" stroke-linecap="round" fill="none"/>
8887
+ <path d="M36 86V76.8C36 62.3 47.7 50.6 62.2 50.6H64C67.314 50.6 70 53.286 70 56.6V86" stroke="#FF9500" stroke-width="8" stroke-linecap="round" fill="none"/>
8888
+ <path d="M48 86V76.8C48 68.8 54.5 62.3 62.5 62.3H62.7C65.461 62.3 67.7 64.539 67.7 67.3V86" stroke="#00C853" stroke-width="8" stroke-linecap="round" fill="none"/>
8889
+ <path d="M60 86V76.8C60 75 61.5 73.5 63.3 73.5C65.1 73.5 66.6 75 66.6 76.8V86" stroke="#2979FF" stroke-width="8" stroke-linecap="round" fill="none"/>
9010
8890
  <defs>
9011
- <linearGradient id="paint0_linear" x1="0" y1="0" x2="120" y2="120" gradientUnits="userSpaceOnUse">
9012
- <stop stop-color="#174299"/>
9013
- <stop offset="1" stop-color="#001E59"/>
9014
- </linearGradient>
9015
- <linearGradient id="paint1_linear" x1="41" y1="39" x2="79" y2="77" gradientUnits="userSpaceOnUse">
9016
- <stop stop-color="#FF4444"/>
9017
- <stop offset="0.2" stop-color="#FF8844"/>
9018
- <stop offset="0.4" stop-color="#FFDD00"/>
9019
- <stop offset="0.6" stop-color="#44FF44"/>
9020
- <stop offset="0.8" stop-color="#0088FF"/>
9021
- <stop offset="1" stop-color="#8844FF"/>
8891
+ <linearGradient id="rk_bg" x1="0" y1="0" x2="120" y2="120">
8892
+ <stop stop-color="#1A1B23"/>
8893
+ <stop offset="1" stop-color="#13141B"/>
9022
8894
  </linearGradient>
9023
8895
  </defs>
9024
8896
  </svg>
9025
8897
  `)}`;
9026
- var RainbowWallet = class extends LiquidEvmBaseWallet {
9027
- provider = null;
8898
+ var RainbowKitWallet = class _RainbowKitWallet extends LiquidEvmBaseWallet {
9028
8899
  options;
8900
+ _connecting = false;
9029
8901
  constructor(params) {
9030
8902
  super(params);
9031
8903
  this.options = params.options || {};
8904
+ if (!this.options.wagmiConfig) {
8905
+ throw new Error("RainbowKitWallet requires wagmiConfig in options");
8906
+ }
8907
+ this.ensureChainRegistered();
9032
8908
  }
9033
8909
  static defaultMetadata = {
9034
- name: "Rainbow",
9035
- icon: ICON14,
8910
+ name: "EVM Wallet",
8911
+ icon: ICON13,
9036
8912
  isLiquid: "EVM"
9037
8913
  };
9038
- async initializeProvider() {
9039
- if (typeof window === "undefined") {
9040
- throw new Error("Rainbow wallet only works in browser environment");
9041
- }
9042
- const windowEth = window.ethereum;
9043
- if (window.rainbow) {
9044
- this.logger.info("Found Rainbow browser extension at window.rainbow");
9045
- return;
9046
- }
9047
- if (windowEth?.providers && Array.isArray(windowEth.providers)) {
9048
- const rainbowProvider = windowEth.providers.find((p2) => p2.isRainbow);
9049
- if (rainbowProvider) {
9050
- this.logger.info("Found Rainbow in providers array");
9051
- return;
9052
- }
9053
- }
9054
- if (windowEth?.isRainbow) {
9055
- this.logger.info("Found Rainbow as the primary provider");
8914
+ /** True while connect() is running. Prevents re-entrancy from bridge components. */
8915
+ get isConnecting() {
8916
+ return this._connecting;
8917
+ }
8918
+ /**
8919
+ * Set the getEvmAccounts callback after construction.
8920
+ *
8921
+ * RainbowKit's connect modal can only be opened via React hooks (useConnectModal)
8922
+ * rendered inside <RainbowKitProvider>, but WalletManager is constructed before
8923
+ * any React tree renders. This method lets WalletUIProvider create the bridge
8924
+ * callback internally and inject it into the wallet on mount — before any
8925
+ * user-initiated connect() call.
8926
+ */
8927
+ setGetEvmAccounts(fn) {
8928
+ this.options.getEvmAccounts = fn;
8929
+ }
8930
+ get wagmiConfig() {
8931
+ return this.options.wagmiConfig;
8932
+ }
8933
+ /**
8934
+ * If the Algorand chain (4160) isn't already in the wagmi config, add it.
8935
+ * This is needed so wagmi's switchChain and signTypedData work without
8936
+ * falling back to raw provider calls.
8937
+ */
8938
+ ensureChainRegistered() {
8939
+ const chains = this.wagmiConfig.chains;
8940
+ if (chains.some((c) => c.id === import_liquid_accounts_evm.ALGORAND_CHAIN_ID)) {
9056
8941
  return;
9057
8942
  }
9058
- this.logger.warn("Rainbow extension not detected. Note: Rainbow mobile app requires WalletConnect.");
8943
+ this.logger.info(`Registering Algorand chain (${import_liquid_accounts_evm.ALGORAND_CHAIN_ID}) in wagmi config`);
8944
+ chains.push(import_liquid_accounts_evm.algorandChain);
8945
+ }
8946
+ async initializeProvider() {
8947
+ this.logger.info("Using wagmi for EVM provider management");
8948
+ }
8949
+ /**
8950
+ * Get the raw EIP-1193 provider from the active wagmi connector.
8951
+ * Used by the base class's getEvmProvider and ensureAlgorandChain.
8952
+ */
8953
+ async getRawProvider() {
8954
+ const { getAccount } = await import("@wagmi/core");
8955
+ const account = getAccount(this.wagmiConfig);
8956
+ if (!account.connector) throw new Error("No EVM wallet connector available");
8957
+ return account.connector.getProvider();
9059
8958
  }
9060
8959
  async getEvmProvider() {
9061
- if (!this.provider) {
9062
- await this.initializeProvider();
9063
- const windowEth = window.ethereum;
9064
- if (window.rainbow) {
9065
- this.provider = window.rainbow;
9066
- } else if (windowEth?.providers && Array.isArray(windowEth.providers)) {
9067
- const rainbowProvider = windowEth.providers.find((p2) => p2.isRainbow);
9068
- if (rainbowProvider) {
9069
- this.provider = rainbowProvider;
8960
+ return this.getRawProvider();
8961
+ }
8962
+ /**
8963
+ * Sign EIP-712 typed data using wagmi's signTypedData.
8964
+ *
8965
+ * wagmi's signTypedData does NOT validate the domain's chainId against the
8966
+ * connected chain it simply forwards the typed data to the wallet via viem.
8967
+ * EIP-712 signing is chain-agnostic (the chain ID is in the typed data domain,
8968
+ * not in the RPC method), so this works regardless of which chain the wallet
8969
+ * reports being on.
8970
+ */
8971
+ async signWithProvider(typedData, evmAddress) {
8972
+ const { signTypedData } = await import("@wagmi/core");
8973
+ const { EIP712Domain: _2, ...types } = typedData.types;
8974
+ return signTypedData(this.wagmiConfig, {
8975
+ account: evmAddress,
8976
+ domain: typedData.domain,
8977
+ types,
8978
+ primaryType: typedData.primaryType,
8979
+ message: typedData.message
8980
+ });
8981
+ }
8982
+ /**
8983
+ * Build a connectorInfo object from a wagmi account, omitting undefined fields.
8984
+ * Uses `any` for the parameter to avoid exactOptionalPropertyTypes conflicts
8985
+ * with wagmi's discriminated union return types.
8986
+ */
8987
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8988
+ static extractConnectorInfo(account) {
8989
+ const info = {};
8990
+ const connector = account?.connector;
8991
+ if (typeof connector?.name === "string") info.name = connector.name;
8992
+ if (typeof connector?.icon === "string") info.icon = connector.icon;
8993
+ return info;
8994
+ }
8995
+ /**
8996
+ * Read connected EVM accounts from wagmi state.
8997
+ * If not connected, tries the getEvmAccounts callback, then falls back to
8998
+ * connecting with the first available connector.
8999
+ *
9000
+ * When getEvmAccounts is provided, it is always called (to show the wallet
9001
+ * selection UI). The callback is responsible for any disconnect/reconnect
9002
+ * needed to present a fresh selection.
9003
+ */
9004
+ async getConnectedEvmAddresses() {
9005
+ const { getAccount, connect: wagmiConnect } = await import("@wagmi/core");
9006
+ if (this.options.getEvmAccounts) {
9007
+ const addresses = await this.options.getEvmAccounts();
9008
+ if (addresses.length > 0) {
9009
+ const account2 = getAccount(this.wagmiConfig);
9010
+ const connectorInfo = _RainbowKitWallet.extractConnectorInfo(account2);
9011
+ if (account2.isConnected && account2.address) {
9012
+ return {
9013
+ addresses: account2.addresses ? [...account2.addresses] : [account2.address],
9014
+ connectorInfo
9015
+ };
9070
9016
  }
9071
- } else if (windowEth?.isRainbow) {
9072
- this.provider = windowEth;
9017
+ return { addresses, connectorInfo };
9073
9018
  }
9074
- if (!this.provider) {
9075
- throw new Error("Rainbow wallet not available. Please install Rainbow browser extension or use WalletConnect for mobile.");
9019
+ }
9020
+ const account = getAccount(this.wagmiConfig);
9021
+ if (account.isConnected && account.address) {
9022
+ return {
9023
+ addresses: account.addresses ? [...account.addresses] : [account.address],
9024
+ connectorInfo: _RainbowKitWallet.extractConnectorInfo(account)
9025
+ };
9026
+ }
9027
+ const connectors = this.wagmiConfig.connectors;
9028
+ if (connectors.length > 0) {
9029
+ this.logger.info("Attempting connection with first available connector...");
9030
+ try {
9031
+ const result = await wagmiConnect(this.wagmiConfig, { connector: connectors[0] });
9032
+ const updatedAccount = getAccount(this.wagmiConfig);
9033
+ return {
9034
+ addresses: [...result.accounts],
9035
+ connectorInfo: _RainbowKitWallet.extractConnectorInfo(updatedAccount)
9036
+ };
9037
+ } catch (error) {
9038
+ this.logger.warn("Auto-connect failed:", error.message);
9076
9039
  }
9077
9040
  }
9078
- return this.provider;
9041
+ throw new Error("No EVM wallet connected. Please connect an EVM wallet first.");
9079
9042
  }
9080
- async signWithProvider(typedData, evmAddress) {
9081
- const provider = await this.getEvmProvider();
9082
- try {
9083
- return await provider.request({
9084
- method: "eth_signTypedData_v4",
9085
- params: [evmAddress, JSON.stringify(typedData)]
9086
- });
9087
- } catch (error) {
9088
- if (error.code === 4001) {
9089
- throw new Error("User rejected the signing request");
9090
- }
9091
- throw error;
9043
+ /**
9044
+ * Apply connector info to wallet-level metadata so the UI displays
9045
+ * the actual wallet name/icon (e.g., "MetaMask") instead of the generic
9046
+ * "EVM Wallet". Falls back to defaults when connector info is unavailable.
9047
+ */
9048
+ applyConnectorMetadata(connectorInfo) {
9049
+ const updates = {};
9050
+ if (connectorInfo.name) updates.name = connectorInfo.name;
9051
+ if (connectorInfo.icon) updates.icon = connectorInfo.icon;
9052
+ if (updates.name || updates.icon) {
9053
+ this.updateMetadata(updates);
9054
+ this.logger.info(`Wallet metadata updated: ${updates.name ?? "(no name)"}`);
9092
9055
  }
9093
9056
  }
9094
9057
  connect = async () => {
9095
- this.logger.info("Connecting...");
9096
- await this.initializeProvider();
9097
- await this.initializeEvmSdk();
9098
- const provider = await this.getEvmProvider();
9058
+ if (this._connecting) {
9059
+ this.logger.info("connect() already in progress, ignoring duplicate call");
9060
+ return [];
9061
+ }
9062
+ this._connecting = true;
9099
9063
  try {
9100
- this.logger.info("Requesting Rainbow wallet connection...");
9101
- const evmAddresses = await provider.request({
9102
- method: "eth_requestAccounts"
9103
- });
9104
- if (evmAddresses.length === 0) {
9105
- this.logger.error("No accounts found!");
9106
- throw new Error("No accounts found!");
9107
- }
9064
+ this.logger.info("Connecting...");
9065
+ await this.initializeEvmSdk();
9066
+ const { addresses: evmAddresses, connectorInfo } = await this.getConnectedEvmAddresses();
9108
9067
  this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
9109
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
9068
+ this.applyConnectorMetadata(connectorInfo);
9069
+ const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses, connectorInfo);
9110
9070
  const activeAccount = walletAccounts[0];
9111
9071
  const walletState = {
9112
9072
  accounts: walletAccounts,
@@ -9116,51 +9076,70 @@ var RainbowWallet = class extends LiquidEvmBaseWallet {
9116
9076
  walletId: this.id,
9117
9077
  wallet: walletState
9118
9078
  });
9119
- this.logger.info("\u2705 Connected.", walletState);
9079
+ this.logger.info("Connected.", walletState);
9120
9080
  this.notifyConnect(evmAddresses[0], activeAccount.address);
9121
9081
  return walletAccounts;
9122
- } catch (error) {
9123
- this.logger.error("Error connecting:", error.message);
9124
- throw error;
9082
+ } finally {
9083
+ this._connecting = false;
9125
9084
  }
9126
9085
  };
9127
9086
  disconnect = async () => {
9128
9087
  this.logger.info("Disconnecting...");
9129
- this.provider = null;
9088
+ try {
9089
+ const { disconnect: wagmiDisconnect } = await import("@wagmi/core");
9090
+ await wagmiDisconnect(this.wagmiConfig);
9091
+ } catch (error) {
9092
+ this.logger.warn("wagmi disconnect error:", error.message);
9093
+ }
9130
9094
  this.evmAddressMap.clear();
9095
+ this.updateMetadata(_RainbowKitWallet.defaultMetadata);
9131
9096
  this.onDisconnect();
9132
9097
  this.logger.info("Disconnected");
9133
9098
  };
9134
9099
  resumeSession = async () => {
9100
+ const state = this.store.state;
9101
+ const walletState = state.wallets[this.id];
9102
+ if (!walletState) {
9103
+ return;
9104
+ }
9105
+ this.logger.info("Resuming session...");
9106
+ await this.initializeEvmSdk();
9107
+ const { getAccount, reconnect } = await import("@wagmi/core");
9135
9108
  try {
9136
- const state = this.store.state;
9137
- const walletState = state.wallets[this.id];
9138
- if (!walletState) {
9139
- this.logger.info("No session to resume");
9140
- return;
9141
- }
9142
- this.logger.info("Resuming session...");
9143
- await this.initializeProvider();
9144
- await this.initializeEvmSdk();
9145
- const provider = await this.getEvmProvider();
9146
- const evmAddresses = await provider.request({
9147
- method: "eth_accounts"
9148
- });
9109
+ await reconnect(this.wagmiConfig);
9110
+ } catch (err) {
9111
+ this.logger.warn("wagmi reconnect error (may be expected):", err.message);
9112
+ }
9113
+ const account = getAccount(this.wagmiConfig);
9114
+ let evmAddresses;
9115
+ let connectorInfo;
9116
+ if (account.isConnected && account.address) {
9117
+ evmAddresses = account.addresses ? [...account.addresses] : [account.address];
9118
+ connectorInfo = _RainbowKitWallet.extractConnectorInfo(account);
9119
+ } else {
9120
+ this.logger.warn("EVM wallet not yet connected, resuming from persisted state");
9121
+ evmAddresses = walletState.accounts.map((a) => a.metadata?.evmAddress).filter(Boolean);
9149
9122
  if (evmAddresses.length === 0) {
9150
- this.logger.error("No accounts found!");
9151
- throw new Error("No accounts found!");
9123
+ this.logger.warn("No persisted EVM addresses, cannot resume");
9124
+ this.onDisconnect();
9125
+ return;
9152
9126
  }
9153
- await this.resumeWithAccounts(evmAddresses, (accounts) => {
9154
- setAccounts(this.store, {
9155
- walletId: this.id,
9156
- accounts
9157
- });
9158
- });
9159
- } catch (error) {
9160
- this.logger.error("Error resuming session:", error.message);
9161
- this.onDisconnect();
9162
- throw error;
9127
+ connectorInfo = {};
9163
9128
  }
9129
+ if (!connectorInfo.name && walletState.accounts.length > 0) {
9130
+ const first = walletState.accounts[0];
9131
+ const persistedName = first.metadata?.connectorName;
9132
+ const persistedIcon = first.metadata?.connectorIcon;
9133
+ if (persistedName) connectorInfo.name = persistedName;
9134
+ if (persistedIcon) connectorInfo.icon = persistedIcon;
9135
+ }
9136
+ this.applyConnectorMetadata(connectorInfo);
9137
+ await this.resumeWithAccounts(evmAddresses, (accounts) => {
9138
+ setAccounts(this.store, {
9139
+ walletId: this.id,
9140
+ accounts
9141
+ });
9142
+ }, connectorInfo);
9164
9143
  };
9165
9144
  };
9166
9145
 
@@ -9277,7 +9256,7 @@ async function deriveAlgorandAccountFromEd25519(ed25519Seed) {
9277
9256
 
9278
9257
  // src/wallets/web3auth.ts
9279
9258
  var LOCAL_STORAGE_WEB3AUTH_KEY = `${LOCAL_STORAGE_KEY}:web3auth`;
9280
- var ICON15 = `data:image/svg+xml;base64,${btoa(`
9259
+ var ICON14 = `data:image/svg+xml;base64,${btoa(`
9281
9260
  <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
9282
9261
  <rect fill="#0364FF" width="40" height="40" rx="8"/>
9283
9262
  <path fill="#FFFFFF" d="M20 8c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12S26.627 8 20 8zm0 21.6c-5.302 0-9.6-4.298-9.6-9.6S14.698 10.4 20 10.4s9.6 4.298 9.6 9.6-4.298 9.6-9.6 9.6zm0-16.8c-3.976 0-7.2 3.224-7.2 7.2s3.224 7.2 7.2 7.2 7.2-3.224 7.2-7.2-3.224-7.2-7.2-7.2zm0 12c-2.651 0-4.8-2.149-4.8-4.8s2.149-4.8 4.8-4.8 4.8 2.149 4.8 4.8-2.149 4.8-4.8 4.8z"/>
@@ -9334,7 +9313,7 @@ var Web3AuthWallet = class extends BaseWallet {
9334
9313
  }
9335
9314
  static defaultMetadata = {
9336
9315
  name: "Web3Auth",
9337
- icon: ICON15
9316
+ icon: ICON14
9338
9317
  };
9339
9318
  /**
9340
9319
  * Initialize the Web3Auth client
@@ -9843,7 +9822,7 @@ var Web3AuthWallet = class extends BaseWallet {
9843
9822
 
9844
9823
  // src/wallets/w3wallet.ts
9845
9824
  var import_algosdk13 = __toESM(require("algosdk"), 1);
9846
- var ICON16 = `data:image/svg+xml;base64,${btoa(`
9825
+ var ICON15 = `data:image/svg+xml;base64,${btoa(`
9847
9826
  <svg width="860" height="860" viewBox="0 0 860 860" fill="none" xmlns="http://www.w3.org/2000/svg">
9848
9827
  <rect width="860" height="860" rx="30" fill="#151923"/>
9849
9828
  <path d="M766 207L496.627 623.406C463.521 675.336 382.014 652.248 382.014 590.941V432.568L260.638 623.28C227.559 675.255 146 652.186 146 590.854V274.844H234.646V499.761L356.022 309.049C389.101 257.074 470.66 280.143 470.66 341.475V499.978L660.146 207L766 207Z" fill="#4BB7D1"/>
@@ -9864,7 +9843,7 @@ var W3Wallet = class extends BaseWallet {
9864
9843
  }
9865
9844
  static defaultMetadata = {
9866
9845
  name: "W3 Wallet",
9867
- icon: ICON16
9846
+ icon: ICON15
9868
9847
  };
9869
9848
  async initializeClient() {
9870
9849
  this.logger.info("Initializing client...");
@@ -9994,10 +9973,9 @@ function createWalletMap() {
9994
9973
  ["kmd" /* KMD */]: KmdWallet,
9995
9974
  ["lute" /* LUTE */]: LuteWallet,
9996
9975
  ["magic" /* MAGIC */]: MagicAuth,
9997
- ["metamask" /* METAMASK */]: MetaMaskWallet,
9998
9976
  ["mnemonic" /* MNEMONIC */]: MnemonicWallet,
9999
9977
  ["pera" /* PERA */]: PeraWallet,
10000
- ["rainbow" /* RAINBOW */]: RainbowWallet,
9978
+ ["rainbowkit" /* RAINBOWKIT */]: RainbowKitWallet,
10001
9979
  ["walletconnect" /* WALLETCONNECT */]: WalletConnect,
10002
9980
  ["web3auth" /* WEB3AUTH */]: Web3AuthWallet,
10003
9981
  ["w3-wallet" /* W3_WALLET */]: W3Wallet
@@ -10118,7 +10096,7 @@ var WalletManager = class {
10118
10096
  activeNetwork,
10119
10097
  algodClient
10120
10098
  };
10121
- this.store = new import_store16.Store(initialState, {
10099
+ this.store = new import_store15.Store(initialState, {
10122
10100
  onUpdate: () => this.savePersistedState()
10123
10101
  });
10124
10102
  this.savePersistedState();
@@ -10491,12 +10469,11 @@ var webpackFallback = {
10491
10469
  LogLevel,
10492
10470
  LuteWallet,
10493
10471
  MagicAuth,
10494
- MetaMaskWallet,
10495
10472
  MnemonicWallet,
10496
10473
  NetworkConfigBuilder,
10497
10474
  NetworkId,
10498
10475
  PeraWallet,
10499
- RainbowWallet,
10476
+ RainbowKitWallet,
10500
10477
  ScopeType,
10501
10478
  SecureKeyContainer,
10502
10479
  SessionError,