@d13co/use-wallet 4.5.4 → 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 +627 -646
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +151 -108
- package/dist/index.d.ts +151 -108
- package/dist/index.js +627 -642
- package/dist/index.js.map +1 -1
- package/package.json +6 -7
package/dist/index.cjs
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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["
|
|
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,109 +8246,142 @@ var MagicAuth = class extends BaseWallet {
|
|
|
8240
8246
|
};
|
|
8241
8247
|
};
|
|
8242
8248
|
|
|
8243
|
-
// src/wallets/
|
|
8249
|
+
// src/wallets/mnemonic.ts
|
|
8244
8250
|
var import_algosdk9 = __toESM(require("algosdk"), 1);
|
|
8245
|
-
var
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
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(
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
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
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
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() {
|
|
8276
8297
|
try {
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
this.logger.info("Algorand chain not found, adding it...");
|
|
8284
|
-
await provider.request({
|
|
8285
|
-
method: "wallet_addEthereumChain",
|
|
8286
|
-
params: [ALGORAND_EVM_CHAIN_CONFIG]
|
|
8287
|
-
});
|
|
8288
|
-
} else {
|
|
8289
|
-
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.");
|
|
8290
8304
|
}
|
|
8305
|
+
} catch (error) {
|
|
8306
|
+
this.disconnect();
|
|
8307
|
+
throw error;
|
|
8291
8308
|
}
|
|
8292
8309
|
}
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
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);
|
|
8305
8322
|
}
|
|
8306
|
-
const { LiquidEvmSdk } = await import("liquid-accounts-evm");
|
|
8307
|
-
this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
|
|
8308
|
-
this.logger.info("Liquid EVM SDK initialized");
|
|
8309
8323
|
}
|
|
8310
|
-
|
|
8324
|
+
const account = import_algosdk9.default.mnemonicToSecretKey(mnemonic);
|
|
8325
|
+
this.account = account;
|
|
8326
|
+
return account;
|
|
8311
8327
|
}
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
const
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
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;
|
|
8327
8361
|
}
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
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
|
+
};
|
|
8336
8377
|
processTxns(txnGroup, indexesToSign) {
|
|
8337
8378
|
const txnsToSign = [];
|
|
8338
8379
|
txnGroup.forEach((txn, index) => {
|
|
8339
8380
|
const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
|
|
8340
8381
|
const signer = txn.sender.toString();
|
|
8341
|
-
const canSignTxn = this.
|
|
8382
|
+
const canSignTxn = signer === this.account.addr.toString();
|
|
8342
8383
|
if (isIndexMatch && canSignTxn) {
|
|
8343
|
-
txnsToSign.push(
|
|
8344
|
-
} else {
|
|
8345
|
-
txnsToSign.push({ txn, signers: [] });
|
|
8384
|
+
txnsToSign.push(txn);
|
|
8346
8385
|
}
|
|
8347
8386
|
});
|
|
8348
8387
|
return txnsToSign;
|
|
@@ -8355,22 +8394,17 @@ var LiquidEvmBaseWallet = class extends BaseWallet {
|
|
|
8355
8394
|
const txn = isSigned ? import_algosdk9.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk9.default.decodeUnsignedTransaction(txnBuffer);
|
|
8356
8395
|
const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
|
|
8357
8396
|
const signer = txn.sender.toString();
|
|
8358
|
-
const canSignTxn = !isSigned && this.
|
|
8397
|
+
const canSignTxn = !isSigned && signer === this.account.addr.toString();
|
|
8359
8398
|
if (isIndexMatch && canSignTxn) {
|
|
8360
|
-
txnsToSign.push(
|
|
8361
|
-
} else {
|
|
8362
|
-
txnsToSign.push({ txn, signers: [] });
|
|
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 liquidEvmSdk = await this.initializeEvmSdk();
|
|
8374
8408
|
let txnsToSign = [];
|
|
8375
8409
|
if (isTransactionArray(txnGroup)) {
|
|
8376
8410
|
const flatTxns = flattenTxnGroup(txnGroup);
|
|
@@ -8379,412 +8413,19 @@ var LiquidEvmBaseWallet = class extends BaseWallet {
|
|
|
8379
8413
|
const flatTxns = flattenTxnGroup(txnGroup);
|
|
8380
8414
|
txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
|
|
8381
8415
|
}
|
|
8382
|
-
const
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
if (!evmAddress) {
|
|
8386
|
-
throw new Error(`No EVM address found for Algorand address: ${algorandAddress}`);
|
|
8387
|
-
}
|
|
8388
|
-
const onBeforeSign = this.options.uiHooks?.onBeforeSign ?? this.managerUIHooks?.onBeforeSign;
|
|
8389
|
-
if (onBeforeSign) {
|
|
8390
|
-
this.logger.debug("Running onBeforeSign hook", { txnGroup, indexesToSign });
|
|
8391
|
-
const txnsAsUint8 = txnsToSign.map(({ txn }) => import_algosdk9.default.encodeUnsignedTransaction(txn));
|
|
8392
|
-
await onBeforeSign(txnsAsUint8, indexesToSign);
|
|
8393
|
-
}
|
|
8394
|
-
await this.ensureAlgorandChain();
|
|
8395
|
-
const { signer: evmSigner } = await liquidEvmSdk.getSigner({
|
|
8396
|
-
evmAddress,
|
|
8397
|
-
signMessage: (typedData) => this.signWithProvider(typedData, evmAddress)
|
|
8398
|
-
});
|
|
8399
|
-
const allTxns = txnsToSign.map((t) => t.txn);
|
|
8400
|
-
const signIndexes = txnsToSign.reduce((acc, t, i) => {
|
|
8401
|
-
if (!("signers" in t)) acc.push(i);
|
|
8402
|
-
return acc;
|
|
8403
|
-
}, []);
|
|
8404
|
-
const signedBlobs = await evmSigner(allTxns, signIndexes);
|
|
8405
|
-
const onAfterSign = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
|
|
8406
|
-
if (onAfterSign) {
|
|
8407
|
-
this.logger.debug("Running onAfterSign hook");
|
|
8408
|
-
try {
|
|
8409
|
-
onAfterSign(true);
|
|
8410
|
-
} catch (e) {
|
|
8411
|
-
}
|
|
8412
|
-
}
|
|
8413
|
-
let signedIdx = 0;
|
|
8414
|
-
const result = txnsToSign.map((_2, index) => {
|
|
8415
|
-
if (signIndexes.includes(index)) {
|
|
8416
|
-
return signedBlobs[signedIdx++];
|
|
8417
|
-
}
|
|
8418
|
-
return null;
|
|
8419
|
-
});
|
|
8420
|
-
this.logger.debug("Transactions signed successfully", result);
|
|
8421
|
-
return result;
|
|
8416
|
+
const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account.sk));
|
|
8417
|
+
this.logger.debug("Transactions signed successfully", { signedTxns });
|
|
8418
|
+
return signedTxns;
|
|
8422
8419
|
} catch (error) {
|
|
8423
|
-
try {
|
|
8424
|
-
const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
|
|
8425
|
-
onAfterSignCleanup?.(false, error.message);
|
|
8426
|
-
} catch (e) {
|
|
8427
|
-
}
|
|
8428
8420
|
this.logger.error("Error signing transactions:", error.message);
|
|
8429
8421
|
throw error;
|
|
8430
8422
|
}
|
|
8431
8423
|
};
|
|
8432
|
-
/**
|
|
8433
|
-
* Helper to compare and update accounts if needed during session resume
|
|
8434
|
-
*/
|
|
8435
|
-
async resumeWithAccounts(evmAddresses, setAccountsFn) {
|
|
8436
|
-
const state = this.store.state;
|
|
8437
|
-
const walletState = state.wallets[this.id];
|
|
8438
|
-
if (!walletState) {
|
|
8439
|
-
this.logger.info("No session to resume");
|
|
8440
|
-
return;
|
|
8441
|
-
}
|
|
8442
|
-
for (const account of walletState.accounts) {
|
|
8443
|
-
const evmAddr = account.metadata?.evmAddress;
|
|
8444
|
-
if (evmAddr) {
|
|
8445
|
-
this.evmAddressMap.set(account.address, evmAddr);
|
|
8446
|
-
}
|
|
8447
|
-
}
|
|
8448
|
-
const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
|
|
8449
|
-
const match = compareAccounts(walletAccounts, walletState.accounts);
|
|
8450
|
-
if (!match) {
|
|
8451
|
-
this.logger.warn("Session accounts mismatch, updating accounts", {
|
|
8452
|
-
prev: walletState.accounts,
|
|
8453
|
-
current: walletAccounts
|
|
8454
|
-
});
|
|
8455
|
-
setAccountsFn(walletAccounts);
|
|
8456
|
-
}
|
|
8457
|
-
this.logger.info("Session resumed");
|
|
8458
|
-
}
|
|
8459
|
-
notifyConnect(evmAddress, algorandAddress) {
|
|
8460
|
-
const onConnect = this.options.uiHooks?.onConnect ?? this.managerUIHooks?.onConnect;
|
|
8461
|
-
if (onConnect) {
|
|
8462
|
-
onConnect({ evmAddress, algorandAddress });
|
|
8463
|
-
}
|
|
8464
|
-
}
|
|
8465
8424
|
};
|
|
8466
8425
|
|
|
8467
|
-
// src/wallets/
|
|
8468
|
-
var ICON11 = `data:image/svg+xml;base64,${btoa(`
|
|
8469
|
-
<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"
|
|
8470
|
-
viewBox="0 0 142 136.878" style="enable-background:new 0 0 142 136.878;" xml:space="preserve">
|
|
8471
|
-
<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
|
|
8472
|
-
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
|
|
8473
|
-
L132.682,132.192z"/>
|
|
8474
|
-
<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
|
|
8475
|
-
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
|
|
8476
|
-
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
|
|
8477
|
-
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
|
|
8478
|
-
C112.604,84.295,112.678,65.975,112.678,65.975z"/>
|
|
8479
|
-
<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
|
|
8480
|
-
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
|
|
8481
|
-
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
|
|
8482
|
-
l-10.498-9.956H82.776V74.338z"/>
|
|
8483
|
-
<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
|
|
8484
|
-
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
|
|
8485
|
-
V100.801z M84.915,28.538h-27.85l-1.891,19.599l9.872,64.013h11.891l9.878-64.013L84.915,28.538z"/>
|
|
8486
|
-
<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
|
|
8487
|
-
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
|
|
8488
|
-
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"/>
|
|
8489
|
-
<path style="fill:#C0C4CD;" d="M79.029,124.384v12.495H62.945v-12.495L79.029,124.384L79.029,124.384z"/>
|
|
8490
|
-
<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
|
|
8491
|
-
M102.113,123.072l-23.084,13.8v-12.495l2.067-7.566C81.096,116.811,102.113,123.072,102.113,123.072z"/>
|
|
8492
|
-
</svg>
|
|
8493
|
-
`)}`;
|
|
8494
|
-
var MetaMaskWallet = class extends LiquidEvmBaseWallet {
|
|
8495
|
-
metamaskSdk = null;
|
|
8496
|
-
provider = null;
|
|
8497
|
-
options;
|
|
8498
|
-
constructor(params) {
|
|
8499
|
-
super(params);
|
|
8500
|
-
this.options = params.options || {};
|
|
8501
|
-
}
|
|
8502
|
-
static defaultMetadata = {
|
|
8503
|
-
name: "MetaMask",
|
|
8504
|
-
icon: ICON11,
|
|
8505
|
-
isLiquid: "EVM"
|
|
8506
|
-
};
|
|
8507
|
-
async initializeProvider() {
|
|
8508
|
-
if (!this.metamaskSdk) {
|
|
8509
|
-
this.logger.info("Initializing MetaMask SDK...");
|
|
8510
|
-
const { MetaMaskSDK } = await import("@metamask/sdk");
|
|
8511
|
-
this.metamaskSdk = new MetaMaskSDK({
|
|
8512
|
-
dappMetadata: {
|
|
8513
|
-
name: this.options.dappMetadata?.name || "Algorand dApp",
|
|
8514
|
-
url: this.options.dappMetadata?.url || (typeof window !== "undefined" ? window.location.href : ""),
|
|
8515
|
-
...this.options.dappMetadata?.iconUrl && { iconUrl: this.options.dappMetadata.iconUrl }
|
|
8516
|
-
}
|
|
8517
|
-
});
|
|
8518
|
-
this.logger.info("MetaMask SDK initialized");
|
|
8519
|
-
}
|
|
8520
|
-
}
|
|
8521
|
-
async getEvmProvider() {
|
|
8522
|
-
if (!this.provider) {
|
|
8523
|
-
await this.initializeProvider();
|
|
8524
|
-
this.provider = this.metamaskSdk.getProvider() || null;
|
|
8525
|
-
if (!this.provider) {
|
|
8526
|
-
throw new Error("MetaMask provider not available. Please install MetaMask.");
|
|
8527
|
-
}
|
|
8528
|
-
}
|
|
8529
|
-
return this.provider;
|
|
8530
|
-
}
|
|
8531
|
-
async signWithProvider(typedData, evmAddress) {
|
|
8532
|
-
const provider = await this.getEvmProvider();
|
|
8533
|
-
return await provider.request({
|
|
8534
|
-
method: "eth_signTypedData_v4",
|
|
8535
|
-
params: [evmAddress, JSON.stringify(typedData)]
|
|
8536
|
-
});
|
|
8537
|
-
}
|
|
8538
|
-
connect = async () => {
|
|
8539
|
-
this.logger.info("Connecting...");
|
|
8540
|
-
await this.initializeProvider();
|
|
8541
|
-
await this.initializeEvmSdk();
|
|
8542
|
-
const provider = await this.getEvmProvider();
|
|
8543
|
-
const evmAddresses = await provider.request({
|
|
8544
|
-
method: "eth_requestAccounts"
|
|
8545
|
-
});
|
|
8546
|
-
if (evmAddresses.length === 0) {
|
|
8547
|
-
this.logger.error("No accounts found!");
|
|
8548
|
-
throw new Error("No accounts found!");
|
|
8549
|
-
}
|
|
8550
|
-
this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
|
|
8551
|
-
const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses);
|
|
8552
|
-
const activeAccount = walletAccounts[0];
|
|
8553
|
-
const walletState = {
|
|
8554
|
-
accounts: walletAccounts,
|
|
8555
|
-
activeAccount
|
|
8556
|
-
};
|
|
8557
|
-
addWallet(this.store, {
|
|
8558
|
-
walletId: this.id,
|
|
8559
|
-
wallet: walletState
|
|
8560
|
-
});
|
|
8561
|
-
this.logger.info("\u2705 Connected.", walletState);
|
|
8562
|
-
this.notifyConnect(evmAddresses[0], activeAccount.address);
|
|
8563
|
-
return walletAccounts;
|
|
8564
|
-
};
|
|
8565
|
-
disconnect = async () => {
|
|
8566
|
-
this.logger.info("Disconnecting...");
|
|
8567
|
-
if (this.metamaskSdk) {
|
|
8568
|
-
await this.metamaskSdk.terminate();
|
|
8569
|
-
}
|
|
8570
|
-
this.provider = null;
|
|
8571
|
-
this.evmAddressMap.clear();
|
|
8572
|
-
this.onDisconnect();
|
|
8573
|
-
this.logger.info("Disconnected");
|
|
8574
|
-
};
|
|
8575
|
-
resumeSession = async () => {
|
|
8576
|
-
try {
|
|
8577
|
-
const state = this.store.state;
|
|
8578
|
-
const walletState = state.wallets[this.id];
|
|
8579
|
-
if (!walletState) {
|
|
8580
|
-
this.logger.info("No session to resume");
|
|
8581
|
-
return;
|
|
8582
|
-
}
|
|
8583
|
-
this.logger.info("Resuming session...");
|
|
8584
|
-
await this.initializeProvider();
|
|
8585
|
-
await this.initializeEvmSdk();
|
|
8586
|
-
const provider = await this.getEvmProvider();
|
|
8587
|
-
const evmAddresses = await provider.request({
|
|
8588
|
-
method: "eth_accounts"
|
|
8589
|
-
});
|
|
8590
|
-
if (evmAddresses.length === 0) {
|
|
8591
|
-
this.logger.error("No accounts found!");
|
|
8592
|
-
throw new Error("No accounts found!");
|
|
8593
|
-
}
|
|
8594
|
-
await this.resumeWithAccounts(evmAddresses, (accounts) => {
|
|
8595
|
-
setAccounts(this.store, {
|
|
8596
|
-
walletId: this.id,
|
|
8597
|
-
accounts
|
|
8598
|
-
});
|
|
8599
|
-
});
|
|
8600
|
-
} catch (error) {
|
|
8601
|
-
this.logger.error("Error resuming session:", error.message);
|
|
8602
|
-
this.onDisconnect();
|
|
8603
|
-
throw error;
|
|
8604
|
-
}
|
|
8605
|
-
};
|
|
8606
|
-
};
|
|
8607
|
-
|
|
8608
|
-
// src/wallets/mnemonic.ts
|
|
8426
|
+
// src/wallets/pera.ts
|
|
8609
8427
|
var import_algosdk10 = __toESM(require("algosdk"), 1);
|
|
8610
|
-
var LOCAL_STORAGE_MNEMONIC_KEY = `${LOCAL_STORAGE_KEY}_mnemonic`;
|
|
8611
8428
|
var ICON12 = `data:image/svg+xml;base64,${btoa(`
|
|
8612
|
-
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
|
|
8613
|
-
<rect fill="#525252" width="400" height="400" />
|
|
8614
|
-
<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" />
|
|
8615
|
-
</svg>
|
|
8616
|
-
`)}`;
|
|
8617
|
-
var MnemonicWallet = class extends BaseWallet {
|
|
8618
|
-
account = null;
|
|
8619
|
-
options;
|
|
8620
|
-
store;
|
|
8621
|
-
constructor({
|
|
8622
|
-
id,
|
|
8623
|
-
store,
|
|
8624
|
-
subscribe,
|
|
8625
|
-
getAlgodClient,
|
|
8626
|
-
options,
|
|
8627
|
-
metadata = {}
|
|
8628
|
-
}) {
|
|
8629
|
-
super({ id, metadata, getAlgodClient, store, subscribe });
|
|
8630
|
-
const {
|
|
8631
|
-
persistToStorage = false,
|
|
8632
|
-
promptForMnemonic = () => Promise.resolve(prompt("Enter 25-word mnemonic passphrase:"))
|
|
8633
|
-
} = options || {};
|
|
8634
|
-
this.options = { persistToStorage, promptForMnemonic };
|
|
8635
|
-
this.store = store;
|
|
8636
|
-
if (this.options.persistToStorage) {
|
|
8637
|
-
this.logger.warn(
|
|
8638
|
-
"Persisting mnemonics to storage is insecure. Any private key mnemonics used should never hold real Algos (i.e., on MainNet). Use with caution!"
|
|
8639
|
-
);
|
|
8640
|
-
}
|
|
8641
|
-
}
|
|
8642
|
-
static defaultMetadata = {
|
|
8643
|
-
name: "Mnemonic",
|
|
8644
|
-
icon: ICON12
|
|
8645
|
-
};
|
|
8646
|
-
loadMnemonicFromStorage() {
|
|
8647
|
-
return StorageAdapter.getItem(LOCAL_STORAGE_MNEMONIC_KEY);
|
|
8648
|
-
}
|
|
8649
|
-
saveMnemonicToStorage(mnemonic) {
|
|
8650
|
-
StorageAdapter.setItem(LOCAL_STORAGE_MNEMONIC_KEY, mnemonic);
|
|
8651
|
-
}
|
|
8652
|
-
removeMnemonicFromStorage() {
|
|
8653
|
-
StorageAdapter.removeItem(LOCAL_STORAGE_MNEMONIC_KEY);
|
|
8654
|
-
}
|
|
8655
|
-
checkMainnet() {
|
|
8656
|
-
try {
|
|
8657
|
-
const network = this.activeNetworkConfig;
|
|
8658
|
-
if (!network.isTestnet) {
|
|
8659
|
-
this.logger.warn(
|
|
8660
|
-
"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)."
|
|
8661
|
-
);
|
|
8662
|
-
throw new Error("Production network detected. Aborting.");
|
|
8663
|
-
}
|
|
8664
|
-
} catch (error) {
|
|
8665
|
-
this.disconnect();
|
|
8666
|
-
throw error;
|
|
8667
|
-
}
|
|
8668
|
-
}
|
|
8669
|
-
async initializeAccount() {
|
|
8670
|
-
let mnemonic = this.loadMnemonicFromStorage();
|
|
8671
|
-
if (!mnemonic) {
|
|
8672
|
-
mnemonic = await this.options.promptForMnemonic();
|
|
8673
|
-
if (!mnemonic) {
|
|
8674
|
-
this.account = null;
|
|
8675
|
-
this.logger.error("No mnemonic provided");
|
|
8676
|
-
throw new Error("No mnemonic provided");
|
|
8677
|
-
}
|
|
8678
|
-
if (this.options.persistToStorage) {
|
|
8679
|
-
this.logger.warn("Mnemonic saved to localStorage.");
|
|
8680
|
-
this.saveMnemonicToStorage(mnemonic);
|
|
8681
|
-
}
|
|
8682
|
-
}
|
|
8683
|
-
const account = import_algosdk10.default.mnemonicToSecretKey(mnemonic);
|
|
8684
|
-
this.account = account;
|
|
8685
|
-
return account;
|
|
8686
|
-
}
|
|
8687
|
-
connect = async () => {
|
|
8688
|
-
this.checkMainnet();
|
|
8689
|
-
this.logger.info("Connecting...");
|
|
8690
|
-
const account = await this.initializeAccount();
|
|
8691
|
-
const walletAccount = {
|
|
8692
|
-
name: `${this.metadata.name} Account`,
|
|
8693
|
-
address: account.addr.toString()
|
|
8694
|
-
};
|
|
8695
|
-
const walletState = {
|
|
8696
|
-
accounts: [walletAccount],
|
|
8697
|
-
activeAccount: walletAccount
|
|
8698
|
-
};
|
|
8699
|
-
addWallet(this.store, {
|
|
8700
|
-
walletId: this.id,
|
|
8701
|
-
wallet: walletState
|
|
8702
|
-
});
|
|
8703
|
-
this.logger.info("Connected successfully", walletState);
|
|
8704
|
-
return [walletAccount];
|
|
8705
|
-
};
|
|
8706
|
-
disconnect = async () => {
|
|
8707
|
-
this.logger.info("Disconnecting...");
|
|
8708
|
-
this.onDisconnect();
|
|
8709
|
-
this.account = null;
|
|
8710
|
-
this.removeMnemonicFromStorage();
|
|
8711
|
-
this.logger.info("Disconnected");
|
|
8712
|
-
};
|
|
8713
|
-
resumeSession = async () => {
|
|
8714
|
-
this.checkMainnet();
|
|
8715
|
-
const state = this.store.state;
|
|
8716
|
-
const walletState = state.wallets[this.id];
|
|
8717
|
-
if (!walletState) {
|
|
8718
|
-
this.logger.info("No session to resume");
|
|
8719
|
-
return;
|
|
8720
|
-
}
|
|
8721
|
-
this.logger.info("Resuming session...");
|
|
8722
|
-
if (this.options.persistToStorage) {
|
|
8723
|
-
try {
|
|
8724
|
-
await this.initializeAccount();
|
|
8725
|
-
this.logger.info("Session resumed successfully");
|
|
8726
|
-
} catch (error) {
|
|
8727
|
-
this.logger.error("Error resuming session:", error.message);
|
|
8728
|
-
this.disconnect();
|
|
8729
|
-
throw error;
|
|
8730
|
-
}
|
|
8731
|
-
} else {
|
|
8732
|
-
this.logger.info("No session to resume, disconnecting...");
|
|
8733
|
-
this.disconnect();
|
|
8734
|
-
}
|
|
8735
|
-
};
|
|
8736
|
-
processTxns(txnGroup, indexesToSign) {
|
|
8737
|
-
const txnsToSign = [];
|
|
8738
|
-
txnGroup.forEach((txn, index) => {
|
|
8739
|
-
const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
|
|
8740
|
-
const signer = txn.sender.toString();
|
|
8741
|
-
const canSignTxn = signer === this.account.addr.toString();
|
|
8742
|
-
if (isIndexMatch && canSignTxn) {
|
|
8743
|
-
txnsToSign.push(txn);
|
|
8744
|
-
}
|
|
8745
|
-
});
|
|
8746
|
-
return txnsToSign;
|
|
8747
|
-
}
|
|
8748
|
-
processEncodedTxns(txnGroup, indexesToSign) {
|
|
8749
|
-
const txnsToSign = [];
|
|
8750
|
-
txnGroup.forEach((txnBuffer, index) => {
|
|
8751
|
-
const decodedObj = import_algosdk10.default.msgpackRawDecode(txnBuffer);
|
|
8752
|
-
const isSigned = isSignedTxn(decodedObj);
|
|
8753
|
-
const txn = isSigned ? import_algosdk10.default.decodeSignedTransaction(txnBuffer).txn : import_algosdk10.default.decodeUnsignedTransaction(txnBuffer);
|
|
8754
|
-
const isIndexMatch = !indexesToSign || indexesToSign.includes(index);
|
|
8755
|
-
const signer = txn.sender.toString();
|
|
8756
|
-
const canSignTxn = !isSigned && signer === this.account.addr.toString();
|
|
8757
|
-
if (isIndexMatch && canSignTxn) {
|
|
8758
|
-
txnsToSign.push(txn);
|
|
8759
|
-
}
|
|
8760
|
-
});
|
|
8761
|
-
return txnsToSign;
|
|
8762
|
-
}
|
|
8763
|
-
signTransactions = async (txnGroup, indexesToSign) => {
|
|
8764
|
-
this.checkMainnet();
|
|
8765
|
-
try {
|
|
8766
|
-
this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
|
|
8767
|
-
let txnsToSign = [];
|
|
8768
|
-
if (isTransactionArray(txnGroup)) {
|
|
8769
|
-
const flatTxns = flattenTxnGroup(txnGroup);
|
|
8770
|
-
txnsToSign = this.processTxns(flatTxns, indexesToSign);
|
|
8771
|
-
} else {
|
|
8772
|
-
const flatTxns = flattenTxnGroup(txnGroup);
|
|
8773
|
-
txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign);
|
|
8774
|
-
}
|
|
8775
|
-
const signedTxns = txnsToSign.map((txn) => txn.signTxn(this.account.sk));
|
|
8776
|
-
this.logger.debug("Transactions signed successfully", { signedTxns });
|
|
8777
|
-
return signedTxns;
|
|
8778
|
-
} catch (error) {
|
|
8779
|
-
this.logger.error("Error signing transactions:", error.message);
|
|
8780
|
-
throw error;
|
|
8781
|
-
}
|
|
8782
|
-
};
|
|
8783
|
-
};
|
|
8784
|
-
|
|
8785
|
-
// src/wallets/pera.ts
|
|
8786
|
-
var import_algosdk11 = __toESM(require("algosdk"), 1);
|
|
8787
|
-
var ICON13 = `data:image/svg+xml;base64,${btoa(`
|
|
8788
8429
|
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
|
8789
8430
|
<rect fill="#FFEE55" width="200" height="200" />
|
|
8790
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" />
|
|
@@ -8813,7 +8454,7 @@ var PeraWallet = class extends BaseWallet {
|
|
|
8813
8454
|
}
|
|
8814
8455
|
static defaultMetadata = {
|
|
8815
8456
|
name: "Pera",
|
|
8816
|
-
icon:
|
|
8457
|
+
icon: ICON12
|
|
8817
8458
|
};
|
|
8818
8459
|
async initializeClient() {
|
|
8819
8460
|
this.logger.info("Initializing client...");
|
|
@@ -8919,18 +8560,178 @@ var PeraWallet = class extends BaseWallet {
|
|
|
8919
8560
|
prev: walletState.accounts,
|
|
8920
8561
|
current: walletAccounts
|
|
8921
8562
|
});
|
|
8922
|
-
setAccounts(this.store, {
|
|
8923
|
-
walletId: this.id,
|
|
8924
|
-
accounts: walletAccounts
|
|
8563
|
+
setAccounts(this.store, {
|
|
8564
|
+
walletId: this.id,
|
|
8565
|
+
accounts: walletAccounts
|
|
8566
|
+
});
|
|
8567
|
+
}
|
|
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
|
|
8925
8701
|
});
|
|
8926
8702
|
}
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
this.logger.
|
|
8930
|
-
this.onDisconnect();
|
|
8931
|
-
throw error;
|
|
8703
|
+
const { LiquidEvmSdk } = await import("liquid-accounts-evm");
|
|
8704
|
+
this.liquidEvmSdk = new LiquidEvmSdk({ algorand: this.algorandClient });
|
|
8705
|
+
this.logger.info("Liquid EVM SDK initialized");
|
|
8932
8706
|
}
|
|
8933
|
-
|
|
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
|
+
*/
|
|
8934
8735
|
processTxns(txnGroup, indexesToSign) {
|
|
8935
8736
|
const txnsToSign = [];
|
|
8936
8737
|
txnGroup.forEach((txn, index) => {
|
|
@@ -8938,13 +8739,14 @@ var PeraWallet = class extends BaseWallet {
|
|
|
8938
8739
|
const signer = txn.sender.toString();
|
|
8939
8740
|
const canSignTxn = this.addresses.includes(signer);
|
|
8940
8741
|
if (isIndexMatch && canSignTxn) {
|
|
8941
|
-
txnsToSign.push(
|
|
8942
|
-
} else {
|
|
8943
|
-
txnsToSign.push({ txn, signers: [] });
|
|
8742
|
+
txnsToSign.push(txn);
|
|
8944
8743
|
}
|
|
8945
8744
|
});
|
|
8946
8745
|
return txnsToSign;
|
|
8947
8746
|
}
|
|
8747
|
+
/**
|
|
8748
|
+
* Process encoded transaction group to extract transactions that need signing
|
|
8749
|
+
*/
|
|
8948
8750
|
processEncodedTxns(txnGroup, indexesToSign) {
|
|
8949
8751
|
const txnsToSign = [];
|
|
8950
8752
|
txnGroup.forEach((txnBuffer, index) => {
|
|
@@ -8955,154 +8757,316 @@ var PeraWallet = class extends BaseWallet {
|
|
|
8955
8757
|
const signer = txn.sender.toString();
|
|
8956
8758
|
const canSignTxn = !isSigned && this.addresses.includes(signer);
|
|
8957
8759
|
if (isIndexMatch && canSignTxn) {
|
|
8958
|
-
txnsToSign.push(
|
|
8959
|
-
} else {
|
|
8960
|
-
txnsToSign.push({ txn, signers: [] });
|
|
8760
|
+
txnsToSign.push(txn);
|
|
8961
8761
|
}
|
|
8962
8762
|
});
|
|
8963
8763
|
return txnsToSign;
|
|
8964
8764
|
}
|
|
8765
|
+
/**
|
|
8766
|
+
* Sign Algorand transactions using EVM wallet signatures
|
|
8767
|
+
*/
|
|
8965
8768
|
signTransactions = async (txnGroup, indexesToSign) => {
|
|
8966
8769
|
try {
|
|
8967
8770
|
this.logger.debug("Signing transactions...", { txnGroup, indexesToSign });
|
|
8968
|
-
|
|
8771
|
+
const evmSdk = await this.initializeEvmSdk();
|
|
8772
|
+
let flatTxns = [];
|
|
8969
8773
|
if (isTransactionArray(txnGroup)) {
|
|
8970
|
-
|
|
8971
|
-
txnsToSign = this.processTxns(flatTxns, indexesToSign);
|
|
8774
|
+
flatTxns = flattenTxnGroup(txnGroup);
|
|
8972
8775
|
} else {
|
|
8973
|
-
const
|
|
8974
|
-
|
|
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
|
+
});
|
|
8975
8782
|
}
|
|
8976
|
-
const
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
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
|
+
}
|
|
8987
8799
|
}
|
|
8800
|
+
evmAddress = this.evmAddressMap.get(algorandAddress);
|
|
8988
8801
|
}
|
|
8989
|
-
|
|
8990
|
-
|
|
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
|
+
});
|
|
8991
8834
|
this.logger.debug("Transactions signed successfully", result);
|
|
8992
8835
|
return result;
|
|
8993
8836
|
} catch (error) {
|
|
8837
|
+
try {
|
|
8838
|
+
const onAfterSignCleanup = this.options.uiHooks?.onAfterSign ?? this.managerUIHooks?.onAfterSign;
|
|
8839
|
+
onAfterSignCleanup?.(false, error.message);
|
|
8840
|
+
} catch (e) {
|
|
8841
|
+
}
|
|
8994
8842
|
this.logger.error("Error signing transactions:", error.message);
|
|
8995
8843
|
throw error;
|
|
8996
8844
|
}
|
|
8997
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
|
+
}
|
|
8998
8879
|
};
|
|
8999
8880
|
|
|
9000
|
-
// src/wallets/
|
|
9001
|
-
var
|
|
8881
|
+
// src/wallets/rainbowkit.ts
|
|
8882
|
+
var import_liquid_accounts_evm = require("liquid-accounts-evm");
|
|
8883
|
+
var ICON13 = `data:image/svg+xml;base64,${btoa(`
|
|
9002
8884
|
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
9003
|
-
<rect width="120" height="120" rx="
|
|
9004
|
-
<path d="
|
|
9005
|
-
<path d="
|
|
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"/>
|
|
9006
8890
|
<defs>
|
|
9007
|
-
<linearGradient id="
|
|
9008
|
-
<stop stop-color="#
|
|
9009
|
-
<stop offset="1" stop-color="#
|
|
9010
|
-
</linearGradient>
|
|
9011
|
-
<linearGradient id="paint1_linear" x1="41" y1="39" x2="79" y2="77" gradientUnits="userSpaceOnUse">
|
|
9012
|
-
<stop stop-color="#FF4444"/>
|
|
9013
|
-
<stop offset="0.2" stop-color="#FF8844"/>
|
|
9014
|
-
<stop offset="0.4" stop-color="#FFDD00"/>
|
|
9015
|
-
<stop offset="0.6" stop-color="#44FF44"/>
|
|
9016
|
-
<stop offset="0.8" stop-color="#0088FF"/>
|
|
9017
|
-
<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"/>
|
|
9018
8894
|
</linearGradient>
|
|
9019
8895
|
</defs>
|
|
9020
8896
|
</svg>
|
|
9021
8897
|
`)}`;
|
|
9022
|
-
var
|
|
9023
|
-
provider = null;
|
|
8898
|
+
var RainbowKitWallet = class _RainbowKitWallet extends LiquidEvmBaseWallet {
|
|
9024
8899
|
options;
|
|
8900
|
+
_connecting = false;
|
|
9025
8901
|
constructor(params) {
|
|
9026
8902
|
super(params);
|
|
9027
8903
|
this.options = params.options || {};
|
|
8904
|
+
if (!this.options.wagmiConfig) {
|
|
8905
|
+
throw new Error("RainbowKitWallet requires wagmiConfig in options");
|
|
8906
|
+
}
|
|
8907
|
+
this.ensureChainRegistered();
|
|
9028
8908
|
}
|
|
9029
8909
|
static defaultMetadata = {
|
|
9030
|
-
name: "
|
|
9031
|
-
icon:
|
|
8910
|
+
name: "EVM Wallet",
|
|
8911
|
+
icon: ICON13,
|
|
9032
8912
|
isLiquid: "EVM"
|
|
9033
8913
|
};
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
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)) {
|
|
9052
8941
|
return;
|
|
9053
8942
|
}
|
|
9054
|
-
this.logger.
|
|
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();
|
|
9055
8958
|
}
|
|
9056
8959
|
async getEvmProvider() {
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
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
|
+
};
|
|
9066
9016
|
}
|
|
9067
|
-
|
|
9068
|
-
this.provider = windowEth;
|
|
9017
|
+
return { addresses, connectorInfo };
|
|
9069
9018
|
}
|
|
9070
|
-
|
|
9071
|
-
|
|
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);
|
|
9072
9039
|
}
|
|
9073
9040
|
}
|
|
9074
|
-
|
|
9041
|
+
throw new Error("No EVM wallet connected. Please connect an EVM wallet first.");
|
|
9075
9042
|
}
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
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)"}`);
|
|
9088
9055
|
}
|
|
9089
9056
|
}
|
|
9090
9057
|
connect = async () => {
|
|
9091
|
-
this.
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9058
|
+
if (this._connecting) {
|
|
9059
|
+
this.logger.info("connect() already in progress, ignoring duplicate call");
|
|
9060
|
+
return [];
|
|
9061
|
+
}
|
|
9062
|
+
this._connecting = true;
|
|
9095
9063
|
try {
|
|
9096
|
-
this.logger.info("
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
});
|
|
9100
|
-
if (evmAddresses.length === 0) {
|
|
9101
|
-
this.logger.error("No accounts found!");
|
|
9102
|
-
throw new Error("No accounts found!");
|
|
9103
|
-
}
|
|
9064
|
+
this.logger.info("Connecting...");
|
|
9065
|
+
await this.initializeEvmSdk();
|
|
9066
|
+
const { addresses: evmAddresses, connectorInfo } = await this.getConnectedEvmAddresses();
|
|
9104
9067
|
this.logger.info(`Connected to ${evmAddresses.length} EVM account(s)`);
|
|
9105
|
-
|
|
9068
|
+
this.applyConnectorMetadata(connectorInfo);
|
|
9069
|
+
const walletAccounts = await this.deriveAlgorandAccounts(evmAddresses, connectorInfo);
|
|
9106
9070
|
const activeAccount = walletAccounts[0];
|
|
9107
9071
|
const walletState = {
|
|
9108
9072
|
accounts: walletAccounts,
|
|
@@ -9112,51 +9076,70 @@ var RainbowWallet = class extends LiquidEvmBaseWallet {
|
|
|
9112
9076
|
walletId: this.id,
|
|
9113
9077
|
wallet: walletState
|
|
9114
9078
|
});
|
|
9115
|
-
this.logger.info("
|
|
9079
|
+
this.logger.info("Connected.", walletState);
|
|
9116
9080
|
this.notifyConnect(evmAddresses[0], activeAccount.address);
|
|
9117
9081
|
return walletAccounts;
|
|
9118
|
-
}
|
|
9119
|
-
this.
|
|
9120
|
-
throw error;
|
|
9082
|
+
} finally {
|
|
9083
|
+
this._connecting = false;
|
|
9121
9084
|
}
|
|
9122
9085
|
};
|
|
9123
9086
|
disconnect = async () => {
|
|
9124
9087
|
this.logger.info("Disconnecting...");
|
|
9125
|
-
|
|
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
|
+
}
|
|
9126
9094
|
this.evmAddressMap.clear();
|
|
9095
|
+
this.updateMetadata(_RainbowKitWallet.defaultMetadata);
|
|
9127
9096
|
this.onDisconnect();
|
|
9128
9097
|
this.logger.info("Disconnected");
|
|
9129
9098
|
};
|
|
9130
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");
|
|
9131
9108
|
try {
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
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);
|
|
9145
9122
|
if (evmAddresses.length === 0) {
|
|
9146
|
-
this.logger.
|
|
9147
|
-
|
|
9123
|
+
this.logger.warn("No persisted EVM addresses, cannot resume");
|
|
9124
|
+
this.onDisconnect();
|
|
9125
|
+
return;
|
|
9148
9126
|
}
|
|
9149
|
-
|
|
9150
|
-
setAccounts(this.store, {
|
|
9151
|
-
walletId: this.id,
|
|
9152
|
-
accounts
|
|
9153
|
-
});
|
|
9154
|
-
});
|
|
9155
|
-
} catch (error) {
|
|
9156
|
-
this.logger.error("Error resuming session:", error.message);
|
|
9157
|
-
this.onDisconnect();
|
|
9158
|
-
throw error;
|
|
9127
|
+
connectorInfo = {};
|
|
9159
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);
|
|
9160
9143
|
};
|
|
9161
9144
|
};
|
|
9162
9145
|
|
|
@@ -9273,7 +9256,7 @@ async function deriveAlgorandAccountFromEd25519(ed25519Seed) {
|
|
|
9273
9256
|
|
|
9274
9257
|
// src/wallets/web3auth.ts
|
|
9275
9258
|
var LOCAL_STORAGE_WEB3AUTH_KEY = `${LOCAL_STORAGE_KEY}:web3auth`;
|
|
9276
|
-
var
|
|
9259
|
+
var ICON14 = `data:image/svg+xml;base64,${btoa(`
|
|
9277
9260
|
<svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
|
9278
9261
|
<rect fill="#0364FF" width="40" height="40" rx="8"/>
|
|
9279
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"/>
|
|
@@ -9330,7 +9313,7 @@ var Web3AuthWallet = class extends BaseWallet {
|
|
|
9330
9313
|
}
|
|
9331
9314
|
static defaultMetadata = {
|
|
9332
9315
|
name: "Web3Auth",
|
|
9333
|
-
icon:
|
|
9316
|
+
icon: ICON14
|
|
9334
9317
|
};
|
|
9335
9318
|
/**
|
|
9336
9319
|
* Initialize the Web3Auth client
|
|
@@ -9839,7 +9822,7 @@ var Web3AuthWallet = class extends BaseWallet {
|
|
|
9839
9822
|
|
|
9840
9823
|
// src/wallets/w3wallet.ts
|
|
9841
9824
|
var import_algosdk13 = __toESM(require("algosdk"), 1);
|
|
9842
|
-
var
|
|
9825
|
+
var ICON15 = `data:image/svg+xml;base64,${btoa(`
|
|
9843
9826
|
<svg width="860" height="860" viewBox="0 0 860 860" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
9844
9827
|
<rect width="860" height="860" rx="30" fill="#151923"/>
|
|
9845
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"/>
|
|
@@ -9860,7 +9843,7 @@ var W3Wallet = class extends BaseWallet {
|
|
|
9860
9843
|
}
|
|
9861
9844
|
static defaultMetadata = {
|
|
9862
9845
|
name: "W3 Wallet",
|
|
9863
|
-
icon:
|
|
9846
|
+
icon: ICON15
|
|
9864
9847
|
};
|
|
9865
9848
|
async initializeClient() {
|
|
9866
9849
|
this.logger.info("Initializing client...");
|
|
@@ -9990,10 +9973,9 @@ function createWalletMap() {
|
|
|
9990
9973
|
["kmd" /* KMD */]: KmdWallet,
|
|
9991
9974
|
["lute" /* LUTE */]: LuteWallet,
|
|
9992
9975
|
["magic" /* MAGIC */]: MagicAuth,
|
|
9993
|
-
["metamask" /* METAMASK */]: MetaMaskWallet,
|
|
9994
9976
|
["mnemonic" /* MNEMONIC */]: MnemonicWallet,
|
|
9995
9977
|
["pera" /* PERA */]: PeraWallet,
|
|
9996
|
-
["
|
|
9978
|
+
["rainbowkit" /* RAINBOWKIT */]: RainbowKitWallet,
|
|
9997
9979
|
["walletconnect" /* WALLETCONNECT */]: WalletConnect,
|
|
9998
9980
|
["web3auth" /* WEB3AUTH */]: Web3AuthWallet,
|
|
9999
9981
|
["w3-wallet" /* W3_WALLET */]: W3Wallet
|
|
@@ -10114,7 +10096,7 @@ var WalletManager = class {
|
|
|
10114
10096
|
activeNetwork,
|
|
10115
10097
|
algodClient
|
|
10116
10098
|
};
|
|
10117
|
-
this.store = new
|
|
10099
|
+
this.store = new import_store15.Store(initialState, {
|
|
10118
10100
|
onUpdate: () => this.savePersistedState()
|
|
10119
10101
|
});
|
|
10120
10102
|
this.savePersistedState();
|
|
@@ -10487,12 +10469,11 @@ var webpackFallback = {
|
|
|
10487
10469
|
LogLevel,
|
|
10488
10470
|
LuteWallet,
|
|
10489
10471
|
MagicAuth,
|
|
10490
|
-
MetaMaskWallet,
|
|
10491
10472
|
MnemonicWallet,
|
|
10492
10473
|
NetworkConfigBuilder,
|
|
10493
10474
|
NetworkId,
|
|
10494
10475
|
PeraWallet,
|
|
10495
|
-
|
|
10476
|
+
RainbowKitWallet,
|
|
10496
10477
|
ScopeType,
|
|
10497
10478
|
SecureKeyContainer,
|
|
10498
10479
|
SessionError,
|