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