@qntx/wallet-worker 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.mts +0 -4
- package/dist/browser.mjs +2 -4
- package/dist/browser.mjs.map +1 -1
- package/dist/kernel.manifest.json +12 -12
- package/dist/kernel.node.js +1213 -1501
- package/dist/kernel.worker.js +1167 -1455
- package/dist/node.d.mts +0 -4
- package/dist/node.mjs +6 -12
- package/dist/node.mjs.map +1 -1
- package/package.json +6 -6
package/dist/kernel.worker.js
CHANGED
|
@@ -94,14 +94,11 @@ var __chunks = (base, ids, nodes, entry) => {
|
|
|
94
94
|
__chunkSeen ||= {};
|
|
95
95
|
__preload(ids[entry], 1);
|
|
96
96
|
};
|
|
97
|
-
__chunks(import.meta.url,["
|
|
97
|
+
__chunks(import.meta.url,["y76qxfny","gs57sjgx","1vpxmqwn","366p4fej","gsare3mw"],[["./kernel.worker.js",3],["./signer-gs57sjgx.js",3,4],["./browser-1vpxmqwn.js",4],["./worker-366p4fej.js"],["./worker-gsare3mw.js"]],0);
|
|
98
98
|
// ../../node_modules/.bun/@qntx+nostr@0.15.3+ea9f70ecde856c26/node_modules/@qntx/nostr/dist/util-BcRBO6o-.mjs
|
|
99
99
|
var NostrError = class extends Error {
|
|
100
100
|
name = "NostrError";
|
|
101
101
|
};
|
|
102
|
-
function errorMessage(error) {
|
|
103
|
-
return error instanceof Error ? error.message : String(error);
|
|
104
|
-
}
|
|
105
102
|
var HexError = class extends NostrError {
|
|
106
103
|
name = "HexError";
|
|
107
104
|
};
|
|
@@ -1856,7 +1853,7 @@ class KernelError extends Error {
|
|
|
1856
1853
|
this.corrupted = corrupted;
|
|
1857
1854
|
}
|
|
1858
1855
|
}
|
|
1859
|
-
// ../wallet/dist/core-
|
|
1856
|
+
// ../wallet/dist/core-Cq5h9X0X.mjs
|
|
1860
1857
|
var ValidationError = class extends Error {
|
|
1861
1858
|
name = "ValidationError";
|
|
1862
1859
|
};
|
|
@@ -1997,6 +1994,7 @@ var publicKey = str(64, /^[0-9a-f]{64}$/);
|
|
|
1997
1994
|
var credentialId = str(1364, /^[A-Za-z0-9_-]+$/);
|
|
1998
1995
|
var safeTime = int(0, Number.MAX_SAFE_INTEGER);
|
|
1999
1996
|
var groupIndex = int(0, 2147483647);
|
|
1997
|
+
var identityIndex = int(0, 2147483646);
|
|
2000
1998
|
var factor = union(obj({ kind: literal("hardware") }), obj({
|
|
2001
1999
|
kind: literal("password"),
|
|
2002
2000
|
password: bytes(1, 1024)
|
|
@@ -2223,7 +2221,7 @@ var CORE_METHODS = {
|
|
|
2223
2221
|
}
|
|
2224
2222
|
};
|
|
2225
2223
|
|
|
2226
|
-
// ../wallet/dist/protocol-
|
|
2224
|
+
// ../wallet/dist/protocol-DbpLncEB.mjs
|
|
2227
2225
|
var MAX_FACTOR_CHARS = 512;
|
|
2228
2226
|
var MAX_STRING_BYTES = 64000;
|
|
2229
2227
|
var MAX_PAYLOAD_CHARS = 1400000;
|
|
@@ -2245,15 +2243,11 @@ var backupEnvelope = obj({
|
|
|
2245
2243
|
factors: arr(backupEnvelopeFactor, 5, 1),
|
|
2246
2244
|
payload: str(MAX_PAYLOAD_CHARS)
|
|
2247
2245
|
});
|
|
2248
|
-
var backupHeader = obj({
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
}), 1000),
|
|
2254
|
-
importedNostrKeyCount: int(0, 1e4),
|
|
2255
|
-
importedChainKeyCount: int(0, 1e4)
|
|
2256
|
-
});
|
|
2246
|
+
var backupHeader = obj({ wallets: arr(obj({
|
|
2247
|
+
walletId: str(128),
|
|
2248
|
+
origin: union(literal("mnemonic"), literal("passkey")),
|
|
2249
|
+
words: union(literal(12), literal(15), literal(18), literal(21), literal(24))
|
|
2250
|
+
}), 1000) });
|
|
2257
2251
|
var backupEnvelopeText = str(MAX_ENVELOPE_CHARS);
|
|
2258
2252
|
var backupInfo = obj({
|
|
2259
2253
|
id: str(32, /^[0-9a-f]{32}$/),
|
|
@@ -2402,36 +2396,19 @@ var CHAINS_METHODS = {
|
|
|
2402
2396
|
}
|
|
2403
2397
|
};
|
|
2404
2398
|
var hex128 = str(128, /^[0-9a-f]{128}$/);
|
|
2405
|
-
var nostrKeyRef =
|
|
2399
|
+
var nostrKeyRef = obj({
|
|
2406
2400
|
kind: literal("derived"),
|
|
2407
2401
|
walletId,
|
|
2408
|
-
|
|
2409
|
-
})
|
|
2410
|
-
|
|
2411
|
-
id: publicKey
|
|
2412
|
-
}), obj({
|
|
2413
|
-
kind: literal("nip46-client"),
|
|
2414
|
-
id: publicKey
|
|
2415
|
-
}));
|
|
2416
|
-
var nostrKeyInfo = union(obj({
|
|
2417
|
-
ref: nostrKeyRef,
|
|
2418
|
-
publicKey,
|
|
2419
|
-
origin: union(literal("nsec"), literal("ncryptsec"), literal("generated")),
|
|
2420
|
-
backedUp: bool,
|
|
2421
|
-
createdAt: safeTime
|
|
2422
|
-
}), obj({
|
|
2402
|
+
index: identityIndex
|
|
2403
|
+
});
|
|
2404
|
+
var nostrKeyInfo = obj({
|
|
2423
2405
|
ref: nostrKeyRef,
|
|
2424
2406
|
publicKey,
|
|
2425
|
-
origin: union(literal("derived"), literal("nip46-client")),
|
|
2426
2407
|
createdAt: safeTime
|
|
2427
|
-
}));
|
|
2428
|
-
var nostrStatus = obj({ keys: arr(nostrKeyInfo, MAX_SNAPSHOT_ITEMS) });
|
|
2429
|
-
var keyResult = obj({
|
|
2430
|
-
key: nostrKeyInfo,
|
|
2431
|
-
session: sessionId
|
|
2432
2408
|
});
|
|
2409
|
+
var nostrStatus = obj({ keys: arr(nostrKeyInfo, MAX_SNAPSHOT_ITEMS) });
|
|
2433
2410
|
var derivedNostrKey = obj({
|
|
2434
|
-
|
|
2411
|
+
index: identityIndex,
|
|
2435
2412
|
publicKey
|
|
2436
2413
|
});
|
|
2437
2414
|
var tags = arr(arr(str(MAX_TAG_ITEM), 64), MAX_TAGS);
|
|
@@ -2459,14 +2436,6 @@ var rumor = obj({
|
|
|
2459
2436
|
tags,
|
|
2460
2437
|
content: str(MAX_TEXT)
|
|
2461
2438
|
});
|
|
2462
|
-
var nostrImportInput = union(obj({
|
|
2463
|
-
kind: literal("nsec"),
|
|
2464
|
-
nsec: bytes(1, 256)
|
|
2465
|
-
}), obj({
|
|
2466
|
-
kind: literal("ncryptsec"),
|
|
2467
|
-
ncryptsec: str(512, /^ncryptsec1/),
|
|
2468
|
-
password: bytes(1, 1024)
|
|
2469
|
-
}));
|
|
2470
2439
|
var nostrExportFormat = union(obj({ kind: literal("nsec") }), obj({
|
|
2471
2440
|
kind: literal("ncryptsec"),
|
|
2472
2441
|
password: bytes(1, 1024)
|
|
@@ -2483,7 +2452,7 @@ var NOSTR_METHODS = {
|
|
|
2483
2452
|
presence: false,
|
|
2484
2453
|
params: obj({
|
|
2485
2454
|
walletId,
|
|
2486
|
-
from:
|
|
2455
|
+
from: identityIndex,
|
|
2487
2456
|
count: int(1, 20)
|
|
2488
2457
|
}),
|
|
2489
2458
|
result: obj({ keys: arr(derivedNostrKey, 20) })
|
|
@@ -2493,38 +2462,14 @@ var NOSTR_METHODS = {
|
|
|
2493
2462
|
presence: false,
|
|
2494
2463
|
params: obj({
|
|
2495
2464
|
walletId,
|
|
2496
|
-
|
|
2497
|
-
}),
|
|
2498
|
-
result: nostrKeyInfo
|
|
2499
|
-
},
|
|
2500
|
-
"nostr.importKey": {
|
|
2501
|
-
session: false,
|
|
2502
|
-
presence: true,
|
|
2503
|
-
params: obj({
|
|
2504
|
-
input: nostrImportInput,
|
|
2505
|
-
factor: opt(factor)
|
|
2465
|
+
index: identityIndex
|
|
2506
2466
|
}),
|
|
2507
|
-
result: keyResult
|
|
2508
|
-
},
|
|
2509
|
-
"nostr.generateKey": {
|
|
2510
|
-
session: false,
|
|
2511
|
-
presence: true,
|
|
2512
|
-
params: obj({ factor: opt(factor) }),
|
|
2513
|
-
result: keyResult
|
|
2514
|
-
},
|
|
2515
|
-
"nostr.createNip46ClientKey": {
|
|
2516
|
-
session: true,
|
|
2517
|
-
presence: false,
|
|
2518
|
-
params: nullValue,
|
|
2519
2467
|
result: nostrKeyInfo
|
|
2520
2468
|
},
|
|
2521
2469
|
"nostr.removeKey": {
|
|
2522
2470
|
session: true,
|
|
2523
2471
|
presence: true,
|
|
2524
|
-
params: obj({
|
|
2525
|
-
publicKey,
|
|
2526
|
-
verify: opt(factor)
|
|
2527
|
-
}),
|
|
2472
|
+
params: obj({ publicKey }),
|
|
2528
2473
|
result: nullValue
|
|
2529
2474
|
},
|
|
2530
2475
|
"nostr.exportKey": {
|
|
@@ -2578,6 +2523,39 @@ var NOSTR_METHODS = {
|
|
|
2578
2523
|
events: arr(signedEvent, 64)
|
|
2579
2524
|
}),
|
|
2580
2525
|
result: obj({ results: arr(union(obj({ ok: rumor }), obj({ err: walletErrorCode })), 64) })
|
|
2526
|
+
},
|
|
2527
|
+
"nostr.syncKey": {
|
|
2528
|
+
session: true,
|
|
2529
|
+
presence: false,
|
|
2530
|
+
params: obj({ walletId }),
|
|
2531
|
+
result: obj({ publicKey })
|
|
2532
|
+
},
|
|
2533
|
+
"nostr.syncSign": {
|
|
2534
|
+
session: true,
|
|
2535
|
+
presence: false,
|
|
2536
|
+
params: obj({
|
|
2537
|
+
walletId,
|
|
2538
|
+
event: signEventInput
|
|
2539
|
+
}),
|
|
2540
|
+
result: signedEvent
|
|
2541
|
+
},
|
|
2542
|
+
"nostr.syncEncrypt": {
|
|
2543
|
+
session: true,
|
|
2544
|
+
presence: false,
|
|
2545
|
+
params: obj({
|
|
2546
|
+
walletId,
|
|
2547
|
+
text: str(MAX_TEXT)
|
|
2548
|
+
}),
|
|
2549
|
+
result: textResult
|
|
2550
|
+
},
|
|
2551
|
+
"nostr.syncDecrypt": {
|
|
2552
|
+
session: true,
|
|
2553
|
+
presence: false,
|
|
2554
|
+
params: obj({
|
|
2555
|
+
walletId,
|
|
2556
|
+
text: str(MAX_TEXT * 4)
|
|
2557
|
+
}),
|
|
2558
|
+
result: textResult
|
|
2581
2559
|
}
|
|
2582
2560
|
};
|
|
2583
2561
|
var MAX_LEAVES = 256;
|
|
@@ -2763,6 +2741,27 @@ var decimalU128 = (value) => {
|
|
|
2763
2741
|
throw new ValidationError;
|
|
2764
2742
|
return value;
|
|
2765
2743
|
};
|
|
2744
|
+
var outflowIntents = [
|
|
2745
|
+
obj({
|
|
2746
|
+
kind: literal("exit"),
|
|
2747
|
+
address: str(128),
|
|
2748
|
+
amountSats: satsAmount(),
|
|
2749
|
+
maxFeeSats: satsAmount()
|
|
2750
|
+
}),
|
|
2751
|
+
obj({
|
|
2752
|
+
kind: literal("onchain"),
|
|
2753
|
+
address: str(128),
|
|
2754
|
+
maxFeeSats: satsAmount()
|
|
2755
|
+
}),
|
|
2756
|
+
obj({
|
|
2757
|
+
kind: literal("token"),
|
|
2758
|
+
tokenIdentifier: bytes(32),
|
|
2759
|
+
receivers: arr(obj({
|
|
2760
|
+
ownerPublicKey: bytes(33),
|
|
2761
|
+
amount: decimalU128
|
|
2762
|
+
}), 256, 1)
|
|
2763
|
+
})
|
|
2764
|
+
];
|
|
2766
2765
|
var approveIntent = union(obj({
|
|
2767
2766
|
kind: literal("transfer"),
|
|
2768
2767
|
receivers: arr(obj({
|
|
@@ -2774,23 +2773,7 @@ var approveIntent = union(obj({
|
|
|
2774
2773
|
invoice: str(4096),
|
|
2775
2774
|
amountSats: opt(satsAmount()),
|
|
2776
2775
|
maxFeeSats: satsAmount()
|
|
2777
|
-
}),
|
|
2778
|
-
kind: literal("exit"),
|
|
2779
|
-
address: str(128),
|
|
2780
|
-
amountSats: satsAmount(),
|
|
2781
|
-
maxFeeSats: satsAmount()
|
|
2782
|
-
}), obj({
|
|
2783
|
-
kind: literal("onchain"),
|
|
2784
|
-
address: str(128),
|
|
2785
|
-
maxFeeSats: satsAmount()
|
|
2786
|
-
}), obj({
|
|
2787
|
-
kind: literal("token"),
|
|
2788
|
-
tokenIdentifier: bytes(32),
|
|
2789
|
-
receivers: arr(obj({
|
|
2790
|
-
ownerPublicKey: bytes(33),
|
|
2791
|
-
amount: decimalU128
|
|
2792
|
-
}), 256, 1)
|
|
2793
|
-
}));
|
|
2776
|
+
}), ...outflowIntents);
|
|
2794
2777
|
var approvalSummary = union(obj({
|
|
2795
2778
|
kind: literal("transfer"),
|
|
2796
2779
|
receivers: arr(obj({
|
|
@@ -2802,23 +2785,7 @@ var approvalSummary = union(obj({
|
|
|
2802
2785
|
paymentHash: bytes(32),
|
|
2803
2786
|
invoiceAmountSats: opt(satsAmount()),
|
|
2804
2787
|
maxFeeSats: satsAmount()
|
|
2805
|
-
}),
|
|
2806
|
-
kind: literal("exit"),
|
|
2807
|
-
address: str(128),
|
|
2808
|
-
amountSats: satsAmount(),
|
|
2809
|
-
maxFeeSats: satsAmount()
|
|
2810
|
-
}), obj({
|
|
2811
|
-
kind: literal("onchain"),
|
|
2812
|
-
address: str(128),
|
|
2813
|
-
maxFeeSats: satsAmount()
|
|
2814
|
-
}), obj({
|
|
2815
|
-
kind: literal("token"),
|
|
2816
|
-
tokenIdentifier: bytes(32),
|
|
2817
|
-
receivers: arr(obj({
|
|
2818
|
-
ownerPublicKey: bytes(33),
|
|
2819
|
-
amount: decimalU128
|
|
2820
|
-
}), 256, 1)
|
|
2821
|
-
}));
|
|
2788
|
+
}), ...outflowIntents);
|
|
2822
2789
|
var SPARK_METHODS = {
|
|
2823
2790
|
"spark.identityPublicKey": {
|
|
2824
2791
|
session: true,
|
|
@@ -2943,7 +2910,7 @@ var SPARK_METHODS = {
|
|
|
2943
2910
|
result: approvalSummary
|
|
2944
2911
|
}
|
|
2945
2912
|
};
|
|
2946
|
-
var PROTOCOL_VERSION =
|
|
2913
|
+
var PROTOCOL_VERSION = 2;
|
|
2947
2914
|
var UNATTRIBUTED_ID = 0;
|
|
2948
2915
|
var MAX_REQUEST_BYTES = 1048576;
|
|
2949
2916
|
function requestBytes(value) {
|
|
@@ -2993,7 +2960,7 @@ function isProtocolValue(value) {
|
|
|
2993
2960
|
return Object.values(value).every(isProtocolValue);
|
|
2994
2961
|
}
|
|
2995
2962
|
var statusPayload = obj({
|
|
2996
|
-
protocol: literal(
|
|
2963
|
+
protocol: literal(2),
|
|
2997
2964
|
vault: union(literal("uninitialized"), literal("locked"), literal("unlocked"), literal("corrupted"), literal("unsupported"), literal("unavailable")),
|
|
2998
2965
|
factors: arr(factorInfo, MAX_SNAPSHOT_ITEMS),
|
|
2999
2966
|
wallets: arr(walletInfo, MAX_SNAPSHOT_ITEMS),
|
|
@@ -3018,11 +2985,11 @@ var errorPayload = obj({
|
|
|
3018
2985
|
retryAt: opt(safeTime)
|
|
3019
2986
|
});
|
|
3020
2987
|
var kernelEvent = union(obj({
|
|
3021
|
-
v: literal(
|
|
2988
|
+
v: literal(2),
|
|
3022
2989
|
event: literal("status"),
|
|
3023
2990
|
status: statusPayload
|
|
3024
2991
|
}), obj({
|
|
3025
|
-
v: literal(
|
|
2992
|
+
v: literal(2),
|
|
3026
2993
|
event: literal("locked"),
|
|
3027
2994
|
reason: lockReason
|
|
3028
2995
|
}));
|
|
@@ -3956,14 +3923,8 @@ function asPublicKey(value) {
|
|
|
3956
3923
|
}
|
|
3957
3924
|
return value;
|
|
3958
3925
|
}
|
|
3959
|
-
function
|
|
3960
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value >
|
|
3961
|
-
throw headerFailure();
|
|
3962
|
-
}
|
|
3963
|
-
return value;
|
|
3964
|
-
}
|
|
3965
|
-
function asBoolean(value) {
|
|
3966
|
-
if (typeof value !== "boolean") {
|
|
3926
|
+
function asIdentityIndex(value) {
|
|
3927
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > 2147483646) {
|
|
3967
3928
|
throw headerFailure();
|
|
3968
3929
|
}
|
|
3969
3930
|
return value;
|
|
@@ -4277,7 +4238,7 @@ var RECORD_KIND_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
|
|
|
4277
4238
|
function isRecordKind(kind) {
|
|
4278
4239
|
return RECORD_KIND_PATTERN.test(kind);
|
|
4279
4240
|
}
|
|
4280
|
-
var VAULT_FORMAT =
|
|
4241
|
+
var VAULT_FORMAT = 3;
|
|
4281
4242
|
|
|
4282
4243
|
// ../wallet-kernel/src/vault/vault.ts
|
|
4283
4244
|
var BACKOFF_MS = [30000, 60000, 300000];
|
|
@@ -6904,6 +6865,14 @@ async function seedFromMnemonic(mnemonic, passphrase, pbkdf2) {
|
|
|
6904
6865
|
async function seedFromEntropy(entropy, pbkdf2) {
|
|
6905
6866
|
return seedFromMnemonic(mnemonicFromEntropy(entropy), "", pbkdf2);
|
|
6906
6867
|
}
|
|
6868
|
+
async function withSeed(pbkdf2, entropy, use) {
|
|
6869
|
+
const seed = await seedFromEntropy(entropy, pbkdf2);
|
|
6870
|
+
try {
|
|
6871
|
+
return await use(seed);
|
|
6872
|
+
} finally {
|
|
6873
|
+
wipe(seed);
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6907
6876
|
|
|
6908
6877
|
// ../wallet-kernel/src/session/session.ts
|
|
6909
6878
|
function wipePendingFactor(pending) {
|
|
@@ -7077,6 +7046,14 @@ class Session {
|
|
|
7077
7046
|
}
|
|
7078
7047
|
|
|
7079
7048
|
// ../wallet-kernel/src/commands/vault.ts
|
|
7049
|
+
async function withWalletSeed(pbkdf2, dek, record, use) {
|
|
7050
|
+
const entropy = openRecord(dek, record);
|
|
7051
|
+
try {
|
|
7052
|
+
return await withSeed(pbkdf2, entropy, use);
|
|
7053
|
+
} finally {
|
|
7054
|
+
wipe(entropy);
|
|
7055
|
+
}
|
|
7056
|
+
}
|
|
7080
7057
|
var EMPTY_IMAGE = { meta: undefined, records: [], factors: [] };
|
|
7081
7058
|
async function unlockVault(ctx, params) {
|
|
7082
7059
|
await ctx.reload();
|
|
@@ -7161,13 +7138,10 @@ async function removeFactor(ctx, params, requestSession) {
|
|
|
7161
7138
|
|
|
7162
7139
|
// ../wallet-kernel/src/commands/wallets.ts
|
|
7163
7140
|
async function deriveWalletMaterial(platform, entropy) {
|
|
7164
|
-
|
|
7165
|
-
try {
|
|
7141
|
+
return withSeed(platform.pbkdf2, entropy, (seed) => {
|
|
7166
7142
|
const master = masterKey(seed);
|
|
7167
7143
|
return { master, walletId: walletIdOf(master) };
|
|
7168
|
-
}
|
|
7169
|
-
wipe(seed);
|
|
7170
|
-
}
|
|
7144
|
+
});
|
|
7171
7145
|
}
|
|
7172
7146
|
async function walletMaterial(platform, entropy, origin, words) {
|
|
7173
7147
|
const { master, walletId } = await deriveWalletMaterial(platform, entropy);
|
|
@@ -7507,13 +7481,11 @@ function parseHeader(text) {
|
|
|
7507
7481
|
return header;
|
|
7508
7482
|
}
|
|
7509
7483
|
var PAYLOAD_WALLET = 1;
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
function encodePayload(wallets, nostrSecrets) {
|
|
7513
|
-
const size = 1 + wallets.reduce((acc, w) => acc + 3 + w.entropy.length, 0) + nostrSecrets.length * 33;
|
|
7484
|
+
function encodePayload(wallets) {
|
|
7485
|
+
const size = 1 + wallets.reduce((acc, w) => acc + 3 + w.entropy.length, 0);
|
|
7514
7486
|
const out = new Uint8Array(size);
|
|
7515
7487
|
let off = 0;
|
|
7516
|
-
out[off++] =
|
|
7488
|
+
out[off++] = 2;
|
|
7517
7489
|
for (const w of wallets) {
|
|
7518
7490
|
out[off++] = PAYLOAD_WALLET;
|
|
7519
7491
|
out[off++] = ORIGIN_BYTE[w.origin] ?? 0;
|
|
@@ -7521,19 +7493,13 @@ function encodePayload(wallets, nostrSecrets) {
|
|
|
7521
7493
|
out.set(w.entropy, off);
|
|
7522
7494
|
off += w.entropy.length;
|
|
7523
7495
|
}
|
|
7524
|
-
for (const s of nostrSecrets) {
|
|
7525
|
-
out[off++] = PAYLOAD_NOSTR;
|
|
7526
|
-
out.set(s, off);
|
|
7527
|
-
off += s.length;
|
|
7528
|
-
}
|
|
7529
7496
|
return out;
|
|
7530
7497
|
}
|
|
7531
7498
|
function decodePayload2(bytes) {
|
|
7532
|
-
if (bytes.length === 0 || bytes[0] !==
|
|
7499
|
+
if (bytes.length === 0 || bytes[0] !== 2) {
|
|
7533
7500
|
throw new KernelError("integrity", "backup: bad payload version");
|
|
7534
7501
|
}
|
|
7535
7502
|
const wallets = [];
|
|
7536
|
-
const nostrSecrets = [];
|
|
7537
7503
|
let off = 1;
|
|
7538
7504
|
while (off < bytes.length) {
|
|
7539
7505
|
const tag = bytes[off++];
|
|
@@ -7553,17 +7519,6 @@ function decodePayload2(bytes) {
|
|
|
7553
7519
|
}
|
|
7554
7520
|
wallets.push({ origin, entropy: bytes.slice(off, off + len) });
|
|
7555
7521
|
off += len;
|
|
7556
|
-
} else if (tag === PAYLOAD_NOSTR) {
|
|
7557
|
-
if (off + 32 > bytes.length) {
|
|
7558
|
-
throw new KernelError("integrity", "backup: truncated payload");
|
|
7559
|
-
}
|
|
7560
|
-
nostrSecrets.push(bytes.slice(off, off + 32));
|
|
7561
|
-
off += 32;
|
|
7562
|
-
} else if (tag === PAYLOAD_CHAIN) {
|
|
7563
|
-
if (off + 33 > bytes.length) {
|
|
7564
|
-
throw new KernelError("integrity", "backup: truncated payload");
|
|
7565
|
-
}
|
|
7566
|
-
off += 33;
|
|
7567
7522
|
} else {
|
|
7568
7523
|
throw new KernelError("integrity", "backup: unknown payload tag");
|
|
7569
7524
|
}
|
|
@@ -7571,7 +7526,7 @@ function decodePayload2(bytes) {
|
|
|
7571
7526
|
if (off !== bytes.length) {
|
|
7572
7527
|
throw new KernelError("integrity", "backup: payload length mismatch");
|
|
7573
7528
|
}
|
|
7574
|
-
return { wallets
|
|
7529
|
+
return { wallets };
|
|
7575
7530
|
}
|
|
7576
7531
|
function collectContents(ctx, dek) {
|
|
7577
7532
|
const wallets = [];
|
|
@@ -7594,13 +7549,10 @@ function collectContents(ctx, dek) {
|
|
|
7594
7549
|
throw error;
|
|
7595
7550
|
}
|
|
7596
7551
|
}
|
|
7597
|
-
const nostrSecrets = ctx.modules.flatMap((module) => module.backupSecrets(ctx.image, dek));
|
|
7598
7552
|
const header = JSON.stringify({
|
|
7599
|
-
wallets: wallets.map(({ walletId, origin, words }) => ({ walletId, origin, words }))
|
|
7600
|
-
importedNostrKeyCount: nostrSecrets.length,
|
|
7601
|
-
importedChainKeyCount: 0
|
|
7553
|
+
wallets: wallets.map(({ walletId, origin, words }) => ({ walletId, origin, words }))
|
|
7602
7554
|
});
|
|
7603
|
-
return { wallets,
|
|
7555
|
+
return { wallets, header };
|
|
7604
7556
|
} catch (error) {
|
|
7605
7557
|
for (const wallet of wallets) {
|
|
7606
7558
|
wallet.entropy.fill(0);
|
|
@@ -7612,9 +7564,6 @@ function wipeContents(contents) {
|
|
|
7612
7564
|
for (const wallet of contents.wallets) {
|
|
7613
7565
|
wallet.entropy.fill(0);
|
|
7614
7566
|
}
|
|
7615
|
-
for (const secretKey of contents.nostrSecrets) {
|
|
7616
|
-
secretKey.fill(0);
|
|
7617
|
-
}
|
|
7618
7567
|
}
|
|
7619
7568
|
var PURPOSE_PROTECTION = 2;
|
|
7620
7569
|
function backupMaterialOf(result) {
|
|
@@ -7737,7 +7686,7 @@ function updateBackup(ctx, _params, requestSession) {
|
|
|
7737
7686
|
const bek = openRecord(dek, record);
|
|
7738
7687
|
const contents = collectContents(ctx, dek);
|
|
7739
7688
|
try {
|
|
7740
|
-
const plaintext = encodePayload(contents.wallets
|
|
7689
|
+
const plaintext = encodePayload(contents.wallets);
|
|
7741
7690
|
const sealedPayload = seal(bek, plaintext, payloadContext(contents.header), "", ctx.platform.random);
|
|
7742
7691
|
try {
|
|
7743
7692
|
const envelope = {
|
|
@@ -7807,7 +7756,7 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7807
7756
|
}
|
|
7808
7757
|
const header = parseHeader(envelope.header);
|
|
7809
7758
|
const decoded = decodePayload2(plaintext);
|
|
7810
|
-
if (decoded.
|
|
7759
|
+
if (decoded.wallets.length !== header.wallets.length) {
|
|
7811
7760
|
plaintext.fill(0);
|
|
7812
7761
|
throw new KernelError("integrity", "backup: payload does not match header");
|
|
7813
7762
|
}
|
|
@@ -7839,9 +7788,6 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7839
7788
|
records.push(record);
|
|
7840
7789
|
restored.push(walletInfoOf(material, backup, now));
|
|
7841
7790
|
}
|
|
7842
|
-
for (const module of ctx.modules) {
|
|
7843
|
-
records.push(...module.backupRecords(ctx.platform, ctx.image, gated.dek, decoded.nostrSecrets, now));
|
|
7844
|
-
}
|
|
7845
7791
|
if (gated.uninitialized) {
|
|
7846
7792
|
records.push(backupKeyRecord(ctx, gated.dek, bek, envelope.factors));
|
|
7847
7793
|
}
|
|
@@ -7859,9 +7805,6 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7859
7805
|
for (const wallet of decoded.wallets) {
|
|
7860
7806
|
wallet.entropy.fill(0);
|
|
7861
7807
|
}
|
|
7862
|
-
for (const secretKey of decoded.nostrSecrets) {
|
|
7863
|
-
secretKey.fill(0);
|
|
7864
|
-
}
|
|
7865
7808
|
}
|
|
7866
7809
|
} finally {
|
|
7867
7810
|
bek.fill(0);
|
|
@@ -8061,7 +8004,30 @@ var ChainError = class extends Error {
|
|
|
8061
8004
|
}
|
|
8062
8005
|
};
|
|
8063
8006
|
|
|
8064
|
-
// ../wallet-chains/dist/
|
|
8007
|
+
// ../wallet-chains/dist/account-ref-C2qrDbVT.mjs
|
|
8008
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8009
|
+
var isAccountRef = (value) => {
|
|
8010
|
+
if (!isRecord2(value) || typeof value["kind"] !== "string")
|
|
8011
|
+
return false;
|
|
8012
|
+
if (value["kind"] === "hd")
|
|
8013
|
+
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
8014
|
+
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
8015
|
+
};
|
|
8016
|
+
var requestBase = (request) => {
|
|
8017
|
+
if (!isRecord2(request))
|
|
8018
|
+
throw new ChainError("invalid-request", "request must be an object");
|
|
8019
|
+
const { network, account } = request;
|
|
8020
|
+
if (typeof network !== "string")
|
|
8021
|
+
throw new ChainError("invalid-request", "request.network must be a string");
|
|
8022
|
+
if (!isAccountRef(account))
|
|
8023
|
+
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
8024
|
+
return {
|
|
8025
|
+
network,
|
|
8026
|
+
account
|
|
8027
|
+
};
|
|
8028
|
+
};
|
|
8029
|
+
|
|
8030
|
+
// ../wallet-chains/dist/message-DuJ5KSRT.mjs
|
|
8065
8031
|
var MAINNET_BIP32 = {
|
|
8066
8032
|
public: 76067358,
|
|
8067
8033
|
private: 76066276
|
|
@@ -8212,15 +8178,15 @@ var signLegacyMessage = (message, privateKey) => {
|
|
|
8212
8178
|
};
|
|
8213
8179
|
|
|
8214
8180
|
// ../wallet-chains/dist/bitcoin.mjs
|
|
8215
|
-
var isRecord$
|
|
8181
|
+
var isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8216
8182
|
var derivationPaths = (map) => {
|
|
8217
|
-
const entries = map instanceof Map ? [...map.values()] : Array.isArray(map) ? map : isRecord$
|
|
8183
|
+
const entries = map instanceof Map ? [...map.values()] : Array.isArray(map) ? map : isRecord$1(map) ? Object.values(map) : [];
|
|
8218
8184
|
const paths = [];
|
|
8219
8185
|
for (const entry of entries) {
|
|
8220
8186
|
const value = Array.isArray(entry) ? entry[1] : entry;
|
|
8221
|
-
if (!isRecord$
|
|
8187
|
+
if (!isRecord$1(value))
|
|
8222
8188
|
continue;
|
|
8223
|
-
const { path } = isRecord$
|
|
8189
|
+
const { path } = isRecord$1(value["der"]) ? value["der"] : value;
|
|
8224
8190
|
if (Array.isArray(path) && path.every((p) => typeof p === "number"))
|
|
8225
8191
|
paths.push(path);
|
|
8226
8192
|
}
|
|
@@ -8359,26 +8325,10 @@ var decodeBitcoinPsbt = (request, ownScripts = /* @__PURE__ */ new Set) => {
|
|
|
8359
8325
|
verifiability
|
|
8360
8326
|
};
|
|
8361
8327
|
};
|
|
8362
|
-
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8363
|
-
var isAccountRef = (value) => {
|
|
8364
|
-
if (!isRecord2(value) || typeof value["kind"] !== "string")
|
|
8365
|
-
return false;
|
|
8366
|
-
if (value["kind"] === "hd")
|
|
8367
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
8368
|
-
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
8369
|
-
};
|
|
8370
8328
|
var common = (request) => {
|
|
8371
|
-
const
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
8375
|
-
if (!isAccountRef(account))
|
|
8376
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
8377
|
-
bitcoinNetwork(network);
|
|
8378
|
-
return {
|
|
8379
|
-
network,
|
|
8380
|
-
account
|
|
8381
|
-
};
|
|
8329
|
+
const base = requestBase(request);
|
|
8330
|
+
bitcoinNetwork(base.network);
|
|
8331
|
+
return base;
|
|
8382
8332
|
};
|
|
8383
8333
|
var messageTarget = (address, network, format) => {
|
|
8384
8334
|
if (typeof address !== "string")
|
|
@@ -8448,26 +8398,6 @@ var normalizeBitcoin = (request) => {
|
|
|
8448
8398
|
};
|
|
8449
8399
|
var decodeMessageTarget = (request) => messageTarget(request.address, request.network, request.format);
|
|
8450
8400
|
|
|
8451
|
-
// ../wallet-chains/dist/bitcoin-sign.mjs
|
|
8452
|
-
var signBitcoinPsbt = (psbt, inputs, auxRand) => {
|
|
8453
|
-
const tx = Transaction.fromPSBT(psbt);
|
|
8454
|
-
for (const { index, privateKey } of inputs) {
|
|
8455
|
-
if (privateKey.length !== 32)
|
|
8456
|
-
throw new ChainError("invalid-request", `input ${index}: private key must be 32 bytes`);
|
|
8457
|
-
if (!tx.signIdx(privateKey, index, undefined, auxRand(index)))
|
|
8458
|
-
throw new ChainError("invalid-request", `input ${index}: key cannot sign`);
|
|
8459
|
-
}
|
|
8460
|
-
return tx.toPSBT(0);
|
|
8461
|
-
};
|
|
8462
|
-
var signBitcoinMessage = (request, privateKey, auxRand) => {
|
|
8463
|
-
if (privateKey.length !== 32)
|
|
8464
|
-
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
8465
|
-
if (request.format === "legacy")
|
|
8466
|
-
return signLegacyMessage(request.message, privateKey);
|
|
8467
|
-
const scriptPubKey = OutScript.encode(Address(bitcoinNetwork(request.network).params).decode(request.address));
|
|
8468
|
-
return signBip322Simple(request.message, scriptPubKey, privateKey, auxRand);
|
|
8469
|
-
};
|
|
8470
|
-
|
|
8471
8401
|
// ../../node_modules/.bun/@noble+hashes@2.4.0/node_modules/@noble/hashes/sha3.js
|
|
8472
8402
|
var _0n4 = BigInt(0);
|
|
8473
8403
|
var _1n4 = BigInt(1);
|
|
@@ -8691,15 +8621,15 @@ class Keccak {
|
|
|
8691
8621
|
var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);
|
|
8692
8622
|
var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32);
|
|
8693
8623
|
|
|
8694
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8624
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/version.js
|
|
8695
8625
|
var version = "0.1.1";
|
|
8696
8626
|
|
|
8697
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8627
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/errors.js
|
|
8698
8628
|
function getVersion() {
|
|
8699
8629
|
return version;
|
|
8700
8630
|
}
|
|
8701
8631
|
|
|
8702
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8632
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Errors.js
|
|
8703
8633
|
class BaseError extends Error {
|
|
8704
8634
|
details;
|
|
8705
8635
|
docs;
|
|
@@ -8779,7 +8709,7 @@ function walk(err, fn) {
|
|
|
8779
8709
|
return fn ? null : err;
|
|
8780
8710
|
}
|
|
8781
8711
|
|
|
8782
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8712
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/bytes.js
|
|
8783
8713
|
function assertSize(bytes, size_) {
|
|
8784
8714
|
if (size(bytes) > size_)
|
|
8785
8715
|
throw new SizeOverflowError({
|
|
@@ -8848,7 +8778,7 @@ function trim(value, options = {}) {
|
|
|
8848
8778
|
return start === 0 && end === value.length ? value : value.slice(start, end);
|
|
8849
8779
|
}
|
|
8850
8780
|
|
|
8851
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8781
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/hex.js
|
|
8852
8782
|
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, "0"));
|
|
8853
8783
|
var nibbleTable = /* @__PURE__ */ (() => {
|
|
8854
8784
|
const table = new Uint8Array(256).fill(255);
|
|
@@ -8936,7 +8866,7 @@ class InvalidLengthError extends BaseError {
|
|
|
8936
8866
|
}
|
|
8937
8867
|
}
|
|
8938
8868
|
|
|
8939
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8869
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/int.js
|
|
8940
8870
|
function bytesToBigInt(value, signed) {
|
|
8941
8871
|
const len = value.length;
|
|
8942
8872
|
if (len === 0)
|
|
@@ -8993,11 +8923,11 @@ class IntegerOutOfRangeError extends BaseError {
|
|
|
8993
8923
|
}
|
|
8994
8924
|
}
|
|
8995
8925
|
|
|
8996
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8926
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/utf8.js
|
|
8997
8927
|
var encoder = /* @__PURE__ */ new TextEncoder;
|
|
8998
8928
|
var decoder = /* @__PURE__ */ new TextDecoder;
|
|
8999
8929
|
|
|
9000
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8930
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Json.js
|
|
9001
8931
|
var bigIntSuffix = "#__bigint";
|
|
9002
8932
|
function stringify(value, replacer, space) {
|
|
9003
8933
|
return JSON.stringify(value, (key, value) => {
|
|
@@ -9009,9 +8939,9 @@ function stringify(value, replacer, space) {
|
|
|
9009
8939
|
}, space);
|
|
9010
8940
|
}
|
|
9011
8941
|
|
|
9012
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8942
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Hex.js
|
|
9013
8943
|
function assert(value, options = {}) {
|
|
9014
|
-
const { strict = false } = options;
|
|
8944
|
+
const { even = false, strict = false } = options;
|
|
9015
8945
|
if (typeof value !== "string")
|
|
9016
8946
|
throw new InvalidHexTypeError(value);
|
|
9017
8947
|
if (strict) {
|
|
@@ -9020,6 +8950,8 @@ function assert(value, options = {}) {
|
|
|
9020
8950
|
}
|
|
9021
8951
|
if (!value.startsWith("0x"))
|
|
9022
8952
|
throw new InvalidHexValueError2(value);
|
|
8953
|
+
if (even && value.length % 2 !== 0)
|
|
8954
|
+
throw new InvalidLengthError2(value);
|
|
9023
8955
|
}
|
|
9024
8956
|
function concat2(...values) {
|
|
9025
8957
|
if (values.length === 0)
|
|
@@ -9143,9 +9075,9 @@ function toBytes(hex, options = {}) {
|
|
|
9143
9075
|
return hexToBytes4(value);
|
|
9144
9076
|
}
|
|
9145
9077
|
function validate2(value, options = {}) {
|
|
9146
|
-
const { strict = false } = options;
|
|
9078
|
+
const { even = false, strict = false } = options;
|
|
9147
9079
|
try {
|
|
9148
|
-
assert(value, { strict });
|
|
9080
|
+
assert(value, { even, strict });
|
|
9149
9081
|
return true;
|
|
9150
9082
|
} catch {
|
|
9151
9083
|
return false;
|
|
@@ -9161,6 +9093,8 @@ class InvalidHexTypeError extends BaseError {
|
|
|
9161
9093
|
}
|
|
9162
9094
|
}
|
|
9163
9095
|
var InvalidHexValueError2 = InvalidHexValueError;
|
|
9096
|
+
var InvalidLengthError2 = InvalidLengthError;
|
|
9097
|
+
|
|
9164
9098
|
class SizeOverflowError2 extends BaseError {
|
|
9165
9099
|
name = "Hex.SizeOverflowError";
|
|
9166
9100
|
constructor({ givenSize, maxSize }) {
|
|
@@ -9182,7 +9116,7 @@ class SizeExceedsPaddingSizeError2 extends BaseError {
|
|
|
9182
9116
|
}
|
|
9183
9117
|
}
|
|
9184
9118
|
|
|
9185
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9119
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/hex.js
|
|
9186
9120
|
function assertSize2(hex, size_) {
|
|
9187
9121
|
const len = hex.length - 2;
|
|
9188
9122
|
const size = len + 1 >> 1;
|
|
@@ -9243,7 +9177,7 @@ function trim2(value, options = {}) {
|
|
|
9243
9177
|
return `0x${data.slice(start, end)}`;
|
|
9244
9178
|
}
|
|
9245
9179
|
|
|
9246
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9180
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Bytes.js
|
|
9247
9181
|
function from2(value) {
|
|
9248
9182
|
if (value instanceof Uint8Array)
|
|
9249
9183
|
return value;
|
|
@@ -9354,7 +9288,7 @@ class SizeExceedsPaddingSizeError extends BaseError {
|
|
|
9354
9288
|
}
|
|
9355
9289
|
}
|
|
9356
9290
|
|
|
9357
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9291
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/lru.js
|
|
9358
9292
|
class BoundedMap extends Map {
|
|
9359
9293
|
maxSize;
|
|
9360
9294
|
constructor(size) {
|
|
@@ -9371,20 +9305,20 @@ class BoundedMap extends Map {
|
|
|
9371
9305
|
}
|
|
9372
9306
|
}
|
|
9373
9307
|
|
|
9374
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9308
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Caches.js
|
|
9375
9309
|
var caches = {
|
|
9376
9310
|
checksum: /* @__PURE__ */ new BoundedMap(32768)
|
|
9377
9311
|
};
|
|
9378
9312
|
var checksum = caches.checksum;
|
|
9379
9313
|
|
|
9380
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9314
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/engine.js
|
|
9381
9315
|
var overrides = {};
|
|
9382
9316
|
|
|
9383
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9317
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/hash.js
|
|
9384
9318
|
var keccak256Default = (input) => keccak_256(input);
|
|
9385
9319
|
var keccak256 = (input) => (overrides.Hash?.keccak256 ?? keccak256Default)(input);
|
|
9386
9320
|
|
|
9387
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9321
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Hash.js
|
|
9388
9322
|
function keccak2562(value, options = {}) {
|
|
9389
9323
|
const isBytes = value instanceof Uint8Array;
|
|
9390
9324
|
const { as = isBytes ? "Bytes" : "Hex" } = options;
|
|
@@ -9394,7 +9328,7 @@ function keccak2562(value, options = {}) {
|
|
|
9394
9328
|
return fromBytes(bytes);
|
|
9395
9329
|
}
|
|
9396
9330
|
|
|
9397
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9331
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/address.js
|
|
9398
9332
|
var length = 42;
|
|
9399
9333
|
var ZERO2 = 48;
|
|
9400
9334
|
var NINE = 57;
|
|
@@ -9447,7 +9381,7 @@ function lowercase(value) {
|
|
|
9447
9381
|
return String.fromCharCode.apply(null, out);
|
|
9448
9382
|
}
|
|
9449
9383
|
|
|
9450
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9384
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Address.js
|
|
9451
9385
|
function assert2(value, options = {}) {
|
|
9452
9386
|
const { strict = true } = options;
|
|
9453
9387
|
const kind = classify(value);
|
|
@@ -9527,7 +9461,7 @@ class InvalidChecksumError extends BaseError {
|
|
|
9527
9461
|
}
|
|
9528
9462
|
}
|
|
9529
9463
|
|
|
9530
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9464
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/regex.js
|
|
9531
9465
|
function execTyped(regex, string) {
|
|
9532
9466
|
const match = regex.exec(string);
|
|
9533
9467
|
return match?.groups;
|
|
@@ -9536,7 +9470,7 @@ var bytesRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
|
9536
9470
|
var integerRegex = /^u?int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/;
|
|
9537
9471
|
var isTupleRegex = /^\(.+?\).*?$/;
|
|
9538
9472
|
|
|
9539
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9473
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/formatAbiParameter.js
|
|
9540
9474
|
var tupleRegex = /^tuple(?<array>(\[(\d*)\])*)$/;
|
|
9541
9475
|
function formatAbiParameter(abiParameter) {
|
|
9542
9476
|
let type = abiParameter.type;
|
|
@@ -9563,7 +9497,7 @@ function formatAbiParameter(abiParameter) {
|
|
|
9563
9497
|
return type;
|
|
9564
9498
|
}
|
|
9565
9499
|
|
|
9566
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9500
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/formatAbiParameters.js
|
|
9567
9501
|
function formatAbiParameters(abiParameters) {
|
|
9568
9502
|
let params = "";
|
|
9569
9503
|
const length = abiParameters.length;
|
|
@@ -9576,7 +9510,7 @@ function formatAbiParameters(abiParameters) {
|
|
|
9576
9510
|
return params;
|
|
9577
9511
|
}
|
|
9578
9512
|
|
|
9579
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9513
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/errors.js
|
|
9580
9514
|
class InvalidAbiItemError extends BaseError {
|
|
9581
9515
|
name = "AbiItem.InvalidAbiItemError";
|
|
9582
9516
|
constructor({ signature }) {
|
|
@@ -9711,7 +9645,7 @@ class CircularReferenceError extends BaseError {
|
|
|
9711
9645
|
}
|
|
9712
9646
|
}
|
|
9713
9647
|
|
|
9714
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9648
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/signatures.js
|
|
9715
9649
|
var errorSignatureRegex = /^error (?<name>[a-zA-Z$_][a-zA-Z0-9$_]*)\((?<parameters>.*?)\)$/;
|
|
9716
9650
|
function isErrorSignature(signature) {
|
|
9717
9651
|
return errorSignatureRegex.test(signature);
|
|
@@ -9771,7 +9705,7 @@ var functionModifiers = new Set([
|
|
|
9771
9705
|
"storage"
|
|
9772
9706
|
]);
|
|
9773
9707
|
|
|
9774
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9708
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/cache.js
|
|
9775
9709
|
function getParameterCacheKey(param, type, structs) {
|
|
9776
9710
|
let structKey = "";
|
|
9777
9711
|
if (structs)
|
|
@@ -9840,7 +9774,7 @@ var parameterCache = new Map([
|
|
|
9840
9774
|
]
|
|
9841
9775
|
]);
|
|
9842
9776
|
|
|
9843
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9777
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/utils.js
|
|
9844
9778
|
function parseSignature(signature, structs = {}) {
|
|
9845
9779
|
if (isFunctionSignature(signature))
|
|
9846
9780
|
return parseFunctionSignature(signature, structs);
|
|
@@ -10039,7 +9973,7 @@ function isValidDataLocation(type, isArray) {
|
|
|
10039
9973
|
return isArray || type === "bytes" || type === "string" || type === "tuple";
|
|
10040
9974
|
}
|
|
10041
9975
|
|
|
10042
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9976
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/structs.js
|
|
10043
9977
|
function parseStructs(signatures) {
|
|
10044
9978
|
const shallowStructs = {};
|
|
10045
9979
|
const signaturesLength = signatures.length;
|
|
@@ -10109,7 +10043,7 @@ function resolveStructs(abiParameters = [], structs = {}, ancestors = new Set) {
|
|
|
10109
10043
|
return components;
|
|
10110
10044
|
}
|
|
10111
10045
|
|
|
10112
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10046
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Solidity.js
|
|
10113
10047
|
var arrayRegex = /^(.*)\[([0-9]*)\]$/;
|
|
10114
10048
|
var bytesRegex2 = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
10115
10049
|
var integerRegex2 = /^(u?int)(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/;
|
|
@@ -10210,7 +10144,7 @@ var maxUint240 = 2n ** 240n - 1n;
|
|
|
10210
10144
|
var maxUint248 = 2n ** 248n - 1n;
|
|
10211
10145
|
var maxUint256 = 2n ** 256n - 1n;
|
|
10212
10146
|
|
|
10213
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10147
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/abiParameters.js
|
|
10214
10148
|
function decodeParameter(cursor, param, options) {
|
|
10215
10149
|
const { checksumAddress, staticPosition } = options;
|
|
10216
10150
|
const arrayComponents = getArrayComponents(param.type);
|
|
@@ -10752,7 +10686,7 @@ function hasDynamicChild(param) {
|
|
|
10752
10686
|
return false;
|
|
10753
10687
|
}
|
|
10754
10688
|
|
|
10755
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10689
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/cursor.js
|
|
10756
10690
|
var staticCursor = {
|
|
10757
10691
|
bytes: new Uint8Array,
|
|
10758
10692
|
dataView: new DataView(new ArrayBuffer(0)),
|
|
@@ -10943,7 +10877,7 @@ class RecursiveReadLimitExceededError extends BaseError {
|
|
|
10943
10877
|
}
|
|
10944
10878
|
}
|
|
10945
10879
|
|
|
10946
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10880
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiParameters.js
|
|
10947
10881
|
function decode2(parameters, data, options = {}) {
|
|
10948
10882
|
const { as = "Array", checksumAddress = true } = options;
|
|
10949
10883
|
const bytes = typeof data === "string" ? fromHex(data) : data;
|
|
@@ -11119,7 +11053,7 @@ class InvalidTypeError extends BaseError {
|
|
|
11119
11053
|
}
|
|
11120
11054
|
}
|
|
11121
11055
|
|
|
11122
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11056
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TypedData.js
|
|
11123
11057
|
function assert3(value) {
|
|
11124
11058
|
const { domain, message, primaryType, types } = value;
|
|
11125
11059
|
const validateValue = (type, value, name) => {
|
|
@@ -11231,7 +11165,7 @@ function encodeType(value) {
|
|
|
11231
11165
|
function extractEip712DomainTypes(domain) {
|
|
11232
11166
|
return [
|
|
11233
11167
|
typeof domain?.name === "string" && { name: "name", type: "string" },
|
|
11234
|
-
domain?.version && { name: "version", type: "string" },
|
|
11168
|
+
typeof domain?.version === "string" && { name: "version", type: "string" },
|
|
11235
11169
|
(typeof domain?.chainId === "number" || typeof domain?.chainId === "bigint") && {
|
|
11236
11170
|
name: "chainId",
|
|
11237
11171
|
type: "uint256"
|
|
@@ -11414,7 +11348,7 @@ function validateReference(type) {
|
|
|
11414
11348
|
throw new InvalidStructTypeError({ type });
|
|
11415
11349
|
}
|
|
11416
11350
|
|
|
11417
|
-
// ../wallet-chains/dist/typed-data-
|
|
11351
|
+
// ../wallet-chains/dist/typed-data-Cf1g7JVv.mjs
|
|
11418
11352
|
var isEvmAddress = (value) => /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
11419
11353
|
function checksumEvmAddress(address) {
|
|
11420
11354
|
if (!isEvmAddress(address))
|
|
@@ -11621,7 +11555,7 @@ var typedDataWarnings = (parsed) => parsed.chainIdMismatch ? [{
|
|
|
11621
11555
|
message: "typed-data domain.chainId does not match the request network"
|
|
11622
11556
|
}] : [];
|
|
11623
11557
|
|
|
11624
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11558
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/formatAbiItem.js
|
|
11625
11559
|
function formatAbiItem(abiItem) {
|
|
11626
11560
|
if (abiItem.type === "function")
|
|
11627
11561
|
return `function ${abiItem.name}(${formatAbiParameters(abiItem.inputs)})${abiItem.stateMutability && abiItem.stateMutability !== "nonpayable" ? ` ${abiItem.stateMutability}` : ""}${abiItem.outputs?.length ? ` returns (${formatAbiParameters(abiItem.outputs)})` : ""}`;
|
|
@@ -11636,7 +11570,7 @@ function formatAbiItem(abiItem) {
|
|
|
11636
11570
|
return "receive() external payable";
|
|
11637
11571
|
}
|
|
11638
11572
|
|
|
11639
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11573
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/parseAbiItem.js
|
|
11640
11574
|
function parseAbiItem(signature) {
|
|
11641
11575
|
let abiItem;
|
|
11642
11576
|
if (typeof signature === "string")
|
|
@@ -11657,7 +11591,7 @@ function parseAbiItem(signature) {
|
|
|
11657
11591
|
return abiItem;
|
|
11658
11592
|
}
|
|
11659
11593
|
|
|
11660
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11594
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/abiItem.js
|
|
11661
11595
|
function normalizeSignature(signature) {
|
|
11662
11596
|
let active = true;
|
|
11663
11597
|
let current = "";
|
|
@@ -11702,8 +11636,6 @@ function normalizeSignature(signature) {
|
|
|
11702
11636
|
}
|
|
11703
11637
|
var integerTypeRegex = /^u?int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/;
|
|
11704
11638
|
var fixedBytesTypeRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
11705
|
-
var arrayTypeRegex = /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/;
|
|
11706
|
-
var arraySuffixStripRegex = /(\[[0-9]{0,}\])$/;
|
|
11707
11639
|
function isArgOfType(arg, abiParameter) {
|
|
11708
11640
|
const argType = typeof arg;
|
|
11709
11641
|
const abiParameterType = abiParameter.type;
|
|
@@ -11719,16 +11651,18 @@ function isArgOfType(arg, abiParameter) {
|
|
|
11719
11651
|
default: {
|
|
11720
11652
|
if (abiParameterType === "tuple" && "components" in abiParameter)
|
|
11721
11653
|
return Object.values(abiParameter.components).every((component, index) => {
|
|
11722
|
-
return isArgOfType(
|
|
11654
|
+
return argType === "object" && isArgOfType(getComponentValue(arg, component, index), component);
|
|
11723
11655
|
});
|
|
11724
11656
|
if (integerTypeRegex.test(abiParameterType))
|
|
11725
11657
|
return argType === "number" || argType === "bigint";
|
|
11726
11658
|
if (fixedBytesTypeRegex.test(abiParameterType))
|
|
11727
11659
|
return argType === "string" || arg instanceof Uint8Array;
|
|
11728
|
-
|
|
11729
|
-
|
|
11660
|
+
const arrayComponents = getArrayComponents(abiParameterType);
|
|
11661
|
+
if (arrayComponents) {
|
|
11662
|
+
const [length, type] = arrayComponents;
|
|
11663
|
+
return Array.isArray(arg) && (length === null || arg.length === length) && arg.every((x) => isArgOfType(x, {
|
|
11730
11664
|
...abiParameter,
|
|
11731
|
-
type
|
|
11665
|
+
type
|
|
11732
11666
|
}));
|
|
11733
11667
|
}
|
|
11734
11668
|
return false;
|
|
@@ -11739,8 +11673,33 @@ function getAmbiguousTypes(sourceParameters, targetParameters, args) {
|
|
|
11739
11673
|
for (let parameterIndex = 0;parameterIndex < sourceParameters.length; parameterIndex++) {
|
|
11740
11674
|
const sourceParameter = sourceParameters[parameterIndex];
|
|
11741
11675
|
const targetParameter = targetParameters[parameterIndex];
|
|
11742
|
-
if (
|
|
11743
|
-
|
|
11676
|
+
if (!targetParameter)
|
|
11677
|
+
continue;
|
|
11678
|
+
if (sourceParameter.type === "tuple" && targetParameter.type === "tuple" && "components" in sourceParameter && "components" in targetParameter) {
|
|
11679
|
+
const value = args[parameterIndex];
|
|
11680
|
+
const types = getAmbiguousTypes(sourceParameter.components, targetParameter.components, sourceParameter.components.map((component, index) => getComponentValue(value, component, index)));
|
|
11681
|
+
if (types)
|
|
11682
|
+
return types;
|
|
11683
|
+
continue;
|
|
11684
|
+
}
|
|
11685
|
+
const sourceArray = getArrayComponents(sourceParameter.type);
|
|
11686
|
+
const targetArray = getArrayComponents(targetParameter.type);
|
|
11687
|
+
if (sourceArray && targetArray) {
|
|
11688
|
+
const types = getAmbiguousTypes([
|
|
11689
|
+
{
|
|
11690
|
+
...sourceParameter,
|
|
11691
|
+
type: sourceArray[1]
|
|
11692
|
+
}
|
|
11693
|
+
], [
|
|
11694
|
+
{
|
|
11695
|
+
...targetParameter,
|
|
11696
|
+
type: targetArray[1]
|
|
11697
|
+
}
|
|
11698
|
+
], [args[parameterIndex]?.[0]]);
|
|
11699
|
+
if (types)
|
|
11700
|
+
return types;
|
|
11701
|
+
continue;
|
|
11702
|
+
}
|
|
11744
11703
|
const sourceType = sourceParameter.type;
|
|
11745
11704
|
const targetType = targetParameter.type;
|
|
11746
11705
|
const arg = args[parameterIndex];
|
|
@@ -11748,14 +11707,19 @@ function getAmbiguousTypes(sourceParameters, targetParameters, args) {
|
|
|
11748
11707
|
if (sourceType === "address" && targetType === "bytes20" || sourceType === "bytes20" && targetType === "address")
|
|
11749
11708
|
ambiguous = true;
|
|
11750
11709
|
else if (sourceType === "address" && targetType === "string" || sourceType === "string" && targetType === "address" || sourceType === "address" && targetType === "bytes" || sourceType === "bytes" && targetType === "address")
|
|
11751
|
-
ambiguous = validate3(arg, { strict: false });
|
|
11710
|
+
ambiguous = arg === undefined || validate3(arg, { strict: false });
|
|
11752
11711
|
if (ambiguous)
|
|
11753
11712
|
return [sourceType, targetType];
|
|
11754
11713
|
}
|
|
11755
11714
|
return;
|
|
11756
11715
|
}
|
|
11716
|
+
function getComponentValue(arg, component, index) {
|
|
11717
|
+
if (Array.isArray(arg))
|
|
11718
|
+
return arg[index];
|
|
11719
|
+
return arg?.[component.name];
|
|
11720
|
+
}
|
|
11757
11721
|
|
|
11758
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11722
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiItem.js
|
|
11759
11723
|
function from3(abiItem, options = {}) {
|
|
11760
11724
|
const { prepare = true } = options;
|
|
11761
11725
|
const item = (() => {
|
|
@@ -11923,7 +11887,7 @@ class InvalidSelectorSizeError extends BaseError {
|
|
|
11923
11887
|
}
|
|
11924
11888
|
}
|
|
11925
11889
|
|
|
11926
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11890
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiFunction.js
|
|
11927
11891
|
function decodeData(...parameters) {
|
|
11928
11892
|
const [abiFunction, data, options] = (() => {
|
|
11929
11893
|
if (Array.isArray(parameters[0])) {
|
|
@@ -11985,7 +11949,7 @@ function getSelector2(abiItem) {
|
|
|
11985
11949
|
return getSelector(abiItem);
|
|
11986
11950
|
}
|
|
11987
11951
|
|
|
11988
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11952
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/PersonalMessage.js
|
|
11989
11953
|
var erc191PrefixHex = "0x19" + fromString(`Ethereum Signed Message:
|
|
11990
11954
|
`).slice(2);
|
|
11991
11955
|
function encode3(data) {
|
|
@@ -11996,7 +11960,7 @@ function getSignPayload2(data) {
|
|
|
11996
11960
|
return keccak2562(encode3(data));
|
|
11997
11961
|
}
|
|
11998
11962
|
|
|
11999
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11963
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Signature.js
|
|
12000
11964
|
function assert4(signature, options = {}) {
|
|
12001
11965
|
const { recovered } = options;
|
|
12002
11966
|
if (typeof signature.r === "undefined")
|
|
@@ -12120,8 +12084,8 @@ function fromRecoveredBytes(bytes) {
|
|
|
12120
12084
|
}
|
|
12121
12085
|
function toHex(signature) {
|
|
12122
12086
|
assert4(signature);
|
|
12123
|
-
const r = signature.r;
|
|
12124
|
-
const s = signature.s;
|
|
12087
|
+
const r = padLeft(signature.r, 32);
|
|
12088
|
+
const s = padLeft(signature.s, 32);
|
|
12125
12089
|
const signature_ = concat2(r, s, typeof signature.yParity === "number" ? fromNumber(yParityToV(signature.yParity), { size: 1 }) : "0x");
|
|
12126
12090
|
return signature_;
|
|
12127
12091
|
}
|
|
@@ -12193,7 +12157,7 @@ class InvalidVError extends BaseError {
|
|
|
12193
12157
|
}
|
|
12194
12158
|
}
|
|
12195
12159
|
|
|
12196
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12160
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/cryptoIo.js
|
|
12197
12161
|
function formatSignature(signature, as) {
|
|
12198
12162
|
if (as === "Hex")
|
|
12199
12163
|
return toHex(signature);
|
|
@@ -12202,7 +12166,7 @@ function formatSignature(signature, as) {
|
|
|
12202
12166
|
return signature;
|
|
12203
12167
|
}
|
|
12204
12168
|
|
|
12205
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12169
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/secp256k1.js
|
|
12206
12170
|
var signDefault = (payload, privateKey, options) => secp256k1.sign(payload, privateKey, {
|
|
12207
12171
|
...options,
|
|
12208
12172
|
format: "recovered",
|
|
@@ -12210,9 +12174,9 @@ var signDefault = (payload, privateKey, options) => secp256k1.sign(payload, priv
|
|
|
12210
12174
|
});
|
|
12211
12175
|
var sign = (payload, privateKey, options) => (overrides.Secp256k1?.sign ?? signDefault)(payload, privateKey, options);
|
|
12212
12176
|
|
|
12213
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12177
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/entropy.js
|
|
12214
12178
|
var extraEntropy = false;
|
|
12215
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12179
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Secp256k1.js
|
|
12216
12180
|
function sign2(options) {
|
|
12217
12181
|
const { as = "Object", extraEntropy: extraEntropy2 = extraEntropy, hash, payload, privateKey } = options;
|
|
12218
12182
|
const sigBytes = sign(from2(payload), from2(privateKey), {
|
|
@@ -12225,7 +12189,7 @@ function sign2(options) {
|
|
|
12225
12189
|
var fromPrfDomain = fromString2("ox.secp256k1.fromPrf.v1");
|
|
12226
12190
|
var fromSeedDomain = fromString2("ox.secp256k1.fromSeed.v1");
|
|
12227
12191
|
|
|
12228
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12192
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AccessList.js
|
|
12229
12193
|
function toTupleList(accessList) {
|
|
12230
12194
|
if (!accessList || accessList.length === 0)
|
|
12231
12195
|
return [];
|
|
@@ -12250,7 +12214,7 @@ class InvalidStorageKeySizeError extends BaseError {
|
|
|
12250
12214
|
}
|
|
12251
12215
|
}
|
|
12252
12216
|
|
|
12253
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12217
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/tx.js
|
|
12254
12218
|
function quantityToHex(value) {
|
|
12255
12219
|
if (value === undefined || value === null)
|
|
12256
12220
|
return "0x";
|
|
@@ -12259,7 +12223,7 @@ function quantityToHex(value) {
|
|
|
12259
12223
|
return fromNumber(value);
|
|
12260
12224
|
}
|
|
12261
12225
|
|
|
12262
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12226
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Rlp.js
|
|
12263
12227
|
function from6(value, options) {
|
|
12264
12228
|
const { as } = options;
|
|
12265
12229
|
const ctx = { lengths: [], cursor: 0 };
|
|
@@ -12502,7 +12466,7 @@ function invalidNibble(hex) {
|
|
|
12502
12466
|
return new BaseError(`Invalid hex string \`${hex}\`.`);
|
|
12503
12467
|
}
|
|
12504
12468
|
|
|
12505
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12469
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeEip2930.js
|
|
12506
12470
|
function assert5(envelope) {
|
|
12507
12471
|
const { chainId, gasPrice, to } = envelope;
|
|
12508
12472
|
if (chainId <= 0)
|
|
@@ -12546,7 +12510,7 @@ function serialize(envelope, options = {}) {
|
|
|
12546
12510
|
return concat2("0x01", fromHex3(serialized));
|
|
12547
12511
|
}
|
|
12548
12512
|
|
|
12549
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12513
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeLegacy.js
|
|
12550
12514
|
function assert6(envelope) {
|
|
12551
12515
|
const { chainId, gasPrice, to } = envelope;
|
|
12552
12516
|
if (to)
|
|
@@ -12623,7 +12587,7 @@ function serialize2(envelope, options = {}) {
|
|
|
12623
12587
|
return fromHex3(serialized);
|
|
12624
12588
|
}
|
|
12625
12589
|
|
|
12626
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12590
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Value.js
|
|
12627
12591
|
var exponents = {
|
|
12628
12592
|
wei: 0,
|
|
12629
12593
|
gwei: 9,
|
|
@@ -12656,7 +12620,7 @@ class InvalidDecimalsError extends BaseError {
|
|
|
12656
12620
|
}
|
|
12657
12621
|
}
|
|
12658
12622
|
|
|
12659
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12623
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelope.js
|
|
12660
12624
|
class FeeCapTooHighError extends BaseError {
|
|
12661
12625
|
name = "TransactionEnvelope.FeeCapTooHighError";
|
|
12662
12626
|
constructor({ feeCap } = {}) {
|
|
@@ -12687,7 +12651,7 @@ class TipAboveFeeCapError extends BaseError {
|
|
|
12687
12651
|
}
|
|
12688
12652
|
}
|
|
12689
12653
|
|
|
12690
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12654
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeEip1559.js
|
|
12691
12655
|
var serializedType = "0x02";
|
|
12692
12656
|
function assert7(envelope) {
|
|
12693
12657
|
const { chainId, maxPriorityFeePerGas, maxFeePerGas, to } = envelope;
|
|
@@ -12959,24 +12923,10 @@ var decodeEvm = (request, table = evmTokenTable) => {
|
|
|
12959
12923
|
verifiability: "opaque"
|
|
12960
12924
|
};
|
|
12961
12925
|
};
|
|
12962
|
-
var isAccountRef2 = (value) => {
|
|
12963
|
-
if (!isRecord3(value) || typeof value["kind"] !== "string")
|
|
12964
|
-
return false;
|
|
12965
|
-
if (value["kind"] === "hd")
|
|
12966
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
12967
|
-
if (value["kind"] === "imported")
|
|
12968
|
-
return typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
12969
|
-
return false;
|
|
12970
|
-
};
|
|
12971
12926
|
var normalizeEvm = (request) => {
|
|
12972
12927
|
if (!isRecord3(request) || typeof request["kind"] !== "string")
|
|
12973
12928
|
throw new ChainError("invalid-request", "request must be an object with a kind");
|
|
12974
|
-
const { network } = request;
|
|
12975
|
-
const { account } = request;
|
|
12976
|
-
if (typeof network !== "string")
|
|
12977
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
12978
|
-
if (!isAccountRef2(account))
|
|
12979
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
12929
|
+
const { network, account } = requestBase(request);
|
|
12980
12930
|
const chainId = networkChainId(network);
|
|
12981
12931
|
if (request["kind"] === "evm.transaction") {
|
|
12982
12932
|
const tx = normalizeEvmTransaction(request["tx"]);
|
|
@@ -13015,79 +12965,6 @@ var normalizeEvm = (request) => {
|
|
|
13015
12965
|
throw new ChainError("unsupported", `unsupported sign request kind: ${request["kind"]}`);
|
|
13016
12966
|
};
|
|
13017
12967
|
|
|
13018
|
-
// ../wallet-chains/dist/evm-sign.mjs
|
|
13019
|
-
function assertHex2(value, field) {
|
|
13020
|
-
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value))
|
|
13021
|
-
throw new ChainError("invalid-quantity", `${field} must be 0x-prefixed bytes`);
|
|
13022
|
-
}
|
|
13023
|
-
var hex = (value, field) => {
|
|
13024
|
-
assertHex2(value, field);
|
|
13025
|
-
return value;
|
|
13026
|
-
};
|
|
13027
|
-
var key = (privateKey) => {
|
|
13028
|
-
if (privateKey.length !== 32)
|
|
13029
|
-
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
13030
|
-
return fromBytes(privateKey);
|
|
13031
|
-
};
|
|
13032
|
-
var accessEntry = (entry) => ({
|
|
13033
|
-
address: hex(entry.address, "accessList.address"),
|
|
13034
|
-
storageKeys: entry.storageKeys.map((k) => hex(k, "accessList.storageKeys"))
|
|
13035
|
-
});
|
|
13036
|
-
var sign3 = (payload, privateKey) => sign2({
|
|
13037
|
-
payload,
|
|
13038
|
-
privateKey,
|
|
13039
|
-
as: "Object"
|
|
13040
|
-
});
|
|
13041
|
-
var signEvmTransaction = (tx, privateKey) => {
|
|
13042
|
-
const privateKeyHex = key(privateKey);
|
|
13043
|
-
const base = {
|
|
13044
|
-
chainId: tx.chainId,
|
|
13045
|
-
to: tx.to === undefined ? undefined : hex(tx.to, "to"),
|
|
13046
|
-
data: hex(tx.data, "data"),
|
|
13047
|
-
value: BigInt(tx.value),
|
|
13048
|
-
nonce: BigInt(tx.nonce),
|
|
13049
|
-
gas: BigInt(tx.gas)
|
|
13050
|
-
};
|
|
13051
|
-
if (tx.type === "legacy") {
|
|
13052
|
-
const envelope = {
|
|
13053
|
-
...base,
|
|
13054
|
-
type: "legacy",
|
|
13055
|
-
gasPrice: BigInt(tx.gasPrice)
|
|
13056
|
-
};
|
|
13057
|
-
const signature = sign3(getSignPayload4(envelope), privateKeyHex);
|
|
13058
|
-
return toBytes(serialize2(envelope, { signature }));
|
|
13059
|
-
}
|
|
13060
|
-
if (tx.type === "eip2930") {
|
|
13061
|
-
const envelope = {
|
|
13062
|
-
...base,
|
|
13063
|
-
type: "eip2930",
|
|
13064
|
-
gasPrice: BigInt(tx.gasPrice),
|
|
13065
|
-
accessList: tx.accessList.map(accessEntry)
|
|
13066
|
-
};
|
|
13067
|
-
const signature = sign3(getSignPayload3(envelope), privateKeyHex);
|
|
13068
|
-
return toBytes(serialize(envelope, { signature }));
|
|
13069
|
-
}
|
|
13070
|
-
const envelope = {
|
|
13071
|
-
...base,
|
|
13072
|
-
type: "eip1559",
|
|
13073
|
-
accessList: tx.accessList.map(accessEntry),
|
|
13074
|
-
maxFeePerGas: BigInt(tx.maxFeePerGas),
|
|
13075
|
-
maxPriorityFeePerGas: BigInt(tx.maxPriorityFeePerGas)
|
|
13076
|
-
};
|
|
13077
|
-
const signature = sign3(getSignPayload5(envelope), privateKeyHex);
|
|
13078
|
-
return toBytes(serialize3(envelope, { signature }));
|
|
13079
|
-
};
|
|
13080
|
-
var rs_v = (signature) => toBytes2(signature);
|
|
13081
|
-
var signEvmPersonalMessage = (message, privateKey) => {
|
|
13082
|
-
const payload = getSignPayload2(fromBytes(message));
|
|
13083
|
-
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
13084
|
-
};
|
|
13085
|
-
var signEvmTypedData = (typedData, privateKey) => {
|
|
13086
|
-
const { json } = parseTypedData(typedData, "eip155:1");
|
|
13087
|
-
const payload = getSignPayload(json);
|
|
13088
|
-
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
13089
|
-
};
|
|
13090
|
-
|
|
13091
12968
|
// ../../node_modules/.bun/@solana+errors@8.5.0+ff0372d108591aba/node_modules/@solana/errors/dist/index.browser.mjs
|
|
13092
12969
|
var SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED = 1;
|
|
13093
12970
|
var SOLANA_ERROR__INVALID_NONCE = 2;
|
|
@@ -14562,14 +14439,14 @@ var parseCompiledMessage = (bytes) => {
|
|
|
14562
14439
|
lookupAddresses: lookups.map((l) => l.lookupTableAddress)
|
|
14563
14440
|
};
|
|
14564
14441
|
};
|
|
14565
|
-
var
|
|
14442
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14566
14443
|
var isStringArray = (value) => Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
14567
14444
|
var isNumberArray = (value) => Array.isArray(value) && value.every((v) => typeof v === "number");
|
|
14568
|
-
var isArrayLike = (value) =>
|
|
14569
|
-
var isIx = (value) =>
|
|
14570
|
-
var isLookup = (value) =>
|
|
14445
|
+
var isArrayLike = (value) => isRecord4(value) && typeof value["length"] === "number";
|
|
14446
|
+
var isIx = (value) => isRecord4(value) && typeof value["programAddressIndex"] === "number" && (value["accountIndices"] === undefined || isNumberArray(value["accountIndices"]) || isArrayLike(value["accountIndices"])) && value["data"] instanceof Uint8Array;
|
|
14447
|
+
var isLookup = (value) => isRecord4(value) && typeof value["lookupTableAddress"] === "string" && (isNumberArray(value["readonlyIndexes"]) || value["readonlyIndexes"] instanceof Uint8Array) && (isNumberArray(value["writableIndexes"]) || value["writableIndexes"] instanceof Uint8Array);
|
|
14571
14448
|
var asCompiledMessage = (value) => {
|
|
14572
|
-
if (!
|
|
14449
|
+
if (!isRecord4(value) || !isRecord4(value["header"]))
|
|
14573
14450
|
throw new ChainError("invalid-request", "compiled message failed to decode");
|
|
14574
14451
|
const { header } = value;
|
|
14575
14452
|
const { staticAccounts } = value;
|
|
@@ -14790,14 +14667,6 @@ var decodeTransaction2 = (request, signer, table) => {
|
|
|
14790
14667
|
};
|
|
14791
14668
|
};
|
|
14792
14669
|
var decodeSolana = (request, signer, table = solanaTokenTable) => decodeTransaction2(request, signer, table);
|
|
14793
|
-
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14794
|
-
var isAccountRef3 = (value) => {
|
|
14795
|
-
if (!isRecord4(value) || typeof value["kind"] !== "string")
|
|
14796
|
-
return false;
|
|
14797
|
-
if (value["kind"] === "hd")
|
|
14798
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
14799
|
-
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
14800
|
-
};
|
|
14801
14670
|
var solanaNetwork = (network) => {
|
|
14802
14671
|
if (!SOLANA_NETWORKS.includes(network))
|
|
14803
14672
|
throw new ChainError("unsupported", `unknown Solana network: ${network}`);
|
|
@@ -14808,7 +14677,7 @@ var validateLookupTablesRaw = (tables) => {
|
|
|
14808
14677
|
if (!Array.isArray(tables))
|
|
14809
14678
|
throw new ChainError("unknown-field", "lookupTables must be an array");
|
|
14810
14679
|
const parsed = tables.map((t) => {
|
|
14811
|
-
if (!
|
|
14680
|
+
if (!isRecord2(t) || typeof t["address"] !== "string" || !Array.isArray(t["addresses"]))
|
|
14812
14681
|
throw new ChainError("unknown-field", "lookupTables entries must be { address, addresses }");
|
|
14813
14682
|
const addresses = t["addresses"].map((a) => {
|
|
14814
14683
|
if (typeof a !== "string")
|
|
@@ -14824,14 +14693,9 @@ var validateLookupTablesRaw = (tables) => {
|
|
|
14824
14693
|
return parsed;
|
|
14825
14694
|
};
|
|
14826
14695
|
var normalizeSolana = (request, signer) => {
|
|
14827
|
-
if (!
|
|
14696
|
+
if (!isRecord2(request) || typeof request["kind"] !== "string")
|
|
14828
14697
|
throw new ChainError("invalid-request", "request must be an object with a kind");
|
|
14829
|
-
const { network } = request;
|
|
14830
|
-
const { account } = request;
|
|
14831
|
-
if (typeof network !== "string")
|
|
14832
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
14833
|
-
if (!isAccountRef3(account))
|
|
14834
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
14698
|
+
const { network, account } = requestBase(request);
|
|
14835
14699
|
solanaNetwork(network);
|
|
14836
14700
|
if (!isSolanaAddress(signer))
|
|
14837
14701
|
throw new ChainError("invalid-address", "signer is not a base58 address");
|
|
@@ -14877,16 +14741,24 @@ var normalizeSolana = (request, signer) => {
|
|
|
14877
14741
|
throw new ChainError("unsupported", `unsupported sign request kind: ${request["kind"]}`);
|
|
14878
14742
|
};
|
|
14879
14743
|
|
|
14880
|
-
// ../wallet-chains/dist/
|
|
14881
|
-
var
|
|
14744
|
+
// ../wallet-chains/dist/bitcoin-sign.mjs
|
|
14745
|
+
var signBitcoinPsbt = (psbt, inputs, auxRand) => {
|
|
14746
|
+
const tx = Transaction.fromPSBT(psbt);
|
|
14747
|
+
for (const { index, privateKey } of inputs) {
|
|
14748
|
+
if (privateKey.length !== 32)
|
|
14749
|
+
throw new ChainError("invalid-request", `input ${index}: private key must be 32 bytes`);
|
|
14750
|
+
if (!tx.signIdx(privateKey, index, undefined, auxRand(index)))
|
|
14751
|
+
throw new ChainError("invalid-request", `input ${index}: key cannot sign`);
|
|
14752
|
+
}
|
|
14753
|
+
return tx.toPSBT(0);
|
|
14754
|
+
};
|
|
14755
|
+
var signBitcoinMessage = (request, privateKey, auxRand) => {
|
|
14882
14756
|
if (privateKey.length !== 32)
|
|
14883
|
-
throw new ChainError("invalid-request", "private key must be
|
|
14884
|
-
if (
|
|
14885
|
-
|
|
14886
|
-
const
|
|
14887
|
-
|
|
14888
|
-
throw new ChainError("invalid-request", "ed25519 produced a malformed signature");
|
|
14889
|
-
return signature;
|
|
14757
|
+
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
14758
|
+
if (request.format === "legacy")
|
|
14759
|
+
return signLegacyMessage(request.message, privateKey);
|
|
14760
|
+
const scriptPubKey = OutScript.encode(Address(bitcoinNetwork(request.network).params).decode(request.address));
|
|
14761
|
+
return signBip322Simple(request.message, scriptPubKey, privateKey, auxRand);
|
|
14890
14762
|
};
|
|
14891
14763
|
|
|
14892
14764
|
// ../wallet-kernel/src/modules/chains/prompt.ts
|
|
@@ -14953,15 +14825,407 @@ function chainPrompt(locale, intent) {
|
|
|
14953
14825
|
return { title, description: joinLines(lines.length === 0 ? [catalog.generic] : lines) };
|
|
14954
14826
|
}
|
|
14955
14827
|
|
|
14956
|
-
// ../wallet-kernel/src/modules/chains/
|
|
14828
|
+
// ../wallet-kernel/src/modules/chains/shared.ts
|
|
14957
14829
|
var BTC_PURPOSE = {
|
|
14958
14830
|
"btc.bip44": 44,
|
|
14959
14831
|
"btc.bip49": 49,
|
|
14960
14832
|
"btc.bip84": 84,
|
|
14961
14833
|
"btc.bip86": 86
|
|
14962
14834
|
};
|
|
14835
|
+
var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Uint8Array);
|
|
14836
|
+
var deepEqual = (a, b) => {
|
|
14837
|
+
if (a === b) {
|
|
14838
|
+
return true;
|
|
14839
|
+
}
|
|
14840
|
+
if (a instanceof Uint8Array || b instanceof Uint8Array) {
|
|
14841
|
+
return a instanceof Uint8Array && b instanceof Uint8Array && a.length === b.length && a.every((byte, i) => byte === b[i]);
|
|
14842
|
+
}
|
|
14843
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
14844
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
14845
|
+
}
|
|
14846
|
+
if (!isObj(a) || !isObj(b)) {
|
|
14847
|
+
return false;
|
|
14848
|
+
}
|
|
14849
|
+
const ka = Object.keys(a);
|
|
14850
|
+
const kb = new Set(Object.keys(b));
|
|
14851
|
+
return ka.length === kb.size && ka.every((k) => kb.has(k) && deepEqual(a[k], b[k]));
|
|
14852
|
+
};
|
|
14853
|
+
function mapChainError(error) {
|
|
14854
|
+
if (error instanceof ChainError) {
|
|
14855
|
+
throw new KernelError("invalid-input", "invalid sign request");
|
|
14856
|
+
}
|
|
14857
|
+
throw error;
|
|
14858
|
+
}
|
|
14859
|
+
|
|
14860
|
+
// ../wallet-kernel/src/modules/chains/bitcoin.ts
|
|
14963
14861
|
var isPath = (path) => Array.isArray(path) && path.every((p) => typeof p === "number");
|
|
14964
|
-
var
|
|
14862
|
+
var hex = (bytes) => bytes.reduce((acc, b) => acc + b.toString(16).padStart(2, "0"), "");
|
|
14863
|
+
var derivationOf = (owner, fingerprint, purpose) => {
|
|
14864
|
+
if (purpose === 86) {
|
|
14865
|
+
const claimed = (der) => der.fingerprint === fingerprint && isPath(der.path);
|
|
14866
|
+
for (const [key, value] of owner.tapBip32Derivation ?? []) {
|
|
14867
|
+
if (claimed(value.der)) {
|
|
14868
|
+
return { pubkey: key, fingerprint: value.der.fingerprint, path: value.der.path };
|
|
14869
|
+
}
|
|
14870
|
+
}
|
|
14871
|
+
return;
|
|
14872
|
+
}
|
|
14873
|
+
for (const [key, value] of owner.bip32Derivation ?? []) {
|
|
14874
|
+
if (value.fingerprint === fingerprint) {
|
|
14875
|
+
return { pubkey: key, fingerprint: value.fingerprint, path: value.path };
|
|
14876
|
+
}
|
|
14877
|
+
}
|
|
14878
|
+
return;
|
|
14879
|
+
};
|
|
14880
|
+
var expectedPub = (purpose, pub) => purpose === 86 ? pub.slice(1) : pub;
|
|
14881
|
+
var expectedScript = (purpose, pub) => purpose === 86 ? p2tr(pub.slice(1)).script : purpose === 49 ? p2sh(p2wpkh(pub)).script : purpose === 44 ? p2pkh(pub).script : p2wpkh(pub).script;
|
|
14882
|
+
var childAt = (b, path) => {
|
|
14883
|
+
const [purposePath, coinPath, groupPath, change, index] = path;
|
|
14884
|
+
if (path.length !== 5 || purposePath !== b.purpose + b.hardened || coinPath !== b.coinType + b.hardened || groupPath !== b.account.groupIndex + b.hardened || change === undefined || index === undefined || change !== 0 && change !== 1 || index < 0 || index >= b.hardened) {
|
|
14885
|
+
throw new KernelError("invalid-input", "derivation path is not this account's");
|
|
14886
|
+
}
|
|
14887
|
+
const child = b.accountNode.deriveChild(change).deriveChild(index);
|
|
14888
|
+
b.children.push(child);
|
|
14889
|
+
return child;
|
|
14890
|
+
};
|
|
14891
|
+
var bitcoinInput = (b, tx, idx) => {
|
|
14892
|
+
const input = tx.getInput(idx);
|
|
14893
|
+
const entry = derivationOf(input, b.master.fingerprint, b.purpose);
|
|
14894
|
+
if (entry === undefined) {
|
|
14895
|
+
throw new KernelError("invalid-input", `input ${idx}: derivation entry is not this account's`);
|
|
14896
|
+
}
|
|
14897
|
+
const child = childAt(b, entry.path);
|
|
14898
|
+
const pub = child.publicKey;
|
|
14899
|
+
const priv = child.privateKey;
|
|
14900
|
+
if (pub === null || priv === null) {
|
|
14901
|
+
throw new KernelError("integrity", "no key at derivation path");
|
|
14902
|
+
}
|
|
14903
|
+
if (!deepEqual(entry.pubkey, expectedPub(b.purpose, pub))) {
|
|
14904
|
+
throw new KernelError("invalid-input", `input ${idx}: derivation pubkey is not ours`);
|
|
14905
|
+
}
|
|
14906
|
+
if (b.purpose === 44) {
|
|
14907
|
+
if (input.nonWitnessUtxo === undefined) {
|
|
14908
|
+
throw new KernelError("invalid-input", `input ${idx}: P2PKH spend requires nonWitnessUtxo`);
|
|
14909
|
+
}
|
|
14910
|
+
const vout = input.index;
|
|
14911
|
+
const outs = input.nonWitnessUtxo.outputs;
|
|
14912
|
+
const prevScript = vout === undefined ? undefined : outs[vout]?.script;
|
|
14913
|
+
if (prevScript === undefined || !deepEqual(prevScript, expectedScript(b.purpose, pub))) {
|
|
14914
|
+
throw new KernelError("invalid-input", `input ${idx}: nonWitnessUtxo prevout is not this key's`);
|
|
14915
|
+
}
|
|
14916
|
+
} else {
|
|
14917
|
+
const prevout = input.witnessUtxo;
|
|
14918
|
+
if (prevout === undefined || !deepEqual(prevout.script, expectedScript(b.purpose, pub))) {
|
|
14919
|
+
throw new KernelError("invalid-input", `input ${idx}: prevout script is not this key's`);
|
|
14920
|
+
}
|
|
14921
|
+
if (b.purpose === 49 && (input.redeemScript === undefined || !deepEqual(input.redeemScript, p2wpkh(pub).script))) {
|
|
14922
|
+
throw new KernelError("invalid-input", `input ${idx}: redeemScript is not this key's`);
|
|
14923
|
+
}
|
|
14924
|
+
}
|
|
14925
|
+
return { index: idx, privateKey: priv };
|
|
14926
|
+
};
|
|
14927
|
+
var bitcoinOwnScripts = (b, tx) => {
|
|
14928
|
+
const ownScripts = new Set;
|
|
14929
|
+
for (let i = 0;i < tx.outputsLength; i++) {
|
|
14930
|
+
const output = tx.getOutput(i);
|
|
14931
|
+
if (output.script === undefined) {
|
|
14932
|
+
continue;
|
|
14933
|
+
}
|
|
14934
|
+
const entry = derivationOf(output, b.master.fingerprint, b.purpose);
|
|
14935
|
+
if (entry === undefined) {
|
|
14936
|
+
continue;
|
|
14937
|
+
}
|
|
14938
|
+
try {
|
|
14939
|
+
const child = childAt(b, entry.path);
|
|
14940
|
+
const pub = child.publicKey;
|
|
14941
|
+
if (pub !== null && deepEqual(output.script, expectedScript(b.purpose, pub))) {
|
|
14942
|
+
ownScripts.add(hex(output.script));
|
|
14943
|
+
}
|
|
14944
|
+
} catch {
|
|
14945
|
+
continue;
|
|
14946
|
+
}
|
|
14947
|
+
}
|
|
14948
|
+
return ownScripts;
|
|
14949
|
+
};
|
|
14950
|
+
var executeBitcoinPsbt = (b, request, random, intentOnly) => {
|
|
14951
|
+
const tx = Transaction.fromPSBT(request.psbt);
|
|
14952
|
+
const inputs = request.sign.map((idx) => bitcoinInput(b, tx, idx));
|
|
14953
|
+
const ownScripts = bitcoinOwnScripts(b, tx);
|
|
14954
|
+
let normalized;
|
|
14955
|
+
try {
|
|
14956
|
+
normalized = normalizeBitcoin(request);
|
|
14957
|
+
} catch (error) {
|
|
14958
|
+
mapChainError(error);
|
|
14959
|
+
}
|
|
14960
|
+
if (!deepEqual(normalized, request)) {
|
|
14961
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
14962
|
+
}
|
|
14963
|
+
let intent;
|
|
14964
|
+
try {
|
|
14965
|
+
intent = decodeBitcoinPsbt(request, ownScripts);
|
|
14966
|
+
} catch (error) {
|
|
14967
|
+
mapChainError(error);
|
|
14968
|
+
}
|
|
14969
|
+
if (intentOnly) {
|
|
14970
|
+
return { prompt: intent };
|
|
14971
|
+
}
|
|
14972
|
+
return {
|
|
14973
|
+
kind: "bitcoin.psbt",
|
|
14974
|
+
signedPsbt: signBitcoinPsbt(request.psbt, inputs, () => random(32))
|
|
14975
|
+
};
|
|
14976
|
+
};
|
|
14977
|
+
var executeBitcoinMessage = (b, request, random, intentOnly) => {
|
|
14978
|
+
if (request.format === "legacy" && b.account.template !== "btc.bip44") {
|
|
14979
|
+
throw new KernelError("unsupported", "legacy message format is btc.bip44-only");
|
|
14980
|
+
}
|
|
14981
|
+
const child = childAt(b, [
|
|
14982
|
+
b.purpose + b.hardened,
|
|
14983
|
+
b.coinType + b.hardened,
|
|
14984
|
+
b.account.groupIndex + b.hardened,
|
|
14985
|
+
request.change,
|
|
14986
|
+
request.index
|
|
14987
|
+
]);
|
|
14988
|
+
const pub = child.publicKey;
|
|
14989
|
+
const priv = child.privateKey;
|
|
14990
|
+
if (pub === null || priv === null) {
|
|
14991
|
+
throw new KernelError("integrity", "no key at derivation path");
|
|
14992
|
+
}
|
|
14993
|
+
const derived = b.purpose === 86 ? p2tr(pub.slice(1), undefined, b.net.params).address : b.purpose === 49 ? p2sh(p2wpkh(pub, b.net.params), b.net.params).address : b.purpose === 44 ? p2pkh(pub, b.net.params).address : p2wpkh(pub, b.net.params).address;
|
|
14994
|
+
if (derived !== request.address) {
|
|
14995
|
+
throw new KernelError("invalid-input", "address is not ours");
|
|
14996
|
+
}
|
|
14997
|
+
let normalized;
|
|
14998
|
+
try {
|
|
14999
|
+
normalized = normalizeBitcoin(request);
|
|
15000
|
+
} catch (error) {
|
|
15001
|
+
mapChainError(error);
|
|
15002
|
+
}
|
|
15003
|
+
if (!deepEqual(normalized, request)) {
|
|
15004
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
15005
|
+
}
|
|
15006
|
+
try {
|
|
15007
|
+
decodeMessageTarget(request);
|
|
15008
|
+
} catch (error) {
|
|
15009
|
+
mapChainError(error);
|
|
15010
|
+
}
|
|
15011
|
+
if (intentOnly) {
|
|
15012
|
+
return { prompt: MESSAGE_INTENT };
|
|
15013
|
+
}
|
|
15014
|
+
return {
|
|
15015
|
+
kind: "bitcoin.message",
|
|
15016
|
+
signature: signBitcoinMessage(request, priv, () => random(32))
|
|
15017
|
+
};
|
|
15018
|
+
};
|
|
15019
|
+
var executeBitcoin = (random, request, account, seed, intentOnly) => {
|
|
15020
|
+
const net = bitcoinNetwork(request.network);
|
|
15021
|
+
const master = HDKey.fromMasterSeed(seed, net.bip32);
|
|
15022
|
+
try {
|
|
15023
|
+
const purpose = BTC_PURPOSE[account.template] ?? 84;
|
|
15024
|
+
const { coinType } = net;
|
|
15025
|
+
const hardened = 2147483648;
|
|
15026
|
+
const accountNode = master.derive(`m/${purpose}'/${coinType}'/${account.groupIndex}'`);
|
|
15027
|
+
const children = [];
|
|
15028
|
+
const b = {
|
|
15029
|
+
master,
|
|
15030
|
+
accountNode,
|
|
15031
|
+
children,
|
|
15032
|
+
purpose,
|
|
15033
|
+
coinType,
|
|
15034
|
+
hardened,
|
|
15035
|
+
account,
|
|
15036
|
+
net
|
|
15037
|
+
};
|
|
15038
|
+
try {
|
|
15039
|
+
if (request.kind === "bitcoin.psbt") {
|
|
15040
|
+
return executeBitcoinPsbt(b, request, random, intentOnly);
|
|
15041
|
+
}
|
|
15042
|
+
return executeBitcoinMessage(b, request, random, intentOnly);
|
|
15043
|
+
} finally {
|
|
15044
|
+
for (const child of children) {
|
|
15045
|
+
child.wipePrivateData();
|
|
15046
|
+
}
|
|
15047
|
+
accountNode.wipePrivateData();
|
|
15048
|
+
}
|
|
15049
|
+
} finally {
|
|
15050
|
+
master.wipePrivateData();
|
|
15051
|
+
}
|
|
15052
|
+
};
|
|
15053
|
+
|
|
15054
|
+
// ../wallet-chains/dist/evm-sign.mjs
|
|
15055
|
+
function assertHex2(value, field) {
|
|
15056
|
+
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value))
|
|
15057
|
+
throw new ChainError("invalid-quantity", `${field} must be 0x-prefixed bytes`);
|
|
15058
|
+
}
|
|
15059
|
+
var hex2 = (value, field) => {
|
|
15060
|
+
assertHex2(value, field);
|
|
15061
|
+
return value;
|
|
15062
|
+
};
|
|
15063
|
+
var key = (privateKey) => {
|
|
15064
|
+
if (privateKey.length !== 32)
|
|
15065
|
+
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
15066
|
+
return fromBytes(privateKey);
|
|
15067
|
+
};
|
|
15068
|
+
var accessEntry = (entry) => ({
|
|
15069
|
+
address: hex2(entry.address, "accessList.address"),
|
|
15070
|
+
storageKeys: entry.storageKeys.map((k) => hex2(k, "accessList.storageKeys"))
|
|
15071
|
+
});
|
|
15072
|
+
var sign3 = (payload, privateKey) => sign2({
|
|
15073
|
+
payload,
|
|
15074
|
+
privateKey,
|
|
15075
|
+
as: "Object"
|
|
15076
|
+
});
|
|
15077
|
+
var signEvmTransaction = (tx, privateKey) => {
|
|
15078
|
+
const privateKeyHex = key(privateKey);
|
|
15079
|
+
const base = {
|
|
15080
|
+
chainId: tx.chainId,
|
|
15081
|
+
to: tx.to === undefined ? undefined : hex2(tx.to, "to"),
|
|
15082
|
+
data: hex2(tx.data, "data"),
|
|
15083
|
+
value: BigInt(tx.value),
|
|
15084
|
+
nonce: BigInt(tx.nonce),
|
|
15085
|
+
gas: BigInt(tx.gas)
|
|
15086
|
+
};
|
|
15087
|
+
if (tx.type === "legacy") {
|
|
15088
|
+
const envelope = {
|
|
15089
|
+
...base,
|
|
15090
|
+
type: "legacy",
|
|
15091
|
+
gasPrice: BigInt(tx.gasPrice)
|
|
15092
|
+
};
|
|
15093
|
+
const signature = sign3(getSignPayload4(envelope), privateKeyHex);
|
|
15094
|
+
return toBytes(serialize2(envelope, { signature }));
|
|
15095
|
+
}
|
|
15096
|
+
if (tx.type === "eip2930") {
|
|
15097
|
+
const envelope = {
|
|
15098
|
+
...base,
|
|
15099
|
+
type: "eip2930",
|
|
15100
|
+
gasPrice: BigInt(tx.gasPrice),
|
|
15101
|
+
accessList: tx.accessList.map(accessEntry)
|
|
15102
|
+
};
|
|
15103
|
+
const signature = sign3(getSignPayload3(envelope), privateKeyHex);
|
|
15104
|
+
return toBytes(serialize(envelope, { signature }));
|
|
15105
|
+
}
|
|
15106
|
+
const envelope = {
|
|
15107
|
+
...base,
|
|
15108
|
+
type: "eip1559",
|
|
15109
|
+
accessList: tx.accessList.map(accessEntry),
|
|
15110
|
+
maxFeePerGas: BigInt(tx.maxFeePerGas),
|
|
15111
|
+
maxPriorityFeePerGas: BigInt(tx.maxPriorityFeePerGas)
|
|
15112
|
+
};
|
|
15113
|
+
const signature = sign3(getSignPayload5(envelope), privateKeyHex);
|
|
15114
|
+
return toBytes(serialize3(envelope, { signature }));
|
|
15115
|
+
};
|
|
15116
|
+
var rs_v = (signature) => toBytes2(signature);
|
|
15117
|
+
var signEvmPersonalMessage = (message, privateKey) => {
|
|
15118
|
+
const payload = getSignPayload2(fromBytes(message));
|
|
15119
|
+
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
15120
|
+
};
|
|
15121
|
+
var signEvmTypedData = (typedData, privateKey) => {
|
|
15122
|
+
const { json } = parseTypedData(typedData, "eip155:1");
|
|
15123
|
+
const payload = getSignPayload(json);
|
|
15124
|
+
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
15125
|
+
};
|
|
15126
|
+
|
|
15127
|
+
// ../wallet-kernel/src/modules/chains/evm.ts
|
|
15128
|
+
var executeEvm = (request, account, seed, intentOnly) => {
|
|
15129
|
+
const master = HDKey.fromMasterSeed(seed);
|
|
15130
|
+
try {
|
|
15131
|
+
const child = master.derive(`m/44'/60'/0'/0/${account.groupIndex}`);
|
|
15132
|
+
try {
|
|
15133
|
+
const priv = child.privateKey;
|
|
15134
|
+
if (priv === null) {
|
|
15135
|
+
throw new KernelError("integrity", "no private key at account path");
|
|
15136
|
+
}
|
|
15137
|
+
let normalized;
|
|
15138
|
+
try {
|
|
15139
|
+
normalized = normalizeEvm(request);
|
|
15140
|
+
} catch (error) {
|
|
15141
|
+
mapChainError(error);
|
|
15142
|
+
}
|
|
15143
|
+
if (!deepEqual(normalized, request)) {
|
|
15144
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
15145
|
+
}
|
|
15146
|
+
let intent;
|
|
15147
|
+
try {
|
|
15148
|
+
intent = decodeEvm(request);
|
|
15149
|
+
} catch (error) {
|
|
15150
|
+
mapChainError(error);
|
|
15151
|
+
}
|
|
15152
|
+
if (intentOnly) {
|
|
15153
|
+
return { prompt: intent };
|
|
15154
|
+
}
|
|
15155
|
+
if (request.kind === "evm.transaction") {
|
|
15156
|
+
return {
|
|
15157
|
+
kind: "evm.transaction",
|
|
15158
|
+
signedTransaction: signEvmTransaction(request.tx, priv)
|
|
15159
|
+
};
|
|
15160
|
+
}
|
|
15161
|
+
if (request.kind === "evm.personal-message") {
|
|
15162
|
+
return {
|
|
15163
|
+
kind: "evm.personal-message",
|
|
15164
|
+
signature: signEvmPersonalMessage(request.message, priv)
|
|
15165
|
+
};
|
|
15166
|
+
}
|
|
15167
|
+
return {
|
|
15168
|
+
kind: "evm.typed-data",
|
|
15169
|
+
signature: signEvmTypedData(request.typedData, priv)
|
|
15170
|
+
};
|
|
15171
|
+
} finally {
|
|
15172
|
+
child.wipePrivateData();
|
|
15173
|
+
}
|
|
15174
|
+
} finally {
|
|
15175
|
+
master.wipePrivateData();
|
|
15176
|
+
}
|
|
15177
|
+
};
|
|
15178
|
+
|
|
15179
|
+
// ../wallet-chains/dist/solana-sign.mjs
|
|
15180
|
+
var signSolanaMessage = (message, privateKey) => {
|
|
15181
|
+
if (privateKey.length !== 32)
|
|
15182
|
+
throw new ChainError("invalid-request", "private key must be a 32-byte seed");
|
|
15183
|
+
if (message.length === 0)
|
|
15184
|
+
throw new ChainError("invalid-request", "message must not be empty");
|
|
15185
|
+
const signature = ed25519.sign(message, privateKey);
|
|
15186
|
+
if (signature.length !== 64)
|
|
15187
|
+
throw new ChainError("invalid-request", "ed25519 produced a malformed signature");
|
|
15188
|
+
return signature;
|
|
15189
|
+
};
|
|
15190
|
+
|
|
15191
|
+
// ../wallet-kernel/src/modules/chains/solana.ts
|
|
15192
|
+
var executeSolana = (request, account, seed, intentOnly) => {
|
|
15193
|
+
const root = HDKey2.fromMasterSeed(seed);
|
|
15194
|
+
const child = root.derive(`m/44'/501'/${account.groupIndex}'/0'`);
|
|
15195
|
+
try {
|
|
15196
|
+
const priv = child.privateKey;
|
|
15197
|
+
const signer = solanaAddressFromPublicKey(ed25519.getPublicKey(priv));
|
|
15198
|
+
let normalized;
|
|
15199
|
+
try {
|
|
15200
|
+
normalized = normalizeSolana(request, signer);
|
|
15201
|
+
} catch (error) {
|
|
15202
|
+
mapChainError(error);
|
|
15203
|
+
}
|
|
15204
|
+
if (!deepEqual(normalized, request)) {
|
|
15205
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
15206
|
+
}
|
|
15207
|
+
let intent = MESSAGE_INTENT;
|
|
15208
|
+
if (request.kind === "solana.transaction") {
|
|
15209
|
+
try {
|
|
15210
|
+
intent = decodeSolana(request, signer);
|
|
15211
|
+
} catch (error) {
|
|
15212
|
+
mapChainError(error);
|
|
15213
|
+
}
|
|
15214
|
+
}
|
|
15215
|
+
if (intentOnly) {
|
|
15216
|
+
return { prompt: intent };
|
|
15217
|
+
}
|
|
15218
|
+
return {
|
|
15219
|
+
kind: request.kind,
|
|
15220
|
+
signature: signSolanaMessage(request.message, priv)
|
|
15221
|
+
};
|
|
15222
|
+
} finally {
|
|
15223
|
+
wipe(child.privateKey);
|
|
15224
|
+
wipe(root.privateKey);
|
|
15225
|
+
}
|
|
15226
|
+
};
|
|
15227
|
+
|
|
15228
|
+
// ../wallet-kernel/src/modules/chains/index.ts
|
|
14965
15229
|
var checkNetwork = (template, network) => {
|
|
14966
15230
|
if (template.startsWith("evm.") && !network.startsWith("eip155:")) {
|
|
14967
15231
|
throw new KernelError("invalid-input", "evm.bip44 requires an eip155 network");
|
|
@@ -15018,30 +15282,60 @@ var accountFor = (master, seed, template, network, groupIndex) => {
|
|
|
15018
15282
|
account.wipePrivateData();
|
|
15019
15283
|
}
|
|
15020
15284
|
};
|
|
15021
|
-
var
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15285
|
+
var walletAccounts = async (ctx, params, session) => {
|
|
15286
|
+
const { dek } = ctx.session.require(session);
|
|
15287
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.walletId);
|
|
15288
|
+
if (record === undefined) {
|
|
15289
|
+
throw new KernelError("not-found", "no such wallet");
|
|
15025
15290
|
}
|
|
15026
|
-
|
|
15027
|
-
|
|
15291
|
+
checkNetwork(params.template, params.network);
|
|
15292
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => {
|
|
15293
|
+
const master = HDKey.fromMasterSeed(seed, params.template.startsWith("btc.") ? bitcoinNetwork(params.network).bip32 : undefined);
|
|
15294
|
+
try {
|
|
15295
|
+
return accountFor(master, seed, params.template, params.network, params.groupIndex);
|
|
15296
|
+
} finally {
|
|
15297
|
+
master.wipePrivateData();
|
|
15298
|
+
}
|
|
15299
|
+
});
|
|
15300
|
+
};
|
|
15301
|
+
var chainSign = async (ctx, params, session) => {
|
|
15302
|
+
const { dek } = ctx.session.require(session);
|
|
15303
|
+
const { request, verify } = params;
|
|
15304
|
+
const { account } = request;
|
|
15305
|
+
if (account.kind !== "hd") {
|
|
15306
|
+
throw new KernelError("unsupported", "imported accounts are not yet supported");
|
|
15028
15307
|
}
|
|
15029
|
-
|
|
15030
|
-
|
|
15308
|
+
const [family] = request.kind.split(".", 1);
|
|
15309
|
+
const expected = family === "evm" ? ["evm.bip44"] : family === "solana" ? ["solana.bip44-change"] : ["btc.bip44", "btc.bip49", "btc.bip84", "btc.bip86"];
|
|
15310
|
+
if (!expected.includes(account.template)) {
|
|
15311
|
+
throw new KernelError("invalid-input", "account template does not match the request family");
|
|
15031
15312
|
}
|
|
15032
|
-
|
|
15033
|
-
|
|
15313
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
15314
|
+
if (record === undefined) {
|
|
15315
|
+
throw new KernelError("not-found", "no such wallet");
|
|
15034
15316
|
}
|
|
15035
|
-
const
|
|
15036
|
-
|
|
15037
|
-
|
|
15317
|
+
const execute = (seed, intentOnly) => {
|
|
15318
|
+
if (request.kind === "evm.transaction" || request.kind === "evm.personal-message" || request.kind === "evm.typed-data") {
|
|
15319
|
+
return executeEvm(request, account, seed, intentOnly);
|
|
15320
|
+
}
|
|
15321
|
+
if (request.kind === "bitcoin.psbt" || request.kind === "bitcoin.message") {
|
|
15322
|
+
return executeBitcoin(ctx.platform.random, request, account, seed, intentOnly);
|
|
15323
|
+
}
|
|
15324
|
+
return executeSolana(request, account, seed, intentOnly);
|
|
15325
|
+
};
|
|
15326
|
+
const withSeed = async (run) => withWalletSeed(ctx.platform.pbkdf2, dek, record, run);
|
|
15327
|
+
const prepared = await withSeed((seed) => execute(seed, true));
|
|
15328
|
+
if (!("prompt" in prepared)) {
|
|
15329
|
+
throw new KernelError("integrity", "unreachable: prepare pass signed");
|
|
15330
|
+
}
|
|
15331
|
+
await verifyFactor(ctx.platform, ctx.image, verify, dek, () => chainPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), prepared.prompt));
|
|
15332
|
+
ctx.session.require(session);
|
|
15333
|
+
const signed = await withSeed((seed) => execute(seed, false));
|
|
15334
|
+
if ("prompt" in signed) {
|
|
15335
|
+
throw new KernelError("integrity", "unreachable: sign pass did not sign");
|
|
15336
|
+
}
|
|
15337
|
+
return signed;
|
|
15038
15338
|
};
|
|
15039
|
-
function mapChainError(error) {
|
|
15040
|
-
if (error instanceof ChainError) {
|
|
15041
|
-
throw new KernelError("invalid-input", "invalid sign request");
|
|
15042
|
-
}
|
|
15043
|
-
throw error;
|
|
15044
|
-
}
|
|
15045
15339
|
function createChainsModule() {
|
|
15046
15340
|
const vault = {
|
|
15047
15341
|
ownsRecord: () => false,
|
|
@@ -15052,348 +15346,22 @@ function createChainsModule() {
|
|
|
15052
15346
|
lock: () => {
|
|
15053
15347
|
return;
|
|
15054
15348
|
},
|
|
15055
|
-
backupSecrets: () => [],
|
|
15056
|
-
backupRecords: () => [],
|
|
15057
15349
|
walletDeleteOps: () => []
|
|
15058
15350
|
};
|
|
15059
15351
|
const handlers = {
|
|
15060
|
-
"wallet.accounts":
|
|
15061
|
-
|
|
15062
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.walletId);
|
|
15063
|
-
if (record === undefined) {
|
|
15064
|
-
throw new KernelError("not-found", "no such wallet");
|
|
15065
|
-
}
|
|
15066
|
-
checkNetwork(params.template, params.network);
|
|
15067
|
-
const entropy = openRecord(dek, record);
|
|
15068
|
-
let seed;
|
|
15069
|
-
try {
|
|
15070
|
-
seed = await seedFromEntropy(entropy, ctx.platform.pbkdf2);
|
|
15071
|
-
} finally {
|
|
15072
|
-
wipe(entropy);
|
|
15073
|
-
}
|
|
15074
|
-
try {
|
|
15075
|
-
const master = HDKey.fromMasterSeed(seed, params.template.startsWith("btc.") ? bitcoinNetwork(params.network).bip32 : undefined);
|
|
15076
|
-
try {
|
|
15077
|
-
return accountFor(master, seed, params.template, params.network, params.groupIndex);
|
|
15078
|
-
} finally {
|
|
15079
|
-
master.wipePrivateData();
|
|
15080
|
-
}
|
|
15081
|
-
} finally {
|
|
15082
|
-
wipe(seed);
|
|
15083
|
-
}
|
|
15084
|
-
},
|
|
15085
|
-
"chain.sign": async (ctx, params, session) => {
|
|
15086
|
-
const { dek } = ctx.session.require(session);
|
|
15087
|
-
const { request, verify } = params;
|
|
15088
|
-
const { account } = request;
|
|
15089
|
-
if (account.kind !== "hd") {
|
|
15090
|
-
throw new KernelError("unsupported", "imported accounts are not yet supported");
|
|
15091
|
-
}
|
|
15092
|
-
const [family] = request.kind.split(".", 1);
|
|
15093
|
-
const expected = family === "evm" ? ["evm.bip44"] : family === "solana" ? ["solana.bip44-change"] : ["btc.bip44", "btc.bip49", "btc.bip84", "btc.bip86"];
|
|
15094
|
-
if (!expected.includes(account.template)) {
|
|
15095
|
-
throw new KernelError("invalid-input", "account template does not match the request family");
|
|
15096
|
-
}
|
|
15097
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
15098
|
-
if (record === undefined) {
|
|
15099
|
-
throw new KernelError("not-found", "no such wallet");
|
|
15100
|
-
}
|
|
15101
|
-
const execute = (seed, intentOnly) => {
|
|
15102
|
-
if (request.kind === "evm.transaction" || request.kind === "evm.personal-message" || request.kind === "evm.typed-data") {
|
|
15103
|
-
const master = HDKey.fromMasterSeed(seed);
|
|
15104
|
-
try {
|
|
15105
|
-
const child = master.derive(`m/44'/60'/0'/0/${account.groupIndex}`);
|
|
15106
|
-
try {
|
|
15107
|
-
const priv = child.privateKey;
|
|
15108
|
-
if (priv === null) {
|
|
15109
|
-
throw new KernelError("integrity", "no private key at account path");
|
|
15110
|
-
}
|
|
15111
|
-
let normalized;
|
|
15112
|
-
try {
|
|
15113
|
-
normalized = normalizeEvm(request);
|
|
15114
|
-
} catch (error) {
|
|
15115
|
-
mapChainError(error);
|
|
15116
|
-
}
|
|
15117
|
-
if (!deepEqual(normalized, request)) {
|
|
15118
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15119
|
-
}
|
|
15120
|
-
let intent;
|
|
15121
|
-
try {
|
|
15122
|
-
intent = decodeEvm(request);
|
|
15123
|
-
} catch (error) {
|
|
15124
|
-
mapChainError(error);
|
|
15125
|
-
}
|
|
15126
|
-
if (intentOnly) {
|
|
15127
|
-
return { prompt: intent };
|
|
15128
|
-
}
|
|
15129
|
-
if (request.kind === "evm.transaction") {
|
|
15130
|
-
return {
|
|
15131
|
-
kind: "evm.transaction",
|
|
15132
|
-
signedTransaction: signEvmTransaction(request.tx, priv)
|
|
15133
|
-
};
|
|
15134
|
-
}
|
|
15135
|
-
if (request.kind === "evm.personal-message") {
|
|
15136
|
-
return {
|
|
15137
|
-
kind: "evm.personal-message",
|
|
15138
|
-
signature: signEvmPersonalMessage(request.message, priv)
|
|
15139
|
-
};
|
|
15140
|
-
}
|
|
15141
|
-
return {
|
|
15142
|
-
kind: "evm.typed-data",
|
|
15143
|
-
signature: signEvmTypedData(request.typedData, priv)
|
|
15144
|
-
};
|
|
15145
|
-
} finally {
|
|
15146
|
-
child.wipePrivateData();
|
|
15147
|
-
}
|
|
15148
|
-
} finally {
|
|
15149
|
-
master.wipePrivateData();
|
|
15150
|
-
}
|
|
15151
|
-
}
|
|
15152
|
-
if (request.kind === "bitcoin.psbt" || request.kind === "bitcoin.message") {
|
|
15153
|
-
const net = bitcoinNetwork(request.network);
|
|
15154
|
-
const master = HDKey.fromMasterSeed(seed, net.bip32);
|
|
15155
|
-
try {
|
|
15156
|
-
const purpose = BTC_PURPOSE[account.template] ?? 84;
|
|
15157
|
-
const { coinType } = net;
|
|
15158
|
-
const hardened = 2147483648;
|
|
15159
|
-
const accountNode = master.derive(`m/${purpose}'/${coinType}'/${account.groupIndex}'`);
|
|
15160
|
-
const children = [];
|
|
15161
|
-
const derivation = (owner) => {
|
|
15162
|
-
if (purpose === 86) {
|
|
15163
|
-
const claimed = (der) => der.fingerprint === master.fingerprint && isPath(der.path);
|
|
15164
|
-
for (const [key, value] of owner.tapBip32Derivation ?? []) {
|
|
15165
|
-
if (claimed(value.der)) {
|
|
15166
|
-
return {
|
|
15167
|
-
pubkey: key,
|
|
15168
|
-
fingerprint: value.der.fingerprint,
|
|
15169
|
-
path: value.der.path
|
|
15170
|
-
};
|
|
15171
|
-
}
|
|
15172
|
-
}
|
|
15173
|
-
return;
|
|
15174
|
-
}
|
|
15175
|
-
for (const [key, value] of owner.bip32Derivation ?? []) {
|
|
15176
|
-
if (value.fingerprint === master.fingerprint) {
|
|
15177
|
-
return { pubkey: key, fingerprint: value.fingerprint, path: value.path };
|
|
15178
|
-
}
|
|
15179
|
-
}
|
|
15180
|
-
return;
|
|
15181
|
-
};
|
|
15182
|
-
const childAt = (path) => {
|
|
15183
|
-
const [purposePath, coinPath, groupPath, change, index] = path;
|
|
15184
|
-
if (path.length !== 5 || purposePath !== purpose + hardened || coinPath !== coinType + hardened || groupPath !== account.groupIndex + hardened || change === undefined || index === undefined || change !== 0 && change !== 1 || index < 0 || index >= hardened) {
|
|
15185
|
-
throw new KernelError("invalid-input", "derivation path is not this account's");
|
|
15186
|
-
}
|
|
15187
|
-
const child = accountNode.deriveChild(change).deriveChild(index);
|
|
15188
|
-
children.push(child);
|
|
15189
|
-
return child;
|
|
15190
|
-
};
|
|
15191
|
-
const expectedPub = (pub) => purpose === 86 ? pub.slice(1) : pub;
|
|
15192
|
-
const expectedScript = (pub) => purpose === 86 ? p2tr(pub.slice(1)).script : purpose === 49 ? p2sh(p2wpkh(pub)).script : purpose === 44 ? p2pkh(pub).script : p2wpkh(pub).script;
|
|
15193
|
-
try {
|
|
15194
|
-
if (request.kind === "bitcoin.psbt") {
|
|
15195
|
-
const tx = Transaction.fromPSBT(request.psbt);
|
|
15196
|
-
const inputs = [];
|
|
15197
|
-
for (const idx of request.sign) {
|
|
15198
|
-
const input = tx.getInput(idx);
|
|
15199
|
-
const entry = derivation(input);
|
|
15200
|
-
if (entry === undefined) {
|
|
15201
|
-
throw new KernelError("invalid-input", `input ${idx}: derivation entry is not this account's`);
|
|
15202
|
-
}
|
|
15203
|
-
const child = childAt(entry.path);
|
|
15204
|
-
const pub = child.publicKey;
|
|
15205
|
-
const priv = child.privateKey;
|
|
15206
|
-
if (pub === null || priv === null) {
|
|
15207
|
-
throw new KernelError("integrity", "no key at derivation path");
|
|
15208
|
-
}
|
|
15209
|
-
if (!deepEqual(entry.pubkey, expectedPub(pub))) {
|
|
15210
|
-
throw new KernelError("invalid-input", `input ${idx}: derivation pubkey is not ours`);
|
|
15211
|
-
}
|
|
15212
|
-
if (purpose === 44) {
|
|
15213
|
-
if (input.nonWitnessUtxo === undefined) {
|
|
15214
|
-
throw new KernelError("invalid-input", `input ${idx}: P2PKH spend requires nonWitnessUtxo`);
|
|
15215
|
-
}
|
|
15216
|
-
const vout = input.index;
|
|
15217
|
-
const outs = input.nonWitnessUtxo.outputs;
|
|
15218
|
-
const prevScript = vout === undefined ? undefined : outs[vout]?.script;
|
|
15219
|
-
if (prevScript === undefined || !deepEqual(prevScript, expectedScript(pub))) {
|
|
15220
|
-
throw new KernelError("invalid-input", `input ${idx}: nonWitnessUtxo prevout is not this key's`);
|
|
15221
|
-
}
|
|
15222
|
-
} else {
|
|
15223
|
-
const prevout = input.witnessUtxo;
|
|
15224
|
-
if (prevout === undefined || !deepEqual(prevout.script, expectedScript(pub))) {
|
|
15225
|
-
throw new KernelError("invalid-input", `input ${idx}: prevout script is not this key's`);
|
|
15226
|
-
}
|
|
15227
|
-
if (purpose === 49 && (input.redeemScript === undefined || !deepEqual(input.redeemScript, p2wpkh(pub).script))) {
|
|
15228
|
-
throw new KernelError("invalid-input", `input ${idx}: redeemScript is not this key's`);
|
|
15229
|
-
}
|
|
15230
|
-
}
|
|
15231
|
-
inputs.push({ index: idx, privateKey: priv });
|
|
15232
|
-
}
|
|
15233
|
-
const ownScripts = new Set;
|
|
15234
|
-
for (let i = 0;i < tx.outputsLength; i++) {
|
|
15235
|
-
const output = tx.getOutput(i);
|
|
15236
|
-
if (output.script === undefined) {
|
|
15237
|
-
continue;
|
|
15238
|
-
}
|
|
15239
|
-
const entry = derivation(output);
|
|
15240
|
-
if (entry === undefined) {
|
|
15241
|
-
continue;
|
|
15242
|
-
}
|
|
15243
|
-
try {
|
|
15244
|
-
const child = childAt(entry.path);
|
|
15245
|
-
const pub = child.publicKey;
|
|
15246
|
-
if (pub !== null && deepEqual(output.script, expectedScript(pub))) {
|
|
15247
|
-
ownScripts.add(hex2(output.script));
|
|
15248
|
-
}
|
|
15249
|
-
} catch {
|
|
15250
|
-
continue;
|
|
15251
|
-
}
|
|
15252
|
-
}
|
|
15253
|
-
let normalized;
|
|
15254
|
-
try {
|
|
15255
|
-
normalized = normalizeBitcoin(request);
|
|
15256
|
-
} catch (error) {
|
|
15257
|
-
mapChainError(error);
|
|
15258
|
-
}
|
|
15259
|
-
if (!deepEqual(normalized, request)) {
|
|
15260
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15261
|
-
}
|
|
15262
|
-
let intent;
|
|
15263
|
-
try {
|
|
15264
|
-
intent = decodeBitcoinPsbt(request, ownScripts);
|
|
15265
|
-
} catch (error) {
|
|
15266
|
-
mapChainError(error);
|
|
15267
|
-
}
|
|
15268
|
-
if (intentOnly) {
|
|
15269
|
-
return { prompt: intent };
|
|
15270
|
-
}
|
|
15271
|
-
return {
|
|
15272
|
-
kind: "bitcoin.psbt",
|
|
15273
|
-
signedPsbt: signBitcoinPsbt(request.psbt, inputs, () => ctx.platform.random(32))
|
|
15274
|
-
};
|
|
15275
|
-
}
|
|
15276
|
-
if (request.format === "legacy" && account.template !== "btc.bip44") {
|
|
15277
|
-
throw new KernelError("unsupported", "legacy message format is btc.bip44-only");
|
|
15278
|
-
}
|
|
15279
|
-
const child = childAt([
|
|
15280
|
-
purpose + hardened,
|
|
15281
|
-
coinType + hardened,
|
|
15282
|
-
account.groupIndex + hardened,
|
|
15283
|
-
request.change,
|
|
15284
|
-
request.index
|
|
15285
|
-
]);
|
|
15286
|
-
const pub = child.publicKey;
|
|
15287
|
-
const priv = child.privateKey;
|
|
15288
|
-
if (pub === null || priv === null) {
|
|
15289
|
-
throw new KernelError("integrity", "no key at derivation path");
|
|
15290
|
-
}
|
|
15291
|
-
const derived = purpose === 86 ? p2tr(pub.slice(1), undefined, net.params).address : purpose === 49 ? p2sh(p2wpkh(pub, net.params), net.params).address : purpose === 44 ? p2pkh(pub, net.params).address : p2wpkh(pub, net.params).address;
|
|
15292
|
-
if (derived !== request.address) {
|
|
15293
|
-
throw new KernelError("invalid-input", "address is not ours");
|
|
15294
|
-
}
|
|
15295
|
-
let normalized;
|
|
15296
|
-
try {
|
|
15297
|
-
normalized = normalizeBitcoin(request);
|
|
15298
|
-
} catch (error) {
|
|
15299
|
-
mapChainError(error);
|
|
15300
|
-
}
|
|
15301
|
-
if (!deepEqual(normalized, request)) {
|
|
15302
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15303
|
-
}
|
|
15304
|
-
try {
|
|
15305
|
-
decodeMessageTarget(request);
|
|
15306
|
-
} catch (error) {
|
|
15307
|
-
mapChainError(error);
|
|
15308
|
-
}
|
|
15309
|
-
if (intentOnly) {
|
|
15310
|
-
return { prompt: MESSAGE_INTENT };
|
|
15311
|
-
}
|
|
15312
|
-
return {
|
|
15313
|
-
kind: "bitcoin.message",
|
|
15314
|
-
signature: signBitcoinMessage(request, priv, () => ctx.platform.random(32))
|
|
15315
|
-
};
|
|
15316
|
-
} finally {
|
|
15317
|
-
for (const child of children) {
|
|
15318
|
-
child.wipePrivateData();
|
|
15319
|
-
}
|
|
15320
|
-
accountNode.wipePrivateData();
|
|
15321
|
-
}
|
|
15322
|
-
} finally {
|
|
15323
|
-
master.wipePrivateData();
|
|
15324
|
-
}
|
|
15325
|
-
}
|
|
15326
|
-
const root = HDKey2.fromMasterSeed(seed);
|
|
15327
|
-
const child = root.derive(`m/44'/501'/${account.groupIndex}'/0'`);
|
|
15328
|
-
try {
|
|
15329
|
-
const priv = child.privateKey;
|
|
15330
|
-
const signer = solanaAddressFromPublicKey(ed25519.getPublicKey(priv));
|
|
15331
|
-
let normalized;
|
|
15332
|
-
try {
|
|
15333
|
-
normalized = normalizeSolana(request, signer);
|
|
15334
|
-
} catch (error) {
|
|
15335
|
-
mapChainError(error);
|
|
15336
|
-
}
|
|
15337
|
-
if (!deepEqual(normalized, request)) {
|
|
15338
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15339
|
-
}
|
|
15340
|
-
let intent = MESSAGE_INTENT;
|
|
15341
|
-
if (request.kind === "solana.transaction") {
|
|
15342
|
-
try {
|
|
15343
|
-
intent = decodeSolana(request, signer);
|
|
15344
|
-
} catch (error) {
|
|
15345
|
-
mapChainError(error);
|
|
15346
|
-
}
|
|
15347
|
-
}
|
|
15348
|
-
if (intentOnly) {
|
|
15349
|
-
return { prompt: intent };
|
|
15350
|
-
}
|
|
15351
|
-
return {
|
|
15352
|
-
kind: request.kind,
|
|
15353
|
-
signature: signSolanaMessage(request.message, priv)
|
|
15354
|
-
};
|
|
15355
|
-
} finally {
|
|
15356
|
-
wipe(child.privateKey);
|
|
15357
|
-
wipe(root.privateKey);
|
|
15358
|
-
}
|
|
15359
|
-
};
|
|
15360
|
-
const withSeed = async (run) => {
|
|
15361
|
-
const entropy = openRecord(dek, record);
|
|
15362
|
-
let seed;
|
|
15363
|
-
try {
|
|
15364
|
-
seed = await seedFromEntropy(entropy, ctx.platform.pbkdf2);
|
|
15365
|
-
} finally {
|
|
15366
|
-
wipe(entropy);
|
|
15367
|
-
}
|
|
15368
|
-
try {
|
|
15369
|
-
return run(seed);
|
|
15370
|
-
} finally {
|
|
15371
|
-
wipe(seed);
|
|
15372
|
-
}
|
|
15373
|
-
};
|
|
15374
|
-
const prepared = await withSeed((seed) => execute(seed, true));
|
|
15375
|
-
if (!("prompt" in prepared)) {
|
|
15376
|
-
throw new KernelError("integrity", "unreachable: prepare pass signed");
|
|
15377
|
-
}
|
|
15378
|
-
await verifyFactor(ctx.platform, ctx.image, verify, dek, () => chainPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), prepared.prompt));
|
|
15379
|
-
ctx.session.require(session);
|
|
15380
|
-
const signed = await withSeed((seed) => execute(seed, false));
|
|
15381
|
-
if ("prompt" in signed) {
|
|
15382
|
-
throw new KernelError("integrity", "unreachable: sign pass did not sign");
|
|
15383
|
-
}
|
|
15384
|
-
return signed;
|
|
15385
|
-
}
|
|
15352
|
+
"wallet.accounts": walletAccounts,
|
|
15353
|
+
"chain.sign": chainSign
|
|
15386
15354
|
};
|
|
15387
15355
|
return { vault, handlers };
|
|
15388
15356
|
}
|
|
15389
15357
|
|
|
15390
15358
|
// ../wallet-kernel/src/modules/nostr/derive.ts
|
|
15391
15359
|
var NIP06_PATH = "m/44'/1237'/i'/0/0";
|
|
15392
|
-
function nostrKeyAt(master,
|
|
15393
|
-
if (!Number.isSafeInteger(
|
|
15394
|
-
throw new KernelError("invalid-input", "
|
|
15360
|
+
function nostrKeyAt(master, index) {
|
|
15361
|
+
if (!Number.isSafeInteger(index) || index < 0 || index > 2147483647) {
|
|
15362
|
+
throw new KernelError("invalid-input", "identity index out of range");
|
|
15395
15363
|
}
|
|
15396
|
-
const path = NIP06_PATH.split("/").map((segment) => segment === "i'" ? `${
|
|
15364
|
+
const path = NIP06_PATH.split("/").map((segment) => segment === "i'" ? `${index}'` : segment).join("/");
|
|
15397
15365
|
const node = master.derive(path);
|
|
15398
15366
|
try {
|
|
15399
15367
|
const key = node.privateKey;
|
|
@@ -15408,32 +15376,6 @@ function nostrKeyAt(master, groupIndex) {
|
|
|
15408
15376
|
|
|
15409
15377
|
// ../../node_modules/.bun/@qntx+nostr@0.15.3+ea9f70ecde856c26/node_modules/@qntx/nostr/dist/nips/nip19.mjs
|
|
15410
15378
|
var Bech32MaxSize2 = 5000;
|
|
15411
|
-
var Nip19Error2 = class extends NostrError {
|
|
15412
|
-
name = "Nip19Error";
|
|
15413
|
-
};
|
|
15414
|
-
function parseTLV(data) {
|
|
15415
|
-
const result = {};
|
|
15416
|
-
let rest = data;
|
|
15417
|
-
while (rest.length > 0) {
|
|
15418
|
-
if (rest.length < 2)
|
|
15419
|
-
throw new Nip19Error2("not enough data to read TLV");
|
|
15420
|
-
const t = rest.at(0);
|
|
15421
|
-
const l = rest.at(1);
|
|
15422
|
-
if (t === undefined || l === undefined)
|
|
15423
|
-
throw new Nip19Error2("not enough data to read TLV");
|
|
15424
|
-
const v = rest.slice(2, 2 + l);
|
|
15425
|
-
rest = rest.slice(2 + l);
|
|
15426
|
-
if (v.length < l)
|
|
15427
|
-
throw new Nip19Error2(`not enough data to read on TLV ${t}`);
|
|
15428
|
-
result[t] = result[t] ?? [];
|
|
15429
|
-
result[t].push(v);
|
|
15430
|
-
}
|
|
15431
|
-
return result;
|
|
15432
|
-
}
|
|
15433
|
-
function assertNip19Kind(kind) {
|
|
15434
|
-
if (!Number.isInteger(kind) || kind < 0 || kind > 65535)
|
|
15435
|
-
throw new Nip19Error2(`invalid kind: ${kind}`);
|
|
15436
|
-
}
|
|
15437
15379
|
function encodeBech32(prefix, data) {
|
|
15438
15380
|
const words = bech32.toWords(data);
|
|
15439
15381
|
return bech32.encode(prefix, words, Bech32MaxSize2);
|
|
@@ -15445,106 +15387,6 @@ function nsecEncode2(key) {
|
|
|
15445
15387
|
assertByteLength(key, 32, "secret key");
|
|
15446
15388
|
return encodeBytes("nsec", key);
|
|
15447
15389
|
}
|
|
15448
|
-
function readUint32(bytes) {
|
|
15449
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);
|
|
15450
|
-
}
|
|
15451
|
-
function decode3(code) {
|
|
15452
|
-
let prefix;
|
|
15453
|
-
let data;
|
|
15454
|
-
try {
|
|
15455
|
-
const { prefix: hrp, words } = bech32.decode(code, Bech32MaxSize2);
|
|
15456
|
-
prefix = hrp;
|
|
15457
|
-
data = new Uint8Array(bech32.fromWords(words));
|
|
15458
|
-
} catch (error) {
|
|
15459
|
-
throw new Nip19Error2(`invalid bech32: ${errorMessage(error)}`, { cause: error });
|
|
15460
|
-
}
|
|
15461
|
-
switch (prefix) {
|
|
15462
|
-
case "nprofile": {
|
|
15463
|
-
const tlv = parseTLV(data);
|
|
15464
|
-
if (!tlv[0]?.[0])
|
|
15465
|
-
throw new Nip19Error2("missing TLV 0 for nprofile");
|
|
15466
|
-
if (tlv[0][0].length !== 32)
|
|
15467
|
-
throw new Nip19Error2("TLV 0 should be 32 bytes");
|
|
15468
|
-
return {
|
|
15469
|
-
type: "nprofile",
|
|
15470
|
-
data: {
|
|
15471
|
-
pubkey: bytesToHex$1(tlv[0][0]),
|
|
15472
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15473
|
-
}
|
|
15474
|
-
};
|
|
15475
|
-
}
|
|
15476
|
-
case "nevent": {
|
|
15477
|
-
const tlv = parseTLV(data);
|
|
15478
|
-
if (!tlv[0]?.[0])
|
|
15479
|
-
throw new Nip19Error2("missing TLV 0 for nevent");
|
|
15480
|
-
if (tlv[0][0].length !== 32)
|
|
15481
|
-
throw new Nip19Error2("TLV 0 should be 32 bytes");
|
|
15482
|
-
if (tlv[2]?.[0] && tlv[2][0].length !== 32)
|
|
15483
|
-
throw new Nip19Error2("TLV 2 should be 32 bytes");
|
|
15484
|
-
if (tlv[3]?.[0] && tlv[3][0].length !== 4)
|
|
15485
|
-
throw new Nip19Error2("TLV 3 should be 4 bytes");
|
|
15486
|
-
const pointer = {
|
|
15487
|
-
id: bytesToHex$1(tlv[0][0]),
|
|
15488
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15489
|
-
};
|
|
15490
|
-
const author = tlv[2]?.[0];
|
|
15491
|
-
if (author !== undefined)
|
|
15492
|
-
pointer.author = bytesToHex$1(author);
|
|
15493
|
-
const kind = tlv[3]?.[0];
|
|
15494
|
-
if (kind !== undefined) {
|
|
15495
|
-
pointer.kind = readUint32(kind);
|
|
15496
|
-
assertNip19Kind(pointer.kind);
|
|
15497
|
-
}
|
|
15498
|
-
return {
|
|
15499
|
-
type: "nevent",
|
|
15500
|
-
data: pointer
|
|
15501
|
-
};
|
|
15502
|
-
}
|
|
15503
|
-
case "naddr": {
|
|
15504
|
-
const tlv = parseTLV(data);
|
|
15505
|
-
if (!tlv[0]?.[0])
|
|
15506
|
-
throw new Nip19Error2("missing TLV 0 for naddr");
|
|
15507
|
-
if (!tlv[2]?.[0])
|
|
15508
|
-
throw new Nip19Error2("missing TLV 2 for naddr");
|
|
15509
|
-
if (tlv[2][0].length !== 32)
|
|
15510
|
-
throw new Nip19Error2("TLV 2 should be 32 bytes");
|
|
15511
|
-
if (!tlv[3]?.[0])
|
|
15512
|
-
throw new Nip19Error2("missing TLV 3 for naddr");
|
|
15513
|
-
if (tlv[3][0].length !== 4)
|
|
15514
|
-
throw new Nip19Error2("TLV 3 should be 4 bytes");
|
|
15515
|
-
const naddrKind = readUint32(tlv[3][0]);
|
|
15516
|
-
assertNip19Kind(naddrKind);
|
|
15517
|
-
return {
|
|
15518
|
-
type: "naddr",
|
|
15519
|
-
data: {
|
|
15520
|
-
identifier: utf8Decoder.decode(tlv[0][0]),
|
|
15521
|
-
pubkey: bytesToHex$1(tlv[2][0]),
|
|
15522
|
-
kind: naddrKind,
|
|
15523
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15524
|
-
}
|
|
15525
|
-
};
|
|
15526
|
-
}
|
|
15527
|
-
case "nsec":
|
|
15528
|
-
if (data.length !== 32)
|
|
15529
|
-
throw new Nip19Error2("nsec must be 32 bytes");
|
|
15530
|
-
if (!secp256k1.utils.isValidSecretKey(data))
|
|
15531
|
-
throw new Nip19Error2("invalid nsec secret key");
|
|
15532
|
-
return {
|
|
15533
|
-
type: "nsec",
|
|
15534
|
-
data
|
|
15535
|
-
};
|
|
15536
|
-
case "npub":
|
|
15537
|
-
case "note":
|
|
15538
|
-
if (data.length !== 32)
|
|
15539
|
-
throw new Nip19Error2(`${prefix} must be 32 bytes`);
|
|
15540
|
-
return {
|
|
15541
|
-
type: prefix,
|
|
15542
|
-
data: bytesToHex$1(data)
|
|
15543
|
-
};
|
|
15544
|
-
default:
|
|
15545
|
-
throw new Nip19Error2(`unknown prefix ${prefix}`);
|
|
15546
|
-
}
|
|
15547
|
-
}
|
|
15548
15390
|
|
|
15549
15391
|
// ../../node_modules/.bun/@noble+hashes@2.4.0/node_modules/@noble/hashes/scrypt.js
|
|
15550
15392
|
function XorAndSalsa(prev, pi, input, ii, out, oi) {
|
|
@@ -15709,7 +15551,6 @@ async function scryptAsync(password, salt, opts) {
|
|
|
15709
15551
|
var VERSION2 = 2;
|
|
15710
15552
|
var SALT_LEN = 16;
|
|
15711
15553
|
var NONCE_LEN = 24;
|
|
15712
|
-
var PAYLOAD_LEN = 91;
|
|
15713
15554
|
var LOGN_MIN = 1;
|
|
15714
15555
|
var LOGN_MAX = 22;
|
|
15715
15556
|
var SCRYPT_R = 8;
|
|
@@ -15753,60 +15594,6 @@ async function encrypt4(secretKey, password, opts) {
|
|
|
15753
15594
|
const bytes = concatBytes(Uint8Array.from([VERSION2]), Uint8Array.from([logn]), salt, nonce, aad, ciphertext);
|
|
15754
15595
|
return encodeBytes("ncryptsec", bytes);
|
|
15755
15596
|
}
|
|
15756
|
-
async function decrypt4(ncryptsec, password, opts) {
|
|
15757
|
-
const { maxLogN } = opts;
|
|
15758
|
-
if (!Number.isInteger(maxLogN) || maxLogN < LOGN_MIN || maxLogN > LOGN_MAX)
|
|
15759
|
-
throw new Nip49Error(`invalid maxLogN ${maxLogN}, expected integer ${LOGN_MIN}..${LOGN_MAX}`);
|
|
15760
|
-
let prefix;
|
|
15761
|
-
let b;
|
|
15762
|
-
try {
|
|
15763
|
-
const decoded = bech32.decode(ncryptsec, Bech32MaxSize2);
|
|
15764
|
-
({ prefix } = decoded);
|
|
15765
|
-
b = new Uint8Array(bech32.fromWords(decoded.words));
|
|
15766
|
-
} catch (error) {
|
|
15767
|
-
throw new Nip49Error("invalid ncryptsec", { cause: error });
|
|
15768
|
-
}
|
|
15769
|
-
if (prefix !== "ncryptsec")
|
|
15770
|
-
throw new Nip49Error(`invalid prefix ${prefix}, expected 'ncryptsec'`);
|
|
15771
|
-
if (b.length !== PAYLOAD_LEN)
|
|
15772
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15773
|
-
const version = b.at(0);
|
|
15774
|
-
if (version === undefined)
|
|
15775
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15776
|
-
if (version !== VERSION2)
|
|
15777
|
-
throw new Nip49Error(`invalid version ${version}, expected 0x02`);
|
|
15778
|
-
const logn = b.at(1);
|
|
15779
|
-
if (logn === undefined)
|
|
15780
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15781
|
-
if (logn > maxLogN)
|
|
15782
|
-
throw new Nip49Error(`logn ${logn} exceeds maxLogN ${maxLogN}`);
|
|
15783
|
-
const salt = b.subarray(2, 18);
|
|
15784
|
-
const nonce = b.subarray(18, 42);
|
|
15785
|
-
const ksb = b.at(42);
|
|
15786
|
-
if (ksb === undefined)
|
|
15787
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15788
|
-
if (ksb !== 0 && ksb !== 1 && ksb !== 2)
|
|
15789
|
-
throw new Nip49Error(`invalid key security byte ${ksb}, expected 0x00, 0x01, or 0x02`);
|
|
15790
|
-
const aad = Uint8Array.from([ksb]);
|
|
15791
|
-
const ciphertext = b.subarray(43);
|
|
15792
|
-
try {
|
|
15793
|
-
const key = await deriveKey(password, salt, logn, opts.scrypt ?? nobleScrypt);
|
|
15794
|
-
try {
|
|
15795
|
-
const secret = xchacha20poly1305(key, nonce, aad).decrypt(ciphertext);
|
|
15796
|
-
if (!secp256k1.utils.isValidSecretKey(secret)) {
|
|
15797
|
-
secret.fill(0);
|
|
15798
|
-
throw new Nip49Error("invalid secret key");
|
|
15799
|
-
}
|
|
15800
|
-
return secret;
|
|
15801
|
-
} finally {
|
|
15802
|
-
key.fill(0);
|
|
15803
|
-
}
|
|
15804
|
-
} catch (error) {
|
|
15805
|
-
if (error instanceof Nip49Error)
|
|
15806
|
-
throw error;
|
|
15807
|
-
throw new Nip49Error("failed to decrypt", { cause: error });
|
|
15808
|
-
}
|
|
15809
|
-
}
|
|
15810
15597
|
|
|
15811
15598
|
// ../wallet-kernel/src/modules/nostr/pool.ts
|
|
15812
15599
|
class SignerPool {
|
|
@@ -15849,63 +15636,6 @@ class SignerPool {
|
|
|
15849
15636
|
this.signers.clear();
|
|
15850
15637
|
}
|
|
15851
15638
|
}
|
|
15852
|
-
function generateSecretKey(random, backend) {
|
|
15853
|
-
for (;; ) {
|
|
15854
|
-
const candidate = random(32);
|
|
15855
|
-
try {
|
|
15856
|
-
Keys.fromSecretKey(candidate, backend);
|
|
15857
|
-
return candidate;
|
|
15858
|
-
} catch {
|
|
15859
|
-
wipe(candidate);
|
|
15860
|
-
}
|
|
15861
|
-
}
|
|
15862
|
-
}
|
|
15863
|
-
function secretKeyFromNsec(nsec) {
|
|
15864
|
-
const text = decodeUtf8Secret(nsec);
|
|
15865
|
-
try {
|
|
15866
|
-
const decoded = decode3(text);
|
|
15867
|
-
if (decoded.type !== "nsec") {
|
|
15868
|
-
throw new KernelError("invalid-input", "expected an nsec bech32 string");
|
|
15869
|
-
}
|
|
15870
|
-
return new Uint8Array(decoded.data);
|
|
15871
|
-
} catch (error) {
|
|
15872
|
-
if (error instanceof KernelError) {
|
|
15873
|
-
throw error;
|
|
15874
|
-
}
|
|
15875
|
-
throw new KernelError("invalid-input", "invalid nsec");
|
|
15876
|
-
}
|
|
15877
|
-
}
|
|
15878
|
-
async function secretKeyFromNcryptsec(ncryptsec, password, maxLogN, scrypt) {
|
|
15879
|
-
const text = decodeUtf8Secret(password);
|
|
15880
|
-
let payload;
|
|
15881
|
-
try {
|
|
15882
|
-
const decoded = bech32.decode(ncryptsec, Bech32MaxSize2);
|
|
15883
|
-
payload = new Uint8Array(bech32.fromWords(decoded.words));
|
|
15884
|
-
if (decoded.prefix !== "ncryptsec" || payload.length !== 91 || payload.at(0) !== 2) {
|
|
15885
|
-
throw new KernelError("invalid-input", "malformed ncryptsec");
|
|
15886
|
-
}
|
|
15887
|
-
} catch (error) {
|
|
15888
|
-
if (error instanceof KernelError) {
|
|
15889
|
-
throw error;
|
|
15890
|
-
}
|
|
15891
|
-
throw new KernelError("invalid-input", "malformed ncryptsec");
|
|
15892
|
-
}
|
|
15893
|
-
const logN = payload.at(1) ?? 0;
|
|
15894
|
-
if (logN > maxLogN) {
|
|
15895
|
-
throw new KernelError("unsupported", "ncryptsec scrypt logN exceeds the policy limit");
|
|
15896
|
-
}
|
|
15897
|
-
try {
|
|
15898
|
-
return await decrypt4(ncryptsec, text, {
|
|
15899
|
-
maxLogN,
|
|
15900
|
-
...scrypt === undefined ? {} : { scrypt }
|
|
15901
|
-
});
|
|
15902
|
-
} catch (error) {
|
|
15903
|
-
if (error instanceof Nip49Error && error.cause instanceof RangeError) {
|
|
15904
|
-
throw new KernelError("unavailable", "ncryptsec scrypt allocation failed");
|
|
15905
|
-
}
|
|
15906
|
-
throw new KernelError("wrong-password", "invalid ncryptsec or wrong password");
|
|
15907
|
-
}
|
|
15908
|
-
}
|
|
15909
15639
|
function nsecFromSecretKey(secretKey) {
|
|
15910
15640
|
return new TextEncoder().encode(nsecEncode2(secretKey));
|
|
15911
15641
|
}
|
|
@@ -15945,58 +15675,27 @@ async function unwrapGiftWrap(pool, publicKey, event, backend) {
|
|
|
15945
15675
|
// ../wallet-kernel/src/modules/nostr/record.ts
|
|
15946
15676
|
var NOSTR_KEY_KIND = "nostr-key";
|
|
15947
15677
|
function encodeNostrKeyHeader(header) {
|
|
15948
|
-
|
|
15949
|
-
return JSON.stringify({
|
|
15950
|
-
publicKey: header.publicKey,
|
|
15951
|
-
origin: header.origin,
|
|
15952
|
-
walletId: header.walletId,
|
|
15953
|
-
groupIndex: header.groupIndex,
|
|
15954
|
-
createdAt: header.createdAt
|
|
15955
|
-
});
|
|
15956
|
-
}
|
|
15957
|
-
return header.origin === "nip46-client" ? JSON.stringify({
|
|
15958
|
-
publicKey: header.publicKey,
|
|
15959
|
-
origin: header.origin,
|
|
15960
|
-
createdAt: header.createdAt
|
|
15961
|
-
}) : JSON.stringify({
|
|
15678
|
+
return JSON.stringify({
|
|
15962
15679
|
publicKey: header.publicKey,
|
|
15963
|
-
|
|
15964
|
-
|
|
15680
|
+
walletId: header.walletId,
|
|
15681
|
+
index: header.index,
|
|
15965
15682
|
createdAt: header.createdAt
|
|
15966
15683
|
});
|
|
15967
15684
|
}
|
|
15968
15685
|
function parseNostrKeyHeader(text) {
|
|
15969
15686
|
const object = headerObject(text);
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
walletId: asWalletId(object["walletId"]),
|
|
15978
|
-
groupIndex: asGroupIndex(object["groupIndex"]),
|
|
15979
|
-
createdAt
|
|
15980
|
-
};
|
|
15981
|
-
}
|
|
15982
|
-
if (object["origin"] === "nip46-client") {
|
|
15983
|
-
expectKeys(object, ["publicKey", "origin", "createdAt"]);
|
|
15984
|
-
return { publicKey, origin: "nip46-client", createdAt };
|
|
15985
|
-
}
|
|
15986
|
-
expectKeys(object, ["publicKey", "origin", "backedUp", "createdAt"]);
|
|
15987
|
-
const { origin } = object;
|
|
15988
|
-
if (origin !== "nsec" && origin !== "ncryptsec" && origin !== "generated") {
|
|
15989
|
-
throw headerFailure();
|
|
15990
|
-
}
|
|
15991
|
-
return { publicKey, origin, backedUp: asBoolean(object["backedUp"]), createdAt };
|
|
15687
|
+
expectKeys(object, ["publicKey", "walletId", "index", "createdAt"]);
|
|
15688
|
+
return {
|
|
15689
|
+
publicKey: asPublicKey(object["publicKey"]),
|
|
15690
|
+
walletId: asWalletId(object["walletId"]),
|
|
15691
|
+
index: asIdentityIndex(object["index"]),
|
|
15692
|
+
createdAt: asCreatedAt(object["createdAt"])
|
|
15693
|
+
};
|
|
15992
15694
|
}
|
|
15993
15695
|
function nostrKeyInfo2(header) {
|
|
15994
|
-
const standalone = header.origin !== "derived" && header.origin !== "nip46-client";
|
|
15995
15696
|
return {
|
|
15996
|
-
ref:
|
|
15697
|
+
ref: { kind: "derived", walletId: header.walletId, index: header.index },
|
|
15997
15698
|
publicKey: header.publicKey,
|
|
15998
|
-
origin: header.origin,
|
|
15999
|
-
...standalone ? { backedUp: header.backedUp } : {},
|
|
16000
15699
|
createdAt: header.createdAt
|
|
16001
15700
|
};
|
|
16002
15701
|
}
|
|
@@ -16004,14 +15703,39 @@ function nostrStatus2(records) {
|
|
|
16004
15703
|
const keys = [];
|
|
16005
15704
|
let corrupted = false;
|
|
16006
15705
|
for (const record of records) {
|
|
16007
|
-
|
|
16008
|
-
|
|
16009
|
-
|
|
16010
|
-
|
|
15706
|
+
if (record.kind === NOSTR_KEY_KIND) {
|
|
15707
|
+
try {
|
|
15708
|
+
keys.push(nostrKeyInfo2(parseNostrKeyHeader(record.header)));
|
|
15709
|
+
} catch {
|
|
15710
|
+
corrupted = true;
|
|
15711
|
+
}
|
|
15712
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15713
|
+
try {
|
|
15714
|
+
parseSyncKeyHeader(record.header);
|
|
15715
|
+
} catch {
|
|
15716
|
+
corrupted = true;
|
|
15717
|
+
}
|
|
16011
15718
|
}
|
|
16012
15719
|
}
|
|
16013
15720
|
return { keys, corrupted };
|
|
16014
15721
|
}
|
|
15722
|
+
var NOSTR_SYNC_KEY_KIND = "nostr-sync-key";
|
|
15723
|
+
function encodeSyncKeyHeader(header) {
|
|
15724
|
+
return JSON.stringify({
|
|
15725
|
+
publicKey: header.publicKey,
|
|
15726
|
+
walletId: header.walletId,
|
|
15727
|
+
createdAt: header.createdAt
|
|
15728
|
+
});
|
|
15729
|
+
}
|
|
15730
|
+
function parseSyncKeyHeader(text) {
|
|
15731
|
+
const object = headerObject(text);
|
|
15732
|
+
expectKeys(object, ["publicKey", "walletId", "createdAt"]);
|
|
15733
|
+
return {
|
|
15734
|
+
publicKey: asPublicKey(object["publicKey"]),
|
|
15735
|
+
walletId: asWalletId(object["walletId"]),
|
|
15736
|
+
createdAt: asCreatedAt(object["createdAt"])
|
|
15737
|
+
};
|
|
15738
|
+
}
|
|
16015
15739
|
|
|
16016
15740
|
// ../wallet-kernel/src/modules/nostr/keys.ts
|
|
16017
15741
|
function keyRecord(ctx, dek, secretKey, header) {
|
|
@@ -16022,114 +15746,57 @@ function ensureNewKey(ctx, publicKey) {
|
|
|
16022
15746
|
throw new KernelError("already-exists", "nostr key already exists");
|
|
16023
15747
|
}
|
|
16024
15748
|
}
|
|
16025
|
-
async function addKey(ctx, secretKey, origin, backedUp, factor, requestSession) {
|
|
16026
|
-
const gated = gate(ctx, factor, requestSession);
|
|
16027
|
-
const publicKey = getPublicKey(secretKey);
|
|
16028
|
-
ensureNewKey(ctx, publicKey);
|
|
16029
|
-
const header = {
|
|
16030
|
-
publicKey,
|
|
16031
|
-
origin,
|
|
16032
|
-
backedUp,
|
|
16033
|
-
createdAt: ctx.platform.now()
|
|
16034
|
-
};
|
|
16035
|
-
const record = keyRecord(ctx, gated.dek, secretKey, header);
|
|
16036
|
-
const session = await commitRecords(ctx, gated, factor, [record]);
|
|
16037
|
-
return { key: nostrKeyInfo2(header), session };
|
|
16038
|
-
}
|
|
16039
|
-
async function importKey(ctx, params, requestSession) {
|
|
16040
|
-
const { input } = params;
|
|
16041
|
-
const secretKey = input.kind === "nsec" ? secretKeyFromNsec(input.nsec) : await secretKeyFromNcryptsec(input.ncryptsec, input.password, ctx.platform.policy.maxScryptLogN);
|
|
16042
|
-
try {
|
|
16043
|
-
return await addKey(ctx, secretKey, input.kind, true, params.factor, requestSession);
|
|
16044
|
-
} finally {
|
|
16045
|
-
wipe(secretKey);
|
|
16046
|
-
}
|
|
16047
|
-
}
|
|
16048
|
-
async function generateKey(ctx, params, requestSession) {
|
|
16049
|
-
const secretKey = generateSecretKey(ctx.platform.random, ctx.platform.backends.nostr);
|
|
16050
|
-
try {
|
|
16051
|
-
return await addKey(ctx, secretKey, "generated", false, params.factor, requestSession);
|
|
16052
|
-
} finally {
|
|
16053
|
-
wipe(secretKey);
|
|
16054
|
-
}
|
|
16055
|
-
}
|
|
16056
|
-
async function createNip46ClientKey(ctx, requestSession) {
|
|
16057
|
-
const { dek } = ctx.session.require(requestSession);
|
|
16058
|
-
const secretKey = generateSecretKey(ctx.platform.random, ctx.platform.backends.nostr);
|
|
16059
|
-
try {
|
|
16060
|
-
const publicKey = getPublicKey(secretKey);
|
|
16061
|
-
ensureNewKey(ctx, publicKey);
|
|
16062
|
-
const header = {
|
|
16063
|
-
publicKey,
|
|
16064
|
-
origin: "nip46-client",
|
|
16065
|
-
createdAt: ctx.platform.now()
|
|
16066
|
-
};
|
|
16067
|
-
await ctx.commit([{ op: "put-record", record: keyRecord(ctx, dek, secretKey, header) }]);
|
|
16068
|
-
return nostrKeyInfo2(header);
|
|
16069
|
-
} finally {
|
|
16070
|
-
wipe(secretKey);
|
|
16071
|
-
}
|
|
16072
|
-
}
|
|
16073
15749
|
async function deriveKey2(ctx, params, requestSession) {
|
|
16074
15750
|
const { dek } = ctx.session.require(requestSession);
|
|
16075
15751
|
const record = findRecord(ctx.image, "entropy", params.walletId);
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
wipe(entropy);
|
|
16079
|
-
const master = masterKey(seed);
|
|
16080
|
-
wipe(seed);
|
|
16081
|
-
try {
|
|
16082
|
-
const secretKey = nostrKeyAt(master, params.groupIndex);
|
|
15752
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, async (seed) => {
|
|
15753
|
+
const master = masterKey(seed);
|
|
16083
15754
|
try {
|
|
16084
|
-
const
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
publicKey
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
15755
|
+
const secretKey = nostrKeyAt(master, params.index);
|
|
15756
|
+
try {
|
|
15757
|
+
const publicKey = getPublicKey(secretKey);
|
|
15758
|
+
ensureNewKey(ctx, publicKey);
|
|
15759
|
+
const header = {
|
|
15760
|
+
publicKey,
|
|
15761
|
+
walletId: params.walletId,
|
|
15762
|
+
index: params.index,
|
|
15763
|
+
createdAt: ctx.platform.now()
|
|
15764
|
+
};
|
|
15765
|
+
await ctx.commit([{ op: "put-record", record: keyRecord(ctx, dek, secretKey, header) }]);
|
|
15766
|
+
return nostrKeyInfo2(header);
|
|
15767
|
+
} finally {
|
|
15768
|
+
wipe(secretKey);
|
|
15769
|
+
}
|
|
16095
15770
|
} finally {
|
|
16096
|
-
|
|
15771
|
+
master.wipePrivateData();
|
|
16097
15772
|
}
|
|
16098
|
-
}
|
|
16099
|
-
master.wipePrivateData();
|
|
16100
|
-
}
|
|
15773
|
+
});
|
|
16101
15774
|
}
|
|
16102
15775
|
async function discover(ctx, params, requestSession) {
|
|
16103
15776
|
const { dek } = ctx.session.require(requestSession);
|
|
16104
15777
|
const record = findRecord(ctx.image, "entropy", params.walletId);
|
|
16105
|
-
|
|
15778
|
+
if (params.from + params.count - 1 > 2147483646) {
|
|
15779
|
+
throw new KernelError("invalid-input", "identity range exceeds 0x7ffffffe");
|
|
15780
|
+
}
|
|
16106
15781
|
const keys = [];
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
15782
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => {
|
|
15783
|
+
const master = masterKey(seed);
|
|
15784
|
+
try {
|
|
15785
|
+
for (let i = 0;i < params.count; i++) {
|
|
15786
|
+
const index = params.from + i;
|
|
15787
|
+
const secretKey = nostrKeyAt(master, index);
|
|
15788
|
+
keys.push({ index, publicKey: getPublicKey(secretKey) });
|
|
15789
|
+
wipe(secretKey);
|
|
15790
|
+
}
|
|
15791
|
+
return { keys };
|
|
15792
|
+
} finally {
|
|
15793
|
+
master.wipePrivateData();
|
|
16117
15794
|
}
|
|
16118
|
-
|
|
16119
|
-
} finally {
|
|
16120
|
-
master.wipePrivateData();
|
|
16121
|
-
}
|
|
15795
|
+
});
|
|
16122
15796
|
}
|
|
16123
15797
|
async function removeKey(ctx, params, requestSession) {
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16127
|
-
if (header.origin !== "nip46-client") {
|
|
16128
|
-
if (params.verify === undefined) {
|
|
16129
|
-
throw new KernelError("invalid-input", "factor verification is required");
|
|
16130
|
-
}
|
|
16131
|
-
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, corePromptFor(ctx.platform.keystore, "remove-key"));
|
|
16132
|
-
}
|
|
15798
|
+
ctx.session.require(requestSession);
|
|
15799
|
+
findRecord(ctx.image, NOSTR_KEY_KIND, params.publicKey);
|
|
16133
15800
|
await ctx.commit([{ op: "delete-record", kind: NOSTR_KEY_KIND, id: params.publicKey }]);
|
|
16134
15801
|
return null;
|
|
16135
15802
|
}
|
|
@@ -16137,19 +15804,9 @@ async function exportKey(ctx, params, requestSession) {
|
|
|
16137
15804
|
const { dek } = ctx.session.require(requestSession);
|
|
16138
15805
|
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, corePromptFor(ctx.platform.keystore, "export-key"));
|
|
16139
15806
|
const record = findRecord(ctx.image, NOSTR_KEY_KIND, params.publicKey);
|
|
16140
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16141
15807
|
const secretKey = openRecord(dek, record);
|
|
16142
15808
|
try {
|
|
16143
15809
|
const exported = params.format.kind === "nsec" ? nsecFromSecretKey(secretKey) : await ncryptsecFromSecretKey(secretKey, params.format.password);
|
|
16144
|
-
if (header.origin !== "derived" && header.origin !== "nip46-client" && !header.backedUp) {
|
|
16145
|
-
const updated = { ...header, backedUp: true };
|
|
16146
|
-
await ctx.commit([
|
|
16147
|
-
{
|
|
16148
|
-
op: "put-record",
|
|
16149
|
-
record: keyRecord(ctx, dek, secretKey, updated)
|
|
16150
|
-
}
|
|
16151
|
-
]);
|
|
16152
|
-
}
|
|
16153
15810
|
return exported;
|
|
16154
15811
|
} finally {
|
|
16155
15812
|
wipe(secretKey);
|
|
@@ -16186,11 +15843,93 @@ async function unwrapGiftWraps(ctx, pool, params, requestSession) {
|
|
|
16186
15843
|
return { results };
|
|
16187
15844
|
}
|
|
16188
15845
|
|
|
15846
|
+
// ../wallet-kernel/src/modules/nostr/sync.ts
|
|
15847
|
+
var SYNC_INDEX = 2147483647;
|
|
15848
|
+
function syncRecord(ctx, walletId) {
|
|
15849
|
+
findRecord(ctx.image, "entropy", walletId);
|
|
15850
|
+
for (const record of ctx.image.records) {
|
|
15851
|
+
if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15852
|
+
const header = parseSyncKeyHeader(record.header);
|
|
15853
|
+
if (header.walletId === walletId) {
|
|
15854
|
+
return record;
|
|
15855
|
+
}
|
|
15856
|
+
}
|
|
15857
|
+
}
|
|
15858
|
+
throw new KernelError("not-found", "no sync key for this wallet");
|
|
15859
|
+
}
|
|
15860
|
+
async function syncKey(ctx, params, requestSession) {
|
|
15861
|
+
const { dek } = ctx.session.require(requestSession);
|
|
15862
|
+
try {
|
|
15863
|
+
return { publicKey: parseSyncKeyHeader(syncRecord(ctx, params.walletId).header).publicKey };
|
|
15864
|
+
} catch (error) {
|
|
15865
|
+
if (!(error instanceof KernelError && error.code === "not-found")) {
|
|
15866
|
+
throw error;
|
|
15867
|
+
}
|
|
15868
|
+
}
|
|
15869
|
+
const wallet = findRecord(ctx.image, "entropy", params.walletId);
|
|
15870
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, wallet, async (seed) => {
|
|
15871
|
+
const master = masterKey(seed);
|
|
15872
|
+
try {
|
|
15873
|
+
const secretKey = nostrKeyAt(master, SYNC_INDEX);
|
|
15874
|
+
try {
|
|
15875
|
+
const publicKey = getPublicKey(secretKey);
|
|
15876
|
+
const header = {
|
|
15877
|
+
publicKey,
|
|
15878
|
+
walletId: params.walletId,
|
|
15879
|
+
createdAt: ctx.platform.now()
|
|
15880
|
+
};
|
|
15881
|
+
const record = sealRecord(ctx.platform, dek, NOSTR_SYNC_KEY_KIND, publicKey, encodeSyncKeyHeader(header), new Uint8Array(secretKey));
|
|
15882
|
+
try {
|
|
15883
|
+
await ctx.commit([{ op: "put-record", record }]);
|
|
15884
|
+
} catch (error) {
|
|
15885
|
+
if (!(error instanceof KernelError && error.code === "conflict")) {
|
|
15886
|
+
throw error;
|
|
15887
|
+
}
|
|
15888
|
+
return {
|
|
15889
|
+
publicKey: parseSyncKeyHeader(syncRecord(ctx, params.walletId).header).publicKey
|
|
15890
|
+
};
|
|
15891
|
+
}
|
|
15892
|
+
return { publicKey };
|
|
15893
|
+
} finally {
|
|
15894
|
+
wipe(secretKey);
|
|
15895
|
+
}
|
|
15896
|
+
} finally {
|
|
15897
|
+
master.wipePrivateData();
|
|
15898
|
+
}
|
|
15899
|
+
});
|
|
15900
|
+
}
|
|
15901
|
+
function requireSyncSigner(ctx, pool, walletId) {
|
|
15902
|
+
const record = syncRecord(ctx, walletId);
|
|
15903
|
+
const { publicKey } = parseSyncKeyHeader(record.header);
|
|
15904
|
+
return pool.get(publicKey);
|
|
15905
|
+
}
|
|
15906
|
+
async function syncSign(ctx, pool, params, requestSession) {
|
|
15907
|
+
ctx.session.require(requestSession);
|
|
15908
|
+
if (params.event.kind !== 30078) {
|
|
15909
|
+
throw new KernelError("invalid-input", "sync signer authors kind-30078 events only");
|
|
15910
|
+
}
|
|
15911
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15912
|
+
return signEvent2(pool, signer.keys.publicKey, params.event);
|
|
15913
|
+
}
|
|
15914
|
+
async function syncEncrypt(ctx, pool, params, requestSession) {
|
|
15915
|
+
ctx.session.require(requestSession);
|
|
15916
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15917
|
+
const { publicKey } = signer.keys;
|
|
15918
|
+
return signer.nip44Encrypt(publicKey, params.text);
|
|
15919
|
+
}
|
|
15920
|
+
async function syncDecrypt(ctx, pool, params, requestSession) {
|
|
15921
|
+
ctx.session.require(requestSession);
|
|
15922
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15923
|
+
const { publicKey } = signer.keys;
|
|
15924
|
+
return signer.nip44Decrypt(publicKey, params.text);
|
|
15925
|
+
}
|
|
15926
|
+
|
|
16189
15927
|
// ../wallet-kernel/src/modules/nostr/index.ts
|
|
16190
15928
|
function createNostrModule(backend) {
|
|
16191
15929
|
const pool = new SignerPool(backend);
|
|
15930
|
+
const syncPool = new SignerPool(backend);
|
|
16192
15931
|
const vault = {
|
|
16193
|
-
ownsRecord: (kind) => kind === NOSTR_KEY_KIND,
|
|
15932
|
+
ownsRecord: (kind) => kind === NOSTR_KEY_KIND || kind === NOSTR_SYNC_KEY_KIND,
|
|
16194
15933
|
claimUnlocked: (records) => {
|
|
16195
15934
|
const unclaimed = [];
|
|
16196
15935
|
for (const record of records) {
|
|
@@ -16199,6 +15938,11 @@ function createNostrModule(backend) {
|
|
|
16199
15938
|
if (claimed !== record.id) {
|
|
16200
15939
|
throw new KernelError("integrity", "nostr key does not match its record", undefined, true);
|
|
16201
15940
|
}
|
|
15941
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15942
|
+
const claimed = syncPool.add(record.plaintext);
|
|
15943
|
+
if (claimed !== record.id) {
|
|
15944
|
+
throw new KernelError("integrity", "sync key does not match its record", undefined, true);
|
|
15945
|
+
}
|
|
16202
15946
|
} else {
|
|
16203
15947
|
unclaimed.push(record);
|
|
16204
15948
|
}
|
|
@@ -16208,61 +15952,35 @@ function createNostrModule(backend) {
|
|
|
16208
15952
|
forget: (kind, id) => {
|
|
16209
15953
|
if (kind === NOSTR_KEY_KIND) {
|
|
16210
15954
|
pool.remove(id);
|
|
15955
|
+
} else if (kind === NOSTR_SYNC_KEY_KIND) {
|
|
15956
|
+
syncPool.remove(id);
|
|
16211
15957
|
}
|
|
16212
15958
|
},
|
|
16213
15959
|
lock: () => {
|
|
16214
15960
|
pool.dispose();
|
|
15961
|
+
syncPool.dispose();
|
|
16215
15962
|
},
|
|
16216
15963
|
walletDeleteOps: (image, walletId) => {
|
|
16217
15964
|
const ops = [];
|
|
16218
15965
|
for (const record of image.records) {
|
|
16219
|
-
if (record.kind
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
15966
|
+
if (record.kind === NOSTR_KEY_KIND) {
|
|
15967
|
+
const header = parseNostrKeyHeader(record.header);
|
|
15968
|
+
if (header.walletId === walletId) {
|
|
15969
|
+
ops.push({ op: "delete-record", kind: NOSTR_KEY_KIND, id: record.id });
|
|
15970
|
+
}
|
|
15971
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15972
|
+
const header = parseSyncKeyHeader(record.header);
|
|
15973
|
+
if (header.walletId === walletId) {
|
|
15974
|
+
ops.push({ op: "delete-record", kind: NOSTR_SYNC_KEY_KIND, id: record.id });
|
|
15975
|
+
}
|
|
16225
15976
|
}
|
|
16226
15977
|
}
|
|
16227
15978
|
return ops;
|
|
16228
|
-
},
|
|
16229
|
-
backupSecrets: (image, dek) => {
|
|
16230
|
-
const secrets = [];
|
|
16231
|
-
for (const record of image.records) {
|
|
16232
|
-
if (record.kind !== NOSTR_KEY_KIND) {
|
|
16233
|
-
continue;
|
|
16234
|
-
}
|
|
16235
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16236
|
-
if (header.origin === "derived" || header.origin === "nip46-client") {
|
|
16237
|
-
continue;
|
|
16238
|
-
}
|
|
16239
|
-
secrets.push(openRecord(dek, record));
|
|
16240
|
-
}
|
|
16241
|
-
return secrets;
|
|
16242
|
-
},
|
|
16243
|
-
backupRecords: (platform, image, dek, secrets, now) => {
|
|
16244
|
-
const records = [];
|
|
16245
|
-
for (const secretKey of secrets) {
|
|
16246
|
-
const publicKey = getPublicKey(secretKey);
|
|
16247
|
-
if (image.records.some((r) => r.kind === NOSTR_KEY_KIND && r.id === publicKey)) {
|
|
16248
|
-
continue;
|
|
16249
|
-
}
|
|
16250
|
-
records.push(sealRecord(platform, dek, NOSTR_KEY_KIND, publicKey, encodeNostrKeyHeader({
|
|
16251
|
-
publicKey,
|
|
16252
|
-
origin: "nsec",
|
|
16253
|
-
backedUp: true,
|
|
16254
|
-
createdAt: now
|
|
16255
|
-
}), secretKey));
|
|
16256
|
-
}
|
|
16257
|
-
return records;
|
|
16258
15979
|
}
|
|
16259
15980
|
};
|
|
16260
15981
|
const handlers = {
|
|
16261
15982
|
"nostr.discover": async (ctx, params, session) => discover(ctx, params, session),
|
|
16262
15983
|
"nostr.deriveKey": async (ctx, params, session) => deriveKey2(ctx, params, session),
|
|
16263
|
-
"nostr.importKey": async (ctx, params, session) => importKey(ctx, params, session),
|
|
16264
|
-
"nostr.generateKey": async (ctx, params, session) => generateKey(ctx, params, session),
|
|
16265
|
-
"nostr.createNip46ClientKey": async (ctx, _params, session) => createNip46ClientKey(ctx, session),
|
|
16266
15984
|
"nostr.removeKey": async (ctx, params, session) => removeKey(ctx, params, session),
|
|
16267
15985
|
"nostr.exportKey": async (ctx, params, session) => exportKey(ctx, params, session),
|
|
16268
15986
|
"nostr.signEvent": async (ctx, params, session) => sign4(ctx, pool, params, session),
|
|
@@ -16270,7 +15988,11 @@ function createNostrModule(backend) {
|
|
|
16270
15988
|
"nostr.nip04Decrypt": async (ctx, params, session) => nip04Decrypt(ctx, pool, params, session),
|
|
16271
15989
|
"nostr.nip44Encrypt": async (ctx, params, session) => nip44Encrypt(ctx, pool, params, session),
|
|
16272
15990
|
"nostr.nip44Decrypt": async (ctx, params, session) => nip44Decrypt(ctx, pool, params, session),
|
|
16273
|
-
"nostr.unwrapGiftWraps": async (ctx, params, session) => unwrapGiftWraps(ctx, pool, params, session)
|
|
15991
|
+
"nostr.unwrapGiftWraps": async (ctx, params, session) => unwrapGiftWraps(ctx, pool, params, session),
|
|
15992
|
+
"nostr.syncKey": async (ctx, params, session) => syncKey(ctx, params, session),
|
|
15993
|
+
"nostr.syncSign": async (ctx, params, session) => syncSign(ctx, syncPool, params, session),
|
|
15994
|
+
"nostr.syncEncrypt": async (ctx, params, session) => syncEncrypt(ctx, syncPool, params, session),
|
|
15995
|
+
"nostr.syncDecrypt": async (ctx, params, session) => syncDecrypt(ctx, syncPool, params, session)
|
|
16274
15996
|
};
|
|
16275
15997
|
return {
|
|
16276
15998
|
vault,
|
|
@@ -16454,228 +16176,241 @@ var decodeIntent = (rt, account, intent) => {
|
|
|
16454
16176
|
}
|
|
16455
16177
|
return result;
|
|
16456
16178
|
};
|
|
16457
|
-
|
|
16458
|
-
|
|
16459
|
-
const approvals = new Map;
|
|
16460
|
-
let backendPromise;
|
|
16461
|
-
let runtimePromise;
|
|
16462
|
-
const sparkRuntime = async () => {
|
|
16463
|
-
runtimePromise ??= (async () => {
|
|
16464
|
-
try {
|
|
16465
|
-
return await loadSparkRuntime();
|
|
16466
|
-
} catch (error) {
|
|
16467
|
-
runtimePromise = undefined;
|
|
16468
|
-
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark runtime failed to load");
|
|
16469
|
-
}
|
|
16470
|
-
})();
|
|
16471
|
-
return runtimePromise;
|
|
16472
|
-
};
|
|
16473
|
-
const liveApprovals = (ctx, key) => {
|
|
16474
|
-
const now = ctx.platform.elapsed();
|
|
16475
|
-
const live = (approvals.get(key) ?? []).filter((approval) => approval.deadline > now);
|
|
16476
|
-
if (live.length === 0) {
|
|
16477
|
-
approvals.delete(key);
|
|
16478
|
-
} else {
|
|
16479
|
-
approvals.set(key, live);
|
|
16480
|
-
}
|
|
16481
|
-
return live;
|
|
16482
|
-
};
|
|
16483
|
-
const backend = async (ctx) => {
|
|
16484
|
-
backendPromise ??= (async () => {
|
|
16485
|
-
try {
|
|
16486
|
-
return await ctx.platform.backends.spark();
|
|
16487
|
-
} catch (error) {
|
|
16488
|
-
backendPromise = undefined;
|
|
16489
|
-
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark backend failed to load");
|
|
16490
|
-
}
|
|
16491
|
-
})();
|
|
16492
|
-
return backendPromise;
|
|
16493
|
-
};
|
|
16494
|
-
const disposeAll = () => {
|
|
16495
|
-
for (const signer of signers.values()) {
|
|
16496
|
-
signer.dispose();
|
|
16497
|
-
}
|
|
16498
|
-
signers.clear();
|
|
16499
|
-
approvals.clear();
|
|
16500
|
-
};
|
|
16501
|
-
const disposeWallet = (walletId) => {
|
|
16502
|
-
for (const [key, signer] of signers) {
|
|
16503
|
-
if (key.startsWith(`${walletId}/`)) {
|
|
16504
|
-
signer.dispose();
|
|
16505
|
-
signers.delete(key);
|
|
16506
|
-
}
|
|
16507
|
-
}
|
|
16508
|
-
for (const key of approvals.keys()) {
|
|
16509
|
-
if (key.startsWith(`${walletId}/`)) {
|
|
16510
|
-
approvals.delete(key);
|
|
16511
|
-
}
|
|
16512
|
-
}
|
|
16513
|
-
};
|
|
16514
|
-
const poison = () => {
|
|
16515
|
-
backendPromise = undefined;
|
|
16516
|
-
disposeAll();
|
|
16517
|
-
return new KernelError("unavailable", "spark backend was disposed after a wasm fault");
|
|
16518
|
-
};
|
|
16519
|
-
const mapError = (error) => {
|
|
16520
|
-
if (error instanceof KernelError) {
|
|
16521
|
-
return error;
|
|
16522
|
-
}
|
|
16523
|
-
if (isNamed(error, "WasmPoisonedError")) {
|
|
16524
|
-
return poison();
|
|
16525
|
-
}
|
|
16526
|
-
if (isNamed(error, "SparkInputError")) {
|
|
16527
|
-
return new KernelError("invalid-input", "spark signer rejected the request");
|
|
16528
|
-
}
|
|
16529
|
-
return new KernelError("integrity", "spark signer call failed");
|
|
16530
|
-
};
|
|
16531
|
-
const signerFor = async (ctx, account, requestSession) => {
|
|
16532
|
-
const { dek } = ctx.session.require(requestSession);
|
|
16533
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
16534
|
-
if (record === undefined) {
|
|
16535
|
-
disposeWallet(account.walletId);
|
|
16536
|
-
throw new KernelError("not-found", "no such wallet");
|
|
16537
|
-
}
|
|
16538
|
-
const existing = signers.get(poolKey(account));
|
|
16539
|
-
if (existing !== undefined) {
|
|
16540
|
-
return existing;
|
|
16541
|
-
}
|
|
16542
|
-
const entropy = openRecord(dek, record);
|
|
16543
|
-
const seed = await seedFromEntropy(entropy, ctx.platform.pbkdf2);
|
|
16544
|
-
wipe(entropy);
|
|
16545
|
-
let accountKey;
|
|
16546
|
-
const rt = await sparkRuntime();
|
|
16179
|
+
var sparkRuntime = async (state) => {
|
|
16180
|
+
state.runtimePromise ??= (async () => {
|
|
16547
16181
|
try {
|
|
16548
|
-
|
|
16182
|
+
return await loadSparkRuntime();
|
|
16549
16183
|
} catch (error) {
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
wipe(seed);
|
|
16184
|
+
state.runtimePromise = undefined;
|
|
16185
|
+
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark runtime failed to load");
|
|
16553
16186
|
}
|
|
16554
|
-
|
|
16187
|
+
})();
|
|
16188
|
+
return state.runtimePromise;
|
|
16189
|
+
};
|
|
16190
|
+
var liveApprovals = (state, ctx, key) => {
|
|
16191
|
+
const now = ctx.platform.elapsed();
|
|
16192
|
+
const live = (state.approvals.get(key) ?? []).filter((approval) => approval.deadline > now);
|
|
16193
|
+
if (live.length === 0) {
|
|
16194
|
+
state.approvals.delete(key);
|
|
16195
|
+
} else {
|
|
16196
|
+
state.approvals.set(key, live);
|
|
16197
|
+
}
|
|
16198
|
+
return live;
|
|
16199
|
+
};
|
|
16200
|
+
var backend = async (state, ctx) => {
|
|
16201
|
+
state.backendPromise ??= (async () => {
|
|
16555
16202
|
try {
|
|
16556
|
-
|
|
16557
|
-
crypto: crypto2,
|
|
16558
|
-
accountKey,
|
|
16559
|
-
network: account.network,
|
|
16560
|
-
random: ctx.platform.random,
|
|
16561
|
-
authorize: async (outflow) => authorizeWithCtx(ctx, account, outflow)
|
|
16562
|
-
});
|
|
16563
|
-
signers.set(poolKey(account), signer);
|
|
16564
|
-
return signer;
|
|
16203
|
+
return await ctx.platform.backends.spark();
|
|
16565
16204
|
} catch (error) {
|
|
16566
|
-
|
|
16567
|
-
|
|
16568
|
-
wipe(accountKey);
|
|
16205
|
+
state.backendPromise = undefined;
|
|
16206
|
+
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark backend failed to load");
|
|
16569
16207
|
}
|
|
16570
|
-
};
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16208
|
+
})();
|
|
16209
|
+
return state.backendPromise;
|
|
16210
|
+
};
|
|
16211
|
+
var disposeAll = (state) => {
|
|
16212
|
+
for (const signer of state.signers.values()) {
|
|
16213
|
+
signer.dispose();
|
|
16214
|
+
}
|
|
16215
|
+
state.signers.clear();
|
|
16216
|
+
state.approvals.clear();
|
|
16217
|
+
};
|
|
16218
|
+
var disposeWallet = (state, walletId) => {
|
|
16219
|
+
for (const [key, signer] of state.signers) {
|
|
16220
|
+
if (key.startsWith(`${walletId}/`)) {
|
|
16221
|
+
signer.dispose();
|
|
16222
|
+
state.signers.delete(key);
|
|
16575
16223
|
}
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
if (outflow.kind === "transfer" && intent.kind === "transfer") {
|
|
16581
|
-
const covered = outflow.receivers.every((receiver) => intent.receivers.some((wanted) => equalBytes(wanted.identityPublicKey, receiver.identityPublicKey) && receiver.amountSats <= wanted.amountSats));
|
|
16582
|
-
if (covered) {
|
|
16583
|
-
live.splice(live.indexOf(approval), 1);
|
|
16584
|
-
return;
|
|
16585
|
-
}
|
|
16586
|
-
continue;
|
|
16587
|
-
}
|
|
16588
|
-
if (outflow.kind === "lightning" && intent.kind === "lightning") {
|
|
16589
|
-
const signer = signers.get(key);
|
|
16590
|
-
const { paymentHash } = approval.decoded;
|
|
16591
|
-
const budget = approval.decoded.invoiceAmountSats;
|
|
16592
|
-
if (signer === undefined || paymentHash === undefined || budget === undefined) {
|
|
16593
|
-
continue;
|
|
16594
|
-
}
|
|
16595
|
-
const expected = rt.lightningSendHtlcScript({
|
|
16596
|
-
paymentHash,
|
|
16597
|
-
sspIdentityPublicKey: rt.sparkNetworkConfig(account.network).ssp.identityPublicKey,
|
|
16598
|
-
identityPublicKey: await signer.identityPublicKey()
|
|
16599
|
-
});
|
|
16600
|
-
if (!equalBytes(expected, outflow.htlcOutputScript)) {
|
|
16601
|
-
continue;
|
|
16602
|
-
}
|
|
16603
|
-
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16604
|
-
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16605
|
-
if (total > budget + intent.maxFeeSats) {
|
|
16606
|
-
continue;
|
|
16607
|
-
}
|
|
16608
|
-
for (const leaf of fresh) {
|
|
16609
|
-
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16610
|
-
}
|
|
16611
|
-
return;
|
|
16612
|
-
}
|
|
16613
|
-
if (outflow.kind === "exit" && intent.kind === "exit") {
|
|
16614
|
-
const { addressScript } = approval.decoded;
|
|
16615
|
-
if (addressScript === undefined) {
|
|
16616
|
-
continue;
|
|
16617
|
-
}
|
|
16618
|
-
const pays = outflow.exitOutputs.some((output) => equalBytes(output.script, addressScript) && output.amountSats >= intent.amountSats);
|
|
16619
|
-
if (!pays) {
|
|
16620
|
-
continue;
|
|
16621
|
-
}
|
|
16622
|
-
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16623
|
-
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16624
|
-
if (total > intent.amountSats + intent.maxFeeSats) {
|
|
16625
|
-
continue;
|
|
16626
|
-
}
|
|
16627
|
-
for (const leaf of fresh) {
|
|
16628
|
-
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16629
|
-
}
|
|
16630
|
-
return;
|
|
16631
|
-
}
|
|
16632
|
-
if (outflow.kind === "onchain" && intent.kind === "onchain") {
|
|
16633
|
-
const { addressScript } = approval.decoded;
|
|
16634
|
-
if (addressScript === undefined) {
|
|
16635
|
-
continue;
|
|
16636
|
-
}
|
|
16637
|
-
const every = outflow.outputs.every((output) => equalBytes(output.script, rt.EPHEMERAL_ANCHOR_SCRIPT) || equalBytes(output.script, addressScript));
|
|
16638
|
-
if (!every) {
|
|
16639
|
-
continue;
|
|
16640
|
-
}
|
|
16641
|
-
const fee = outflow.inputSats - outflow.totalSats;
|
|
16642
|
-
if (fee > intent.maxFeeSats) {
|
|
16643
|
-
continue;
|
|
16644
|
-
}
|
|
16645
|
-
live.splice(live.indexOf(approval), 1);
|
|
16646
|
-
return;
|
|
16647
|
-
}
|
|
16648
|
-
if (outflow.kind === "token" && intent.kind === "token") {
|
|
16649
|
-
const signer = signers.get(key);
|
|
16650
|
-
if (signer === undefined) {
|
|
16651
|
-
continue;
|
|
16652
|
-
}
|
|
16653
|
-
const identity = await signer.identityPublicKey();
|
|
16654
|
-
const covered = outflow.outputs.every((output) => {
|
|
16655
|
-
if (equalBytes(output.ownerPublicKey, identity)) {
|
|
16656
|
-
return true;
|
|
16657
|
-
}
|
|
16658
|
-
if (!equalBytes(output.tokenIdentifier, intent.tokenIdentifier)) {
|
|
16659
|
-
return false;
|
|
16660
|
-
}
|
|
16661
|
-
return intent.receivers.some((wanted) => equalBytes(wanted.ownerPublicKey, output.ownerPublicKey) && output.amount <= BigInt(wanted.amount));
|
|
16662
|
-
});
|
|
16663
|
-
if (!covered) {
|
|
16664
|
-
continue;
|
|
16665
|
-
}
|
|
16666
|
-
live.splice(live.indexOf(approval), 1);
|
|
16667
|
-
return;
|
|
16668
|
-
}
|
|
16224
|
+
}
|
|
16225
|
+
for (const key of state.approvals.keys()) {
|
|
16226
|
+
if (key.startsWith(`${walletId}/`)) {
|
|
16227
|
+
state.approvals.delete(key);
|
|
16669
16228
|
}
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16229
|
+
}
|
|
16230
|
+
};
|
|
16231
|
+
var poison = (state) => {
|
|
16232
|
+
state.backendPromise = undefined;
|
|
16233
|
+
disposeAll(state);
|
|
16234
|
+
return new KernelError("unavailable", "spark backend was disposed after a wasm fault");
|
|
16235
|
+
};
|
|
16236
|
+
var mapError = (state, error) => {
|
|
16237
|
+
if (error instanceof KernelError) {
|
|
16238
|
+
return error;
|
|
16239
|
+
}
|
|
16240
|
+
if (isNamed(error, "WasmPoisonedError")) {
|
|
16241
|
+
return poison(state);
|
|
16242
|
+
}
|
|
16243
|
+
if (isNamed(error, "SparkInputError")) {
|
|
16244
|
+
return new KernelError("invalid-input", "spark signer rejected the request");
|
|
16245
|
+
}
|
|
16246
|
+
return new KernelError("integrity", "spark signer call failed");
|
|
16247
|
+
};
|
|
16248
|
+
var signerFor = async (state, ctx, account, requestSession) => {
|
|
16249
|
+
const { dek } = ctx.session.require(requestSession);
|
|
16250
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
16251
|
+
if (record === undefined) {
|
|
16252
|
+
disposeWallet(state, account.walletId);
|
|
16253
|
+
throw new KernelError("not-found", "no such wallet");
|
|
16254
|
+
}
|
|
16255
|
+
const existing = state.signers.get(poolKey(account));
|
|
16256
|
+
if (existing !== undefined) {
|
|
16257
|
+
return existing;
|
|
16258
|
+
}
|
|
16259
|
+
let accountKey;
|
|
16260
|
+
const rt = await sparkRuntime(state);
|
|
16261
|
+
try {
|
|
16262
|
+
accountKey = await withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => rt.sparkAccountKey(seed, account.network, account.network === "mainnet" ? account.groupIndex + 1 : account.groupIndex));
|
|
16263
|
+
} catch (error) {
|
|
16264
|
+
throw mapError(state, error);
|
|
16265
|
+
}
|
|
16266
|
+
const crypto2 = await backend(state, ctx);
|
|
16267
|
+
try {
|
|
16268
|
+
const signer = rt.createSparkSigner({
|
|
16269
|
+
crypto: crypto2,
|
|
16270
|
+
accountKey,
|
|
16271
|
+
network: account.network,
|
|
16272
|
+
random: ctx.platform.random,
|
|
16273
|
+
authorize: async (outflow) => authorizeWithCtx(state, ctx, account, outflow)
|
|
16274
|
+
});
|
|
16275
|
+
state.signers.set(poolKey(account), signer);
|
|
16276
|
+
return signer;
|
|
16277
|
+
} catch (error) {
|
|
16278
|
+
throw mapError(state, error);
|
|
16279
|
+
} finally {
|
|
16280
|
+
wipe(accountKey);
|
|
16281
|
+
}
|
|
16282
|
+
};
|
|
16283
|
+
var transferCovered = (outflow, intent) => outflow.receivers.every((receiver) => intent.receivers.some((wanted) => equalBytes(wanted.identityPublicKey, receiver.identityPublicKey) && receiver.amountSats <= wanted.amountSats));
|
|
16284
|
+
var lightningCovered = async (state, rt, key, network, outflow, approval, intent) => {
|
|
16285
|
+
const signer = state.signers.get(key);
|
|
16286
|
+
const { paymentHash } = approval.decoded;
|
|
16287
|
+
const budget = approval.decoded.invoiceAmountSats;
|
|
16288
|
+
if (signer === undefined || paymentHash === undefined || budget === undefined) {
|
|
16289
|
+
return false;
|
|
16290
|
+
}
|
|
16291
|
+
const expected = rt.lightningSendHtlcScript({
|
|
16292
|
+
paymentHash,
|
|
16293
|
+
sspIdentityPublicKey: rt.sparkNetworkConfig(network).ssp.identityPublicKey,
|
|
16294
|
+
identityPublicKey: await signer.identityPublicKey()
|
|
16295
|
+
});
|
|
16296
|
+
if (!equalBytes(expected, outflow.htlcOutputScript)) {
|
|
16297
|
+
return false;
|
|
16298
|
+
}
|
|
16299
|
+
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16300
|
+
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16301
|
+
if (total > budget + intent.maxFeeSats) {
|
|
16302
|
+
return false;
|
|
16303
|
+
}
|
|
16304
|
+
for (const leaf of fresh) {
|
|
16305
|
+
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16306
|
+
}
|
|
16307
|
+
return true;
|
|
16308
|
+
};
|
|
16309
|
+
var exitCovered = (outflow, approval, intent) => {
|
|
16310
|
+
const { addressScript } = approval.decoded;
|
|
16311
|
+
if (addressScript === undefined) {
|
|
16312
|
+
return false;
|
|
16313
|
+
}
|
|
16314
|
+
const pays = outflow.exitOutputs.some((output) => equalBytes(output.script, addressScript) && output.amountSats >= intent.amountSats);
|
|
16315
|
+
if (!pays) {
|
|
16316
|
+
return false;
|
|
16317
|
+
}
|
|
16318
|
+
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16319
|
+
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16320
|
+
if (total > intent.amountSats + intent.maxFeeSats) {
|
|
16321
|
+
return false;
|
|
16322
|
+
}
|
|
16323
|
+
for (const leaf of fresh) {
|
|
16324
|
+
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16325
|
+
}
|
|
16326
|
+
return true;
|
|
16327
|
+
};
|
|
16328
|
+
var onchainCovered = (rt, outflow, approval, intent) => {
|
|
16329
|
+
const { addressScript } = approval.decoded;
|
|
16330
|
+
if (addressScript === undefined) {
|
|
16331
|
+
return false;
|
|
16332
|
+
}
|
|
16333
|
+
const every = outflow.outputs.every((output) => equalBytes(output.script, rt.EPHEMERAL_ANCHOR_SCRIPT) || equalBytes(output.script, addressScript));
|
|
16334
|
+
if (!every) {
|
|
16335
|
+
return false;
|
|
16336
|
+
}
|
|
16337
|
+
const fee = outflow.inputSats - outflow.totalSats;
|
|
16338
|
+
return fee <= intent.maxFeeSats;
|
|
16339
|
+
};
|
|
16340
|
+
var tokenCovered = async (state, key, outflow, intent) => {
|
|
16341
|
+
const signer = state.signers.get(key);
|
|
16342
|
+
if (signer === undefined) {
|
|
16343
|
+
return false;
|
|
16344
|
+
}
|
|
16345
|
+
const identity = await signer.identityPublicKey();
|
|
16346
|
+
return outflow.outputs.every((output) => {
|
|
16347
|
+
if (equalBytes(output.ownerPublicKey, identity)) {
|
|
16348
|
+
return true;
|
|
16349
|
+
}
|
|
16350
|
+
if (!equalBytes(output.tokenIdentifier, intent.tokenIdentifier)) {
|
|
16351
|
+
return false;
|
|
16352
|
+
}
|
|
16353
|
+
return intent.receivers.some((wanted) => equalBytes(wanted.ownerPublicKey, output.ownerPublicKey) && output.amount <= BigInt(wanted.amount));
|
|
16354
|
+
});
|
|
16355
|
+
};
|
|
16356
|
+
var authorizeWithCtx = async (state, ctx, account, outflow) => {
|
|
16357
|
+
const rt = await sparkRuntime(state);
|
|
16358
|
+
if (outflow.kind === "swap") {
|
|
16359
|
+
return;
|
|
16360
|
+
}
|
|
16361
|
+
const key = poolKey(account);
|
|
16362
|
+
const live = liveApprovals(state, ctx, key);
|
|
16363
|
+
for (const approval of live) {
|
|
16364
|
+
const { intent } = approval;
|
|
16365
|
+
const covered = outflow.kind === "transfer" && intent.kind === "transfer" ? transferCovered(outflow, intent) : outflow.kind === "lightning" && intent.kind === "lightning" ? await lightningCovered(state, rt, key, account.network, outflow, approval, intent) : outflow.kind === "exit" && intent.kind === "exit" ? exitCovered(outflow, approval, intent) : outflow.kind === "onchain" && intent.kind === "onchain" ? onchainCovered(rt, outflow, approval, intent) : outflow.kind === "token" && intent.kind === "token" ? await tokenCovered(state, key, outflow, intent) : false;
|
|
16366
|
+
if (covered) {
|
|
16367
|
+
live.splice(live.indexOf(approval), 1);
|
|
16368
|
+
return;
|
|
16678
16369
|
}
|
|
16370
|
+
}
|
|
16371
|
+
throw approvalRequired();
|
|
16372
|
+
};
|
|
16373
|
+
var call = async (state, ctx, account, requestSession, run) => {
|
|
16374
|
+
const signer = await signerFor(state, ctx, account, requestSession);
|
|
16375
|
+
try {
|
|
16376
|
+
return await run(signer);
|
|
16377
|
+
} catch (error) {
|
|
16378
|
+
throw mapError(state, error);
|
|
16379
|
+
}
|
|
16380
|
+
};
|
|
16381
|
+
var sparkApprove = async (state, ctx, params, session) => {
|
|
16382
|
+
const { dek } = ctx.session.require(session);
|
|
16383
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.account.walletId);
|
|
16384
|
+
if (record === undefined) {
|
|
16385
|
+
throw new KernelError("not-found", "no such wallet");
|
|
16386
|
+
}
|
|
16387
|
+
const key = poolKey(params.account);
|
|
16388
|
+
if (liveApprovals(state, ctx, key).length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16389
|
+
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16390
|
+
}
|
|
16391
|
+
const { summary, decoded } = decodeIntent(await sparkRuntime(state), params.account, params.intent);
|
|
16392
|
+
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, () => sparkPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), summary));
|
|
16393
|
+
ctx.session.require(session);
|
|
16394
|
+
const live = liveApprovals(state, ctx, key);
|
|
16395
|
+
if (live.length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16396
|
+
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16397
|
+
}
|
|
16398
|
+
live.push({
|
|
16399
|
+
intent: params.intent,
|
|
16400
|
+
deadline: ctx.platform.elapsed() + APPROVAL_TTL_MS,
|
|
16401
|
+
decoded,
|
|
16402
|
+
summary,
|
|
16403
|
+
spentLeaves: new Map
|
|
16404
|
+
});
|
|
16405
|
+
state.approvals.set(key, live);
|
|
16406
|
+
return summary;
|
|
16407
|
+
};
|
|
16408
|
+
function createSparkModule() {
|
|
16409
|
+
const state = {
|
|
16410
|
+
signers: new Map,
|
|
16411
|
+
approvals: new Map,
|
|
16412
|
+
backendPromise: undefined,
|
|
16413
|
+
runtimePromise: undefined
|
|
16679
16414
|
};
|
|
16680
16415
|
const vault = {
|
|
16681
16416
|
ownsRecord: () => false,
|
|
@@ -16684,56 +16419,28 @@ function createSparkModule() {
|
|
|
16684
16419
|
return;
|
|
16685
16420
|
},
|
|
16686
16421
|
lock: () => {
|
|
16687
|
-
disposeAll();
|
|
16422
|
+
disposeAll(state);
|
|
16688
16423
|
},
|
|
16689
|
-
backupSecrets: () => [],
|
|
16690
|
-
backupRecords: () => [],
|
|
16691
16424
|
walletDeleteOps: (_image, walletId) => {
|
|
16692
|
-
disposeWallet(walletId);
|
|
16425
|
+
disposeWallet(state, walletId);
|
|
16693
16426
|
return [];
|
|
16694
16427
|
}
|
|
16695
16428
|
};
|
|
16696
16429
|
const handlers = {
|
|
16697
|
-
"spark.identityPublicKey": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.identityPublicKey()),
|
|
16698
|
-
"spark.publicKeys": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.publicKeys(params.keys)),
|
|
16699
|
-
"spark.receivedPublicKeys": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.receivedPublicKeys(params.ciphertexts)),
|
|
16700
|
-
"spark.newCommitments": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.newCommitments(params.count)),
|
|
16701
|
-
"spark.signFrost": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signFrost(params.jobs)),
|
|
16702
|
-
"spark.aggregateFrost": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.aggregateFrost(params.jobs)),
|
|
16703
|
-
"spark.signIdentity": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signIdentity(params.statement)),
|
|
16704
|
-
"spark.signKeySpend": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signKeySpend(params.key, params.target)),
|
|
16705
|
-
"spark.signHtlcTimeout": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signHtlcTimeout(params.request)),
|
|
16706
|
-
"spark.prepareTransfer": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareTransfer(params.request)),
|
|
16707
|
-
"spark.prepareClaim": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareClaim(params.request)),
|
|
16708
|
-
"spark.prepareLightningReceive": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareLightningReceive()),
|
|
16709
|
-
"spark.claimStaticDeposit": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.claimStaticDeposit(params.request)),
|
|
16710
|
-
"spark.approve": async (ctx, params, session) =>
|
|
16711
|
-
const { dek } = ctx.session.require(session);
|
|
16712
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.account.walletId);
|
|
16713
|
-
if (record === undefined) {
|
|
16714
|
-
throw new KernelError("not-found", "no such wallet");
|
|
16715
|
-
}
|
|
16716
|
-
const key = poolKey(params.account);
|
|
16717
|
-
if (liveApprovals(ctx, key).length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16718
|
-
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16719
|
-
}
|
|
16720
|
-
const { summary, decoded } = decodeIntent(await sparkRuntime(), params.account, params.intent);
|
|
16721
|
-
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, () => sparkPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), summary));
|
|
16722
|
-
ctx.session.require(session);
|
|
16723
|
-
const live = liveApprovals(ctx, key);
|
|
16724
|
-
if (live.length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16725
|
-
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16726
|
-
}
|
|
16727
|
-
live.push({
|
|
16728
|
-
intent: params.intent,
|
|
16729
|
-
deadline: ctx.platform.elapsed() + APPROVAL_TTL_MS,
|
|
16730
|
-
decoded,
|
|
16731
|
-
summary,
|
|
16732
|
-
spentLeaves: new Map
|
|
16733
|
-
});
|
|
16734
|
-
approvals.set(key, live);
|
|
16735
|
-
return summary;
|
|
16736
|
-
}
|
|
16430
|
+
"spark.identityPublicKey": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.identityPublicKey()),
|
|
16431
|
+
"spark.publicKeys": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.publicKeys(params.keys)),
|
|
16432
|
+
"spark.receivedPublicKeys": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.receivedPublicKeys(params.ciphertexts)),
|
|
16433
|
+
"spark.newCommitments": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.newCommitments(params.count)),
|
|
16434
|
+
"spark.signFrost": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signFrost(params.jobs)),
|
|
16435
|
+
"spark.aggregateFrost": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.aggregateFrost(params.jobs)),
|
|
16436
|
+
"spark.signIdentity": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signIdentity(params.statement)),
|
|
16437
|
+
"spark.signKeySpend": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signKeySpend(params.key, params.target)),
|
|
16438
|
+
"spark.signHtlcTimeout": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signHtlcTimeout(params.request)),
|
|
16439
|
+
"spark.prepareTransfer": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareTransfer(params.request)),
|
|
16440
|
+
"spark.prepareClaim": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareClaim(params.request)),
|
|
16441
|
+
"spark.prepareLightningReceive": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareLightningReceive()),
|
|
16442
|
+
"spark.claimStaticDeposit": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.claimStaticDeposit(params.request)),
|
|
16443
|
+
"spark.approve": async (ctx, params, session) => sparkApprove(state, ctx, params, session)
|
|
16737
16444
|
};
|
|
16738
16445
|
return { vault, handlers };
|
|
16739
16446
|
}
|
|
@@ -17516,17 +17223,6 @@ function createIndexedDbStore() {
|
|
|
17516
17223
|
};
|
|
17517
17224
|
}
|
|
17518
17225
|
|
|
17519
|
-
// src/worker/spark.ts
|
|
17520
|
-
async function loadSparkBackend(readWasm) {
|
|
17521
|
-
const { loadSparkWasm, SPARK_WASM_INTEGRITY } = await (__preload("1vpxmqwn"), import("./browser-1vpxmqwn.js"));
|
|
17522
|
-
const bytes = await readWasm();
|
|
17523
|
-
const integrity = `sha256-${base64.encode(sha256(bytes))}`;
|
|
17524
|
-
if (integrity !== SPARK_WASM_INTEGRITY) {
|
|
17525
|
-
throw new KernelError("integrity", "spark.wasm failed the integrity check");
|
|
17526
|
-
}
|
|
17527
|
-
return loadSparkWasm({ module: bytes });
|
|
17528
|
-
}
|
|
17529
|
-
|
|
17530
17226
|
// src/worker/subtle.ts
|
|
17531
17227
|
var SUBTLE_HASH = {
|
|
17532
17228
|
sha256: "SHA-256",
|
|
@@ -17544,6 +17240,33 @@ var subtlePbkdf2 = async (hash, password, salt, iterations, length) => {
|
|
|
17544
17240
|
}
|
|
17545
17241
|
};
|
|
17546
17242
|
|
|
17243
|
+
// src/worker/platform.ts
|
|
17244
|
+
var basePlatform = () => ({
|
|
17245
|
+
random: (length) => crypto.getRandomValues(new Uint8Array(length)),
|
|
17246
|
+
now: () => Date.now(),
|
|
17247
|
+
elapsed: () => performance.now(),
|
|
17248
|
+
setTimer: (delayMs, fn) => {
|
|
17249
|
+
const timer = setTimeout(fn, delayMs);
|
|
17250
|
+
return () => {
|
|
17251
|
+
clearTimeout(timer);
|
|
17252
|
+
};
|
|
17253
|
+
},
|
|
17254
|
+
pbkdf2: subtlePbkdf2,
|
|
17255
|
+
keystore: undefined,
|
|
17256
|
+
passkey: undefined
|
|
17257
|
+
});
|
|
17258
|
+
|
|
17259
|
+
// src/worker/spark.ts
|
|
17260
|
+
async function loadSparkBackend(readWasm) {
|
|
17261
|
+
const { loadSparkWasm, SPARK_WASM_INTEGRITY } = await (__preload("1vpxmqwn"), import("./browser-1vpxmqwn.js"));
|
|
17262
|
+
const bytes = await readWasm();
|
|
17263
|
+
const integrity = `sha256-${base64.encode(sha256(bytes))}`;
|
|
17264
|
+
if (integrity !== SPARK_WASM_INTEGRITY) {
|
|
17265
|
+
throw new KernelError("integrity", "spark.wasm failed the integrity check");
|
|
17266
|
+
}
|
|
17267
|
+
return loadSparkWasm({ module: bytes });
|
|
17268
|
+
}
|
|
17269
|
+
|
|
17547
17270
|
// src/worker/worker.ts
|
|
17548
17271
|
var onInit = (event) => {
|
|
17549
17272
|
const { data } = event;
|
|
@@ -17552,19 +17275,8 @@ var onInit = (event) => {
|
|
|
17552
17275
|
}
|
|
17553
17276
|
removeEventListener("message", onInit);
|
|
17554
17277
|
const platform = {
|
|
17555
|
-
|
|
17556
|
-
now: () => Date.now(),
|
|
17557
|
-
elapsed: () => performance.now(),
|
|
17558
|
-
setTimer: (delayMs, fn) => {
|
|
17559
|
-
const timer = setTimeout(fn, delayMs);
|
|
17560
|
-
return () => {
|
|
17561
|
-
clearTimeout(timer);
|
|
17562
|
-
};
|
|
17563
|
-
},
|
|
17564
|
-
pbkdf2: subtlePbkdf2,
|
|
17278
|
+
...basePlatform(),
|
|
17565
17279
|
store: createIndexedDbStore(),
|
|
17566
|
-
keystore: undefined,
|
|
17567
|
-
passkey: undefined,
|
|
17568
17280
|
policy: {
|
|
17569
17281
|
idle: { ms: idleMsOf(data.idleMinutes), activity: "presence" },
|
|
17570
17282
|
maxSessionMs: MAX_SESSION_MS,
|