@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.js CHANGED
@@ -37,10 +37,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
37
  mod
38
38
  ));
39
39
 
40
- // ../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs
40
+ // ../../../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs
41
41
  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;
42
42
  var init_es = __esm({
43
- "../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs"() {
43
+ "../../../../node_modules/.pnpm/@magic-sdk+types@24.22.0/node_modules/@magic-sdk/types/dist/es/index.mjs"() {
44
44
  "use strict";
45
45
  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 || {});
46
46
  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 || {});
@@ -84,7 +84,7 @@ var init_es = __esm({
84
84
  }
85
85
  });
86
86
 
87
- // ../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs
87
+ // ../../../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs
88
88
  function ir(r10) {
89
89
  let e = { exports: {} };
90
90
  return r10(e, e.exports), e.exports;
@@ -387,7 +387,7 @@ function On(r10) {
387
387
  }
388
388
  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;
389
389
  var init_es2 = __esm({
390
- "../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs"() {
390
+ "../../../../node_modules/.pnpm/@magic-sdk+provider@29.5.0_localforage@1.10.0/node_modules/@magic-sdk/provider/dist/es/index.mjs"() {
391
391
  "use strict";
392
392
  init_es();
393
393
  init_es();
@@ -1507,16 +1507,16 @@ var init_es2 = __esm({
1507
1507
  }
1508
1508
  });
1509
1509
 
1510
- // ../../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
1510
+ // ../../../../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
1511
1511
  var init_es3 = __esm({
1512
- "../../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"() {
1512
+ "../../../../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"() {
1513
1513
  "use strict";
1514
1514
  init_es2();
1515
1515
  init_es();
1516
1516
  }
1517
1517
  });
1518
1518
 
1519
- // ../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs
1519
+ // ../../../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs
1520
1520
  var es_exports = {};
1521
1521
  __export(es_exports, {
1522
1522
  AuthEventOnReceived: () => k,
@@ -1575,7 +1575,7 @@ function st2(_2) {
1575
1575
  }
1576
1576
  var $r2, Qe2, Zr2, qr2, kr2, et2, de2, Je2, rt2, $e2, qe2, er2, pe2, Te2, at2, ye2, wt2;
1577
1577
  var init_es4 = __esm({
1578
- "../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs"() {
1578
+ "../../../../node_modules/.pnpm/magic-sdk@29.4.2/node_modules/magic-sdk/dist/es/index.mjs"() {
1579
1579
  "use strict";
1580
1580
  init_es2();
1581
1581
  init_es2();
@@ -3199,14 +3199,14 @@ var init_es4 = __esm({
3199
3199
  }
3200
3200
  });
3201
3201
 
3202
- // ../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs
3202
+ // ../../../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs
3203
3203
  var es_exports2 = {};
3204
3204
  __export(es_exports2, {
3205
3205
  AlgorandExtension: () => r9
3206
3206
  });
3207
3207
  var r9;
3208
3208
  var init_es5 = __esm({
3209
- "../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs"() {
3209
+ "../../../../node_modules/.pnpm/@magic-ext+algorand@24.4.2/node_modules/@magic-ext/algorand/dist/es/index.mjs"() {
3210
3210
  "use strict";
3211
3211
  init_es3();
3212
3212
  r9 = class extends He.Internal {
@@ -3236,9 +3236,9 @@ var init_es5 = __esm({
3236
3236
  }
3237
3237
  });
3238
3238
 
3239
- // ../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js
3239
+ // ../../../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js
3240
3240
  var require_nacl_fast = __commonJS({
3241
- "../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js"(exports, module) {
3241
+ "../../../../node_modules/.pnpm/tweetnacl@1.0.3/node_modules/tweetnacl/nacl-fast.js"(exports, module) {
3242
3242
  "use strict";
3243
3243
  (function(nacl) {
3244
3244
  "use strict";
@@ -5736,10 +5736,9 @@ var WalletId = /* @__PURE__ */ ((WalletId2) => {
5736
5736
  WalletId2["KMD"] = "kmd";
5737
5737
  WalletId2["LUTE"] = "lute";
5738
5738
  WalletId2["MAGIC"] = "magic";
5739
- WalletId2["METAMASK"] = "metamask";
5740
5739
  WalletId2["MNEMONIC"] = "mnemonic";
5741
5740
  WalletId2["PERA"] = "pera";
5742
- WalletId2["RAINBOW"] = "rainbow";
5741
+ WalletId2["RAINBOWKIT"] = "rainbowkit";
5743
5742
  WalletId2["WALLETCONNECT"] = "walletconnect";
5744
5743
  WalletId2["WEB3AUTH"] = "web3auth";
5745
5744
  WalletId2["W3_WALLET"] = "w3-wallet";
@@ -5981,6 +5980,14 @@ var BaseWallet = class {
5981
5980
  return networkConfig[activeNetwork];
5982
5981
  }
5983
5982
  // ---------- Protected Methods ------------------------------------- //
5983
+ /**
5984
+ * Dynamically update wallet metadata (e.g., after learning the actual
5985
+ * connector name/icon during connect).
5986
+ */
5987
+ updateMetadata(updates) {
5988
+ ;
5989
+ this.metadata = { ...this.metadata, ...updates };
5990
+ }
5984
5991
  onDisconnect = () => {
5985
5992
  this.logger.debug(`Removing wallet from store...`);
5986
5993
  removeWallet(this.store, { walletId: this.walletKey });
@@ -8194,115 +8201,146 @@ var MagicAuth = class extends BaseWallet {
8194
8201
  };
8195
8202
  };
8196
8203
 
8197
- // src/wallets/liquid-evm-base.ts
8204
+ // src/wallets/mnemonic.ts
8198
8205
  import algosdk9 from "algosdk";
8199
- var LiquidEvmBaseWallet = class extends BaseWallet {
8200
- liquidEvmSdk = null;
8201
- algorandClient = null;
8202
- evmAddressMap = /* @__PURE__ */ new Map();
8203
- // algorandAddress -> evmAddress
8206
+ var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
8207
+ var ICON11 = `data:image/svg+xml;base64,${btoa(`
8208
+ <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
8209
+ <rect fill="#525252" width="400" height="400" />
8210
+ <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" />
8211
+ </svg>
8212
+ `)}`;
8213
+ var MnemonicWallet = class extends BaseWallet {
8214
+ account = null;
8204
8215
  options;
8205
8216
  store;
8206
- constructor(params) {
8207
- super(params);
8208
- this.options = params.options || {};
8209
- this.store = params.store;
8210
- }
8211
- /**
8212
- * Default metadata for Liquid EVM wallets.
8213
- * Subclasses MUST override this with their own metadata including isLiquid: "EVM"
8214
- */
8215
- static defaultMetadata;
8216
- /**
8217
- * Ensure the wallet is on the Algorand chain (4160).
8218
- * Queries the current chain first, and only switches/adds if needed.
8219
- */
8220
- async ensureAlgorandChain() {
8221
- const provider = await this.getEvmProvider();
8222
- const { ALGORAND_CHAIN_ID_HEX, ALGORAND_EVM_CHAIN_CONFIG } = await import("liquid-accounts-evm");
8223
- const currentChainId = await provider.request({ method: "eth_chainId" });
8224
- if (currentChainId === ALGORAND_CHAIN_ID_HEX) {
8225
- return;
8217
+ constructor({
8218
+ id,
8219
+ store,
8220
+ subscribe,
8221
+ getAlgodClient,
8222
+ options,
8223
+ metadata = {}
8224
+ }) {
8225
+ super({ id, metadata, getAlgodClient, store, subscribe });
8226
+ const {
8227
+ persistToStorage = false,
8228
+ promptForMnemonic = () => Promise.resolve(prompt("Enter 25-word mnemonic passphrase:"))
8229
+ } = options || {};
8230
+ this.options = { persistToStorage, promptForMnemonic };
8231
+ this.store = store;
8232
+ if (this.options.persistToStorage) {
8233
+ this.logger.warn(
8234
+ "Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!"
8235
+ );
8226
8236
  }
8227
- this.logger.info(`Wrong chain (${currentChainId}), switching to Algorand (${ALGORAND_CHAIN_ID_HEX})...`);
8237
+ }
8238
+ static defaultMetadata = {
8239
+ name: "Mnemonic",
8240
+ icon: ICON11
8241
+ };
8242
+ loadMnemonicFromStorage() {
8243
+ return StorageAdapter.getItem(LOCAL_STORAGE_MNEMONIC_KEY);
8244
+ }
8245
+ saveMnemonicToStorage(mnemonic) {
8246
+ StorageAdapter.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic);
8247
+ }
8248
+ removeMnemonicFromStorage() {
8249
+ StorageAdapter.removeItem(LOCAL_STORAGE_MNEMONIC_KEY);
8250
+ }
8251
+ checkMainnet() {
8228
8252
  try {
8229
- await provider.request({
8230
- method: "wallet_switchEthereumChain",
8231
- params: [{ chainId: ALGORAND_CHAIN_ID_HEX }]
8232
- });
8233
- } catch (switchError) {
8234
- if (switchError.code === 4902) {
8235
- this.logger.info("Algorand chain not found, adding it...");
8236
- await provider.request({
8237
- method: "wallet_addEthereumChain",
8238
- params: [ALGORAND_EVM_CHAIN_CONFIG]
8239
- });
8240
- } else {
8241
- throw switchError;
8253
+ const network = this.activeNetworkConfig;
8254
+ if (!network.isTestnet) {
8255
+ this.logger.warn(
8256
+ "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)."
8257
+ );
8258
+ throw new Error("Production network detected. Aborting.");
8242
8259
  }
8260
+ } catch (error) {
8261
+ this.disconnect();
8262
+ throw error;
8243
8263
  }
8244
8264
  }
8245
- /**
8246
- * Initialize the Liquid EVM SDK for deriving Algorand addresses
8247
- */
8248
- async initializeEvmSdk() {
8249
- if (!this.liquidEvmSdk) {
8250
- this.logger.info("Initializing Liquid EVM SDK...");
8251
- if (!this.algorandClient) {
8252
- const { AlgorandClient } = await import("@algorandfoundation/algokit-utils");
8253
- const algodClient = this.getAlgodClient();
8254
- this.algorandClient = AlgorandClient.fromClients({
8255
- algod: algodClient
8256
- });
8265
+ async initializeAccount() {
8266
+ let mnemonic = this.loadMnemonicFromStorage();
8267
+ if (!mnemonic) {
8268
+ mnemonic = await this.options.promptForMnemonic();
8269
+ if (!mnemonic) {
8270
+ this.account = null;
8271
+ this.logger.error("No mnemonic provided");
8272
+ throw new Error("No mnemonic provided");
8273
+ }
8274
+ if (this.options.persistToStorage) {
8275
+ this.logger.warn("Mnemonic saved to localStorage.");
8276
+ this.saveMnemonicToStorage(mnemonic);
8257
8277
  }
8258
- const { LiquidEvmSdk } = await import("liquid-accounts-evm");
8259
- this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
8260
- this.logger.info("Liquid EVM SDK initialized");
8261
8278
  }
8262
- return this.liquidEvmSdk;
8279
+ const account = algosdk9.mnemonicToSecretKey(mnemonic);
8280
+ this.account = account;
8281
+ return account;
8263
8282
  }
8264
- /**
8265
- * Derive Algorand accounts from EVM addresses
8266
- */
8267
- async deriveAlgorandAccounts(evmAddresses) {
8268
- const liquidEvmSdk = await this.initializeEvmSdk();
8269
- const walletAccounts = [];
8270
- for (let i = 0; i < evmAddresses.length; i++) {
8271
- const evmAddress = evmAddresses[i];
8272
- const algorandAddress = await liquidEvmSdk.getAddress({ evmAddress });
8273
- this.evmAddressMap.set(algorandAddress, evmAddress);
8274
- walletAccounts.push({
8275
- name: `${this.metadata.name} ${evmAddress}`,
8276
- address: algorandAddress,
8277
- metadata: { evmAddress }
8278
- });
8283
+ connect = async () => {
8284
+ this.checkMainnet();
8285
+ this.logger.info("Connecting...");
8286
+ const account = await this.initializeAccount();
8287
+ const walletAccount = {
8288
+ name: `${this.metadata.name} Account`,
8289
+ address: account.addr.toString()
8290
+ };
8291
+ const walletState = {
8292
+ accounts: [walletAccount],
8293
+ activeAccount: walletAccount
8294
+ };
8295
+ addWallet(this.store, {
8296
+ walletId: this.id,
8297
+ wallet: walletState
8298
+ });
8299
+ this.logger.info("Connected successfully", walletState);
8300
+ return [walletAccount];
8301
+ };
8302
+ disconnect = async () => {
8303
+ this.logger.info("Disconnecting...");
8304
+ this.onDisconnect();
8305
+ this.account = null;
8306
+ this.removeMnemonicFromStorage();
8307
+ this.logger.info("Disconnected");
8308
+ };
8309
+ resumeSession = async () => {
8310
+ this.checkMainnet();
8311
+ const state = this.store.state;
8312
+ const walletState = state.wallets[this.id];
8313
+ if (!walletState) {
8314
+ this.logger.info("No session to resume");
8315
+ return;
8279
8316
  }
8280
- return walletAccounts;
8281
- }
8282
- /**
8283
- * Convert bytes to hex string with 0x prefix
8284
- */
8285
- bytesToHex(bytes) {
8286
- return "0x" + Array.from(bytes).map((b3) => b3.toString(16).padStart(2, "0")).join("");
8287
- }
8288
- /**
8289
- * Process transaction group to extract transactions that need signing
8290
- */
8317
+ this.logger.info("Resuming session...");
8318
+ if (this.options.persistToStorage) {
8319
+ try {
8320
+ await this.initializeAccount();
8321
+ this.logger.info("Session resumed successfully");
8322
+ } catch (error) {
8323
+ this.logger.error("Error resuming session:", error.message);
8324
+ this.disconnect();
8325
+ throw error;
8326
+ }
8327
+ } else {
8328
+ this.logger.info("No session to resume, disconnecting...");
8329
+ this.disconnect();
8330
+ }
8331
+ };
8291
8332
  processTxns(txnGroup, indexesToSign) {
8292
8333
  const txnsToSign = [];
8293
8334
  txnGroup.forEach((txn, index) => {
8294
8335
  const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8295
8336
  const signer = txn.sender.toString();
8296
- const canSignTxn = this.addresses.includes(signer);
8337
+ const canSignTxn = signer === this.account.addr.toString();
8297
8338
  if (isIndexMatch && canSignTxn) {
8298
8339
  txnsToSign.push(txn);
8299
8340
  }
8300
8341
  });
8301
8342
  return txnsToSign;
8302
8343
  }
8303
- /**
8304
- * Process encoded transaction group to extract transactions that need signing
8305
- */
8306
8344
  processEncodedTxns(txnGroup, indexesToSign) {
8307
8345
  const txnsToSign = [];
8308
8346
  txnGroup.forEach((txnBuffer, index) => {
@@ -8311,424 +8349,24 @@ var LiquidEvmBaseWallet = class extends BaseWallet {
8311
8349
  const txn = isSigned ? algosdk9.decodeSignedTransaction(txnBuffer).txn : algosdk9.decodeUnsignedTransaction(txnBuffer);
8312
8350
  const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8313
8351
  const signer = txn.sender.toString();
8314
- const canSignTxn = !isSigned && this.addresses.includes(signer);
8352
+ const canSignTxn = !isSigned && signer === this.account.addr.toString();
8315
8353
  if (isIndexMatch && canSignTxn) {
8316
8354
  txnsToSign.push(txn);
8317
8355
  }
8318
8356
  });
8319
8357
  return txnsToSign;
8320
8358
  }
8321
- /**
8322
- * Sign Algorand transactions using EVM wallet signatures
8323
- */
8324
8359
  signTransactions = async (txnGroup, indexesToSign) => {
8360
+ this.checkMainnet();
8325
8361
  try {
8326
8362
  this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8327
- const evmSdk = await this.initializeEvmSdk();
8328
- let flatTxns = [];
8363
+ let txnsToSign = [];
8329
8364
  if (isTransactionArray(txnGroup)) {
8330
- flatTxns = flattenTxnGroup(txnGroup);
8365
+ const flatTxns = flattenTxnGroup(txnGroup);
8366
+ txnsToSign = this.processTxns(flatTxns, indexesToSign);
8331
8367
  } else {
8332
- const flatEncoded = flattenTxnGroup(txnGroup);
8333
- flatTxns = flatEncoded.map((txnBuffer) => {
8334
- const decodedObj = algosdk9.msgpackRawDecode(txnBuffer);
8335
- const isSigned = isSignedTxn(decodedObj);
8336
- return isSigned ? algosdk9.decodeSignedTransaction(txnBuffer).txn : algosdk9.decodeUnsignedTransaction(txnBuffer);
8337
- });
8338
- }
8339
- const txnsToSign = isTransactionArray(txnGroup) ? this.processTxns(flatTxns, indexesToSign) : this.processEncodedTxns(flattenTxnGroup(txnGroup), indexesToSign);
8340
- if (txnsToSign.length === 0) {
8341
- this.logger.debug("No transactions to sign");
8342
- return flatTxns.map(() => null);
8343
- }
8344
- const firstTxn = txnsToSign[0];
8345
- const algorandAddress = firstTxn.sender.toString();
8346
- const evmAddress = this.evmAddressMap.get(algorandAddress);
8347
- if (!evmAddress) {
8348
- throw new Error(`No EVM address found for Algorand address: ${algorandAddress}`);
8349
- }
8350
- const onBeforeSign = this.options.uiHooks?.onBeforeSign ?? this.managerUIHooks?.onBeforeSign;
8351
- if (onBeforeSign) {
8352
- this.logger.debug("Running onBeforeSign hook", { txnGroup, indexesToSign });
8353
- await onBeforeSign(txnGroup, indexesToSign);
8354
- }
8355
- await this.ensureAlgorandChain();
8356
- const signedBlobs = await evmSdk.signTxn({
8357
- evmAddress,
8358
- txns: flatTxns,
8359
- signMessage: (typedData) => this.signWithProvider(typedData, evmAddress)
8360
- });
8361
- const onAfterSign = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8362
- if (onAfterSign) {
8363
- this.logger.debug("Running onAfterSign hook");
8364
- try {
8365
- onAfterSign(true);
8366
- } catch (e) {
8367
- }
8368
- }
8369
- const result = flatTxns.map((txn, index) => {
8370
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8371
- const signer = txn.sender.toString();
8372
- const canSignTxn = this.addresses.includes(signer);
8373
- if (isIndexMatch && canSignTxn) {
8374
- return signedBlobs[index];
8375
- }
8376
- return null;
8377
- });
8378
- this.logger.debug("Transactions signed successfully", result);
8379
- return result;
8380
- } catch (error) {
8381
- try {
8382
- const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8383
- onAfterSignCleanup?.(false, error.message);
8384
- } catch (e) {
8385
- }
8386
- this.logger.error("Error signing transactions:", error.message);
8387
- throw error;
8388
- }
8389
- };
8390
- /**
8391
- * Helper to compare and update accounts if needed during session resume
8392
- */
8393
- async resumeWithAccounts(evmAddresses, setAccountsFn) {
8394
- const state = this.store.state;
8395
- const walletState = state.wallets[this.id];
8396
- if (!walletState) {
8397
- this.logger.info("No session to resume");
8398
- return;
8399
- }
8400
- for (const account of walletState.accounts) {
8401
- const evmAddr = account.metadata?.evmAddress;
8402
- if (evmAddr) {
8403
- this.evmAddressMap.set(account.address, evmAddr);
8404
- }
8405
- }
8406
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
8407
- const match = compareAccounts(walletAccounts, walletState.accounts);
8408
- if (!match) {
8409
- this.logger.warn("Session accounts mismatch, updating accounts", {
8410
- prev: walletState.accounts,
8411
- current: walletAccounts
8412
- });
8413
- setAccountsFn(walletAccounts);
8414
- }
8415
- this.logger.info("Session resumed");
8416
- }
8417
- notifyConnect(evmAddress, algorandAddress) {
8418
- const onConnect = this.options.uiHooks?.onConnect ?? this.managerUIHooks?.onConnect;
8419
- if (onConnect) {
8420
- onConnect({ evmAddress, algorandAddress });
8421
- }
8422
- }
8423
- };
8424
-
8425
- // src/wallets/metamask.ts
8426
- var ICON11 = `data:image/svg+xml;base64,${btoa(`
8427
- <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"
8428
- viewBox="0 0 142 136.878" style="enable-background:new 0 0 142 136.878;" xml:space="preserve">
8429
- <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
8430
- 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
8431
- L132.682,132.192z"/>
8432
- <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
8433
- 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
8434
- 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
8435
- 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
8436
- C112.604,84.295,112.678,65.975,112.678,65.975z"/>
8437
- <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
8438
- 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
8439
- 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
8440
- l-10.498-9.956H82.776V74.338z"/>
8441
- <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
8442
- 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
8443
- V100.801z M84.915,28.538h-27.85l-1.891,19.599l9.872,64.013h11.891l9.878-64.013L84.915,28.538z"/>
8444
- <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
8445
- 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
8446
- 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"/>
8447
- <path style="fill:#C0C4CD;" d="M79.029,124.384v12.495H62.945v-12.495L79.029,124.384L79.029,124.384z"/>
8448
- <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
8449
- M102.113,123.072l-23.084,13.8v-12.495l2.067-7.566C81.096,116.811,102.113,123.072,102.113,123.072z"/>
8450
- </svg>
8451
- `)}`;
8452
- var MetaMaskWallet = class extends LiquidEvmBaseWallet {
8453
- metamaskSdk = null;
8454
- provider = null;
8455
- options;
8456
- constructor(params) {
8457
- super(params);
8458
- this.options = params.options || {};
8459
- }
8460
- static defaultMetadata = {
8461
- name: "MetaMask",
8462
- icon: ICON11,
8463
- isLiquid: "EVM"
8464
- };
8465
- async initializeProvider() {
8466
- if (!this.metamaskSdk) {
8467
- this.logger.info("Initializing MetaMask SDK...");
8468
- const { MetaMaskSDK } = await import("@metamask/sdk");
8469
- this.metamaskSdk = new MetaMaskSDK({
8470
- dappMetadata: {
8471
- name: this.options.dappMetadata?.name || "Algorand dApp",
8472
- url: this.options.dappMetadata?.url || (typeof window !== "undefined" ? window.location.href : ""),
8473
- ...this.options.dappMetadata?.iconUrl && { iconUrl: this.options.dappMetadata.iconUrl }
8474
- }
8475
- });
8476
- this.logger.info("MetaMask SDK initialized");
8477
- }
8478
- }
8479
- async getEvmProvider() {
8480
- if (!this.provider) {
8481
- await this.initializeProvider();
8482
- this.provider = this.metamaskSdk.getProvider() || null;
8483
- if (!this.provider) {
8484
- throw new Error("MetaMask provider not available. Please install MetaMask.");
8485
- }
8486
- }
8487
- return this.provider;
8488
- }
8489
- async signWithProvider(typedData, evmAddress) {
8490
- const provider = await this.getEvmProvider();
8491
- return await provider.request({
8492
- method: "eth_signTypedData_v4",
8493
- params: [evmAddress, JSON.stringify(typedData)]
8494
- });
8495
- }
8496
- connect = async () => {
8497
- this.logger.info("Connecting...");
8498
- await this.initializeProvider();
8499
- await this.initializeEvmSdk();
8500
- const provider = await this.getEvmProvider();
8501
- const evmAddresses = await provider.request({
8502
- method: "eth_requestAccounts"
8503
- });
8504
- if (evmAddresses.length === 0) {
8505
- this.logger.error("No accounts found!");
8506
- throw new Error("No accounts found!");
8507
- }
8508
- this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
8509
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
8510
- const activeAccount = walletAccounts[0];
8511
- const walletState = {
8512
- accounts: walletAccounts,
8513
- activeAccount
8514
- };
8515
- addWallet(this.store, {
8516
- walletId: this.id,
8517
- wallet: walletState
8518
- });
8519
- this.logger.info("\u2705 Connected.", walletState);
8520
- this.notifyConnect(evmAddresses[0], activeAccount.address);
8521
- return walletAccounts;
8522
- };
8523
- disconnect = async () => {
8524
- this.logger.info("Disconnecting...");
8525
- if (this.metamaskSdk) {
8526
- await this.metamaskSdk.terminate();
8527
- }
8528
- this.provider = null;
8529
- this.evmAddressMap.clear();
8530
- this.onDisconnect();
8531
- this.logger.info("Disconnected");
8532
- };
8533
- resumeSession = async () => {
8534
- try {
8535
- const state = this.store.state;
8536
- const walletState = state.wallets[this.id];
8537
- if (!walletState) {
8538
- this.logger.info("No session to resume");
8539
- return;
8540
- }
8541
- this.logger.info("Resuming session...");
8542
- await this.initializeProvider();
8543
- await this.initializeEvmSdk();
8544
- const provider = await this.getEvmProvider();
8545
- const evmAddresses = await provider.request({
8546
- method: "eth_accounts"
8547
- });
8548
- if (evmAddresses.length === 0) {
8549
- this.logger.error("No accounts found!");
8550
- throw new Error("No accounts found!");
8551
- }
8552
- await this.resumeWithAccounts(evmAddresses, (accounts) => {
8553
- setAccounts(this.store, {
8554
- walletId: this.id,
8555
- accounts
8556
- });
8557
- });
8558
- } catch (error) {
8559
- this.logger.error("Error resuming session:", error.message);
8560
- this.onDisconnect();
8561
- throw error;
8562
- }
8563
- };
8564
- };
8565
-
8566
- // src/wallets/mnemonic.ts
8567
- import algosdk10 from "algosdk";
8568
- var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
8569
- var ICON12 = `data:image/svg+xml;base64,${btoa(`
8570
- <svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
8571
- <rect fill="#525252" width="400" height="400" />
8572
- <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" />
8573
- </svg>
8574
- `)}`;
8575
- var MnemonicWallet = class extends BaseWallet {
8576
- account = null;
8577
- options;
8578
- store;
8579
- constructor({
8580
- id,
8581
- store,
8582
- subscribe,
8583
- getAlgodClient,
8584
- options,
8585
- metadata = {}
8586
- }) {
8587
- super({ id, metadata, getAlgodClient, store, subscribe });
8588
- const {
8589
- persistToStorage = false,
8590
- promptForMnemonic = () => Promise.resolve(prompt("Enter 25-word mnemonic passphrase:"))
8591
- } = options || {};
8592
- this.options = { persistToStorage, promptForMnemonic };
8593
- this.store = store;
8594
- if (this.options.persistToStorage) {
8595
- this.logger.warn(
8596
- "Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!"
8597
- );
8598
- }
8599
- }
8600
- static defaultMetadata = {
8601
- name: "Mnemonic",
8602
- icon: ICON12
8603
- };
8604
- loadMnemonicFromStorage() {
8605
- return StorageAdapter.getItem(LOCAL_STORAGE_MNEMONIC_KEY);
8606
- }
8607
- saveMnemonicToStorage(mnemonic) {
8608
- StorageAdapter.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic);
8609
- }
8610
- removeMnemonicFromStorage() {
8611
- StorageAdapter.removeItem(LOCAL_STORAGE_MNEMONIC_KEY);
8612
- }
8613
- checkMainnet() {
8614
- try {
8615
- const network = this.activeNetworkConfig;
8616
- if (!network.isTestnet) {
8617
- this.logger.warn(
8618
- "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)."
8619
- );
8620
- throw new Error("Production network detected. Aborting.");
8621
- }
8622
- } catch (error) {
8623
- this.disconnect();
8624
- throw error;
8625
- }
8626
- }
8627
- async initializeAccount() {
8628
- let mnemonic = this.loadMnemonicFromStorage();
8629
- if (!mnemonic) {
8630
- mnemonic = await this.options.promptForMnemonic();
8631
- if (!mnemonic) {
8632
- this.account = null;
8633
- this.logger.error("No mnemonic provided");
8634
- throw new Error("No mnemonic provided");
8635
- }
8636
- if (this.options.persistToStorage) {
8637
- this.logger.warn("Mnemonic saved to localStorage.");
8638
- this.saveMnemonicToStorage(mnemonic);
8639
- }
8640
- }
8641
- const account = algosdk10.mnemonicToSecretKey(mnemonic);
8642
- this.account = account;
8643
- return account;
8644
- }
8645
- connect = async () => {
8646
- this.checkMainnet();
8647
- this.logger.info("Connecting...");
8648
- const account = await this.initializeAccount();
8649
- const walletAccount = {
8650
- name: `${this.metadata.name} Account`,
8651
- address: account.addr.toString()
8652
- };
8653
- const walletState = {
8654
- accounts: [walletAccount],
8655
- activeAccount: walletAccount
8656
- };
8657
- addWallet(this.store, {
8658
- walletId: this.id,
8659
- wallet: walletState
8660
- });
8661
- this.logger.info("Connected successfully", walletState);
8662
- return [walletAccount];
8663
- };
8664
- disconnect = async () => {
8665
- this.logger.info("Disconnecting...");
8666
- this.onDisconnect();
8667
- this.account = null;
8668
- this.removeMnemonicFromStorage();
8669
- this.logger.info("Disconnected");
8670
- };
8671
- resumeSession = async () => {
8672
- this.checkMainnet();
8673
- const state = this.store.state;
8674
- const walletState = state.wallets[this.id];
8675
- if (!walletState) {
8676
- this.logger.info("No session to resume");
8677
- return;
8678
- }
8679
- this.logger.info("Resuming session...");
8680
- if (this.options.persistToStorage) {
8681
- try {
8682
- await this.initializeAccount();
8683
- this.logger.info("Session resumed successfully");
8684
- } catch (error) {
8685
- this.logger.error("Error resuming session:", error.message);
8686
- this.disconnect();
8687
- throw error;
8688
- }
8689
- } else {
8690
- this.logger.info("No session to resume, disconnecting...");
8691
- this.disconnect();
8692
- }
8693
- };
8694
- processTxns(txnGroup, indexesToSign) {
8695
- const txnsToSign = [];
8696
- txnGroup.forEach((txn, index) => {
8697
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8698
- const signer = txn.sender.toString();
8699
- const canSignTxn = signer === this.account.addr.toString();
8700
- if (isIndexMatch && canSignTxn) {
8701
- txnsToSign.push(txn);
8702
- }
8703
- });
8704
- return txnsToSign;
8705
- }
8706
- processEncodedTxns(txnGroup, indexesToSign) {
8707
- const txnsToSign = [];
8708
- txnGroup.forEach((txnBuffer, index) => {
8709
- const decodedObj = algosdk10.msgpackRawDecode(txnBuffer);
8710
- const isSigned = isSignedTxn(decodedObj);
8711
- const txn = isSigned ? algosdk10.decodeSignedTransaction(txnBuffer).txn : algosdk10.decodeUnsignedTransaction(txnBuffer);
8712
- const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8713
- const signer = txn.sender.toString();
8714
- const canSignTxn = !isSigned && signer === this.account.addr.toString();
8715
- if (isIndexMatch && canSignTxn) {
8716
- txnsToSign.push(txn);
8717
- }
8718
- });
8719
- return txnsToSign;
8720
- }
8721
- signTransactions = async (txnGroup, indexesToSign) => {
8722
- this.checkMainnet();
8723
- try {
8724
- this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8725
- let txnsToSign = [];
8726
- if (isTransactionArray(txnGroup)) {
8727
- const flatTxns = flattenTxnGroup(txnGroup);
8728
- txnsToSign = this.processTxns(flatTxns, indexesToSign);
8729
- } else {
8730
- const flatTxns = flattenTxnGroup(txnGroup);
8731
- txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8368
+ const flatTxns = flattenTxnGroup(txnGroup);
8369
+ txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8732
8370
  }
8733
8371
  const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account.sk));
8734
8372
  this.logger.debug("Transactions signed successfully", { signedTxns });
@@ -8741,8 +8379,8 @@ var MnemonicWallet = class extends BaseWallet {
8741
8379
  };
8742
8380
 
8743
8381
  // src/wallets/pera.ts
8744
- import algosdk11 from "algosdk";
8745
- var ICON13 = `data:image/svg+xml;base64,${btoa(`
8382
+ import algosdk10 from "algosdk";
8383
+ var ICON12 = `data:image/svg+xml;base64,${btoa(`
8746
8384
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
8747
8385
  <rect fill="#FFEE55" width="200" height="200" />
8748
8386
  <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" />
@@ -8771,7 +8409,7 @@ var PeraWallet = class extends BaseWallet {
8771
8409
  }
8772
8410
  static defaultMetadata = {
8773
8411
  name: "Pera",
8774
- icon: ICON13
8412
+ icon: ICON12
8775
8413
  };
8776
8414
  async initializeClient() {
8777
8415
  this.logger.info("Initializing client...");
@@ -8882,13 +8520,173 @@ var PeraWallet = class extends BaseWallet {
8882
8520
  accounts: walletAccounts
8883
8521
  });
8884
8522
  }
8885
- this.logger.info("Session resumed successfully");
8886
- } catch (error) {
8887
- this.logger.error("Error resuming session:", error.message);
8888
- this.onDisconnect();
8889
- throw error;
8523
+ this.logger.info("Session resumed successfully");
8524
+ } catch (error) {
8525
+ this.logger.error("Error resuming session:", error.message);
8526
+ this.onDisconnect();
8527
+ throw error;
8528
+ }
8529
+ };
8530
+ processTxns(txnGroup, indexesToSign) {
8531
+ const txnsToSign = [];
8532
+ txnGroup.forEach((txn, index) => {
8533
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8534
+ const signer = txn.sender.toString();
8535
+ const canSignTxn = this.addresses.includes(signer);
8536
+ if (isIndexMatch && canSignTxn) {
8537
+ txnsToSign.push({ txn });
8538
+ } else {
8539
+ txnsToSign.push({ txn, signers: [] });
8540
+ }
8541
+ });
8542
+ return txnsToSign;
8543
+ }
8544
+ processEncodedTxns(txnGroup, indexesToSign) {
8545
+ const txnsToSign = [];
8546
+ txnGroup.forEach((txnBuffer, index) => {
8547
+ const decodedObj = algosdk10.msgpackRawDecode(txnBuffer);
8548
+ const isSigned = isSignedTxn(decodedObj);
8549
+ const txn = isSigned ? algosdk10.decodeSignedTransaction(txnBuffer).txn : algosdk10.decodeUnsignedTransaction(txnBuffer);
8550
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8551
+ const signer = txn.sender.toString();
8552
+ const canSignTxn = !isSigned && this.addresses.includes(signer);
8553
+ if (isIndexMatch && canSignTxn) {
8554
+ txnsToSign.push({ txn });
8555
+ } else {
8556
+ txnsToSign.push({ txn, signers: [] });
8557
+ }
8558
+ });
8559
+ return txnsToSign;
8560
+ }
8561
+ signTransactions = async (txnGroup, indexesToSign) => {
8562
+ try {
8563
+ this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8564
+ let txnsToSign = [];
8565
+ if (isTransactionArray(txnGroup)) {
8566
+ const flatTxns = flattenTxnGroup(txnGroup);
8567
+ txnsToSign = this.processTxns(flatTxns, indexesToSign);
8568
+ } else {
8569
+ const flatTxns = flattenTxnGroup(txnGroup);
8570
+ txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8571
+ }
8572
+ const client = this.client || await this.initializeClient();
8573
+ this.logger.debug("Sending processed transactions to wallet...", [txnsToSign]);
8574
+ const signedTxns = await client.signTransaction([txnsToSign]);
8575
+ this.logger.debug("Received signed transactions from wallet", signedTxns);
8576
+ const result = txnsToSign.reduce((acc, txn) => {
8577
+ if (txn.signers && txn.signers.length == 0) {
8578
+ acc.push(null);
8579
+ } else {
8580
+ const signedTxn = signedTxns.shift();
8581
+ if (signedTxn) {
8582
+ acc.push(signedTxn);
8583
+ }
8584
+ }
8585
+ return acc;
8586
+ }, []);
8587
+ this.logger.debug("Transactions signed successfully", result);
8588
+ return result;
8589
+ } catch (error) {
8590
+ this.logger.error("Error signing transactions:", error.message);
8591
+ throw error;
8592
+ }
8593
+ };
8594
+ };
8595
+
8596
+ // src/wallets/liquid-evm-base.ts
8597
+ import algosdk11 from "algosdk";
8598
+ var LiquidEvmBaseWallet = class extends BaseWallet {
8599
+ liquidEvmSdk = null;
8600
+ algorandClient = null;
8601
+ evmAddressMap = /* @__PURE__ */ new Map();
8602
+ // algorandAddress -> evmAddress
8603
+ options;
8604
+ store;
8605
+ constructor(params) {
8606
+ super(params);
8607
+ this.options = params.options || {};
8608
+ this.store = params.store;
8609
+ }
8610
+ /**
8611
+ * Default metadata for Liquid EVM wallets.
8612
+ * Subclasses MUST override this with their own metadata including isLiquid: "EVM"
8613
+ */
8614
+ static defaultMetadata;
8615
+ /**
8616
+ * Ensure the wallet is on the Algorand chain (4160).
8617
+ * Queries the current chain first, and only switches/adds if needed.
8618
+ */
8619
+ async ensureAlgorandChain() {
8620
+ const provider = await this.getEvmProvider();
8621
+ const { ALGORAND_CHAIN_ID_HEX, ALGORAND_EVM_CHAIN_CONFIG } = await import("liquid-accounts-evm");
8622
+ const currentChainId = await provider.request({ method: "eth_chainId" });
8623
+ if (currentChainId.toLowerCase() === ALGORAND_CHAIN_ID_HEX.toLowerCase()) {
8624
+ return;
8625
+ }
8626
+ this.logger.info(`Wrong chain (${currentChainId}), switching to Algorand (${ALGORAND_CHAIN_ID_HEX})...`);
8627
+ try {
8628
+ await provider.request({
8629
+ method: "wallet_switchEthereumChain",
8630
+ params: [{ chainId: ALGORAND_CHAIN_ID_HEX }]
8631
+ });
8632
+ } catch (switchError) {
8633
+ const chainUnknown = [4902, -32600, -32603].includes(switchError.code);
8634
+ if (chainUnknown) {
8635
+ this.logger.info("Algorand chain not found, adding it...");
8636
+ await provider.request({
8637
+ method: "wallet_addEthereumChain",
8638
+ params: [ALGORAND_EVM_CHAIN_CONFIG]
8639
+ });
8640
+ } else {
8641
+ throw switchError;
8642
+ }
8643
+ }
8644
+ }
8645
+ /**
8646
+ * Initialize the Liquid EVM SDK for deriving Algorand addresses
8647
+ */
8648
+ async initializeEvmSdk() {
8649
+ if (!this.liquidEvmSdk) {
8650
+ this.logger.info("Initializing Liquid EVM SDK...");
8651
+ if (!this.algorandClient) {
8652
+ const { AlgorandClient } = await import("@algorandfoundation/algokit-utils");
8653
+ const algodClient = this.getAlgodClient();
8654
+ this.algorandClient = AlgorandClient.fromClients({
8655
+ algod: algodClient
8656
+ });
8657
+ }
8658
+ const { LiquidEvmSdk } = await import("liquid-accounts-evm");
8659
+ this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
8660
+ this.logger.info("Liquid EVM SDK initialized");
8890
8661
  }
8891
- };
8662
+ return this.liquidEvmSdk;
8663
+ }
8664
+ /**
8665
+ * Derive Algorand accounts from EVM addresses.
8666
+ * @param evmAddresses - EVM addresses to derive Algorand accounts from
8667
+ * @param connectorInfo - Optional connector name/icon to include in account metadata
8668
+ */
8669
+ async deriveAlgorandAccounts(evmAddresses, connectorInfo) {
8670
+ const liquidEvmSdk = await this.initializeEvmSdk();
8671
+ const walletAccounts = [];
8672
+ for (let i = 0; i < evmAddresses.length; i++) {
8673
+ const evmAddress = evmAddresses[i];
8674
+ const algorandAddress = await liquidEvmSdk.getAddress({ evmAddress });
8675
+ this.evmAddressMap.set(algorandAddress, evmAddress);
8676
+ const metadata = { evmAddress };
8677
+ if (connectorInfo?.name) metadata.connectorName = connectorInfo.name;
8678
+ if (connectorInfo?.icon) metadata.connectorIcon = connectorInfo.icon;
8679
+ walletAccounts.push({
8680
+ name: `${this.metadata.name} ${evmAddress}`,
8681
+ address: algorandAddress,
8682
+ metadata
8683
+ });
8684
+ }
8685
+ return walletAccounts;
8686
+ }
8687
+ /**
8688
+ * Process transaction group to extract transactions that need signing
8689
+ */
8892
8690
  processTxns(txnGroup, indexesToSign) {
8893
8691
  const txnsToSign = [];
8894
8692
  txnGroup.forEach((txn, index) => {
@@ -8896,13 +8694,14 @@ var PeraWallet = class extends BaseWallet {
8896
8694
  const signer = txn.sender.toString();
8897
8695
  const canSignTxn = this.addresses.includes(signer);
8898
8696
  if (isIndexMatch && canSignTxn) {
8899
- txnsToSign.push({ txn });
8900
- } else {
8901
- txnsToSign.push({ txn, signers: [] });
8697
+ txnsToSign.push(txn);
8902
8698
  }
8903
8699
  });
8904
8700
  return txnsToSign;
8905
8701
  }
8702
+ /**
8703
+ * Process encoded transaction group to extract transactions that need signing
8704
+ */
8906
8705
  processEncodedTxns(txnGroup, indexesToSign) {
8907
8706
  const txnsToSign = [];
8908
8707
  txnGroup.forEach((txnBuffer, index) => {
@@ -8913,154 +8712,319 @@ var PeraWallet = class extends BaseWallet {
8913
8712
  const signer = txn.sender.toString();
8914
8713
  const canSignTxn = !isSigned && this.addresses.includes(signer);
8915
8714
  if (isIndexMatch && canSignTxn) {
8916
- txnsToSign.push({ txn });
8917
- } else {
8918
- txnsToSign.push({ txn, signers: [] });
8715
+ txnsToSign.push(txn);
8919
8716
  }
8920
8717
  });
8921
8718
  return txnsToSign;
8922
8719
  }
8720
+ /**
8721
+ * Sign Algorand transactions using EVM wallet signatures
8722
+ */
8923
8723
  signTransactions = async (txnGroup, indexesToSign) => {
8924
8724
  try {
8925
8725
  this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
8926
- let txnsToSign = [];
8726
+ const evmSdk = await this.initializeEvmSdk();
8727
+ let flatTxns = [];
8927
8728
  if (isTransactionArray(txnGroup)) {
8928
- const flatTxns = flattenTxnGroup(txnGroup);
8929
- txnsToSign = this.processTxns(flatTxns, indexesToSign);
8729
+ flatTxns = flattenTxnGroup(txnGroup);
8930
8730
  } else {
8931
- const flatTxns = flattenTxnGroup(txnGroup);
8932
- txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
8731
+ const flatEncoded = flattenTxnGroup(txnGroup);
8732
+ flatTxns = flatEncoded.map((txnBuffer) => {
8733
+ const decodedObj = algosdk11.msgpackRawDecode(txnBuffer);
8734
+ const isSigned = isSignedTxn(decodedObj);
8735
+ return isSigned ? algosdk11.decodeSignedTransaction(txnBuffer).txn : algosdk11.decodeUnsignedTransaction(txnBuffer);
8736
+ });
8933
8737
  }
8934
- const client = this.client || await this.initializeClient();
8935
- this.logger.debug("Sending processed transactions to wallet...", [txnsToSign]);
8936
- const signedTxns = await client.signTransaction([txnsToSign]);
8937
- this.logger.debug("Received signed transactions from wallet", signedTxns);
8938
- const result = txnsToSign.reduce((acc, txn) => {
8939
- if (txn.signers && txn.signers.length == 0) {
8940
- acc.push(null);
8941
- } else {
8942
- const signedTxn = signedTxns.shift();
8943
- if (signedTxn) {
8944
- acc.push(signedTxn);
8738
+ const txnsToSign = isTransactionArray(txnGroup) ? this.processTxns(flatTxns, indexesToSign) : this.processEncodedTxns(flattenTxnGroup(txnGroup), indexesToSign);
8739
+ if (txnsToSign.length === 0) {
8740
+ this.logger.debug("No transactions to sign");
8741
+ return flatTxns.map(() => null);
8742
+ }
8743
+ const firstTxn = txnsToSign[0];
8744
+ const algorandAddress = firstTxn.sender.toString();
8745
+ let evmAddress = this.evmAddressMap.get(algorandAddress);
8746
+ if (!evmAddress) {
8747
+ const walletState = this.store.state.wallets[this.id];
8748
+ if (walletState) {
8749
+ for (const account of walletState.accounts) {
8750
+ const addr = account.metadata?.evmAddress;
8751
+ if (addr) {
8752
+ this.evmAddressMap.set(account.address, addr);
8753
+ }
8945
8754
  }
8755
+ evmAddress = this.evmAddressMap.get(algorandAddress);
8946
8756
  }
8947
- return acc;
8948
- }, []);
8757
+ }
8758
+ if (!evmAddress) {
8759
+ throw new Error(`No EVM address found for Algorand address: ${algorandAddress}`);
8760
+ }
8761
+ const onBeforeSign = this.options.uiHooks?.onBeforeSign ?? this.managerUIHooks?.onBeforeSign;
8762
+ if (onBeforeSign) {
8763
+ this.logger.debug("Running onBeforeSign hook", { txnGroup, indexesToSign });
8764
+ await onBeforeSign(txnGroup, indexesToSign);
8765
+ }
8766
+ await this.ensureAlgorandChain();
8767
+ const signedBlobs = await evmSdk.signTxn({
8768
+ evmAddress,
8769
+ txns: flatTxns,
8770
+ signMessage: (typedData) => this.signWithProvider(typedData, evmAddress)
8771
+ });
8772
+ const onAfterSign = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8773
+ if (onAfterSign) {
8774
+ this.logger.debug("Running onAfterSign hook");
8775
+ try {
8776
+ onAfterSign(true);
8777
+ } catch (e) {
8778
+ }
8779
+ }
8780
+ const result = flatTxns.map((txn, index) => {
8781
+ const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
8782
+ const signer = txn.sender.toString();
8783
+ const canSignTxn = this.addresses.includes(signer);
8784
+ if (isIndexMatch && canSignTxn) {
8785
+ return signedBlobs[index];
8786
+ }
8787
+ return null;
8788
+ });
8949
8789
  this.logger.debug("Transactions signed successfully", result);
8950
8790
  return result;
8951
8791
  } catch (error) {
8792
+ try {
8793
+ const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
8794
+ onAfterSignCleanup?.(false, error.message);
8795
+ } catch (e) {
8796
+ }
8952
8797
  this.logger.error("Error signing transactions:", error.message);
8953
8798
  throw error;
8954
8799
  }
8955
8800
  };
8801
+ /**
8802
+ * Helper to compare and update accounts if needed during session resume
8803
+ */
8804
+ async resumeWithAccounts(evmAddresses, setAccountsFn, connectorInfo) {
8805
+ const state = this.store.state;
8806
+ const walletState = state.wallets[this.id];
8807
+ if (!walletState) {
8808
+ this.logger.info("No session to resume");
8809
+ return;
8810
+ }
8811
+ for (const account of walletState.accounts) {
8812
+ const evmAddr = account.metadata?.evmAddress;
8813
+ if (evmAddr) {
8814
+ this.evmAddressMap.set(account.address, evmAddr);
8815
+ }
8816
+ }
8817
+ const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses, connectorInfo);
8818
+ const match = compareAccounts(walletAccounts, walletState.accounts);
8819
+ if (!match) {
8820
+ this.logger.warn("Session accounts mismatch, updating accounts", {
8821
+ prev: walletState.accounts,
8822
+ current: walletAccounts
8823
+ });
8824
+ }
8825
+ setAccountsFn(walletAccounts);
8826
+ this.logger.info("Session resumed");
8827
+ }
8828
+ notifyConnect(evmAddress, algorandAddress) {
8829
+ const onConnect = this.options.uiHooks?.onConnect ?? this.managerUIHooks?.onConnect;
8830
+ if (onConnect) {
8831
+ onConnect({ evmAddress, algorandAddress });
8832
+ }
8833
+ }
8956
8834
  };
8957
8835
 
8958
- // src/wallets/rainbow.ts
8959
- var ICON14 = `data:image/svg+xml;base64,${btoa(`
8836
+ // src/wallets/rainbowkit.ts
8837
+ import {
8838
+ ALGORAND_CHAIN_ID,
8839
+ algorandChain
8840
+ } from "liquid-accounts-evm";
8841
+ var ICON13 = `data:image/svg+xml;base64,${btoa(`
8960
8842
  <svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
8961
- <rect width="120" height="120" rx="60" fill="url(#paint0_linear)"/>
8962
- <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"/>
8963
- <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)"/>
8843
+ <rect width="120" height="120" rx="24" fill="url(#rk_bg)"/>
8844
+ <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"/>
8845
+ <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"/>
8846
+ <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"/>
8847
+ <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"/>
8964
8848
  <defs>
8965
- <linearGradient id="paint0_linear" x1="0" y1="0" x2="120" y2="120" gradientUnits="userSpaceOnUse">
8966
- <stop stop-color="#174299"/>
8967
- <stop offset="1" stop-color="#001E59"/>
8968
- </linearGradient>
8969
- <linearGradient id="paint1_linear" x1="41" y1="39" x2="79" y2="77" gradientUnits="userSpaceOnUse">
8970
- <stop stop-color="#FF4444"/>
8971
- <stop offset="0.2" stop-color="#FF8844"/>
8972
- <stop offset="0.4" stop-color="#FFDD00"/>
8973
- <stop offset="0.6" stop-color="#44FF44"/>
8974
- <stop offset="0.8" stop-color="#0088FF"/>
8975
- <stop offset="1" stop-color="#8844FF"/>
8849
+ <linearGradient id="rk_bg" x1="0" y1="0" x2="120" y2="120">
8850
+ <stop stop-color="#1A1B23"/>
8851
+ <stop offset="1" stop-color="#13141B"/>
8976
8852
  </linearGradient>
8977
8853
  </defs>
8978
8854
  </svg>
8979
8855
  `)}`;
8980
- var RainbowWallet = class extends LiquidEvmBaseWallet {
8981
- provider = null;
8856
+ var RainbowKitWallet = class _RainbowKitWallet extends LiquidEvmBaseWallet {
8982
8857
  options;
8858
+ _connecting = false;
8983
8859
  constructor(params) {
8984
8860
  super(params);
8985
8861
  this.options = params.options || {};
8862
+ if (!this.options.wagmiConfig) {
8863
+ throw new Error("RainbowKitWallet requires wagmiConfig in options");
8864
+ }
8865
+ this.ensureChainRegistered();
8986
8866
  }
8987
8867
  static defaultMetadata = {
8988
- name: "Rainbow",
8989
- icon: ICON14,
8868
+ name: "EVM Wallet",
8869
+ icon: ICON13,
8990
8870
  isLiquid: "EVM"
8991
8871
  };
8992
- async initializeProvider() {
8993
- if (typeof window === "undefined") {
8994
- throw new Error("Rainbow wallet only works in browser environment");
8995
- }
8996
- const windowEth = window.ethereum;
8997
- if (window.rainbow) {
8998
- this.logger.info("Found Rainbow browser extension at window.rainbow");
8999
- return;
9000
- }
9001
- if (windowEth?.providers && Array.isArray(windowEth.providers)) {
9002
- const rainbowProvider = windowEth.providers.find((p2) => p2.isRainbow);
9003
- if (rainbowProvider) {
9004
- this.logger.info("Found Rainbow in providers array");
9005
- return;
9006
- }
9007
- }
9008
- if (windowEth?.isRainbow) {
9009
- this.logger.info("Found Rainbow as the primary provider");
8872
+ /** True while connect() is running. Prevents re-entrancy from bridge components. */
8873
+ get isConnecting() {
8874
+ return this._connecting;
8875
+ }
8876
+ /**
8877
+ * Set the getEvmAccounts callback after construction.
8878
+ *
8879
+ * RainbowKit's connect modal can only be opened via React hooks (useConnectModal)
8880
+ * rendered inside <RainbowKitProvider>, but WalletManager is constructed before
8881
+ * any React tree renders. This method lets WalletUIProvider create the bridge
8882
+ * callback internally and inject it into the wallet on mount — before any
8883
+ * user-initiated connect() call.
8884
+ */
8885
+ setGetEvmAccounts(fn) {
8886
+ this.options.getEvmAccounts = fn;
8887
+ }
8888
+ get wagmiConfig() {
8889
+ return this.options.wagmiConfig;
8890
+ }
8891
+ /**
8892
+ * If the Algorand chain (4160) isn't already in the wagmi config, add it.
8893
+ * This is needed so wagmi's switchChain and signTypedData work without
8894
+ * falling back to raw provider calls.
8895
+ */
8896
+ ensureChainRegistered() {
8897
+ const chains = this.wagmiConfig.chains;
8898
+ if (chains.some((c) => c.id === ALGORAND_CHAIN_ID)) {
9010
8899
  return;
9011
8900
  }
9012
- this.logger.warn("Rainbow extension not detected. Note: Rainbow mobile app requires WalletConnect.");
8901
+ this.logger.info(`Registering Algorand chain (${ALGORAND_CHAIN_ID}) in wagmi config`);
8902
+ chains.push(algorandChain);
8903
+ }
8904
+ async initializeProvider() {
8905
+ this.logger.info("Using wagmi for EVM provider management");
8906
+ }
8907
+ /**
8908
+ * Get the raw EIP-1193 provider from the active wagmi connector.
8909
+ * Used by the base class's getEvmProvider and ensureAlgorandChain.
8910
+ */
8911
+ async getRawProvider() {
8912
+ const { getAccount } = await import("@wagmi/core");
8913
+ const account = getAccount(this.wagmiConfig);
8914
+ if (!account.connector) throw new Error("No EVM wallet connector available");
8915
+ return account.connector.getProvider();
9013
8916
  }
9014
8917
  async getEvmProvider() {
9015
- if (!this.provider) {
9016
- await this.initializeProvider();
9017
- const windowEth = window.ethereum;
9018
- if (window.rainbow) {
9019
- this.provider = window.rainbow;
9020
- } else if (windowEth?.providers && Array.isArray(windowEth.providers)) {
9021
- const rainbowProvider = windowEth.providers.find((p2) => p2.isRainbow);
9022
- if (rainbowProvider) {
9023
- this.provider = rainbowProvider;
8918
+ return this.getRawProvider();
8919
+ }
8920
+ /**
8921
+ * Sign EIP-712 typed data using wagmi's signTypedData.
8922
+ *
8923
+ * wagmi's signTypedData does NOT validate the domain's chainId against the
8924
+ * connected chain it simply forwards the typed data to the wallet via viem.
8925
+ * EIP-712 signing is chain-agnostic (the chain ID is in the typed data domain,
8926
+ * not in the RPC method), so this works regardless of which chain the wallet
8927
+ * reports being on.
8928
+ */
8929
+ async signWithProvider(typedData, evmAddress) {
8930
+ const { signTypedData } = await import("@wagmi/core");
8931
+ const { EIP712Domain: _2, ...types } = typedData.types;
8932
+ return signTypedData(this.wagmiConfig, {
8933
+ account: evmAddress,
8934
+ domain: typedData.domain,
8935
+ types,
8936
+ primaryType: typedData.primaryType,
8937
+ message: typedData.message
8938
+ });
8939
+ }
8940
+ /**
8941
+ * Build a connectorInfo object from a wagmi account, omitting undefined fields.
8942
+ * Uses `any` for the parameter to avoid exactOptionalPropertyTypes conflicts
8943
+ * with wagmi's discriminated union return types.
8944
+ */
8945
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8946
+ static extractConnectorInfo(account) {
8947
+ const info = {};
8948
+ const connector = account?.connector;
8949
+ if (typeof connector?.name === "string") info.name = connector.name;
8950
+ if (typeof connector?.icon === "string") info.icon = connector.icon;
8951
+ return info;
8952
+ }
8953
+ /**
8954
+ * Read connected EVM accounts from wagmi state.
8955
+ * If not connected, tries the getEvmAccounts callback, then falls back to
8956
+ * connecting with the first available connector.
8957
+ *
8958
+ * When getEvmAccounts is provided, it is always called (to show the wallet
8959
+ * selection UI). The callback is responsible for any disconnect/reconnect
8960
+ * needed to present a fresh selection.
8961
+ */
8962
+ async getConnectedEvmAddresses() {
8963
+ const { getAccount, connect: wagmiConnect } = await import("@wagmi/core");
8964
+ if (this.options.getEvmAccounts) {
8965
+ const addresses = await this.options.getEvmAccounts();
8966
+ if (addresses.length > 0) {
8967
+ const account2 = getAccount(this.wagmiConfig);
8968
+ const connectorInfo = _RainbowKitWallet.extractConnectorInfo(account2);
8969
+ if (account2.isConnected && account2.address) {
8970
+ return {
8971
+ addresses: account2.addresses ? [...account2.addresses] : [account2.address],
8972
+ connectorInfo
8973
+ };
9024
8974
  }
9025
- } else if (windowEth?.isRainbow) {
9026
- this.provider = windowEth;
8975
+ return { addresses, connectorInfo };
9027
8976
  }
9028
- if (!this.provider) {
9029
- throw new Error("Rainbow wallet not available. Please install Rainbow browser extension or use WalletConnect for mobile.");
8977
+ }
8978
+ const account = getAccount(this.wagmiConfig);
8979
+ if (account.isConnected && account.address) {
8980
+ return {
8981
+ addresses: account.addresses ? [...account.addresses] : [account.address],
8982
+ connectorInfo: _RainbowKitWallet.extractConnectorInfo(account)
8983
+ };
8984
+ }
8985
+ const connectors = this.wagmiConfig.connectors;
8986
+ if (connectors.length > 0) {
8987
+ this.logger.info("Attempting connection with first available connector...");
8988
+ try {
8989
+ const result = await wagmiConnect(this.wagmiConfig, { connector: connectors[0] });
8990
+ const updatedAccount = getAccount(this.wagmiConfig);
8991
+ return {
8992
+ addresses: [...result.accounts],
8993
+ connectorInfo: _RainbowKitWallet.extractConnectorInfo(updatedAccount)
8994
+ };
8995
+ } catch (error) {
8996
+ this.logger.warn("Auto-connect failed:", error.message);
9030
8997
  }
9031
8998
  }
9032
- return this.provider;
8999
+ throw new Error("No EVM wallet connected. Please connect an EVM wallet first.");
9033
9000
  }
9034
- async signWithProvider(typedData, evmAddress) {
9035
- const provider = await this.getEvmProvider();
9036
- try {
9037
- return await provider.request({
9038
- method: "eth_signTypedData_v4",
9039
- params: [evmAddress, JSON.stringify(typedData)]
9040
- });
9041
- } catch (error) {
9042
- if (error.code === 4001) {
9043
- throw new Error("User rejected the signing request");
9044
- }
9045
- throw error;
9001
+ /**
9002
+ * Apply connector info to wallet-level metadata so the UI displays
9003
+ * the actual wallet name/icon (e.g., "MetaMask") instead of the generic
9004
+ * "EVM Wallet". Falls back to defaults when connector info is unavailable.
9005
+ */
9006
+ applyConnectorMetadata(connectorInfo) {
9007
+ const updates = {};
9008
+ if (connectorInfo.name) updates.name = connectorInfo.name;
9009
+ if (connectorInfo.icon) updates.icon = connectorInfo.icon;
9010
+ if (updates.name || updates.icon) {
9011
+ this.updateMetadata(updates);
9012
+ this.logger.info(`Wallet metadata updated: ${updates.name ?? "(no name)"}`);
9046
9013
  }
9047
9014
  }
9048
9015
  connect = async () => {
9049
- this.logger.info("Connecting...");
9050
- await this.initializeProvider();
9051
- await this.initializeEvmSdk();
9052
- const provider = await this.getEvmProvider();
9016
+ if (this._connecting) {
9017
+ this.logger.info("connect() already in progress, ignoring duplicate call");
9018
+ return [];
9019
+ }
9020
+ this._connecting = true;
9053
9021
  try {
9054
- this.logger.info("Requesting Rainbow wallet connection...");
9055
- const evmAddresses = await provider.request({
9056
- method: "eth_requestAccounts"
9057
- });
9058
- if (evmAddresses.length === 0) {
9059
- this.logger.error("No accounts found!");
9060
- throw new Error("No accounts found!");
9061
- }
9022
+ this.logger.info("Connecting...");
9023
+ await this.initializeEvmSdk();
9024
+ const { addresses: evmAddresses, connectorInfo } = await this.getConnectedEvmAddresses();
9062
9025
  this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
9063
- const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
9026
+ this.applyConnectorMetadata(connectorInfo);
9027
+ const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses, connectorInfo);
9064
9028
  const activeAccount = walletAccounts[0];
9065
9029
  const walletState = {
9066
9030
  accounts: walletAccounts,
@@ -9070,51 +9034,70 @@ var RainbowWallet = class extends LiquidEvmBaseWallet {
9070
9034
  walletId: this.id,
9071
9035
  wallet: walletState
9072
9036
  });
9073
- this.logger.info("\u2705 Connected.", walletState);
9037
+ this.logger.info("Connected.", walletState);
9074
9038
  this.notifyConnect(evmAddresses[0], activeAccount.address);
9075
9039
  return walletAccounts;
9076
- } catch (error) {
9077
- this.logger.error("Error connecting:", error.message);
9078
- throw error;
9040
+ } finally {
9041
+ this._connecting = false;
9079
9042
  }
9080
9043
  };
9081
9044
  disconnect = async () => {
9082
9045
  this.logger.info("Disconnecting...");
9083
- this.provider = null;
9046
+ try {
9047
+ const { disconnect: wagmiDisconnect } = await import("@wagmi/core");
9048
+ await wagmiDisconnect(this.wagmiConfig);
9049
+ } catch (error) {
9050
+ this.logger.warn("wagmi disconnect error:", error.message);
9051
+ }
9084
9052
  this.evmAddressMap.clear();
9053
+ this.updateMetadata(_RainbowKitWallet.defaultMetadata);
9085
9054
  this.onDisconnect();
9086
9055
  this.logger.info("Disconnected");
9087
9056
  };
9088
9057
  resumeSession = async () => {
9058
+ const state = this.store.state;
9059
+ const walletState = state.wallets[this.id];
9060
+ if (!walletState) {
9061
+ return;
9062
+ }
9063
+ this.logger.info("Resuming session...");
9064
+ await this.initializeEvmSdk();
9065
+ const { getAccount, reconnect } = await import("@wagmi/core");
9089
9066
  try {
9090
- const state = this.store.state;
9091
- const walletState = state.wallets[this.id];
9092
- if (!walletState) {
9093
- this.logger.info("No session to resume");
9094
- return;
9095
- }
9096
- this.logger.info("Resuming session...");
9097
- await this.initializeProvider();
9098
- await this.initializeEvmSdk();
9099
- const provider = await this.getEvmProvider();
9100
- const evmAddresses = await provider.request({
9101
- method: "eth_accounts"
9102
- });
9067
+ await reconnect(this.wagmiConfig);
9068
+ } catch (err) {
9069
+ this.logger.warn("wagmi reconnect error (may be expected):", err.message);
9070
+ }
9071
+ const account = getAccount(this.wagmiConfig);
9072
+ let evmAddresses;
9073
+ let connectorInfo;
9074
+ if (account.isConnected && account.address) {
9075
+ evmAddresses = account.addresses ? [...account.addresses] : [account.address];
9076
+ connectorInfo = _RainbowKitWallet.extractConnectorInfo(account);
9077
+ } else {
9078
+ this.logger.warn("EVM wallet not yet connected, resuming from persisted state");
9079
+ evmAddresses = walletState.accounts.map((a) => a.metadata?.evmAddress).filter(Boolean);
9103
9080
  if (evmAddresses.length === 0) {
9104
- this.logger.error("No accounts found!");
9105
- throw new Error("No accounts found!");
9081
+ this.logger.warn("No persisted EVM addresses, cannot resume");
9082
+ this.onDisconnect();
9083
+ return;
9106
9084
  }
9107
- await this.resumeWithAccounts(evmAddresses, (accounts) => {
9108
- setAccounts(this.store, {
9109
- walletId: this.id,
9110
- accounts
9111
- });
9112
- });
9113
- } catch (error) {
9114
- this.logger.error("Error resuming session:", error.message);
9115
- this.onDisconnect();
9116
- throw error;
9085
+ connectorInfo = {};
9117
9086
  }
9087
+ if (!connectorInfo.name && walletState.accounts.length > 0) {
9088
+ const first = walletState.accounts[0];
9089
+ const persistedName = first.metadata?.connectorName;
9090
+ const persistedIcon = first.metadata?.connectorIcon;
9091
+ if (persistedName) connectorInfo.name = persistedName;
9092
+ if (persistedIcon) connectorInfo.icon = persistedIcon;
9093
+ }
9094
+ this.applyConnectorMetadata(connectorInfo);
9095
+ await this.resumeWithAccounts(evmAddresses, (accounts) => {
9096
+ setAccounts(this.store, {
9097
+ walletId: this.id,
9098
+ accounts
9099
+ });
9100
+ }, connectorInfo);
9118
9101
  };
9119
9102
  };
9120
9103
 
@@ -9231,7 +9214,7 @@ async function deriveAlgorandAccountFromEd25519(ed25519Seed) {
9231
9214
 
9232
9215
  // src/wallets/web3auth.ts
9233
9216
  var LOCAL_STORAGE_WEB3AUTH_KEY = `${LOCAL_STORAGE_KEY}:web3auth`;
9234
- var ICON15 = `data:image/svg+xml;base64,${btoa(`
9217
+ var ICON14 = `data:image/svg+xml;base64,${btoa(`
9235
9218
  <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
9236
9219
  <rect fill="#0364FF" width="40" height="40" rx="8"/>
9237
9220
  <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"/>
@@ -9288,7 +9271,7 @@ var Web3AuthWallet = class extends BaseWallet {
9288
9271
  }
9289
9272
  static defaultMetadata = {
9290
9273
  name: "Web3Auth",
9291
- icon: ICON15
9274
+ icon: ICON14
9292
9275
  };
9293
9276
  /**
9294
9277
  * Initialize the Web3Auth client
@@ -9797,7 +9780,7 @@ var Web3AuthWallet = class extends BaseWallet {
9797
9780
 
9798
9781
  // src/wallets/w3wallet.ts
9799
9782
  import algosdk13 from "algosdk";
9800
- var ICON16 = `data:image/svg+xml;base64,${btoa(`
9783
+ var ICON15 = `data:image/svg+xml;base64,${btoa(`
9801
9784
  <svg width="860" height="860" viewBox="0 0 860 860" fill="none" xmlns="http://www.w3.org/2000/svg">
9802
9785
  <rect width="860" height="860" rx="30" fill="#151923"/>
9803
9786
  <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"/>
@@ -9818,7 +9801,7 @@ var W3Wallet = class extends BaseWallet {
9818
9801
  }
9819
9802
  static defaultMetadata = {
9820
9803
  name: "W3 Wallet",
9821
- icon: ICON16
9804
+ icon: ICON15
9822
9805
  };
9823
9806
  async initializeClient() {
9824
9807
  this.logger.info("Initializing client...");
@@ -9948,10 +9931,9 @@ function createWalletMap() {
9948
9931
  ["kmd" /* KMD */]: KmdWallet,
9949
9932
  ["lute" /* LUTE */]: LuteWallet,
9950
9933
  ["magic" /* MAGIC */]: MagicAuth,
9951
- ["metamask" /* METAMASK */]: MetaMaskWallet,
9952
9934
  ["mnemonic" /* MNEMONIC */]: MnemonicWallet,
9953
9935
  ["pera" /* PERA */]: PeraWallet,
9954
- ["rainbow" /* RAINBOW */]: RainbowWallet,
9936
+ ["rainbowkit" /* RAINBOWKIT */]: RainbowKitWallet,
9955
9937
  ["walletconnect" /* WALLETCONNECT */]: WalletConnect,
9956
9938
  ["web3auth" /* WEB3AUTH */]: Web3AuthWallet,
9957
9939
  ["w3-wallet" /* W3_WALLET */]: W3Wallet
@@ -10444,12 +10426,11 @@ export {
10444
10426
  LogLevel,
10445
10427
  LuteWallet,
10446
10428
  MagicAuth,
10447
- MetaMaskWallet,
10448
10429
  MnemonicWallet,
10449
10430
  NetworkConfigBuilder,
10450
10431
  NetworkId,
10451
10432
  PeraWallet,
10452
- RainbowWallet,
10433
+ RainbowKitWallet,
10453
10434
  ScopeType,
10454
10435
  SecureKeyContainer,
10455
10436
  SessionError,