@unicitylabs/sphere-sdk 0.2.1 → 0.2.3
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/README.md +22 -69
- package/dist/core/index.cjs +944 -465
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +127 -6
- package/dist/core/index.d.ts +127 -6
- package/dist/core/index.js +833 -351
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +115 -19
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +115 -19
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +3 -1
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +3 -1
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +85 -17
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +22 -0
- package/dist/impl/nodejs/index.d.ts +22 -0
- package/dist/impl/nodejs/index.js +85 -17
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +1083 -644
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -6
- package/dist/index.d.ts +118 -6
- package/dist/index.js +993 -554
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +18 -0
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.d.cts +4 -0
- package/dist/l1/index.d.ts +4 -0
- package/dist/l1/index.js +18 -0
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,218 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
30
|
-
// index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
COIN_TYPES: () => COIN_TYPES,
|
|
34
|
-
CoinGeckoPriceProvider: () => CoinGeckoPriceProvider,
|
|
35
|
-
CommunicationsModule: () => CommunicationsModule,
|
|
36
|
-
DEFAULT_AGGREGATOR_TIMEOUT: () => DEFAULT_AGGREGATOR_TIMEOUT,
|
|
37
|
-
DEFAULT_AGGREGATOR_URL: () => DEFAULT_AGGREGATOR_URL,
|
|
38
|
-
DEFAULT_DERIVATION_PATH: () => DEFAULT_DERIVATION_PATH,
|
|
39
|
-
DEFAULT_ELECTRUM_URL: () => DEFAULT_ELECTRUM_URL,
|
|
40
|
-
DEFAULT_IPFS_BOOTSTRAP_PEERS: () => DEFAULT_IPFS_BOOTSTRAP_PEERS,
|
|
41
|
-
DEFAULT_IPFS_GATEWAYS: () => DEFAULT_IPFS_GATEWAYS,
|
|
42
|
-
DEFAULT_NOSTR_RELAYS: () => DEFAULT_NOSTR_RELAYS,
|
|
43
|
-
DEV_AGGREGATOR_URL: () => DEV_AGGREGATOR_URL,
|
|
44
|
-
L1: () => l1_exports,
|
|
45
|
-
L1PaymentsModule: () => L1PaymentsModule,
|
|
46
|
-
LIMITS: () => LIMITS,
|
|
47
|
-
NETWORKS: () => NETWORKS,
|
|
48
|
-
NOSTR_EVENT_KINDS: () => NOSTR_EVENT_KINDS,
|
|
49
|
-
PaymentsModule: () => PaymentsModule,
|
|
50
|
-
STORAGE_KEYS: () => STORAGE_KEYS,
|
|
51
|
-
STORAGE_PREFIX: () => STORAGE_PREFIX,
|
|
52
|
-
Sphere: () => Sphere,
|
|
53
|
-
SphereError: () => SphereError,
|
|
54
|
-
TEST_AGGREGATOR_URL: () => TEST_AGGREGATOR_URL,
|
|
55
|
-
TEST_ELECTRUM_URL: () => TEST_ELECTRUM_URL,
|
|
56
|
-
TEST_NOSTR_RELAYS: () => TEST_NOSTR_RELAYS,
|
|
57
|
-
TIMEOUTS: () => TIMEOUTS,
|
|
58
|
-
TokenRegistry: () => TokenRegistry,
|
|
59
|
-
TokenValidator: () => TokenValidator,
|
|
60
|
-
archivedKeyFromTokenId: () => archivedKeyFromTokenId,
|
|
61
|
-
base58Decode: () => base58Decode,
|
|
62
|
-
base58Encode: () => base58Encode2,
|
|
63
|
-
buildTxfStorageData: () => buildTxfStorageData,
|
|
64
|
-
bytesToHex: () => bytesToHex2,
|
|
65
|
-
countCommittedTransactions: () => countCommittedTransactions,
|
|
66
|
-
createAddress: () => createAddress,
|
|
67
|
-
createCommunicationsModule: () => createCommunicationsModule,
|
|
68
|
-
createKeyPair: () => createKeyPair,
|
|
69
|
-
createL1PaymentsModule: () => createL1PaymentsModule,
|
|
70
|
-
createPaymentSession: () => createPaymentSession,
|
|
71
|
-
createPaymentSessionError: () => createPaymentSessionError,
|
|
72
|
-
createPaymentsModule: () => createPaymentsModule,
|
|
73
|
-
createPriceProvider: () => createPriceProvider,
|
|
74
|
-
createSphere: () => createSphere,
|
|
75
|
-
createSplitPaymentSession: () => createSplitPaymentSession,
|
|
76
|
-
createTokenValidator: () => createTokenValidator,
|
|
77
|
-
decodeBech32: () => decodeBech32,
|
|
78
|
-
decryptCMasterKey: () => decryptCMasterKey,
|
|
79
|
-
decryptPrivateKey: () => decryptPrivateKey,
|
|
80
|
-
decryptTextFormatKey: () => decryptTextFormatKey,
|
|
81
|
-
deriveAddressInfo: () => deriveAddressInfo,
|
|
82
|
-
deriveChildKey: () => deriveChildKey,
|
|
83
|
-
deriveKeyAtPath: () => deriveKeyAtPath,
|
|
84
|
-
doubleSha256: () => doubleSha256,
|
|
85
|
-
encodeBech32: () => encodeBech32,
|
|
86
|
-
extractFromText: () => extractFromText,
|
|
87
|
-
findPattern: () => findPattern,
|
|
88
|
-
forkedKeyFromTokenIdAndState: () => forkedKeyFromTokenIdAndState,
|
|
89
|
-
formatAmount: () => formatAmount,
|
|
90
|
-
generateMasterKey: () => generateMasterKey,
|
|
91
|
-
generateMnemonic: () => generateMnemonic2,
|
|
92
|
-
getAddressHrp: () => getAddressHrp,
|
|
93
|
-
getCoinIdByName: () => getCoinIdByName,
|
|
94
|
-
getCoinIdBySymbol: () => getCoinIdBySymbol,
|
|
95
|
-
getCurrentStateHash: () => getCurrentStateHash,
|
|
96
|
-
getPublicKey: () => getPublicKey,
|
|
97
|
-
getSphere: () => getSphere,
|
|
98
|
-
getTokenDecimals: () => getTokenDecimals,
|
|
99
|
-
getTokenDefinition: () => getTokenDefinition,
|
|
100
|
-
getTokenIconUrl: () => getTokenIconUrl,
|
|
101
|
-
getTokenId: () => getTokenId,
|
|
102
|
-
getTokenName: () => getTokenName,
|
|
103
|
-
getTokenSymbol: () => getTokenSymbol,
|
|
104
|
-
hasMissingNewStateHash: () => hasMissingNewStateHash,
|
|
105
|
-
hasUncommittedTransactions: () => hasUncommittedTransactions,
|
|
106
|
-
hasValidTxfData: () => hasValidTxfData,
|
|
107
|
-
hash160: () => hash160,
|
|
108
|
-
hexToBytes: () => hexToBytes,
|
|
109
|
-
identityFromMnemonicSync: () => identityFromMnemonicSync,
|
|
110
|
-
initSphere: () => initSphere,
|
|
111
|
-
isArchivedKey: () => isArchivedKey,
|
|
112
|
-
isForkedKey: () => isForkedKey,
|
|
113
|
-
isInstantSplitBundle: () => isInstantSplitBundle,
|
|
114
|
-
isInstantSplitBundleV4: () => isInstantSplitBundleV4,
|
|
115
|
-
isInstantSplitBundleV5: () => isInstantSplitBundleV5,
|
|
116
|
-
isKnownToken: () => isKnownToken,
|
|
117
|
-
isPaymentSessionTerminal: () => isPaymentSessionTerminal,
|
|
118
|
-
isPaymentSessionTimedOut: () => isPaymentSessionTimedOut,
|
|
119
|
-
isSQLiteDatabase: () => isSQLiteDatabase,
|
|
120
|
-
isTextWalletEncrypted: () => isTextWalletEncrypted,
|
|
121
|
-
isTokenKey: () => isTokenKey,
|
|
122
|
-
isValidBech32: () => isValidBech32,
|
|
123
|
-
isValidPrivateKey: () => isValidPrivateKey,
|
|
124
|
-
isValidTokenId: () => isValidTokenId,
|
|
125
|
-
isWalletDatEncrypted: () => isWalletDatEncrypted,
|
|
126
|
-
isWalletTextFormat: () => isWalletTextFormat,
|
|
127
|
-
keyFromTokenId: () => keyFromTokenId,
|
|
128
|
-
loadSphere: () => loadSphere,
|
|
129
|
-
mnemonicToSeedSync: () => mnemonicToSeedSync2,
|
|
130
|
-
normalizeSdkTokenToStorage: () => normalizeSdkTokenToStorage,
|
|
131
|
-
objectToTxf: () => objectToTxf,
|
|
132
|
-
parseAndDecryptWalletDat: () => parseAndDecryptWalletDat,
|
|
133
|
-
parseAndDecryptWalletText: () => parseAndDecryptWalletText,
|
|
134
|
-
parseForkedKey: () => parseForkedKey,
|
|
135
|
-
parseTxfStorageData: () => parseTxfStorageData,
|
|
136
|
-
parseWalletDat: () => parseWalletDat,
|
|
137
|
-
parseWalletText: () => parseWalletText,
|
|
138
|
-
randomBytes: () => randomBytes,
|
|
139
|
-
randomHex: () => randomHex,
|
|
140
|
-
randomUUID: () => randomUUID,
|
|
141
|
-
ripemd160: () => ripemd160,
|
|
142
|
-
sha256: () => sha256,
|
|
143
|
-
sleep: () => sleep,
|
|
144
|
-
sphereExists: () => sphereExists,
|
|
145
|
-
toHumanReadable: () => toHumanReadable,
|
|
146
|
-
toSmallestUnit: () => toSmallestUnit,
|
|
147
|
-
tokenIdFromArchivedKey: () => tokenIdFromArchivedKey,
|
|
148
|
-
tokenIdFromKey: () => tokenIdFromKey,
|
|
149
|
-
tokenToTxf: () => tokenToTxf,
|
|
150
|
-
txfToToken: () => txfToToken,
|
|
151
|
-
validateMnemonic: () => validateMnemonic2
|
|
152
|
-
});
|
|
153
|
-
module.exports = __toCommonJS(index_exports);
|
|
154
|
-
|
|
155
|
-
// l1/index.ts
|
|
156
|
-
var l1_exports = {};
|
|
157
|
-
__export(l1_exports, {
|
|
158
|
-
CHARSET: () => CHARSET,
|
|
159
|
-
VESTING_THRESHOLD: () => VESTING_THRESHOLD,
|
|
160
|
-
WalletAddressHelper: () => WalletAddressHelper,
|
|
161
|
-
addressToScriptHash: () => addressToScriptHash,
|
|
162
|
-
broadcast: () => broadcast,
|
|
163
|
-
buildSegWitTransaction: () => buildSegWitTransaction,
|
|
164
|
-
collectUtxosForAmount: () => collectUtxosForAmount,
|
|
165
|
-
computeHash160: () => computeHash160,
|
|
166
|
-
connect: () => connect,
|
|
167
|
-
convertBits: () => convertBits,
|
|
168
|
-
createAndSignTransaction: () => createAndSignTransaction,
|
|
169
|
-
createBech32: () => createBech32,
|
|
170
|
-
createScriptPubKey: () => createScriptPubKey,
|
|
171
|
-
createTransactionPlan: () => createTransactionPlan,
|
|
172
|
-
decodeBech32: () => decodeBech32,
|
|
173
|
-
decrypt: () => decrypt,
|
|
174
|
-
decryptWallet: () => decryptWallet,
|
|
175
|
-
deriveChildKey: () => deriveChildKey2,
|
|
176
|
-
deriveChildKeyBIP32: () => deriveChildKeyBIP32,
|
|
177
|
-
deriveKeyAtPath: () => deriveKeyAtPath2,
|
|
178
|
-
disconnect: () => disconnect,
|
|
179
|
-
domIdToPath: () => domIdToPath,
|
|
180
|
-
ec: () => ec,
|
|
181
|
-
encodeBech32: () => encodeBech32,
|
|
182
|
-
encrypt: () => encrypt,
|
|
183
|
-
encryptWallet: () => encryptWallet,
|
|
184
|
-
generateAddressFromMasterKey: () => generateAddressFromMasterKey,
|
|
185
|
-
generateAddressInfo: () => generateAddressInfo,
|
|
186
|
-
generateHDAddress: () => generateHDAddress,
|
|
187
|
-
generateHDAddressBIP32: () => generateHDAddressBIP32,
|
|
188
|
-
generateMasterKeyFromSeed: () => generateMasterKeyFromSeed,
|
|
189
|
-
generatePrivateKey: () => generatePrivateKey,
|
|
190
|
-
getBalance: () => getBalance,
|
|
191
|
-
getBlockHeader: () => getBlockHeader,
|
|
192
|
-
getCurrentBlockHeight: () => getCurrentBlockHeight,
|
|
193
|
-
getIndexFromPath: () => getIndexFromPath,
|
|
194
|
-
getTransaction: () => getTransaction,
|
|
195
|
-
getTransactionHistory: () => getTransactionHistory,
|
|
196
|
-
getUtxo: () => getUtxo,
|
|
197
|
-
hash160: () => hash160,
|
|
198
|
-
hash160ToBytes: () => hash160ToBytes,
|
|
199
|
-
hexToWIF: () => hexToWIF,
|
|
200
|
-
isChangePath: () => isChangePath,
|
|
201
|
-
isWebSocketConnected: () => isWebSocketConnected,
|
|
202
|
-
parsePathComponents: () => parsePathComponents,
|
|
203
|
-
pathToDOMId: () => pathToDOMId,
|
|
204
|
-
privateKeyToAddressInfo: () => privateKeyToAddressInfo,
|
|
205
|
-
publicKeyToAddress: () => publicKeyToAddress,
|
|
206
|
-
rpc: () => rpc,
|
|
207
|
-
sendAlpha: () => sendAlpha,
|
|
208
|
-
subscribeBlocks: () => subscribeBlocks,
|
|
209
|
-
vestingClassifier: () => vestingClassifier,
|
|
210
|
-
vestingState: () => vestingState,
|
|
211
|
-
waitForConnection: () => waitForConnection
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// l1/types.ts
|
|
215
|
-
function parsePathComponents(path) {
|
|
216
|
-
const match = path.match(/m\/\d+'\/\d+'\/\d+'\/(\d+)\/(\d+)/);
|
|
217
|
-
if (!match) return null;
|
|
218
|
-
return { chain: parseInt(match[1], 10), index: parseInt(match[2], 10) };
|
|
219
|
-
}
|
|
220
|
-
function isChangePath(path) {
|
|
221
|
-
const parsed = parsePathComponents(path);
|
|
222
|
-
return parsed?.chain === 1;
|
|
223
|
-
}
|
|
224
|
-
function getIndexFromPath(path) {
|
|
225
|
-
const parsed = parsePathComponents(path);
|
|
226
|
-
return parsed?.index ?? 0;
|
|
227
|
-
}
|
|
228
|
-
function pathToDOMId(path) {
|
|
229
|
-
return path.replace(/'/g, "h").replace(/\//g, "-");
|
|
230
|
-
}
|
|
231
|
-
function domIdToPath(encoded) {
|
|
232
|
-
const parts = encoded.split("-");
|
|
233
|
-
return parts.map((part, idx) => {
|
|
234
|
-
if (idx === 0) return part;
|
|
235
|
-
return part.endsWith("h") ? `${part.slice(0, -1)}'` : part;
|
|
236
|
-
}).join("/");
|
|
237
|
-
}
|
|
238
|
-
|
|
239
33
|
// core/bech32.ts
|
|
240
|
-
var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
241
|
-
var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
242
34
|
function convertBits(data, fromBits, toBits, pad) {
|
|
243
35
|
let acc = 0;
|
|
244
36
|
let bits = 0;
|
|
@@ -345,10 +137,17 @@ function getAddressHrp(addr) {
|
|
|
345
137
|
const result = decodeBech32(addr);
|
|
346
138
|
return result?.hrp ?? null;
|
|
347
139
|
}
|
|
348
|
-
var
|
|
140
|
+
var CHARSET, GENERATOR, createBech32;
|
|
141
|
+
var init_bech32 = __esm({
|
|
142
|
+
"core/bech32.ts"() {
|
|
143
|
+
"use strict";
|
|
144
|
+
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
145
|
+
GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
146
|
+
createBech32 = encodeBech32;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
349
149
|
|
|
350
150
|
// l1/addressToScriptHash.ts
|
|
351
|
-
var import_crypto_js = __toESM(require("crypto-js"), 1);
|
|
352
151
|
function bytesToHex(buf) {
|
|
353
152
|
return Array.from(buf).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
354
153
|
}
|
|
@@ -359,301 +158,34 @@ function addressToScriptHash(address) {
|
|
|
359
158
|
const sha = import_crypto_js.default.SHA256(import_crypto_js.default.enc.Hex.parse(scriptHex)).toString();
|
|
360
159
|
return sha.match(/../g).reverse().join("");
|
|
361
160
|
}
|
|
161
|
+
var import_crypto_js;
|
|
162
|
+
var init_addressToScriptHash = __esm({
|
|
163
|
+
"l1/addressToScriptHash.ts"() {
|
|
164
|
+
"use strict";
|
|
165
|
+
init_bech32();
|
|
166
|
+
import_crypto_js = __toESM(require("crypto-js"), 1);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
362
169
|
|
|
363
|
-
//
|
|
364
|
-
var
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const I = import_crypto_js2.default.HmacSHA512(
|
|
383
|
-
import_crypto_js2.default.enc.Hex.parse(seedHex),
|
|
384
|
-
import_crypto_js2.default.enc.Utf8.parse("Bitcoin seed")
|
|
385
|
-
).toString();
|
|
386
|
-
const IL = I.substring(0, 64);
|
|
387
|
-
const IR = I.substring(64);
|
|
388
|
-
const masterKeyBigInt = BigInt("0x" + IL);
|
|
389
|
-
if (masterKeyBigInt === 0n || masterKeyBigInt >= CURVE_ORDER) {
|
|
390
|
-
throw new Error("Invalid master key generated");
|
|
391
|
-
}
|
|
392
|
-
return {
|
|
393
|
-
privateKey: IL,
|
|
394
|
-
chainCode: IR
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
function deriveChildKey(parentPrivKey, parentChainCode, index) {
|
|
398
|
-
const isHardened = index >= 2147483648;
|
|
399
|
-
let data;
|
|
400
|
-
if (isHardened) {
|
|
401
|
-
const indexHex = index.toString(16).padStart(8, "0");
|
|
402
|
-
data = "00" + parentPrivKey + indexHex;
|
|
403
|
-
} else {
|
|
404
|
-
const keyPair = ec.keyFromPrivate(parentPrivKey, "hex");
|
|
405
|
-
const compressedPubKey = keyPair.getPublic(true, "hex");
|
|
406
|
-
const indexHex = index.toString(16).padStart(8, "0");
|
|
407
|
-
data = compressedPubKey + indexHex;
|
|
408
|
-
}
|
|
409
|
-
const I = import_crypto_js2.default.HmacSHA512(
|
|
410
|
-
import_crypto_js2.default.enc.Hex.parse(data),
|
|
411
|
-
import_crypto_js2.default.enc.Hex.parse(parentChainCode)
|
|
412
|
-
).toString();
|
|
413
|
-
const IL = I.substring(0, 64);
|
|
414
|
-
const IR = I.substring(64);
|
|
415
|
-
const ilBigInt = BigInt("0x" + IL);
|
|
416
|
-
const parentKeyBigInt = BigInt("0x" + parentPrivKey);
|
|
417
|
-
if (ilBigInt >= CURVE_ORDER) {
|
|
418
|
-
throw new Error("Invalid key: IL >= curve order");
|
|
419
|
-
}
|
|
420
|
-
const childKeyBigInt = (ilBigInt + parentKeyBigInt) % CURVE_ORDER;
|
|
421
|
-
if (childKeyBigInt === 0n) {
|
|
422
|
-
throw new Error("Invalid key: child key is zero");
|
|
423
|
-
}
|
|
424
|
-
const childPrivKey = childKeyBigInt.toString(16).padStart(64, "0");
|
|
425
|
-
return {
|
|
426
|
-
privateKey: childPrivKey,
|
|
427
|
-
chainCode: IR
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
function deriveKeyAtPath(masterPrivKey, masterChainCode, path) {
|
|
431
|
-
const pathParts = path.replace("m/", "").split("/");
|
|
432
|
-
let currentKey = masterPrivKey;
|
|
433
|
-
let currentChainCode = masterChainCode;
|
|
434
|
-
for (const part of pathParts) {
|
|
435
|
-
const isHardened = part.endsWith("'") || part.endsWith("h");
|
|
436
|
-
const indexStr = part.replace(/['h]$/, "");
|
|
437
|
-
let index = parseInt(indexStr, 10);
|
|
438
|
-
if (isHardened) {
|
|
439
|
-
index += 2147483648;
|
|
440
|
-
}
|
|
441
|
-
const derived = deriveChildKey(currentKey, currentChainCode, index);
|
|
442
|
-
currentKey = derived.privateKey;
|
|
443
|
-
currentChainCode = derived.chainCode;
|
|
444
|
-
}
|
|
445
|
-
return {
|
|
446
|
-
privateKey: currentKey,
|
|
447
|
-
chainCode: currentChainCode
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
function getPublicKey(privateKey, compressed = true) {
|
|
451
|
-
const keyPair = ec.keyFromPrivate(privateKey, "hex");
|
|
452
|
-
return keyPair.getPublic(compressed, "hex");
|
|
453
|
-
}
|
|
454
|
-
function createKeyPair(privateKey) {
|
|
455
|
-
return {
|
|
456
|
-
privateKey,
|
|
457
|
-
publicKey: getPublicKey(privateKey)
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
function sha256(data, inputEncoding = "hex") {
|
|
461
|
-
const parsed = inputEncoding === "hex" ? import_crypto_js2.default.enc.Hex.parse(data) : import_crypto_js2.default.enc.Utf8.parse(data);
|
|
462
|
-
return import_crypto_js2.default.SHA256(parsed).toString();
|
|
463
|
-
}
|
|
464
|
-
function ripemd160(data, inputEncoding = "hex") {
|
|
465
|
-
const parsed = inputEncoding === "hex" ? import_crypto_js2.default.enc.Hex.parse(data) : import_crypto_js2.default.enc.Utf8.parse(data);
|
|
466
|
-
return import_crypto_js2.default.RIPEMD160(parsed).toString();
|
|
467
|
-
}
|
|
468
|
-
function hash160(data) {
|
|
469
|
-
const sha = sha256(data, "hex");
|
|
470
|
-
return ripemd160(sha, "hex");
|
|
471
|
-
}
|
|
472
|
-
function doubleSha256(data, inputEncoding = "hex") {
|
|
473
|
-
const first = sha256(data, inputEncoding);
|
|
474
|
-
return sha256(first, "hex");
|
|
475
|
-
}
|
|
476
|
-
var computeHash160 = hash160;
|
|
477
|
-
function hash160ToBytes(hash160Hex) {
|
|
478
|
-
const matches = hash160Hex.match(/../g);
|
|
479
|
-
if (!matches) return new Uint8Array(0);
|
|
480
|
-
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
481
|
-
}
|
|
482
|
-
function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
483
|
-
const pubKeyHash = hash160(publicKey);
|
|
484
|
-
const programBytes = hash160ToBytes(pubKeyHash);
|
|
485
|
-
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
486
|
-
}
|
|
487
|
-
function privateKeyToAddressInfo(privateKey, prefix = "alpha") {
|
|
488
|
-
const publicKey = getPublicKey(privateKey);
|
|
489
|
-
const address = publicKeyToAddress(publicKey, prefix);
|
|
490
|
-
return { address, publicKey };
|
|
491
|
-
}
|
|
492
|
-
function hexToBytes(hex) {
|
|
493
|
-
const matches = hex.match(/../g);
|
|
494
|
-
if (!matches) {
|
|
495
|
-
return new Uint8Array(0);
|
|
496
|
-
}
|
|
497
|
-
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
498
|
-
}
|
|
499
|
-
function bytesToHex2(bytes) {
|
|
500
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
501
|
-
}
|
|
502
|
-
function randomBytes(length) {
|
|
503
|
-
const words = import_crypto_js2.default.lib.WordArray.random(length);
|
|
504
|
-
return words.toString(import_crypto_js2.default.enc.Hex);
|
|
505
|
-
}
|
|
506
|
-
function identityFromMnemonicSync(mnemonic, passphrase = "") {
|
|
507
|
-
if (!validateMnemonic2(mnemonic)) {
|
|
508
|
-
throw new Error("Invalid mnemonic phrase");
|
|
509
|
-
}
|
|
510
|
-
const seedHex = mnemonicToSeedSync2(mnemonic, passphrase);
|
|
511
|
-
return generateMasterKey(seedHex);
|
|
512
|
-
}
|
|
513
|
-
function deriveAddressInfo(masterKey, basePath, index, isChange = false, prefix = "alpha") {
|
|
514
|
-
const chain = isChange ? 1 : 0;
|
|
515
|
-
const fullPath = `${basePath}/${chain}/${index}`;
|
|
516
|
-
const derived = deriveKeyAtPath(masterKey.privateKey, masterKey.chainCode, fullPath);
|
|
517
|
-
const publicKey = getPublicKey(derived.privateKey);
|
|
518
|
-
const address = publicKeyToAddress(publicKey, prefix);
|
|
519
|
-
return {
|
|
520
|
-
privateKey: derived.privateKey,
|
|
521
|
-
publicKey,
|
|
522
|
-
address,
|
|
523
|
-
path: fullPath,
|
|
524
|
-
index
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
function generateAddressInfo(privateKey, index, path, prefix = "alpha") {
|
|
528
|
-
const { address, publicKey } = privateKeyToAddressInfo(privateKey, prefix);
|
|
529
|
-
return {
|
|
530
|
-
privateKey,
|
|
531
|
-
publicKey,
|
|
532
|
-
address,
|
|
533
|
-
path,
|
|
534
|
-
index
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// l1/crypto.ts
|
|
539
|
-
var import_crypto_js3 = __toESM(require("crypto-js"), 1);
|
|
540
|
-
var SALT = "alpha_wallet_salt";
|
|
541
|
-
var PBKDF2_ITERATIONS = 1e5;
|
|
542
|
-
function encrypt(text, password) {
|
|
543
|
-
return import_crypto_js3.default.AES.encrypt(text, password).toString();
|
|
544
|
-
}
|
|
545
|
-
function decrypt(encrypted, password) {
|
|
546
|
-
const bytes = import_crypto_js3.default.AES.decrypt(encrypted, password);
|
|
547
|
-
return bytes.toString(import_crypto_js3.default.enc.Utf8);
|
|
548
|
-
}
|
|
549
|
-
function generatePrivateKey() {
|
|
550
|
-
return import_crypto_js3.default.lib.WordArray.random(32).toString();
|
|
551
|
-
}
|
|
552
|
-
function encryptWallet(masterPrivateKey, password) {
|
|
553
|
-
const passwordKey = import_crypto_js3.default.PBKDF2(password, SALT, {
|
|
554
|
-
keySize: 256 / 32,
|
|
555
|
-
iterations: PBKDF2_ITERATIONS
|
|
556
|
-
}).toString();
|
|
557
|
-
const encrypted = import_crypto_js3.default.AES.encrypt(
|
|
558
|
-
masterPrivateKey,
|
|
559
|
-
passwordKey
|
|
560
|
-
).toString();
|
|
561
|
-
return encrypted;
|
|
562
|
-
}
|
|
563
|
-
function decryptWallet(encryptedData, password) {
|
|
564
|
-
const passwordKey = import_crypto_js3.default.PBKDF2(password, SALT, {
|
|
565
|
-
keySize: 256 / 32,
|
|
566
|
-
iterations: PBKDF2_ITERATIONS
|
|
567
|
-
}).toString();
|
|
568
|
-
const decrypted = import_crypto_js3.default.AES.decrypt(encryptedData, passwordKey);
|
|
569
|
-
return decrypted.toString(import_crypto_js3.default.enc.Utf8);
|
|
570
|
-
}
|
|
571
|
-
function hexToWIF(hexKey) {
|
|
572
|
-
const versionByte = "80";
|
|
573
|
-
const extendedKey = versionByte + hexKey;
|
|
574
|
-
const hash1 = import_crypto_js3.default.SHA256(import_crypto_js3.default.enc.Hex.parse(extendedKey)).toString();
|
|
575
|
-
const hash2 = import_crypto_js3.default.SHA256(import_crypto_js3.default.enc.Hex.parse(hash1)).toString();
|
|
576
|
-
const checksum = hash2.substring(0, 8);
|
|
577
|
-
const finalHex = extendedKey + checksum;
|
|
578
|
-
return base58Encode(finalHex);
|
|
579
|
-
}
|
|
580
|
-
function base58Encode(hex) {
|
|
581
|
-
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
582
|
-
let num = BigInt("0x" + hex);
|
|
583
|
-
let encoded = "";
|
|
584
|
-
while (num > 0n) {
|
|
585
|
-
const remainder = Number(num % 58n);
|
|
586
|
-
num = num / 58n;
|
|
587
|
-
encoded = ALPHABET[remainder] + encoded;
|
|
588
|
-
}
|
|
589
|
-
for (let i = 0; i < hex.length && hex.substring(i, i + 2) === "00"; i += 2) {
|
|
590
|
-
encoded = "1" + encoded;
|
|
591
|
-
}
|
|
592
|
-
return encoded;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// l1/address.ts
|
|
596
|
-
var import_crypto_js4 = __toESM(require("crypto-js"), 1);
|
|
597
|
-
var deriveChildKeyBIP32 = deriveChildKey;
|
|
598
|
-
var deriveKeyAtPath2 = deriveKeyAtPath;
|
|
599
|
-
function generateMasterKeyFromSeed(seedHex) {
|
|
600
|
-
const result = generateMasterKey(seedHex);
|
|
601
|
-
return {
|
|
602
|
-
masterPrivateKey: result.privateKey,
|
|
603
|
-
masterChainCode: result.chainCode
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
function generateHDAddressBIP32(masterPriv, chainCode, index, basePath = "m/44'/0'/0'", isChange = false) {
|
|
607
|
-
const chain = isChange ? 1 : 0;
|
|
608
|
-
const fullPath = `${basePath}/${chain}/${index}`;
|
|
609
|
-
const derived = deriveKeyAtPath(masterPriv, chainCode, fullPath);
|
|
610
|
-
return generateAddressInfo(derived.privateKey, index, fullPath);
|
|
611
|
-
}
|
|
612
|
-
function generateAddressFromMasterKey(masterPrivateKey, index) {
|
|
613
|
-
const derivationPath = `m/44'/0'/${index}'`;
|
|
614
|
-
const hmacInput = import_crypto_js4.default.enc.Hex.parse(masterPrivateKey);
|
|
615
|
-
const hmacKey = import_crypto_js4.default.enc.Utf8.parse(derivationPath);
|
|
616
|
-
const hmacOutput = import_crypto_js4.default.HmacSHA512(hmacInput, hmacKey).toString();
|
|
617
|
-
const childPrivateKey = hmacOutput.substring(0, 64);
|
|
618
|
-
return generateAddressInfo(childPrivateKey, index, derivationPath);
|
|
619
|
-
}
|
|
620
|
-
function deriveChildKey2(masterPriv, chainCode, index) {
|
|
621
|
-
const data = masterPriv + index.toString(16).padStart(8, "0");
|
|
622
|
-
const I = import_crypto_js4.default.HmacSHA512(
|
|
623
|
-
import_crypto_js4.default.enc.Hex.parse(data),
|
|
624
|
-
import_crypto_js4.default.enc.Hex.parse(chainCode)
|
|
625
|
-
).toString();
|
|
626
|
-
return {
|
|
627
|
-
privateKey: I.substring(0, 64),
|
|
628
|
-
nextChainCode: I.substring(64)
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
function generateHDAddress(masterPriv, chainCode, index) {
|
|
632
|
-
const child = deriveChildKey2(masterPriv, chainCode, index);
|
|
633
|
-
const path = `m/44'/0'/0'/${index}`;
|
|
634
|
-
return generateAddressInfo(child.privateKey, index, path);
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// l1/network.ts
|
|
638
|
-
var DEFAULT_ENDPOINT = "wss://fulcrum.unicity.network:50004";
|
|
639
|
-
var ws = null;
|
|
640
|
-
var isConnected = false;
|
|
641
|
-
var isConnecting = false;
|
|
642
|
-
var requestId = 0;
|
|
643
|
-
var intentionalClose = false;
|
|
644
|
-
var reconnectAttempts = 0;
|
|
645
|
-
var isBlockSubscribed = false;
|
|
646
|
-
var lastBlockHeader = null;
|
|
647
|
-
var pending = {};
|
|
648
|
-
var blockSubscribers = [];
|
|
649
|
-
var connectionCallbacks = [];
|
|
650
|
-
var MAX_RECONNECT_ATTEMPTS = 10;
|
|
651
|
-
var BASE_DELAY = 2e3;
|
|
652
|
-
var MAX_DELAY = 6e4;
|
|
653
|
-
var RPC_TIMEOUT = 3e4;
|
|
654
|
-
var CONNECTION_TIMEOUT = 3e4;
|
|
655
|
-
function isWebSocketConnected() {
|
|
656
|
-
return isConnected && ws !== null && ws.readyState === WebSocket.OPEN;
|
|
170
|
+
// l1/network.ts
|
|
171
|
+
var network_exports = {};
|
|
172
|
+
__export(network_exports, {
|
|
173
|
+
broadcast: () => broadcast,
|
|
174
|
+
connect: () => connect,
|
|
175
|
+
disconnect: () => disconnect,
|
|
176
|
+
getBalance: () => getBalance,
|
|
177
|
+
getBlockHeader: () => getBlockHeader,
|
|
178
|
+
getCurrentBlockHeight: () => getCurrentBlockHeight,
|
|
179
|
+
getTransaction: () => getTransaction,
|
|
180
|
+
getTransactionHistory: () => getTransactionHistory,
|
|
181
|
+
getUtxo: () => getUtxo,
|
|
182
|
+
isWebSocketConnected: () => isWebSocketConnected,
|
|
183
|
+
rpc: () => rpc,
|
|
184
|
+
subscribeBlocks: () => subscribeBlocks,
|
|
185
|
+
waitForConnection: () => waitForConnection
|
|
186
|
+
});
|
|
187
|
+
function isWebSocketConnected() {
|
|
188
|
+
return isConnected && ws !== null && ws.readyState === WebSocket.OPEN;
|
|
657
189
|
}
|
|
658
190
|
function waitForConnection() {
|
|
659
191
|
if (isWebSocketConnected()) {
|
|
@@ -874,48 +406,566 @@ async function getTransactionHistory(address) {
|
|
|
874
406
|
console.warn("get_history returned non-array:", result);
|
|
875
407
|
return [];
|
|
876
408
|
}
|
|
877
|
-
return result;
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
async function getTransaction(txid) {
|
|
412
|
+
return await rpc("blockchain.transaction.get", [txid, true]);
|
|
413
|
+
}
|
|
414
|
+
async function getBlockHeader(height) {
|
|
415
|
+
return await rpc("blockchain.block.header", [height, height]);
|
|
416
|
+
}
|
|
417
|
+
async function getCurrentBlockHeight() {
|
|
418
|
+
try {
|
|
419
|
+
const header = await rpc("blockchain.headers.subscribe", []);
|
|
420
|
+
return header?.height || 0;
|
|
421
|
+
} catch (err) {
|
|
422
|
+
console.error("Error getting current block height:", err);
|
|
423
|
+
return 0;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
function disconnect() {
|
|
427
|
+
if (ws) {
|
|
428
|
+
intentionalClose = true;
|
|
429
|
+
ws.close();
|
|
430
|
+
ws = null;
|
|
431
|
+
}
|
|
432
|
+
isConnected = false;
|
|
433
|
+
isConnecting = false;
|
|
434
|
+
reconnectAttempts = 0;
|
|
435
|
+
isBlockSubscribed = false;
|
|
436
|
+
Object.values(pending).forEach((req) => {
|
|
437
|
+
if (req.timeoutId) clearTimeout(req.timeoutId);
|
|
438
|
+
});
|
|
439
|
+
Object.keys(pending).forEach((key) => delete pending[Number(key)]);
|
|
440
|
+
connectionCallbacks.forEach((cb) => {
|
|
441
|
+
if (cb.timeoutId) clearTimeout(cb.timeoutId);
|
|
442
|
+
});
|
|
443
|
+
connectionCallbacks.length = 0;
|
|
444
|
+
}
|
|
445
|
+
var DEFAULT_ENDPOINT, ws, isConnected, isConnecting, requestId, intentionalClose, reconnectAttempts, isBlockSubscribed, lastBlockHeader, pending, blockSubscribers, connectionCallbacks, MAX_RECONNECT_ATTEMPTS, BASE_DELAY, MAX_DELAY, RPC_TIMEOUT, CONNECTION_TIMEOUT;
|
|
446
|
+
var init_network = __esm({
|
|
447
|
+
"l1/network.ts"() {
|
|
448
|
+
"use strict";
|
|
449
|
+
init_addressToScriptHash();
|
|
450
|
+
DEFAULT_ENDPOINT = "wss://fulcrum.unicity.network:50004";
|
|
451
|
+
ws = null;
|
|
452
|
+
isConnected = false;
|
|
453
|
+
isConnecting = false;
|
|
454
|
+
requestId = 0;
|
|
455
|
+
intentionalClose = false;
|
|
456
|
+
reconnectAttempts = 0;
|
|
457
|
+
isBlockSubscribed = false;
|
|
458
|
+
lastBlockHeader = null;
|
|
459
|
+
pending = {};
|
|
460
|
+
blockSubscribers = [];
|
|
461
|
+
connectionCallbacks = [];
|
|
462
|
+
MAX_RECONNECT_ATTEMPTS = 10;
|
|
463
|
+
BASE_DELAY = 2e3;
|
|
464
|
+
MAX_DELAY = 6e4;
|
|
465
|
+
RPC_TIMEOUT = 3e4;
|
|
466
|
+
CONNECTION_TIMEOUT = 3e4;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// index.ts
|
|
471
|
+
var index_exports = {};
|
|
472
|
+
__export(index_exports, {
|
|
473
|
+
COIN_TYPES: () => COIN_TYPES,
|
|
474
|
+
CoinGeckoPriceProvider: () => CoinGeckoPriceProvider,
|
|
475
|
+
CommunicationsModule: () => CommunicationsModule,
|
|
476
|
+
DEFAULT_AGGREGATOR_TIMEOUT: () => DEFAULT_AGGREGATOR_TIMEOUT,
|
|
477
|
+
DEFAULT_AGGREGATOR_URL: () => DEFAULT_AGGREGATOR_URL,
|
|
478
|
+
DEFAULT_DERIVATION_PATH: () => DEFAULT_DERIVATION_PATH,
|
|
479
|
+
DEFAULT_ELECTRUM_URL: () => DEFAULT_ELECTRUM_URL,
|
|
480
|
+
DEFAULT_IPFS_BOOTSTRAP_PEERS: () => DEFAULT_IPFS_BOOTSTRAP_PEERS,
|
|
481
|
+
DEFAULT_IPFS_GATEWAYS: () => DEFAULT_IPFS_GATEWAYS,
|
|
482
|
+
DEFAULT_NOSTR_RELAYS: () => DEFAULT_NOSTR_RELAYS,
|
|
483
|
+
DEV_AGGREGATOR_URL: () => DEV_AGGREGATOR_URL,
|
|
484
|
+
L1: () => l1_exports,
|
|
485
|
+
L1PaymentsModule: () => L1PaymentsModule,
|
|
486
|
+
LIMITS: () => LIMITS,
|
|
487
|
+
NETWORKS: () => NETWORKS,
|
|
488
|
+
NOSTR_EVENT_KINDS: () => NOSTR_EVENT_KINDS,
|
|
489
|
+
PaymentsModule: () => PaymentsModule,
|
|
490
|
+
STORAGE_KEYS: () => STORAGE_KEYS,
|
|
491
|
+
STORAGE_PREFIX: () => STORAGE_PREFIX,
|
|
492
|
+
Sphere: () => Sphere,
|
|
493
|
+
SphereError: () => SphereError,
|
|
494
|
+
TEST_AGGREGATOR_URL: () => TEST_AGGREGATOR_URL,
|
|
495
|
+
TEST_ELECTRUM_URL: () => TEST_ELECTRUM_URL,
|
|
496
|
+
TEST_NOSTR_RELAYS: () => TEST_NOSTR_RELAYS,
|
|
497
|
+
TIMEOUTS: () => TIMEOUTS,
|
|
498
|
+
TokenRegistry: () => TokenRegistry,
|
|
499
|
+
TokenValidator: () => TokenValidator,
|
|
500
|
+
archivedKeyFromTokenId: () => archivedKeyFromTokenId,
|
|
501
|
+
base58Decode: () => base58Decode,
|
|
502
|
+
base58Encode: () => base58Encode2,
|
|
503
|
+
buildTxfStorageData: () => buildTxfStorageData,
|
|
504
|
+
bytesToHex: () => bytesToHex2,
|
|
505
|
+
countCommittedTransactions: () => countCommittedTransactions,
|
|
506
|
+
createAddress: () => createAddress,
|
|
507
|
+
createCommunicationsModule: () => createCommunicationsModule,
|
|
508
|
+
createKeyPair: () => createKeyPair,
|
|
509
|
+
createL1PaymentsModule: () => createL1PaymentsModule,
|
|
510
|
+
createPaymentSession: () => createPaymentSession,
|
|
511
|
+
createPaymentSessionError: () => createPaymentSessionError,
|
|
512
|
+
createPaymentsModule: () => createPaymentsModule,
|
|
513
|
+
createPriceProvider: () => createPriceProvider,
|
|
514
|
+
createSphere: () => createSphere,
|
|
515
|
+
createSplitPaymentSession: () => createSplitPaymentSession,
|
|
516
|
+
createTokenValidator: () => createTokenValidator,
|
|
517
|
+
decodeBech32: () => decodeBech32,
|
|
518
|
+
decryptCMasterKey: () => decryptCMasterKey,
|
|
519
|
+
decryptPrivateKey: () => decryptPrivateKey,
|
|
520
|
+
decryptTextFormatKey: () => decryptTextFormatKey,
|
|
521
|
+
deriveAddressInfo: () => deriveAddressInfo,
|
|
522
|
+
deriveChildKey: () => deriveChildKey,
|
|
523
|
+
deriveKeyAtPath: () => deriveKeyAtPath,
|
|
524
|
+
doubleSha256: () => doubleSha256,
|
|
525
|
+
encodeBech32: () => encodeBech32,
|
|
526
|
+
extractFromText: () => extractFromText,
|
|
527
|
+
findPattern: () => findPattern,
|
|
528
|
+
forkedKeyFromTokenIdAndState: () => forkedKeyFromTokenIdAndState,
|
|
529
|
+
formatAmount: () => formatAmount,
|
|
530
|
+
generateMasterKey: () => generateMasterKey,
|
|
531
|
+
generateMnemonic: () => generateMnemonic2,
|
|
532
|
+
getAddressHrp: () => getAddressHrp,
|
|
533
|
+
getCoinIdByName: () => getCoinIdByName,
|
|
534
|
+
getCoinIdBySymbol: () => getCoinIdBySymbol,
|
|
535
|
+
getCurrentStateHash: () => getCurrentStateHash,
|
|
536
|
+
getPublicKey: () => getPublicKey,
|
|
537
|
+
getSphere: () => getSphere,
|
|
538
|
+
getTokenDecimals: () => getTokenDecimals,
|
|
539
|
+
getTokenDefinition: () => getTokenDefinition,
|
|
540
|
+
getTokenIconUrl: () => getTokenIconUrl,
|
|
541
|
+
getTokenId: () => getTokenId,
|
|
542
|
+
getTokenName: () => getTokenName,
|
|
543
|
+
getTokenSymbol: () => getTokenSymbol,
|
|
544
|
+
hasMissingNewStateHash: () => hasMissingNewStateHash,
|
|
545
|
+
hasUncommittedTransactions: () => hasUncommittedTransactions,
|
|
546
|
+
hasValidTxfData: () => hasValidTxfData,
|
|
547
|
+
hash160: () => hash160,
|
|
548
|
+
hexToBytes: () => hexToBytes,
|
|
549
|
+
identityFromMnemonicSync: () => identityFromMnemonicSync,
|
|
550
|
+
initSphere: () => initSphere,
|
|
551
|
+
isArchivedKey: () => isArchivedKey,
|
|
552
|
+
isForkedKey: () => isForkedKey,
|
|
553
|
+
isInstantSplitBundle: () => isInstantSplitBundle,
|
|
554
|
+
isInstantSplitBundleV4: () => isInstantSplitBundleV4,
|
|
555
|
+
isInstantSplitBundleV5: () => isInstantSplitBundleV5,
|
|
556
|
+
isKnownToken: () => isKnownToken,
|
|
557
|
+
isPaymentSessionTerminal: () => isPaymentSessionTerminal,
|
|
558
|
+
isPaymentSessionTimedOut: () => isPaymentSessionTimedOut,
|
|
559
|
+
isSQLiteDatabase: () => isSQLiteDatabase,
|
|
560
|
+
isTextWalletEncrypted: () => isTextWalletEncrypted,
|
|
561
|
+
isTokenKey: () => isTokenKey,
|
|
562
|
+
isValidBech32: () => isValidBech32,
|
|
563
|
+
isValidPrivateKey: () => isValidPrivateKey,
|
|
564
|
+
isValidTokenId: () => isValidTokenId,
|
|
565
|
+
isWalletDatEncrypted: () => isWalletDatEncrypted,
|
|
566
|
+
isWalletTextFormat: () => isWalletTextFormat,
|
|
567
|
+
keyFromTokenId: () => keyFromTokenId,
|
|
568
|
+
loadSphere: () => loadSphere,
|
|
569
|
+
mnemonicToSeedSync: () => mnemonicToSeedSync2,
|
|
570
|
+
normalizeSdkTokenToStorage: () => normalizeSdkTokenToStorage,
|
|
571
|
+
objectToTxf: () => objectToTxf,
|
|
572
|
+
parseAndDecryptWalletDat: () => parseAndDecryptWalletDat,
|
|
573
|
+
parseAndDecryptWalletText: () => parseAndDecryptWalletText,
|
|
574
|
+
parseForkedKey: () => parseForkedKey,
|
|
575
|
+
parseTxfStorageData: () => parseTxfStorageData,
|
|
576
|
+
parseWalletDat: () => parseWalletDat,
|
|
577
|
+
parseWalletText: () => parseWalletText,
|
|
578
|
+
randomBytes: () => randomBytes,
|
|
579
|
+
randomHex: () => randomHex,
|
|
580
|
+
randomUUID: () => randomUUID,
|
|
581
|
+
ripemd160: () => ripemd160,
|
|
582
|
+
sha256: () => sha256,
|
|
583
|
+
sleep: () => sleep,
|
|
584
|
+
sphereExists: () => sphereExists,
|
|
585
|
+
toHumanReadable: () => toHumanReadable,
|
|
586
|
+
toSmallestUnit: () => toSmallestUnit,
|
|
587
|
+
tokenIdFromArchivedKey: () => tokenIdFromArchivedKey,
|
|
588
|
+
tokenIdFromKey: () => tokenIdFromKey,
|
|
589
|
+
tokenToTxf: () => tokenToTxf,
|
|
590
|
+
txfToToken: () => txfToToken,
|
|
591
|
+
validateMnemonic: () => validateMnemonic2
|
|
592
|
+
});
|
|
593
|
+
module.exports = __toCommonJS(index_exports);
|
|
594
|
+
|
|
595
|
+
// l1/index.ts
|
|
596
|
+
var l1_exports = {};
|
|
597
|
+
__export(l1_exports, {
|
|
598
|
+
CHARSET: () => CHARSET,
|
|
599
|
+
VESTING_THRESHOLD: () => VESTING_THRESHOLD,
|
|
600
|
+
WalletAddressHelper: () => WalletAddressHelper,
|
|
601
|
+
addressToScriptHash: () => addressToScriptHash,
|
|
602
|
+
broadcast: () => broadcast,
|
|
603
|
+
buildSegWitTransaction: () => buildSegWitTransaction,
|
|
604
|
+
collectUtxosForAmount: () => collectUtxosForAmount,
|
|
605
|
+
computeHash160: () => computeHash160,
|
|
606
|
+
connect: () => connect,
|
|
607
|
+
convertBits: () => convertBits,
|
|
608
|
+
createAndSignTransaction: () => createAndSignTransaction,
|
|
609
|
+
createBech32: () => createBech32,
|
|
610
|
+
createScriptPubKey: () => createScriptPubKey,
|
|
611
|
+
createTransactionPlan: () => createTransactionPlan,
|
|
612
|
+
decodeBech32: () => decodeBech32,
|
|
613
|
+
decrypt: () => decrypt,
|
|
614
|
+
decryptWallet: () => decryptWallet,
|
|
615
|
+
deriveChildKey: () => deriveChildKey2,
|
|
616
|
+
deriveChildKeyBIP32: () => deriveChildKeyBIP32,
|
|
617
|
+
deriveKeyAtPath: () => deriveKeyAtPath2,
|
|
618
|
+
disconnect: () => disconnect,
|
|
619
|
+
domIdToPath: () => domIdToPath,
|
|
620
|
+
ec: () => ec,
|
|
621
|
+
encodeBech32: () => encodeBech32,
|
|
622
|
+
encrypt: () => encrypt,
|
|
623
|
+
encryptWallet: () => encryptWallet,
|
|
624
|
+
generateAddressFromMasterKey: () => generateAddressFromMasterKey,
|
|
625
|
+
generateAddressInfo: () => generateAddressInfo,
|
|
626
|
+
generateHDAddress: () => generateHDAddress,
|
|
627
|
+
generateHDAddressBIP32: () => generateHDAddressBIP32,
|
|
628
|
+
generateMasterKeyFromSeed: () => generateMasterKeyFromSeed,
|
|
629
|
+
generatePrivateKey: () => generatePrivateKey,
|
|
630
|
+
getBalance: () => getBalance,
|
|
631
|
+
getBlockHeader: () => getBlockHeader,
|
|
632
|
+
getCurrentBlockHeight: () => getCurrentBlockHeight,
|
|
633
|
+
getIndexFromPath: () => getIndexFromPath,
|
|
634
|
+
getTransaction: () => getTransaction,
|
|
635
|
+
getTransactionHistory: () => getTransactionHistory,
|
|
636
|
+
getUtxo: () => getUtxo,
|
|
637
|
+
hash160: () => hash160,
|
|
638
|
+
hash160ToBytes: () => hash160ToBytes,
|
|
639
|
+
hexToWIF: () => hexToWIF,
|
|
640
|
+
isChangePath: () => isChangePath,
|
|
641
|
+
isWebSocketConnected: () => isWebSocketConnected,
|
|
642
|
+
parsePathComponents: () => parsePathComponents,
|
|
643
|
+
pathToDOMId: () => pathToDOMId,
|
|
644
|
+
privateKeyToAddressInfo: () => privateKeyToAddressInfo,
|
|
645
|
+
publicKeyToAddress: () => publicKeyToAddress,
|
|
646
|
+
rpc: () => rpc,
|
|
647
|
+
sendAlpha: () => sendAlpha,
|
|
648
|
+
subscribeBlocks: () => subscribeBlocks,
|
|
649
|
+
vestingClassifier: () => vestingClassifier,
|
|
650
|
+
vestingState: () => vestingState,
|
|
651
|
+
waitForConnection: () => waitForConnection
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// l1/types.ts
|
|
655
|
+
function parsePathComponents(path) {
|
|
656
|
+
const match = path.match(/m\/\d+'\/\d+'\/\d+'\/(\d+)\/(\d+)/);
|
|
657
|
+
if (!match) return null;
|
|
658
|
+
return { chain: parseInt(match[1], 10), index: parseInt(match[2], 10) };
|
|
659
|
+
}
|
|
660
|
+
function isChangePath(path) {
|
|
661
|
+
const parsed = parsePathComponents(path);
|
|
662
|
+
return parsed?.chain === 1;
|
|
663
|
+
}
|
|
664
|
+
function getIndexFromPath(path) {
|
|
665
|
+
const parsed = parsePathComponents(path);
|
|
666
|
+
return parsed?.index ?? 0;
|
|
667
|
+
}
|
|
668
|
+
function pathToDOMId(path) {
|
|
669
|
+
return path.replace(/'/g, "h").replace(/\//g, "-");
|
|
670
|
+
}
|
|
671
|
+
function domIdToPath(encoded) {
|
|
672
|
+
const parts = encoded.split("-");
|
|
673
|
+
return parts.map((part, idx) => {
|
|
674
|
+
if (idx === 0) return part;
|
|
675
|
+
return part.endsWith("h") ? `${part.slice(0, -1)}'` : part;
|
|
676
|
+
}).join("/");
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// l1/index.ts
|
|
680
|
+
init_bech32();
|
|
681
|
+
init_addressToScriptHash();
|
|
682
|
+
|
|
683
|
+
// core/crypto.ts
|
|
684
|
+
var bip39 = __toESM(require("bip39"), 1);
|
|
685
|
+
var import_crypto_js2 = __toESM(require("crypto-js"), 1);
|
|
686
|
+
var import_elliptic = __toESM(require("elliptic"), 1);
|
|
687
|
+
init_bech32();
|
|
688
|
+
var ec = new import_elliptic.default.ec("secp256k1");
|
|
689
|
+
var CURVE_ORDER = BigInt(
|
|
690
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
|
|
691
|
+
);
|
|
692
|
+
function generateMnemonic2(strength = 128) {
|
|
693
|
+
return bip39.generateMnemonic(strength);
|
|
694
|
+
}
|
|
695
|
+
function validateMnemonic2(mnemonic) {
|
|
696
|
+
return bip39.validateMnemonic(mnemonic);
|
|
697
|
+
}
|
|
698
|
+
function mnemonicToSeedSync2(mnemonic, passphrase = "") {
|
|
699
|
+
const seedBuffer = bip39.mnemonicToSeedSync(mnemonic, passphrase);
|
|
700
|
+
return Buffer.from(seedBuffer).toString("hex");
|
|
701
|
+
}
|
|
702
|
+
function generateMasterKey(seedHex) {
|
|
703
|
+
const I = import_crypto_js2.default.HmacSHA512(
|
|
704
|
+
import_crypto_js2.default.enc.Hex.parse(seedHex),
|
|
705
|
+
import_crypto_js2.default.enc.Utf8.parse("Bitcoin seed")
|
|
706
|
+
).toString();
|
|
707
|
+
const IL = I.substring(0, 64);
|
|
708
|
+
const IR = I.substring(64);
|
|
709
|
+
const masterKeyBigInt = BigInt("0x" + IL);
|
|
710
|
+
if (masterKeyBigInt === 0n || masterKeyBigInt >= CURVE_ORDER) {
|
|
711
|
+
throw new Error("Invalid master key generated");
|
|
712
|
+
}
|
|
713
|
+
return {
|
|
714
|
+
privateKey: IL,
|
|
715
|
+
chainCode: IR
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
function deriveChildKey(parentPrivKey, parentChainCode, index) {
|
|
719
|
+
const isHardened = index >= 2147483648;
|
|
720
|
+
let data;
|
|
721
|
+
if (isHardened) {
|
|
722
|
+
const indexHex = index.toString(16).padStart(8, "0");
|
|
723
|
+
data = "00" + parentPrivKey + indexHex;
|
|
724
|
+
} else {
|
|
725
|
+
const keyPair = ec.keyFromPrivate(parentPrivKey, "hex");
|
|
726
|
+
const compressedPubKey = keyPair.getPublic(true, "hex");
|
|
727
|
+
const indexHex = index.toString(16).padStart(8, "0");
|
|
728
|
+
data = compressedPubKey + indexHex;
|
|
729
|
+
}
|
|
730
|
+
const I = import_crypto_js2.default.HmacSHA512(
|
|
731
|
+
import_crypto_js2.default.enc.Hex.parse(data),
|
|
732
|
+
import_crypto_js2.default.enc.Hex.parse(parentChainCode)
|
|
733
|
+
).toString();
|
|
734
|
+
const IL = I.substring(0, 64);
|
|
735
|
+
const IR = I.substring(64);
|
|
736
|
+
const ilBigInt = BigInt("0x" + IL);
|
|
737
|
+
const parentKeyBigInt = BigInt("0x" + parentPrivKey);
|
|
738
|
+
if (ilBigInt >= CURVE_ORDER) {
|
|
739
|
+
throw new Error("Invalid key: IL >= curve order");
|
|
740
|
+
}
|
|
741
|
+
const childKeyBigInt = (ilBigInt + parentKeyBigInt) % CURVE_ORDER;
|
|
742
|
+
if (childKeyBigInt === 0n) {
|
|
743
|
+
throw new Error("Invalid key: child key is zero");
|
|
744
|
+
}
|
|
745
|
+
const childPrivKey = childKeyBigInt.toString(16).padStart(64, "0");
|
|
746
|
+
return {
|
|
747
|
+
privateKey: childPrivKey,
|
|
748
|
+
chainCode: IR
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function deriveKeyAtPath(masterPrivKey, masterChainCode, path) {
|
|
752
|
+
const pathParts = path.replace("m/", "").split("/");
|
|
753
|
+
let currentKey = masterPrivKey;
|
|
754
|
+
let currentChainCode = masterChainCode;
|
|
755
|
+
for (const part of pathParts) {
|
|
756
|
+
const isHardened = part.endsWith("'") || part.endsWith("h");
|
|
757
|
+
const indexStr = part.replace(/['h]$/, "");
|
|
758
|
+
let index = parseInt(indexStr, 10);
|
|
759
|
+
if (isHardened) {
|
|
760
|
+
index += 2147483648;
|
|
761
|
+
}
|
|
762
|
+
const derived = deriveChildKey(currentKey, currentChainCode, index);
|
|
763
|
+
currentKey = derived.privateKey;
|
|
764
|
+
currentChainCode = derived.chainCode;
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
privateKey: currentKey,
|
|
768
|
+
chainCode: currentChainCode
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
function getPublicKey(privateKey, compressed = true) {
|
|
772
|
+
const keyPair = ec.keyFromPrivate(privateKey, "hex");
|
|
773
|
+
return keyPair.getPublic(compressed, "hex");
|
|
774
|
+
}
|
|
775
|
+
function createKeyPair(privateKey) {
|
|
776
|
+
return {
|
|
777
|
+
privateKey,
|
|
778
|
+
publicKey: getPublicKey(privateKey)
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
function sha256(data, inputEncoding = "hex") {
|
|
782
|
+
const parsed = inputEncoding === "hex" ? import_crypto_js2.default.enc.Hex.parse(data) : import_crypto_js2.default.enc.Utf8.parse(data);
|
|
783
|
+
return import_crypto_js2.default.SHA256(parsed).toString();
|
|
784
|
+
}
|
|
785
|
+
function ripemd160(data, inputEncoding = "hex") {
|
|
786
|
+
const parsed = inputEncoding === "hex" ? import_crypto_js2.default.enc.Hex.parse(data) : import_crypto_js2.default.enc.Utf8.parse(data);
|
|
787
|
+
return import_crypto_js2.default.RIPEMD160(parsed).toString();
|
|
788
|
+
}
|
|
789
|
+
function hash160(data) {
|
|
790
|
+
const sha = sha256(data, "hex");
|
|
791
|
+
return ripemd160(sha, "hex");
|
|
792
|
+
}
|
|
793
|
+
function doubleSha256(data, inputEncoding = "hex") {
|
|
794
|
+
const first = sha256(data, inputEncoding);
|
|
795
|
+
return sha256(first, "hex");
|
|
796
|
+
}
|
|
797
|
+
var computeHash160 = hash160;
|
|
798
|
+
function hash160ToBytes(hash160Hex) {
|
|
799
|
+
const matches = hash160Hex.match(/../g);
|
|
800
|
+
if (!matches) return new Uint8Array(0);
|
|
801
|
+
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
802
|
+
}
|
|
803
|
+
function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
804
|
+
const pubKeyHash = hash160(publicKey);
|
|
805
|
+
const programBytes = hash160ToBytes(pubKeyHash);
|
|
806
|
+
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
807
|
+
}
|
|
808
|
+
function privateKeyToAddressInfo(privateKey, prefix = "alpha") {
|
|
809
|
+
const publicKey = getPublicKey(privateKey);
|
|
810
|
+
const address = publicKeyToAddress(publicKey, prefix);
|
|
811
|
+
return { address, publicKey };
|
|
812
|
+
}
|
|
813
|
+
function hexToBytes(hex) {
|
|
814
|
+
const matches = hex.match(/../g);
|
|
815
|
+
if (!matches) {
|
|
816
|
+
return new Uint8Array(0);
|
|
817
|
+
}
|
|
818
|
+
return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
|
|
819
|
+
}
|
|
820
|
+
function bytesToHex2(bytes) {
|
|
821
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
822
|
+
}
|
|
823
|
+
function randomBytes(length) {
|
|
824
|
+
const words = import_crypto_js2.default.lib.WordArray.random(length);
|
|
825
|
+
return words.toString(import_crypto_js2.default.enc.Hex);
|
|
826
|
+
}
|
|
827
|
+
function identityFromMnemonicSync(mnemonic, passphrase = "") {
|
|
828
|
+
if (!validateMnemonic2(mnemonic)) {
|
|
829
|
+
throw new Error("Invalid mnemonic phrase");
|
|
830
|
+
}
|
|
831
|
+
const seedHex = mnemonicToSeedSync2(mnemonic, passphrase);
|
|
832
|
+
return generateMasterKey(seedHex);
|
|
833
|
+
}
|
|
834
|
+
function deriveAddressInfo(masterKey, basePath, index, isChange = false, prefix = "alpha") {
|
|
835
|
+
const chain = isChange ? 1 : 0;
|
|
836
|
+
const fullPath = `${basePath}/${chain}/${index}`;
|
|
837
|
+
const derived = deriveKeyAtPath(masterKey.privateKey, masterKey.chainCode, fullPath);
|
|
838
|
+
const publicKey = getPublicKey(derived.privateKey);
|
|
839
|
+
const address = publicKeyToAddress(publicKey, prefix);
|
|
840
|
+
return {
|
|
841
|
+
privateKey: derived.privateKey,
|
|
842
|
+
publicKey,
|
|
843
|
+
address,
|
|
844
|
+
path: fullPath,
|
|
845
|
+
index
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
function generateAddressInfo(privateKey, index, path, prefix = "alpha") {
|
|
849
|
+
const { address, publicKey } = privateKeyToAddressInfo(privateKey, prefix);
|
|
850
|
+
return {
|
|
851
|
+
privateKey,
|
|
852
|
+
publicKey,
|
|
853
|
+
address,
|
|
854
|
+
path,
|
|
855
|
+
index
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// l1/crypto.ts
|
|
860
|
+
var import_crypto_js3 = __toESM(require("crypto-js"), 1);
|
|
861
|
+
var SALT = "alpha_wallet_salt";
|
|
862
|
+
var PBKDF2_ITERATIONS = 1e5;
|
|
863
|
+
function encrypt(text, password) {
|
|
864
|
+
return import_crypto_js3.default.AES.encrypt(text, password).toString();
|
|
865
|
+
}
|
|
866
|
+
function decrypt(encrypted, password) {
|
|
867
|
+
const bytes = import_crypto_js3.default.AES.decrypt(encrypted, password);
|
|
868
|
+
return bytes.toString(import_crypto_js3.default.enc.Utf8);
|
|
869
|
+
}
|
|
870
|
+
function generatePrivateKey() {
|
|
871
|
+
return import_crypto_js3.default.lib.WordArray.random(32).toString();
|
|
872
|
+
}
|
|
873
|
+
function encryptWallet(masterPrivateKey, password) {
|
|
874
|
+
const passwordKey = import_crypto_js3.default.PBKDF2(password, SALT, {
|
|
875
|
+
keySize: 256 / 32,
|
|
876
|
+
iterations: PBKDF2_ITERATIONS
|
|
877
|
+
}).toString();
|
|
878
|
+
const encrypted = import_crypto_js3.default.AES.encrypt(
|
|
879
|
+
masterPrivateKey,
|
|
880
|
+
passwordKey
|
|
881
|
+
).toString();
|
|
882
|
+
return encrypted;
|
|
883
|
+
}
|
|
884
|
+
function decryptWallet(encryptedData, password) {
|
|
885
|
+
const passwordKey = import_crypto_js3.default.PBKDF2(password, SALT, {
|
|
886
|
+
keySize: 256 / 32,
|
|
887
|
+
iterations: PBKDF2_ITERATIONS
|
|
888
|
+
}).toString();
|
|
889
|
+
const decrypted = import_crypto_js3.default.AES.decrypt(encryptedData, passwordKey);
|
|
890
|
+
return decrypted.toString(import_crypto_js3.default.enc.Utf8);
|
|
891
|
+
}
|
|
892
|
+
function hexToWIF(hexKey) {
|
|
893
|
+
const versionByte = "80";
|
|
894
|
+
const extendedKey = versionByte + hexKey;
|
|
895
|
+
const hash1 = import_crypto_js3.default.SHA256(import_crypto_js3.default.enc.Hex.parse(extendedKey)).toString();
|
|
896
|
+
const hash2 = import_crypto_js3.default.SHA256(import_crypto_js3.default.enc.Hex.parse(hash1)).toString();
|
|
897
|
+
const checksum = hash2.substring(0, 8);
|
|
898
|
+
const finalHex = extendedKey + checksum;
|
|
899
|
+
return base58Encode(finalHex);
|
|
900
|
+
}
|
|
901
|
+
function base58Encode(hex) {
|
|
902
|
+
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
903
|
+
let num = BigInt("0x" + hex);
|
|
904
|
+
let encoded = "";
|
|
905
|
+
while (num > 0n) {
|
|
906
|
+
const remainder = Number(num % 58n);
|
|
907
|
+
num = num / 58n;
|
|
908
|
+
encoded = ALPHABET[remainder] + encoded;
|
|
909
|
+
}
|
|
910
|
+
for (let i = 0; i < hex.length && hex.substring(i, i + 2) === "00"; i += 2) {
|
|
911
|
+
encoded = "1" + encoded;
|
|
912
|
+
}
|
|
913
|
+
return encoded;
|
|
878
914
|
}
|
|
879
|
-
|
|
880
|
-
|
|
915
|
+
|
|
916
|
+
// l1/address.ts
|
|
917
|
+
var import_crypto_js4 = __toESM(require("crypto-js"), 1);
|
|
918
|
+
var deriveChildKeyBIP32 = deriveChildKey;
|
|
919
|
+
var deriveKeyAtPath2 = deriveKeyAtPath;
|
|
920
|
+
function generateMasterKeyFromSeed(seedHex) {
|
|
921
|
+
const result = generateMasterKey(seedHex);
|
|
922
|
+
return {
|
|
923
|
+
masterPrivateKey: result.privateKey,
|
|
924
|
+
masterChainCode: result.chainCode
|
|
925
|
+
};
|
|
881
926
|
}
|
|
882
|
-
|
|
883
|
-
|
|
927
|
+
function generateHDAddressBIP32(masterPriv, chainCode, index, basePath = "m/44'/0'/0'", isChange = false) {
|
|
928
|
+
const chain = isChange ? 1 : 0;
|
|
929
|
+
const fullPath = `${basePath}/${chain}/${index}`;
|
|
930
|
+
const derived = deriveKeyAtPath(masterPriv, chainCode, fullPath);
|
|
931
|
+
return generateAddressInfo(derived.privateKey, index, fullPath);
|
|
884
932
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
}
|
|
933
|
+
function generateAddressFromMasterKey(masterPrivateKey, index) {
|
|
934
|
+
const derivationPath = `m/44'/0'/${index}'`;
|
|
935
|
+
const hmacInput = import_crypto_js4.default.enc.Hex.parse(masterPrivateKey);
|
|
936
|
+
const hmacKey = import_crypto_js4.default.enc.Utf8.parse(derivationPath);
|
|
937
|
+
const hmacOutput = import_crypto_js4.default.HmacSHA512(hmacInput, hmacKey).toString();
|
|
938
|
+
const childPrivateKey = hmacOutput.substring(0, 64);
|
|
939
|
+
return generateAddressInfo(childPrivateKey, index, derivationPath);
|
|
893
940
|
}
|
|
894
|
-
function
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
if (cb.timeoutId) clearTimeout(cb.timeoutId);
|
|
910
|
-
});
|
|
911
|
-
connectionCallbacks.length = 0;
|
|
941
|
+
function deriveChildKey2(masterPriv, chainCode, index) {
|
|
942
|
+
const data = masterPriv + index.toString(16).padStart(8, "0");
|
|
943
|
+
const I = import_crypto_js4.default.HmacSHA512(
|
|
944
|
+
import_crypto_js4.default.enc.Hex.parse(data),
|
|
945
|
+
import_crypto_js4.default.enc.Hex.parse(chainCode)
|
|
946
|
+
).toString();
|
|
947
|
+
return {
|
|
948
|
+
privateKey: I.substring(0, 64),
|
|
949
|
+
nextChainCode: I.substring(64)
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
function generateHDAddress(masterPriv, chainCode, index) {
|
|
953
|
+
const child = deriveChildKey2(masterPriv, chainCode, index);
|
|
954
|
+
const path = `m/44'/0'/0'/${index}`;
|
|
955
|
+
return generateAddressInfo(child.privateKey, index, path);
|
|
912
956
|
}
|
|
913
957
|
|
|
958
|
+
// l1/index.ts
|
|
959
|
+
init_network();
|
|
960
|
+
|
|
914
961
|
// l1/tx.ts
|
|
962
|
+
init_network();
|
|
963
|
+
init_bech32();
|
|
915
964
|
var import_crypto_js5 = __toESM(require("crypto-js"), 1);
|
|
916
965
|
var import_elliptic2 = __toESM(require("elliptic"), 1);
|
|
917
966
|
|
|
918
967
|
// l1/vesting.ts
|
|
968
|
+
init_network();
|
|
919
969
|
var VESTING_THRESHOLD = 28e4;
|
|
920
970
|
var currentBlockHeight = null;
|
|
921
971
|
var VestingClassifier = class {
|
|
@@ -1134,6 +1184,24 @@ var VestingClassifier = class {
|
|
|
1134
1184
|
tx.objectStore(this.storeName).clear();
|
|
1135
1185
|
}
|
|
1136
1186
|
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Destroy caches and delete the IndexedDB database entirely.
|
|
1189
|
+
*/
|
|
1190
|
+
async destroy() {
|
|
1191
|
+
this.memoryCache.clear();
|
|
1192
|
+
if (this.db) {
|
|
1193
|
+
this.db.close();
|
|
1194
|
+
this.db = null;
|
|
1195
|
+
}
|
|
1196
|
+
if (typeof indexedDB !== "undefined") {
|
|
1197
|
+
await new Promise((resolve) => {
|
|
1198
|
+
const req = indexedDB.deleteDatabase(this.dbName);
|
|
1199
|
+
req.onsuccess = () => resolve();
|
|
1200
|
+
req.onerror = () => resolve();
|
|
1201
|
+
req.onblocked = () => resolve();
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1137
1205
|
};
|
|
1138
1206
|
var vestingClassifier = new VestingClassifier();
|
|
1139
1207
|
|
|
@@ -1686,7 +1754,7 @@ var L1PaymentsModule = class {
|
|
|
1686
1754
|
_transport;
|
|
1687
1755
|
constructor(config) {
|
|
1688
1756
|
this._config = {
|
|
1689
|
-
electrumUrl: config?.electrumUrl ?? "wss://fulcrum.
|
|
1757
|
+
electrumUrl: config?.electrumUrl ?? "wss://fulcrum.unicity.network:50004",
|
|
1690
1758
|
network: config?.network ?? "mainnet",
|
|
1691
1759
|
defaultFeeRate: config?.defaultFeeRate ?? 10,
|
|
1692
1760
|
enableVesting: config?.enableVesting ?? true
|
|
@@ -1718,10 +1786,17 @@ var L1PaymentsModule = class {
|
|
|
1718
1786
|
});
|
|
1719
1787
|
}
|
|
1720
1788
|
}
|
|
1721
|
-
|
|
1789
|
+
this._initialized = true;
|
|
1790
|
+
}
|
|
1791
|
+
/**
|
|
1792
|
+
* Ensure the Fulcrum WebSocket is connected. Called lazily before any
|
|
1793
|
+
* operation that needs the network. If the singleton is already connected
|
|
1794
|
+
* (e.g. by the address scanner), this is a no-op.
|
|
1795
|
+
*/
|
|
1796
|
+
async ensureConnected() {
|
|
1797
|
+
if (!isWebSocketConnected() && this._config.electrumUrl) {
|
|
1722
1798
|
await connect(this._config.electrumUrl);
|
|
1723
1799
|
}
|
|
1724
|
-
this._initialized = true;
|
|
1725
1800
|
}
|
|
1726
1801
|
destroy() {
|
|
1727
1802
|
if (isWebSocketConnected()) {
|
|
@@ -1779,6 +1854,7 @@ var L1PaymentsModule = class {
|
|
|
1779
1854
|
}
|
|
1780
1855
|
async send(request) {
|
|
1781
1856
|
this.ensureInitialized();
|
|
1857
|
+
await this.ensureConnected();
|
|
1782
1858
|
if (!this._wallet || !this._identity) {
|
|
1783
1859
|
return { success: false, error: "No wallet available" };
|
|
1784
1860
|
}
|
|
@@ -1813,6 +1889,7 @@ var L1PaymentsModule = class {
|
|
|
1813
1889
|
}
|
|
1814
1890
|
async getBalance() {
|
|
1815
1891
|
this.ensureInitialized();
|
|
1892
|
+
await this.ensureConnected();
|
|
1816
1893
|
const addresses = this._getWatchedAddresses();
|
|
1817
1894
|
let totalAlpha = 0;
|
|
1818
1895
|
let vestedSats = BigInt(0);
|
|
@@ -1844,6 +1921,7 @@ var L1PaymentsModule = class {
|
|
|
1844
1921
|
}
|
|
1845
1922
|
async getUtxos() {
|
|
1846
1923
|
this.ensureInitialized();
|
|
1924
|
+
await this.ensureConnected();
|
|
1847
1925
|
const result = [];
|
|
1848
1926
|
const currentHeight = await getCurrentBlockHeight();
|
|
1849
1927
|
const allUtxos = await this._getAllUtxos();
|
|
@@ -1879,42 +1957,73 @@ var L1PaymentsModule = class {
|
|
|
1879
1957
|
return result;
|
|
1880
1958
|
}
|
|
1881
1959
|
async getHistory(limit) {
|
|
1960
|
+
await this.ensureConnected();
|
|
1882
1961
|
this.ensureInitialized();
|
|
1883
1962
|
const addresses = this._getWatchedAddresses();
|
|
1884
1963
|
const transactions = [];
|
|
1885
1964
|
const seenTxids = /* @__PURE__ */ new Set();
|
|
1886
1965
|
const currentHeight = await getCurrentBlockHeight();
|
|
1966
|
+
const txCache = /* @__PURE__ */ new Map();
|
|
1967
|
+
const fetchTx = async (txid) => {
|
|
1968
|
+
if (txCache.has(txid)) return txCache.get(txid);
|
|
1969
|
+
const detail = await getTransaction(txid);
|
|
1970
|
+
txCache.set(txid, detail);
|
|
1971
|
+
return detail;
|
|
1972
|
+
};
|
|
1973
|
+
const addressSet = new Set(addresses.map((a) => a.toLowerCase()));
|
|
1887
1974
|
for (const address of addresses) {
|
|
1888
1975
|
const history = await getTransactionHistory(address);
|
|
1889
1976
|
for (const item of history) {
|
|
1890
1977
|
if (seenTxids.has(item.tx_hash)) continue;
|
|
1891
1978
|
seenTxids.add(item.tx_hash);
|
|
1892
|
-
const tx = await
|
|
1979
|
+
const tx = await fetchTx(item.tx_hash);
|
|
1893
1980
|
if (!tx) continue;
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1981
|
+
let isSend = false;
|
|
1982
|
+
for (const vin of tx.vin ?? []) {
|
|
1983
|
+
if (!vin.txid) continue;
|
|
1984
|
+
const prevTx = await fetchTx(vin.txid);
|
|
1985
|
+
if (prevTx?.vout?.[vin.vout]) {
|
|
1986
|
+
const prevOut = prevTx.vout[vin.vout];
|
|
1987
|
+
const prevAddrs = [
|
|
1988
|
+
...prevOut.scriptPubKey?.addresses ?? [],
|
|
1989
|
+
...prevOut.scriptPubKey?.address ? [prevOut.scriptPubKey.address] : []
|
|
1990
|
+
];
|
|
1991
|
+
if (prevAddrs.some((a) => addressSet.has(a.toLowerCase()))) {
|
|
1992
|
+
isSend = true;
|
|
1993
|
+
break;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
let amountToUs = 0;
|
|
1998
|
+
let amountToOthers = 0;
|
|
1898
1999
|
let txAddress = address;
|
|
2000
|
+
let externalAddress = "";
|
|
1899
2001
|
if (tx.vout) {
|
|
1900
2002
|
for (const vout of tx.vout) {
|
|
1901
|
-
const voutAddresses =
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
const
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2003
|
+
const voutAddresses = [
|
|
2004
|
+
...vout.scriptPubKey?.addresses ?? [],
|
|
2005
|
+
...vout.scriptPubKey?.address ? [vout.scriptPubKey.address] : []
|
|
2006
|
+
];
|
|
2007
|
+
const isOurs = voutAddresses.some((a) => addressSet.has(a.toLowerCase()));
|
|
2008
|
+
const valueSats = Math.floor((vout.value ?? 0) * 1e8);
|
|
2009
|
+
if (isOurs) {
|
|
2010
|
+
amountToUs += valueSats;
|
|
2011
|
+
if (!txAddress) txAddress = voutAddresses[0];
|
|
2012
|
+
} else {
|
|
2013
|
+
amountToOthers += valueSats;
|
|
2014
|
+
if (!externalAddress && voutAddresses.length > 0) {
|
|
2015
|
+
externalAddress = voutAddresses[0];
|
|
2016
|
+
}
|
|
1910
2017
|
}
|
|
1911
2018
|
}
|
|
1912
2019
|
}
|
|
2020
|
+
const amount = isSend ? amountToOthers.toString() : amountToUs.toString();
|
|
2021
|
+
const displayAddress = isSend ? externalAddress || txAddress : txAddress;
|
|
1913
2022
|
transactions.push({
|
|
1914
2023
|
txid: item.tx_hash,
|
|
1915
2024
|
type: isSend ? "send" : "receive",
|
|
1916
2025
|
amount,
|
|
1917
|
-
address:
|
|
2026
|
+
address: displayAddress,
|
|
1918
2027
|
confirmations: item.height > 0 ? currentHeight - item.height : 0,
|
|
1919
2028
|
timestamp: tx.time ? tx.time * 1e3 : Date.now(),
|
|
1920
2029
|
blockHeight: item.height > 0 ? item.height : void 0
|
|
@@ -1926,6 +2035,7 @@ var L1PaymentsModule = class {
|
|
|
1926
2035
|
}
|
|
1927
2036
|
async getTransaction(txid) {
|
|
1928
2037
|
this.ensureInitialized();
|
|
2038
|
+
await this.ensureConnected();
|
|
1929
2039
|
const tx = await getTransaction(txid);
|
|
1930
2040
|
if (!tx) return null;
|
|
1931
2041
|
const addresses = this._getWatchedAddresses();
|
|
@@ -1961,6 +2071,7 @@ var L1PaymentsModule = class {
|
|
|
1961
2071
|
}
|
|
1962
2072
|
async estimateFee(to, amount) {
|
|
1963
2073
|
this.ensureInitialized();
|
|
2074
|
+
await this.ensureConnected();
|
|
1964
2075
|
if (!this._wallet) {
|
|
1965
2076
|
return { fee: "0", feeRate: this._config.defaultFeeRate ?? 10 };
|
|
1966
2077
|
}
|
|
@@ -2484,7 +2595,9 @@ var STORAGE_KEYS_GLOBAL = {
|
|
|
2484
2595
|
/** Nametag cache per address (separate from tracked addresses registry) */
|
|
2485
2596
|
ADDRESS_NAMETAGS: "address_nametags",
|
|
2486
2597
|
/** Active addresses registry (JSON: TrackedAddressesStorage) */
|
|
2487
|
-
TRACKED_ADDRESSES: "tracked_addresses"
|
|
2598
|
+
TRACKED_ADDRESSES: "tracked_addresses",
|
|
2599
|
+
/** Last processed Nostr wallet event timestamp (unix seconds), keyed per pubkey */
|
|
2600
|
+
LAST_WALLET_EVENT_TS: "last_wallet_event_ts"
|
|
2488
2601
|
};
|
|
2489
2602
|
var STORAGE_KEYS_ADDRESS = {
|
|
2490
2603
|
/** Pending transfers for this address */
|
|
@@ -4057,7 +4170,7 @@ async function parseTokenInfo(tokenData) {
|
|
|
4057
4170
|
try {
|
|
4058
4171
|
const sdkToken = await import_Token6.Token.fromJSON(data);
|
|
4059
4172
|
if (sdkToken.id) {
|
|
4060
|
-
defaultInfo.tokenId = sdkToken.id.
|
|
4173
|
+
defaultInfo.tokenId = sdkToken.id.toJSON();
|
|
4061
4174
|
}
|
|
4062
4175
|
if (sdkToken.coins && sdkToken.coins.coins) {
|
|
4063
4176
|
const rawCoins = sdkToken.coins.coins;
|
|
@@ -4348,8 +4461,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4348
4461
|
maxRetries: config?.maxRetries ?? 3,
|
|
4349
4462
|
debug: config?.debug ?? false
|
|
4350
4463
|
};
|
|
4351
|
-
|
|
4352
|
-
this.l1 = l1Enabled ? new L1PaymentsModule(config?.l1) : null;
|
|
4464
|
+
this.l1 = config?.l1 === null ? null : new L1PaymentsModule(config?.l1);
|
|
4353
4465
|
}
|
|
4354
4466
|
/** Get module configuration */
|
|
4355
4467
|
getConfig() {
|
|
@@ -4551,7 +4663,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4551
4663
|
memo: request.memo
|
|
4552
4664
|
});
|
|
4553
4665
|
console.log(`[Payments] Split token sent successfully`);
|
|
4554
|
-
await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag);
|
|
4666
|
+
await this.removeToken(splitPlan.tokenToSplit.uiToken.id, recipientNametag, true);
|
|
4555
4667
|
result.txHash = "split-" + Date.now().toString(16);
|
|
4556
4668
|
this.log(`Split transfer completed`);
|
|
4557
4669
|
}
|
|
@@ -4577,7 +4689,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4577
4689
|
});
|
|
4578
4690
|
console.log(`[Payments] Direct token sent successfully`);
|
|
4579
4691
|
this.log(`Token ${token.id} transferred, txHash: ${result.txHash}`);
|
|
4580
|
-
await this.removeToken(token.id, recipientNametag);
|
|
4692
|
+
await this.removeToken(token.id, recipientNametag, true);
|
|
4581
4693
|
}
|
|
4582
4694
|
result.status = "delivered";
|
|
4583
4695
|
await this.save();
|
|
@@ -4726,7 +4838,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
4726
4838
|
);
|
|
4727
4839
|
if (result.success) {
|
|
4728
4840
|
const recipientNametag = request.recipient.startsWith("@") ? request.recipient.slice(1) : void 0;
|
|
4729
|
-
await this.removeToken(tokenToSplit.id, recipientNametag);
|
|
4841
|
+
await this.removeToken(tokenToSplit.id, recipientNametag, true);
|
|
4730
4842
|
await this.addToHistory({
|
|
4731
4843
|
type: "SENT",
|
|
4732
4844
|
amount: request.amount,
|
|
@@ -5011,13 +5123,16 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5011
5123
|
if (this.paymentRequests.find((r) => r.id === transportRequest.id)) {
|
|
5012
5124
|
return;
|
|
5013
5125
|
}
|
|
5126
|
+
const coinId = transportRequest.request.coinId;
|
|
5127
|
+
const registry = TokenRegistry.getInstance();
|
|
5128
|
+
const coinDef = registry.getDefinition(coinId);
|
|
5014
5129
|
const request = {
|
|
5015
5130
|
id: transportRequest.id,
|
|
5016
5131
|
senderPubkey: transportRequest.senderTransportPubkey,
|
|
5132
|
+
senderNametag: transportRequest.senderNametag,
|
|
5017
5133
|
amount: transportRequest.request.amount,
|
|
5018
|
-
coinId
|
|
5019
|
-
symbol:
|
|
5020
|
-
// Use coinId as symbol for now
|
|
5134
|
+
coinId,
|
|
5135
|
+
symbol: coinDef?.symbol || coinId.slice(0, 8),
|
|
5021
5136
|
message: transportRequest.request.message,
|
|
5022
5137
|
recipientNametag: transportRequest.request.recipientNametag,
|
|
5023
5138
|
requestId: transportRequest.request.requestId,
|
|
@@ -5232,35 +5347,39 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5232
5347
|
const rawAssets = Array.from(assetsMap.values());
|
|
5233
5348
|
let priceMap = null;
|
|
5234
5349
|
if (this.priceProvider && rawAssets.length > 0) {
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
const
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
existing
|
|
5243
|
-
|
|
5244
|
-
|
|
5350
|
+
try {
|
|
5351
|
+
const registry = TokenRegistry.getInstance();
|
|
5352
|
+
const nameToCoins = /* @__PURE__ */ new Map();
|
|
5353
|
+
for (const asset of rawAssets) {
|
|
5354
|
+
const def = registry.getDefinition(asset.coinId);
|
|
5355
|
+
if (def?.name) {
|
|
5356
|
+
const existing = nameToCoins.get(def.name);
|
|
5357
|
+
if (existing) {
|
|
5358
|
+
existing.push(asset.coinId);
|
|
5359
|
+
} else {
|
|
5360
|
+
nameToCoins.set(def.name, [asset.coinId]);
|
|
5361
|
+
}
|
|
5245
5362
|
}
|
|
5246
5363
|
}
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
}
|
|
5364
|
+
if (nameToCoins.size > 0) {
|
|
5365
|
+
const tokenNames = Array.from(nameToCoins.keys());
|
|
5366
|
+
const prices = await this.priceProvider.getPrices(tokenNames);
|
|
5367
|
+
priceMap = /* @__PURE__ */ new Map();
|
|
5368
|
+
for (const [name, coinIds] of nameToCoins) {
|
|
5369
|
+
const price = prices.get(name);
|
|
5370
|
+
if (price) {
|
|
5371
|
+
for (const cid of coinIds) {
|
|
5372
|
+
priceMap.set(cid, {
|
|
5373
|
+
priceUsd: price.priceUsd,
|
|
5374
|
+
priceEur: price.priceEur,
|
|
5375
|
+
change24h: price.change24h
|
|
5376
|
+
});
|
|
5377
|
+
}
|
|
5261
5378
|
}
|
|
5262
5379
|
}
|
|
5263
5380
|
}
|
|
5381
|
+
} catch (error) {
|
|
5382
|
+
console.warn("[Payments] Failed to fetch prices, returning assets without price data:", error);
|
|
5264
5383
|
}
|
|
5265
5384
|
}
|
|
5266
5385
|
return rawAssets.map((raw) => {
|
|
@@ -5463,6 +5582,12 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5463
5582
|
updatedAt: Date.now(),
|
|
5464
5583
|
sdkData: typeof tokenJson === "string" ? tokenJson : JSON.stringify(tokenJson)
|
|
5465
5584
|
};
|
|
5585
|
+
const loadedTokenId = extractTokenIdFromSdkData(token.sdkData);
|
|
5586
|
+
const loadedStateHash = extractStateHashFromSdkData(token.sdkData);
|
|
5587
|
+
if (loadedTokenId && loadedStateHash && this.isStateTombstoned(loadedTokenId, loadedStateHash)) {
|
|
5588
|
+
this.log(`Skipping tombstoned token file ${tokenId} (${loadedTokenId.slice(0, 8)}...)`);
|
|
5589
|
+
continue;
|
|
5590
|
+
}
|
|
5466
5591
|
this.tokens.set(token.id, token);
|
|
5467
5592
|
this.log(`Loaded token from file: ${tokenId}`);
|
|
5468
5593
|
} catch (tokenError) {
|
|
@@ -5520,6 +5645,7 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5520
5645
|
this.log(`Warning: Could not create tombstone for token ${tokenId.slice(0, 8)}... (missing tokenId or stateHash)`);
|
|
5521
5646
|
}
|
|
5522
5647
|
this.tokens.delete(tokenId);
|
|
5648
|
+
await this.deleteTokenFiles(token);
|
|
5523
5649
|
if (!skipHistory && token.coinId && token.amount) {
|
|
5524
5650
|
await this.addToHistory({
|
|
5525
5651
|
type: "SENT",
|
|
@@ -5532,6 +5658,31 @@ var PaymentsModule = class _PaymentsModule {
|
|
|
5532
5658
|
}
|
|
5533
5659
|
await this.save();
|
|
5534
5660
|
}
|
|
5661
|
+
/**
|
|
5662
|
+
* Delete physical token file(s) from all storage providers.
|
|
5663
|
+
* Finds files by matching the SDK token ID prefix in the filename.
|
|
5664
|
+
*/
|
|
5665
|
+
async deleteTokenFiles(token) {
|
|
5666
|
+
const sdkTokenId = extractTokenIdFromSdkData(token.sdkData);
|
|
5667
|
+
if (!sdkTokenId) return;
|
|
5668
|
+
const tokenIdPrefix = sdkTokenId.slice(0, 16);
|
|
5669
|
+
const providers = this.getTokenStorageProviders();
|
|
5670
|
+
for (const [providerId, provider] of providers) {
|
|
5671
|
+
if (!provider.listTokenIds || !provider.deleteToken) continue;
|
|
5672
|
+
try {
|
|
5673
|
+
const allIds = await provider.listTokenIds();
|
|
5674
|
+
const matchingFiles = allIds.filter(
|
|
5675
|
+
(id) => id.startsWith(`token-${tokenIdPrefix}`)
|
|
5676
|
+
);
|
|
5677
|
+
for (const fileId of matchingFiles) {
|
|
5678
|
+
await provider.deleteToken(fileId);
|
|
5679
|
+
this.log(`Deleted token file ${fileId} from ${providerId}`);
|
|
5680
|
+
}
|
|
5681
|
+
} catch (error) {
|
|
5682
|
+
console.warn(`[Payments] Failed to delete token files from ${providerId}:`, error);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5535
5686
|
// ===========================================================================
|
|
5536
5687
|
// Public API - Tombstones
|
|
5537
5688
|
// ===========================================================================
|
|
@@ -6977,6 +7128,95 @@ function decryptSimple(ciphertext, password) {
|
|
|
6977
7128
|
}
|
|
6978
7129
|
return result;
|
|
6979
7130
|
}
|
|
7131
|
+
function decryptWithSalt(ciphertext, password, salt) {
|
|
7132
|
+
try {
|
|
7133
|
+
const key = import_crypto_js6.default.PBKDF2(password, salt, {
|
|
7134
|
+
keySize: 256 / 32,
|
|
7135
|
+
iterations: 1e5,
|
|
7136
|
+
hasher: import_crypto_js6.default.algo.SHA256
|
|
7137
|
+
}).toString();
|
|
7138
|
+
const decrypted = import_crypto_js6.default.AES.decrypt(ciphertext, key);
|
|
7139
|
+
const result = decrypted.toString(import_crypto_js6.default.enc.Utf8);
|
|
7140
|
+
return result || null;
|
|
7141
|
+
} catch {
|
|
7142
|
+
return null;
|
|
7143
|
+
}
|
|
7144
|
+
}
|
|
7145
|
+
|
|
7146
|
+
// core/scan.ts
|
|
7147
|
+
async function scanAddressesImpl(deriveAddress, options = {}) {
|
|
7148
|
+
const maxAddresses = options.maxAddresses ?? 50;
|
|
7149
|
+
const gapLimit = options.gapLimit ?? 20;
|
|
7150
|
+
const includeChange = options.includeChange ?? true;
|
|
7151
|
+
const { onProgress, signal, resolveNametag } = options;
|
|
7152
|
+
const { connect: connect2, getBalance: getBalance2 } = await Promise.resolve().then(() => (init_network(), network_exports));
|
|
7153
|
+
await connect2();
|
|
7154
|
+
const foundAddresses = [];
|
|
7155
|
+
let totalBalance = 0;
|
|
7156
|
+
let totalScanned = 0;
|
|
7157
|
+
let nametagsFoundCount = 0;
|
|
7158
|
+
const chains = includeChange ? [false, true] : [false];
|
|
7159
|
+
const totalToScan = maxAddresses * chains.length;
|
|
7160
|
+
for (const isChange of chains) {
|
|
7161
|
+
let consecutiveEmpty = 0;
|
|
7162
|
+
for (let index = 0; index < maxAddresses; index++) {
|
|
7163
|
+
if (signal?.aborted) break;
|
|
7164
|
+
const addrInfo = deriveAddress(index, isChange);
|
|
7165
|
+
totalScanned++;
|
|
7166
|
+
onProgress?.({
|
|
7167
|
+
scanned: totalScanned,
|
|
7168
|
+
total: totalToScan,
|
|
7169
|
+
currentAddress: addrInfo.address,
|
|
7170
|
+
foundCount: foundAddresses.length,
|
|
7171
|
+
currentGap: consecutiveEmpty,
|
|
7172
|
+
nametagsFoundCount
|
|
7173
|
+
});
|
|
7174
|
+
try {
|
|
7175
|
+
const balance = await getBalance2(addrInfo.address);
|
|
7176
|
+
if (balance > 0) {
|
|
7177
|
+
let nametag;
|
|
7178
|
+
if (resolveNametag) {
|
|
7179
|
+
try {
|
|
7180
|
+
const tag = await resolveNametag(addrInfo.address);
|
|
7181
|
+
if (tag) {
|
|
7182
|
+
nametag = tag;
|
|
7183
|
+
nametagsFoundCount++;
|
|
7184
|
+
}
|
|
7185
|
+
} catch {
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
foundAddresses.push({
|
|
7189
|
+
index,
|
|
7190
|
+
address: addrInfo.address,
|
|
7191
|
+
path: addrInfo.path,
|
|
7192
|
+
balance,
|
|
7193
|
+
isChange,
|
|
7194
|
+
nametag
|
|
7195
|
+
});
|
|
7196
|
+
totalBalance += balance;
|
|
7197
|
+
consecutiveEmpty = 0;
|
|
7198
|
+
} else {
|
|
7199
|
+
consecutiveEmpty++;
|
|
7200
|
+
}
|
|
7201
|
+
} catch (err) {
|
|
7202
|
+
console.warn(`[scanAddresses] Error checking ${addrInfo.address}:`, err);
|
|
7203
|
+
consecutiveEmpty++;
|
|
7204
|
+
}
|
|
7205
|
+
if (consecutiveEmpty >= gapLimit) {
|
|
7206
|
+
break;
|
|
7207
|
+
}
|
|
7208
|
+
if (totalScanned % 5 === 0) {
|
|
7209
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
if (signal?.aborted) break;
|
|
7213
|
+
}
|
|
7214
|
+
return {
|
|
7215
|
+
addresses: foundAddresses,
|
|
7216
|
+
totalBalance,
|
|
7217
|
+
scannedCount: totalScanned
|
|
7218
|
+
};
|
|
7219
|
+
}
|
|
6980
7220
|
|
|
6981
7221
|
// serialization/wallet-text.ts
|
|
6982
7222
|
var import_crypto_js7 = __toESM(require("crypto-js"), 1);
|
|
@@ -7234,10 +7474,11 @@ function parseWalletText(content) {
|
|
|
7234
7474
|
);
|
|
7235
7475
|
const descriptorPath = extractFromText(content, /DESCRIPTOR PATH:\s*([^\n]+)/);
|
|
7236
7476
|
const isBIP32 = content.includes("WALLET TYPE: BIP32 hierarchical deterministic wallet") || content.includes("WALLET TYPE: Alpha descriptor wallet") || !!chainCode;
|
|
7477
|
+
const effectiveDescriptorPath = descriptorPath ?? (isBIP32 ? "84'/1'/0'" : void 0);
|
|
7237
7478
|
const data = {
|
|
7238
7479
|
masterKey,
|
|
7239
7480
|
chainCode: chainCode ?? void 0,
|
|
7240
|
-
descriptorPath:
|
|
7481
|
+
descriptorPath: effectiveDescriptorPath,
|
|
7241
7482
|
derivationMode: isBIP32 ? "bip32" : "wif_hmac"
|
|
7242
7483
|
};
|
|
7243
7484
|
return {
|
|
@@ -7280,10 +7521,11 @@ function parseAndDecryptWalletText(content, password) {
|
|
|
7280
7521
|
);
|
|
7281
7522
|
const descriptorPath = extractFromText(content, /DESCRIPTOR PATH:\s*([^\n]+)/);
|
|
7282
7523
|
const isBIP32 = content.includes("WALLET TYPE: BIP32 hierarchical deterministic wallet") || content.includes("WALLET TYPE: Alpha descriptor wallet") || !!chainCode;
|
|
7524
|
+
const effectiveDescriptorPath = descriptorPath ?? (isBIP32 ? "84'/1'/0'" : void 0);
|
|
7283
7525
|
const data = {
|
|
7284
7526
|
masterKey,
|
|
7285
7527
|
chainCode: chainCode ?? void 0,
|
|
7286
|
-
descriptorPath:
|
|
7528
|
+
descriptorPath: effectiveDescriptorPath,
|
|
7287
7529
|
derivationMode: isBIP32 ? "bip32" : "wif_hmac"
|
|
7288
7530
|
};
|
|
7289
7531
|
return {
|
|
@@ -7824,8 +8066,8 @@ var Sphere = class _Sphere {
|
|
|
7824
8066
|
if (options.nametag) {
|
|
7825
8067
|
await sphere.registerNametag(options.nametag);
|
|
7826
8068
|
} else {
|
|
7827
|
-
await sphere.syncIdentityWithTransport();
|
|
7828
8069
|
await sphere.recoverNametagFromTransport();
|
|
8070
|
+
await sphere.syncIdentityWithTransport();
|
|
7829
8071
|
}
|
|
7830
8072
|
return sphere;
|
|
7831
8073
|
}
|
|
@@ -7872,7 +8114,15 @@ var Sphere = class _Sphere {
|
|
|
7872
8114
|
if (!options.mnemonic && !options.masterKey) {
|
|
7873
8115
|
throw new Error("Either mnemonic or masterKey is required");
|
|
7874
8116
|
}
|
|
8117
|
+
console.log("[Sphere.import] Starting import...");
|
|
8118
|
+
console.log("[Sphere.import] Clearing existing wallet data...");
|
|
7875
8119
|
await _Sphere.clear({ storage: options.storage, tokenStorage: options.tokenStorage });
|
|
8120
|
+
console.log("[Sphere.import] Clear done");
|
|
8121
|
+
if (!options.storage.isConnected()) {
|
|
8122
|
+
console.log("[Sphere.import] Reconnecting storage...");
|
|
8123
|
+
await options.storage.connect();
|
|
8124
|
+
console.log("[Sphere.import] Storage reconnected");
|
|
8125
|
+
}
|
|
7876
8126
|
const sphere = new _Sphere(
|
|
7877
8127
|
options.storage,
|
|
7878
8128
|
options.transport,
|
|
@@ -7885,9 +8135,12 @@ var Sphere = class _Sphere {
|
|
|
7885
8135
|
if (!_Sphere.validateMnemonic(options.mnemonic)) {
|
|
7886
8136
|
throw new Error("Invalid mnemonic");
|
|
7887
8137
|
}
|
|
8138
|
+
console.log("[Sphere.import] Storing mnemonic...");
|
|
7888
8139
|
await sphere.storeMnemonic(options.mnemonic, options.derivationPath, options.basePath);
|
|
8140
|
+
console.log("[Sphere.import] Initializing identity from mnemonic...");
|
|
7889
8141
|
await sphere.initializeIdentityFromMnemonic(options.mnemonic, options.derivationPath);
|
|
7890
8142
|
} else if (options.masterKey) {
|
|
8143
|
+
console.log("[Sphere.import] Storing master key...");
|
|
7891
8144
|
await sphere.storeMasterKey(
|
|
7892
8145
|
options.masterKey,
|
|
7893
8146
|
options.chainCode,
|
|
@@ -7895,24 +8148,35 @@ var Sphere = class _Sphere {
|
|
|
7895
8148
|
options.basePath,
|
|
7896
8149
|
options.derivationMode
|
|
7897
8150
|
);
|
|
8151
|
+
console.log("[Sphere.import] Initializing identity from master key...");
|
|
7898
8152
|
await sphere.initializeIdentityFromMasterKey(
|
|
7899
8153
|
options.masterKey,
|
|
7900
8154
|
options.chainCode,
|
|
7901
8155
|
options.derivationPath
|
|
7902
8156
|
);
|
|
7903
8157
|
}
|
|
8158
|
+
console.log("[Sphere.import] Initializing providers...");
|
|
7904
8159
|
await sphere.initializeProviders();
|
|
8160
|
+
console.log("[Sphere.import] Providers initialized. Initializing modules...");
|
|
7905
8161
|
await sphere.initializeModules();
|
|
8162
|
+
console.log("[Sphere.import] Modules initialized");
|
|
7906
8163
|
if (!options.nametag) {
|
|
8164
|
+
console.log("[Sphere.import] Recovering nametag from transport...");
|
|
7907
8165
|
await sphere.recoverNametagFromTransport();
|
|
8166
|
+
console.log("[Sphere.import] Nametag recovery done");
|
|
8167
|
+
await sphere.syncIdentityWithTransport();
|
|
7908
8168
|
}
|
|
8169
|
+
console.log("[Sphere.import] Finalizing wallet creation...");
|
|
7909
8170
|
await sphere.finalizeWalletCreation();
|
|
7910
8171
|
sphere._initialized = true;
|
|
7911
8172
|
_Sphere.instance = sphere;
|
|
8173
|
+
console.log("[Sphere.import] Tracking address 0...");
|
|
7912
8174
|
await sphere.ensureAddressTracked(0);
|
|
7913
8175
|
if (options.nametag) {
|
|
8176
|
+
console.log("[Sphere.import] Registering nametag...");
|
|
7914
8177
|
await sphere.registerNametag(options.nametag);
|
|
7915
8178
|
}
|
|
8179
|
+
console.log("[Sphere.import] Import complete");
|
|
7916
8180
|
return sphere;
|
|
7917
8181
|
}
|
|
7918
8182
|
/**
|
|
@@ -7937,6 +8201,10 @@ var Sphere = class _Sphere {
|
|
|
7937
8201
|
static async clear(storageOrOptions) {
|
|
7938
8202
|
const storage = "get" in storageOrOptions ? storageOrOptions : storageOrOptions.storage;
|
|
7939
8203
|
const tokenStorage = "get" in storageOrOptions ? void 0 : storageOrOptions.tokenStorage;
|
|
8204
|
+
if (!storage.isConnected()) {
|
|
8205
|
+
await storage.connect();
|
|
8206
|
+
}
|
|
8207
|
+
console.log("[Sphere.clear] Removing storage keys...");
|
|
7940
8208
|
await storage.remove(STORAGE_KEYS_GLOBAL.MNEMONIC);
|
|
7941
8209
|
await storage.remove(STORAGE_KEYS_GLOBAL.MASTER_KEY);
|
|
7942
8210
|
await storage.remove(STORAGE_KEYS_GLOBAL.CHAIN_CODE);
|
|
@@ -7949,11 +8217,30 @@ var Sphere = class _Sphere {
|
|
|
7949
8217
|
await storage.remove(STORAGE_KEYS_GLOBAL.ADDRESS_NAMETAGS);
|
|
7950
8218
|
await storage.remove(STORAGE_KEYS_ADDRESS.PENDING_TRANSFERS);
|
|
7951
8219
|
await storage.remove(STORAGE_KEYS_ADDRESS.OUTBOX);
|
|
8220
|
+
console.log("[Sphere.clear] Storage keys removed");
|
|
7952
8221
|
if (tokenStorage?.clear) {
|
|
7953
|
-
|
|
8222
|
+
console.log("[Sphere.clear] Clearing token storage...");
|
|
8223
|
+
try {
|
|
8224
|
+
await Promise.race([
|
|
8225
|
+
tokenStorage.clear(),
|
|
8226
|
+
new Promise(
|
|
8227
|
+
(_, reject) => setTimeout(() => reject(new Error("tokenStorage.clear() timed out after 2s")), 2e3)
|
|
8228
|
+
)
|
|
8229
|
+
]);
|
|
8230
|
+
console.log("[Sphere.clear] Token storage cleared");
|
|
8231
|
+
} catch (err) {
|
|
8232
|
+
console.warn("[Sphere.clear] Token storage clear failed/timed out:", err);
|
|
8233
|
+
}
|
|
7954
8234
|
}
|
|
8235
|
+
console.log("[Sphere.clear] Destroying vesting classifier...");
|
|
8236
|
+
await vestingClassifier.destroy();
|
|
8237
|
+
console.log("[Sphere.clear] Vesting classifier destroyed");
|
|
7955
8238
|
if (_Sphere.instance) {
|
|
8239
|
+
console.log("[Sphere.clear] Destroying Sphere instance...");
|
|
7956
8240
|
await _Sphere.instance.destroy();
|
|
8241
|
+
console.log("[Sphere.clear] Sphere instance destroyed");
|
|
8242
|
+
} else {
|
|
8243
|
+
console.log("[Sphere.clear] No Sphere instance to destroy");
|
|
7957
8244
|
}
|
|
7958
8245
|
}
|
|
7959
8246
|
/**
|
|
@@ -8134,7 +8421,7 @@ var Sphere = class _Sphere {
|
|
|
8134
8421
|
return {
|
|
8135
8422
|
source: this._source,
|
|
8136
8423
|
hasMnemonic: this._mnemonic !== null,
|
|
8137
|
-
hasChainCode: this._masterKey?.chainCode
|
|
8424
|
+
hasChainCode: !!this._masterKey?.chainCode,
|
|
8138
8425
|
derivationMode: this._derivationMode,
|
|
8139
8426
|
basePath: this._basePath,
|
|
8140
8427
|
address0
|
|
@@ -8187,7 +8474,7 @@ var Sphere = class _Sphere {
|
|
|
8187
8474
|
let chainCode;
|
|
8188
8475
|
if (this._masterKey) {
|
|
8189
8476
|
masterPrivateKey = this._masterKey.privateKey;
|
|
8190
|
-
chainCode = this._masterKey.chainCode;
|
|
8477
|
+
chainCode = this._masterKey.chainCode || void 0;
|
|
8191
8478
|
}
|
|
8192
8479
|
let mnemonic;
|
|
8193
8480
|
let encrypted = false;
|
|
@@ -8264,7 +8551,7 @@ var Sphere = class _Sphere {
|
|
|
8264
8551
|
}
|
|
8265
8552
|
}
|
|
8266
8553
|
const masterPrivateKey = this._masterKey?.privateKey || "";
|
|
8267
|
-
const chainCode = this._masterKey?.chainCode;
|
|
8554
|
+
const chainCode = this._masterKey?.chainCode || void 0;
|
|
8268
8555
|
const isBIP32 = this._derivationMode === "bip32";
|
|
8269
8556
|
const descriptorPath = this._basePath.replace(/^m\//, "");
|
|
8270
8557
|
if (options.password) {
|
|
@@ -8334,7 +8621,8 @@ var Sphere = class _Sphere {
|
|
|
8334
8621
|
storage: options.storage,
|
|
8335
8622
|
transport: options.transport,
|
|
8336
8623
|
oracle: options.oracle,
|
|
8337
|
-
tokenStorage: options.tokenStorage
|
|
8624
|
+
tokenStorage: options.tokenStorage,
|
|
8625
|
+
l1: options.l1
|
|
8338
8626
|
});
|
|
8339
8627
|
return { success: true, mnemonic };
|
|
8340
8628
|
}
|
|
@@ -8347,7 +8635,8 @@ var Sphere = class _Sphere {
|
|
|
8347
8635
|
storage: options.storage,
|
|
8348
8636
|
transport: options.transport,
|
|
8349
8637
|
oracle: options.oracle,
|
|
8350
|
-
tokenStorage: options.tokenStorage
|
|
8638
|
+
tokenStorage: options.tokenStorage,
|
|
8639
|
+
l1: options.l1
|
|
8351
8640
|
});
|
|
8352
8641
|
return { success: true };
|
|
8353
8642
|
}
|
|
@@ -8406,7 +8695,8 @@ var Sphere = class _Sphere {
|
|
|
8406
8695
|
transport: options.transport,
|
|
8407
8696
|
oracle: options.oracle,
|
|
8408
8697
|
tokenStorage: options.tokenStorage,
|
|
8409
|
-
nametag: options.nametag
|
|
8698
|
+
nametag: options.nametag,
|
|
8699
|
+
l1: options.l1
|
|
8410
8700
|
});
|
|
8411
8701
|
return { success: true, sphere, mnemonic };
|
|
8412
8702
|
}
|
|
@@ -8435,7 +8725,8 @@ var Sphere = class _Sphere {
|
|
|
8435
8725
|
transport: options.transport,
|
|
8436
8726
|
oracle: options.oracle,
|
|
8437
8727
|
tokenStorage: options.tokenStorage,
|
|
8438
|
-
nametag: options.nametag
|
|
8728
|
+
nametag: options.nametag,
|
|
8729
|
+
l1: options.l1
|
|
8439
8730
|
});
|
|
8440
8731
|
return { success: true, sphere };
|
|
8441
8732
|
}
|
|
@@ -8466,25 +8757,94 @@ var Sphere = class _Sphere {
|
|
|
8466
8757
|
transport: options.transport,
|
|
8467
8758
|
oracle: options.oracle,
|
|
8468
8759
|
tokenStorage: options.tokenStorage,
|
|
8469
|
-
nametag: options.nametag
|
|
8760
|
+
nametag: options.nametag,
|
|
8761
|
+
l1: options.l1
|
|
8470
8762
|
});
|
|
8471
8763
|
return { success: true, sphere };
|
|
8472
8764
|
}
|
|
8473
8765
|
if (fileType === "json") {
|
|
8474
8766
|
const content = typeof fileContent === "string" ? fileContent : new TextDecoder().decode(fileContent);
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8767
|
+
let parsed;
|
|
8768
|
+
try {
|
|
8769
|
+
parsed = JSON.parse(content);
|
|
8770
|
+
} catch {
|
|
8771
|
+
return { success: false, error: "Invalid JSON file" };
|
|
8772
|
+
}
|
|
8773
|
+
if (parsed.type === "sphere-wallet") {
|
|
8774
|
+
const result = await _Sphere.importFromJSON({
|
|
8775
|
+
jsonContent: content,
|
|
8776
|
+
password,
|
|
8777
|
+
storage: options.storage,
|
|
8778
|
+
transport: options.transport,
|
|
8779
|
+
oracle: options.oracle,
|
|
8780
|
+
tokenStorage: options.tokenStorage,
|
|
8781
|
+
l1: options.l1
|
|
8782
|
+
});
|
|
8783
|
+
if (result.success) {
|
|
8784
|
+
const sphere2 = _Sphere.getInstance();
|
|
8785
|
+
return { success: true, sphere: sphere2, mnemonic: result.mnemonic };
|
|
8786
|
+
}
|
|
8787
|
+
if (!password && result.error?.includes("Password required")) {
|
|
8788
|
+
return { success: false, needsPassword: true, error: result.error };
|
|
8789
|
+
}
|
|
8790
|
+
return { success: false, error: result.error };
|
|
8791
|
+
}
|
|
8792
|
+
let masterKey;
|
|
8793
|
+
let mnemonic;
|
|
8794
|
+
if (parsed.encrypted && typeof parsed.encrypted === "object") {
|
|
8795
|
+
if (!password) {
|
|
8796
|
+
return { success: false, needsPassword: true, error: "Password required for encrypted wallet" };
|
|
8797
|
+
}
|
|
8798
|
+
const enc = parsed.encrypted;
|
|
8799
|
+
if (!enc.salt || !enc.masterPrivateKey) {
|
|
8800
|
+
return { success: false, error: "Invalid encrypted wallet format" };
|
|
8801
|
+
}
|
|
8802
|
+
const decryptedKey = decryptWithSalt(enc.masterPrivateKey, password, enc.salt);
|
|
8803
|
+
if (!decryptedKey) {
|
|
8804
|
+
return { success: false, error: "Failed to decrypt - incorrect password?" };
|
|
8805
|
+
}
|
|
8806
|
+
masterKey = decryptedKey;
|
|
8807
|
+
if (enc.mnemonic) {
|
|
8808
|
+
mnemonic = decryptWithSalt(enc.mnemonic, password, enc.salt) ?? void 0;
|
|
8809
|
+
}
|
|
8810
|
+
} else {
|
|
8811
|
+
masterKey = parsed.masterPrivateKey;
|
|
8812
|
+
mnemonic = parsed.mnemonic;
|
|
8813
|
+
}
|
|
8814
|
+
if (!masterKey) {
|
|
8815
|
+
return { success: false, error: "No master key found in wallet JSON" };
|
|
8816
|
+
}
|
|
8817
|
+
const chainCode = parsed.chainCode;
|
|
8818
|
+
const descriptorPath = parsed.descriptorPath;
|
|
8819
|
+
const derivationMode = parsed.derivationMode;
|
|
8820
|
+
const isBIP32 = derivationMode === "bip32" || !!chainCode;
|
|
8821
|
+
const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
|
|
8822
|
+
if (mnemonic) {
|
|
8823
|
+
const sphere2 = await _Sphere.import({
|
|
8824
|
+
mnemonic,
|
|
8825
|
+
basePath,
|
|
8826
|
+
storage: options.storage,
|
|
8827
|
+
transport: options.transport,
|
|
8828
|
+
oracle: options.oracle,
|
|
8829
|
+
tokenStorage: options.tokenStorage,
|
|
8830
|
+
nametag: options.nametag,
|
|
8831
|
+
l1: options.l1
|
|
8832
|
+
});
|
|
8833
|
+
return { success: true, sphere: sphere2, mnemonic };
|
|
8834
|
+
}
|
|
8835
|
+
const sphere = await _Sphere.import({
|
|
8836
|
+
masterKey,
|
|
8837
|
+
chainCode,
|
|
8838
|
+
basePath,
|
|
8839
|
+
derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
|
|
8478
8840
|
storage: options.storage,
|
|
8479
8841
|
transport: options.transport,
|
|
8480
8842
|
oracle: options.oracle,
|
|
8481
|
-
tokenStorage: options.tokenStorage
|
|
8843
|
+
tokenStorage: options.tokenStorage,
|
|
8844
|
+
nametag: options.nametag,
|
|
8845
|
+
l1: options.l1
|
|
8482
8846
|
});
|
|
8483
|
-
|
|
8484
|
-
const sphere = _Sphere.getInstance();
|
|
8485
|
-
return { success: true, sphere, mnemonic: result.mnemonic };
|
|
8486
|
-
}
|
|
8487
|
-
return result;
|
|
8847
|
+
return { success: true, sphere };
|
|
8488
8848
|
}
|
|
8489
8849
|
return { success: false, error: "Unsupported file type" };
|
|
8490
8850
|
}
|
|
@@ -8782,7 +9142,7 @@ var Sphere = class _Sphere {
|
|
|
8782
9142
|
transport: this._transport,
|
|
8783
9143
|
oracle: this._oracle,
|
|
8784
9144
|
emitEvent,
|
|
8785
|
-
chainCode: this._masterKey?.chainCode,
|
|
9145
|
+
chainCode: this._masterKey?.chainCode || void 0,
|
|
8786
9146
|
price: this._priceProvider ?? void 0
|
|
8787
9147
|
});
|
|
8788
9148
|
this._communications.initialize({
|
|
@@ -8827,6 +9187,9 @@ var Sphere = class _Sphere {
|
|
|
8827
9187
|
if (!this._masterKey) {
|
|
8828
9188
|
throw new Error("HD derivation requires master key with chain code");
|
|
8829
9189
|
}
|
|
9190
|
+
if (this._derivationMode === "wif_hmac") {
|
|
9191
|
+
return generateAddressFromMasterKey(this._masterKey.privateKey, index);
|
|
9192
|
+
}
|
|
8830
9193
|
const info = deriveAddressInfo(
|
|
8831
9194
|
this._masterKey,
|
|
8832
9195
|
this._basePath,
|
|
@@ -8898,6 +9261,66 @@ var Sphere = class _Sphere {
|
|
|
8898
9261
|
}
|
|
8899
9262
|
return addresses;
|
|
8900
9263
|
}
|
|
9264
|
+
/**
|
|
9265
|
+
* Scan blockchain addresses to discover used addresses with balances.
|
|
9266
|
+
* Derives addresses sequentially and checks L1 balance via Fulcrum.
|
|
9267
|
+
* Uses gap limit to stop after N consecutive empty addresses.
|
|
9268
|
+
*
|
|
9269
|
+
* @param options - Scanning options
|
|
9270
|
+
* @returns Scan results with found addresses and total balance
|
|
9271
|
+
*
|
|
9272
|
+
* @example
|
|
9273
|
+
* ```ts
|
|
9274
|
+
* const result = await sphere.scanAddresses({
|
|
9275
|
+
* maxAddresses: 100,
|
|
9276
|
+
* gapLimit: 20,
|
|
9277
|
+
* onProgress: (p) => console.log(`Scanned ${p.scanned}/${p.total}, found ${p.foundCount}`),
|
|
9278
|
+
* });
|
|
9279
|
+
* console.log(`Found ${result.addresses.length} addresses, total: ${result.totalBalance} ALPHA`);
|
|
9280
|
+
* ```
|
|
9281
|
+
*/
|
|
9282
|
+
async scanAddresses(options = {}) {
|
|
9283
|
+
this.ensureReady();
|
|
9284
|
+
if (!this._masterKey) {
|
|
9285
|
+
throw new Error("Address scanning requires HD master key");
|
|
9286
|
+
}
|
|
9287
|
+
const resolveNametag = options.resolveNametag ?? (this._transport.resolveAddressInfo ? async (l1Address) => {
|
|
9288
|
+
try {
|
|
9289
|
+
const info = await this._transport.resolveAddressInfo(l1Address);
|
|
9290
|
+
return info?.nametag ?? null;
|
|
9291
|
+
} catch {
|
|
9292
|
+
return null;
|
|
9293
|
+
}
|
|
9294
|
+
} : void 0);
|
|
9295
|
+
return scanAddressesImpl(
|
|
9296
|
+
(index, isChange) => this._deriveAddressInternal(index, isChange),
|
|
9297
|
+
{ ...options, resolveNametag }
|
|
9298
|
+
);
|
|
9299
|
+
}
|
|
9300
|
+
/**
|
|
9301
|
+
* Bulk-track scanned addresses with visibility and nametag data.
|
|
9302
|
+
* Selected addresses get `hidden: false`, unselected get `hidden: true`.
|
|
9303
|
+
* Performs only 2 storage writes total (tracked addresses + nametags).
|
|
9304
|
+
*/
|
|
9305
|
+
async trackScannedAddresses(entries) {
|
|
9306
|
+
this.ensureReady();
|
|
9307
|
+
for (const { index, hidden, nametag } of entries) {
|
|
9308
|
+
const tracked = await this.ensureAddressTracked(index);
|
|
9309
|
+
if (nametag) {
|
|
9310
|
+
let nametags = this._addressNametags.get(tracked.addressId);
|
|
9311
|
+
if (!nametags) {
|
|
9312
|
+
nametags = /* @__PURE__ */ new Map();
|
|
9313
|
+
this._addressNametags.set(tracked.addressId, nametags);
|
|
9314
|
+
}
|
|
9315
|
+
if (!nametags.has(0)) nametags.set(0, nametag);
|
|
9316
|
+
}
|
|
9317
|
+
if (tracked.hidden !== hidden) {
|
|
9318
|
+
tracked.hidden = hidden;
|
|
9319
|
+
}
|
|
9320
|
+
}
|
|
9321
|
+
await this.persistTrackedAddresses();
|
|
9322
|
+
await this.persistAddressNametags();
|
|
9323
|
+
}
|
|
8901
9324
|
// ===========================================================================
|
|
8902
9325
|
// Public Methods - Status
|
|
8903
9326
|
// ===========================================================================
|
|
@@ -9282,35 +9705,40 @@ var Sphere = class _Sphere {
|
|
|
9282
9705
|
if (this._identity?.nametag) {
|
|
9283
9706
|
return;
|
|
9284
9707
|
}
|
|
9285
|
-
|
|
9708
|
+
let recoveredNametag = null;
|
|
9709
|
+
if (this._transport.recoverNametag) {
|
|
9710
|
+
try {
|
|
9711
|
+
recoveredNametag = await this._transport.recoverNametag();
|
|
9712
|
+
} catch {
|
|
9713
|
+
}
|
|
9714
|
+
}
|
|
9715
|
+
if (!recoveredNametag && this._transport.resolveAddressInfo && this._identity?.l1Address) {
|
|
9716
|
+
try {
|
|
9717
|
+
const info = await this._transport.resolveAddressInfo(this._identity.l1Address);
|
|
9718
|
+
if (info?.nametag) {
|
|
9719
|
+
recoveredNametag = info.nametag;
|
|
9720
|
+
}
|
|
9721
|
+
} catch {
|
|
9722
|
+
}
|
|
9723
|
+
}
|
|
9724
|
+
if (!recoveredNametag) {
|
|
9286
9725
|
return;
|
|
9287
9726
|
}
|
|
9288
9727
|
try {
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
this._identity.nametag = recoveredNametag;
|
|
9293
|
-
await this._updateCachedProxyAddress();
|
|
9294
|
-
}
|
|
9295
|
-
const entry = await this.ensureAddressTracked(this._currentAddressIndex);
|
|
9296
|
-
let nametags = this._addressNametags.get(entry.addressId);
|
|
9297
|
-
if (!nametags) {
|
|
9298
|
-
nametags = /* @__PURE__ */ new Map();
|
|
9299
|
-
this._addressNametags.set(entry.addressId, nametags);
|
|
9300
|
-
}
|
|
9301
|
-
const nextIndex = nametags.size;
|
|
9302
|
-
nametags.set(nextIndex, recoveredNametag);
|
|
9303
|
-
await this.persistAddressNametags();
|
|
9304
|
-
if (this._transport.publishIdentityBinding) {
|
|
9305
|
-
await this._transport.publishIdentityBinding(
|
|
9306
|
-
this._identity.chainPubkey,
|
|
9307
|
-
this._identity.l1Address,
|
|
9308
|
-
this._identity.directAddress || "",
|
|
9309
|
-
recoveredNametag
|
|
9310
|
-
);
|
|
9311
|
-
}
|
|
9312
|
-
this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
|
|
9728
|
+
if (this._identity) {
|
|
9729
|
+
this._identity.nametag = recoveredNametag;
|
|
9730
|
+
await this._updateCachedProxyAddress();
|
|
9313
9731
|
}
|
|
9732
|
+
const entry = await this.ensureAddressTracked(this._currentAddressIndex);
|
|
9733
|
+
let nametags = this._addressNametags.get(entry.addressId);
|
|
9734
|
+
if (!nametags) {
|
|
9735
|
+
nametags = /* @__PURE__ */ new Map();
|
|
9736
|
+
this._addressNametags.set(entry.addressId, nametags);
|
|
9737
|
+
}
|
|
9738
|
+
const nextIndex = nametags.size;
|
|
9739
|
+
nametags.set(nextIndex, recoveredNametag);
|
|
9740
|
+
await this.persistAddressNametags();
|
|
9741
|
+
this.emitEvent("nametag:recovered", { nametag: recoveredNametag });
|
|
9314
9742
|
} catch {
|
|
9315
9743
|
}
|
|
9316
9744
|
}
|
|
@@ -9479,8 +9907,8 @@ var Sphere = class _Sphere {
|
|
|
9479
9907
|
};
|
|
9480
9908
|
this._masterKey = masterKey;
|
|
9481
9909
|
}
|
|
9482
|
-
async initializeIdentityFromMasterKey(masterKey, chainCode,
|
|
9483
|
-
const basePath =
|
|
9910
|
+
async initializeIdentityFromMasterKey(masterKey, chainCode, _derivationPath) {
|
|
9911
|
+
const basePath = this._basePath;
|
|
9484
9912
|
const fullPath = `${basePath}/0/0`;
|
|
9485
9913
|
let privateKey;
|
|
9486
9914
|
if (chainCode) {
|
|
@@ -9491,8 +9919,12 @@ var Sphere = class _Sphere {
|
|
|
9491
9919
|
chainCode
|
|
9492
9920
|
};
|
|
9493
9921
|
} else {
|
|
9494
|
-
|
|
9495
|
-
|
|
9922
|
+
const addr0 = generateAddressFromMasterKey(masterKey, 0);
|
|
9923
|
+
privateKey = addr0.privateKey;
|
|
9924
|
+
this._masterKey = {
|
|
9925
|
+
privateKey: masterKey,
|
|
9926
|
+
chainCode: ""
|
|
9927
|
+
};
|
|
9496
9928
|
}
|
|
9497
9929
|
const publicKey = getPublicKey(privateKey);
|
|
9498
9930
|
const address = publicKeyToAddress(publicKey, "alpha");
|
|
@@ -9515,8 +9947,12 @@ var Sphere = class _Sphere {
|
|
|
9515
9947
|
for (const provider of this._tokenStorageProviders.values()) {
|
|
9516
9948
|
provider.setIdentity(this._identity);
|
|
9517
9949
|
}
|
|
9518
|
-
|
|
9519
|
-
|
|
9950
|
+
if (!this._storage.isConnected()) {
|
|
9951
|
+
await this._storage.connect();
|
|
9952
|
+
}
|
|
9953
|
+
if (!this._transport.isConnected()) {
|
|
9954
|
+
await this._transport.connect();
|
|
9955
|
+
}
|
|
9520
9956
|
await this._oracle.initialize();
|
|
9521
9957
|
for (const provider of this._tokenStorageProviders.values()) {
|
|
9522
9958
|
await provider.initialize();
|
|
@@ -9532,7 +9968,7 @@ var Sphere = class _Sphere {
|
|
|
9532
9968
|
oracle: this._oracle,
|
|
9533
9969
|
emitEvent,
|
|
9534
9970
|
// Pass chain code for L1 HD derivation
|
|
9535
|
-
chainCode: this._masterKey?.chainCode,
|
|
9971
|
+
chainCode: this._masterKey?.chainCode || void 0,
|
|
9536
9972
|
price: this._priceProvider ?? void 0
|
|
9537
9973
|
});
|
|
9538
9974
|
this._communications.initialize({
|
|
@@ -9615,6 +10051,9 @@ function formatAmount(amount, options = {}) {
|
|
|
9615
10051
|
return symbol ? `${readable} ${symbol}` : readable;
|
|
9616
10052
|
}
|
|
9617
10053
|
|
|
10054
|
+
// core/index.ts
|
|
10055
|
+
init_bech32();
|
|
10056
|
+
|
|
9618
10057
|
// types/payment-session.ts
|
|
9619
10058
|
function createPaymentSession(params) {
|
|
9620
10059
|
const now = Date.now();
|