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