@qntx/wallet-worker 0.5.2 → 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.node.js
CHANGED
|
@@ -72,9 +72,6 @@ import { parentPort, workerData } from "node:worker_threads";
|
|
|
72
72
|
var NostrError = class extends Error {
|
|
73
73
|
name = "NostrError";
|
|
74
74
|
};
|
|
75
|
-
function errorMessage(error) {
|
|
76
|
-
return error instanceof Error ? error.message : String(error);
|
|
77
|
-
}
|
|
78
75
|
var HexError = class extends NostrError {
|
|
79
76
|
name = "HexError";
|
|
80
77
|
};
|
|
@@ -1829,7 +1826,7 @@ class KernelError extends Error {
|
|
|
1829
1826
|
this.corrupted = corrupted;
|
|
1830
1827
|
}
|
|
1831
1828
|
}
|
|
1832
|
-
// ../wallet/dist/core-
|
|
1829
|
+
// ../wallet/dist/core-Cq5h9X0X.mjs
|
|
1833
1830
|
var ValidationError = class extends Error {
|
|
1834
1831
|
name = "ValidationError";
|
|
1835
1832
|
};
|
|
@@ -1970,6 +1967,7 @@ var publicKey = str(64, /^[0-9a-f]{64}$/);
|
|
|
1970
1967
|
var credentialId = str(1364, /^[A-Za-z0-9_-]+$/);
|
|
1971
1968
|
var safeTime = int(0, Number.MAX_SAFE_INTEGER);
|
|
1972
1969
|
var groupIndex = int(0, 2147483647);
|
|
1970
|
+
var identityIndex = int(0, 2147483646);
|
|
1973
1971
|
var factor = union(obj({ kind: literal("hardware") }), obj({
|
|
1974
1972
|
kind: literal("password"),
|
|
1975
1973
|
password: bytes(1, 1024)
|
|
@@ -2196,7 +2194,7 @@ var CORE_METHODS = {
|
|
|
2196
2194
|
}
|
|
2197
2195
|
};
|
|
2198
2196
|
|
|
2199
|
-
// ../wallet/dist/protocol-
|
|
2197
|
+
// ../wallet/dist/protocol-DbpLncEB.mjs
|
|
2200
2198
|
var MAX_FACTOR_CHARS = 512;
|
|
2201
2199
|
var MAX_STRING_BYTES = 64000;
|
|
2202
2200
|
var MAX_PAYLOAD_CHARS = 1400000;
|
|
@@ -2218,15 +2216,11 @@ var backupEnvelope = obj({
|
|
|
2218
2216
|
factors: arr(backupEnvelopeFactor, 5, 1),
|
|
2219
2217
|
payload: str(MAX_PAYLOAD_CHARS)
|
|
2220
2218
|
});
|
|
2221
|
-
var backupHeader = obj({
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
}), 1000),
|
|
2227
|
-
importedNostrKeyCount: int(0, 1e4),
|
|
2228
|
-
importedChainKeyCount: int(0, 1e4)
|
|
2229
|
-
});
|
|
2219
|
+
var backupHeader = obj({ wallets: arr(obj({
|
|
2220
|
+
walletId: str(128),
|
|
2221
|
+
origin: union(literal("mnemonic"), literal("passkey")),
|
|
2222
|
+
words: union(literal(12), literal(15), literal(18), literal(21), literal(24))
|
|
2223
|
+
}), 1000) });
|
|
2230
2224
|
var backupEnvelopeText = str(MAX_ENVELOPE_CHARS);
|
|
2231
2225
|
var backupInfo = obj({
|
|
2232
2226
|
id: str(32, /^[0-9a-f]{32}$/),
|
|
@@ -2375,36 +2369,19 @@ var CHAINS_METHODS = {
|
|
|
2375
2369
|
}
|
|
2376
2370
|
};
|
|
2377
2371
|
var hex128 = str(128, /^[0-9a-f]{128}$/);
|
|
2378
|
-
var nostrKeyRef =
|
|
2372
|
+
var nostrKeyRef = obj({
|
|
2379
2373
|
kind: literal("derived"),
|
|
2380
2374
|
walletId,
|
|
2381
|
-
|
|
2382
|
-
})
|
|
2383
|
-
|
|
2384
|
-
id: publicKey
|
|
2385
|
-
}), obj({
|
|
2386
|
-
kind: literal("nip46-client"),
|
|
2387
|
-
id: publicKey
|
|
2388
|
-
}));
|
|
2389
|
-
var nostrKeyInfo = union(obj({
|
|
2390
|
-
ref: nostrKeyRef,
|
|
2391
|
-
publicKey,
|
|
2392
|
-
origin: union(literal("nsec"), literal("ncryptsec"), literal("generated")),
|
|
2393
|
-
backedUp: bool,
|
|
2394
|
-
createdAt: safeTime
|
|
2395
|
-
}), obj({
|
|
2375
|
+
index: identityIndex
|
|
2376
|
+
});
|
|
2377
|
+
var nostrKeyInfo = obj({
|
|
2396
2378
|
ref: nostrKeyRef,
|
|
2397
2379
|
publicKey,
|
|
2398
|
-
origin: union(literal("derived"), literal("nip46-client")),
|
|
2399
2380
|
createdAt: safeTime
|
|
2400
|
-
}));
|
|
2401
|
-
var nostrStatus = obj({ keys: arr(nostrKeyInfo, MAX_SNAPSHOT_ITEMS) });
|
|
2402
|
-
var keyResult = obj({
|
|
2403
|
-
key: nostrKeyInfo,
|
|
2404
|
-
session: sessionId
|
|
2405
2381
|
});
|
|
2382
|
+
var nostrStatus = obj({ keys: arr(nostrKeyInfo, MAX_SNAPSHOT_ITEMS) });
|
|
2406
2383
|
var derivedNostrKey = obj({
|
|
2407
|
-
|
|
2384
|
+
index: identityIndex,
|
|
2408
2385
|
publicKey
|
|
2409
2386
|
});
|
|
2410
2387
|
var tags = arr(arr(str(MAX_TAG_ITEM), 64), MAX_TAGS);
|
|
@@ -2432,14 +2409,6 @@ var rumor = obj({
|
|
|
2432
2409
|
tags,
|
|
2433
2410
|
content: str(MAX_TEXT)
|
|
2434
2411
|
});
|
|
2435
|
-
var nostrImportInput = union(obj({
|
|
2436
|
-
kind: literal("nsec"),
|
|
2437
|
-
nsec: bytes(1, 256)
|
|
2438
|
-
}), obj({
|
|
2439
|
-
kind: literal("ncryptsec"),
|
|
2440
|
-
ncryptsec: str(512, /^ncryptsec1/),
|
|
2441
|
-
password: bytes(1, 1024)
|
|
2442
|
-
}));
|
|
2443
2412
|
var nostrExportFormat = union(obj({ kind: literal("nsec") }), obj({
|
|
2444
2413
|
kind: literal("ncryptsec"),
|
|
2445
2414
|
password: bytes(1, 1024)
|
|
@@ -2456,7 +2425,7 @@ var NOSTR_METHODS = {
|
|
|
2456
2425
|
presence: false,
|
|
2457
2426
|
params: obj({
|
|
2458
2427
|
walletId,
|
|
2459
|
-
from:
|
|
2428
|
+
from: identityIndex,
|
|
2460
2429
|
count: int(1, 20)
|
|
2461
2430
|
}),
|
|
2462
2431
|
result: obj({ keys: arr(derivedNostrKey, 20) })
|
|
@@ -2466,38 +2435,14 @@ var NOSTR_METHODS = {
|
|
|
2466
2435
|
presence: false,
|
|
2467
2436
|
params: obj({
|
|
2468
2437
|
walletId,
|
|
2469
|
-
|
|
2470
|
-
}),
|
|
2471
|
-
result: nostrKeyInfo
|
|
2472
|
-
},
|
|
2473
|
-
"nostr.importKey": {
|
|
2474
|
-
session: false,
|
|
2475
|
-
presence: true,
|
|
2476
|
-
params: obj({
|
|
2477
|
-
input: nostrImportInput,
|
|
2478
|
-
factor: opt(factor)
|
|
2438
|
+
index: identityIndex
|
|
2479
2439
|
}),
|
|
2480
|
-
result: keyResult
|
|
2481
|
-
},
|
|
2482
|
-
"nostr.generateKey": {
|
|
2483
|
-
session: false,
|
|
2484
|
-
presence: true,
|
|
2485
|
-
params: obj({ factor: opt(factor) }),
|
|
2486
|
-
result: keyResult
|
|
2487
|
-
},
|
|
2488
|
-
"nostr.createNip46ClientKey": {
|
|
2489
|
-
session: true,
|
|
2490
|
-
presence: false,
|
|
2491
|
-
params: nullValue,
|
|
2492
2440
|
result: nostrKeyInfo
|
|
2493
2441
|
},
|
|
2494
2442
|
"nostr.removeKey": {
|
|
2495
2443
|
session: true,
|
|
2496
2444
|
presence: true,
|
|
2497
|
-
params: obj({
|
|
2498
|
-
publicKey,
|
|
2499
|
-
verify: opt(factor)
|
|
2500
|
-
}),
|
|
2445
|
+
params: obj({ publicKey }),
|
|
2501
2446
|
result: nullValue
|
|
2502
2447
|
},
|
|
2503
2448
|
"nostr.exportKey": {
|
|
@@ -2551,6 +2496,39 @@ var NOSTR_METHODS = {
|
|
|
2551
2496
|
events: arr(signedEvent, 64)
|
|
2552
2497
|
}),
|
|
2553
2498
|
result: obj({ results: arr(union(obj({ ok: rumor }), obj({ err: walletErrorCode })), 64) })
|
|
2499
|
+
},
|
|
2500
|
+
"nostr.syncKey": {
|
|
2501
|
+
session: true,
|
|
2502
|
+
presence: false,
|
|
2503
|
+
params: obj({ walletId }),
|
|
2504
|
+
result: obj({ publicKey })
|
|
2505
|
+
},
|
|
2506
|
+
"nostr.syncSign": {
|
|
2507
|
+
session: true,
|
|
2508
|
+
presence: false,
|
|
2509
|
+
params: obj({
|
|
2510
|
+
walletId,
|
|
2511
|
+
event: signEventInput
|
|
2512
|
+
}),
|
|
2513
|
+
result: signedEvent
|
|
2514
|
+
},
|
|
2515
|
+
"nostr.syncEncrypt": {
|
|
2516
|
+
session: true,
|
|
2517
|
+
presence: false,
|
|
2518
|
+
params: obj({
|
|
2519
|
+
walletId,
|
|
2520
|
+
text: str(MAX_TEXT)
|
|
2521
|
+
}),
|
|
2522
|
+
result: textResult
|
|
2523
|
+
},
|
|
2524
|
+
"nostr.syncDecrypt": {
|
|
2525
|
+
session: true,
|
|
2526
|
+
presence: false,
|
|
2527
|
+
params: obj({
|
|
2528
|
+
walletId,
|
|
2529
|
+
text: str(MAX_TEXT * 4)
|
|
2530
|
+
}),
|
|
2531
|
+
result: textResult
|
|
2554
2532
|
}
|
|
2555
2533
|
};
|
|
2556
2534
|
var MAX_LEAVES = 256;
|
|
@@ -2736,6 +2714,27 @@ var decimalU128 = (value) => {
|
|
|
2736
2714
|
throw new ValidationError;
|
|
2737
2715
|
return value;
|
|
2738
2716
|
};
|
|
2717
|
+
var outflowIntents = [
|
|
2718
|
+
obj({
|
|
2719
|
+
kind: literal("exit"),
|
|
2720
|
+
address: str(128),
|
|
2721
|
+
amountSats: satsAmount(),
|
|
2722
|
+
maxFeeSats: satsAmount()
|
|
2723
|
+
}),
|
|
2724
|
+
obj({
|
|
2725
|
+
kind: literal("onchain"),
|
|
2726
|
+
address: str(128),
|
|
2727
|
+
maxFeeSats: satsAmount()
|
|
2728
|
+
}),
|
|
2729
|
+
obj({
|
|
2730
|
+
kind: literal("token"),
|
|
2731
|
+
tokenIdentifier: bytes(32),
|
|
2732
|
+
receivers: arr(obj({
|
|
2733
|
+
ownerPublicKey: bytes(33),
|
|
2734
|
+
amount: decimalU128
|
|
2735
|
+
}), 256, 1)
|
|
2736
|
+
})
|
|
2737
|
+
];
|
|
2739
2738
|
var approveIntent = union(obj({
|
|
2740
2739
|
kind: literal("transfer"),
|
|
2741
2740
|
receivers: arr(obj({
|
|
@@ -2747,23 +2746,7 @@ var approveIntent = union(obj({
|
|
|
2747
2746
|
invoice: str(4096),
|
|
2748
2747
|
amountSats: opt(satsAmount()),
|
|
2749
2748
|
maxFeeSats: satsAmount()
|
|
2750
|
-
}),
|
|
2751
|
-
kind: literal("exit"),
|
|
2752
|
-
address: str(128),
|
|
2753
|
-
amountSats: satsAmount(),
|
|
2754
|
-
maxFeeSats: satsAmount()
|
|
2755
|
-
}), obj({
|
|
2756
|
-
kind: literal("onchain"),
|
|
2757
|
-
address: str(128),
|
|
2758
|
-
maxFeeSats: satsAmount()
|
|
2759
|
-
}), obj({
|
|
2760
|
-
kind: literal("token"),
|
|
2761
|
-
tokenIdentifier: bytes(32),
|
|
2762
|
-
receivers: arr(obj({
|
|
2763
|
-
ownerPublicKey: bytes(33),
|
|
2764
|
-
amount: decimalU128
|
|
2765
|
-
}), 256, 1)
|
|
2766
|
-
}));
|
|
2749
|
+
}), ...outflowIntents);
|
|
2767
2750
|
var approvalSummary = union(obj({
|
|
2768
2751
|
kind: literal("transfer"),
|
|
2769
2752
|
receivers: arr(obj({
|
|
@@ -2775,23 +2758,7 @@ var approvalSummary = union(obj({
|
|
|
2775
2758
|
paymentHash: bytes(32),
|
|
2776
2759
|
invoiceAmountSats: opt(satsAmount()),
|
|
2777
2760
|
maxFeeSats: satsAmount()
|
|
2778
|
-
}),
|
|
2779
|
-
kind: literal("exit"),
|
|
2780
|
-
address: str(128),
|
|
2781
|
-
amountSats: satsAmount(),
|
|
2782
|
-
maxFeeSats: satsAmount()
|
|
2783
|
-
}), obj({
|
|
2784
|
-
kind: literal("onchain"),
|
|
2785
|
-
address: str(128),
|
|
2786
|
-
maxFeeSats: satsAmount()
|
|
2787
|
-
}), obj({
|
|
2788
|
-
kind: literal("token"),
|
|
2789
|
-
tokenIdentifier: bytes(32),
|
|
2790
|
-
receivers: arr(obj({
|
|
2791
|
-
ownerPublicKey: bytes(33),
|
|
2792
|
-
amount: decimalU128
|
|
2793
|
-
}), 256, 1)
|
|
2794
|
-
}));
|
|
2761
|
+
}), ...outflowIntents);
|
|
2795
2762
|
var SPARK_METHODS = {
|
|
2796
2763
|
"spark.identityPublicKey": {
|
|
2797
2764
|
session: true,
|
|
@@ -2916,7 +2883,7 @@ var SPARK_METHODS = {
|
|
|
2916
2883
|
result: approvalSummary
|
|
2917
2884
|
}
|
|
2918
2885
|
};
|
|
2919
|
-
var PROTOCOL_VERSION =
|
|
2886
|
+
var PROTOCOL_VERSION = 2;
|
|
2920
2887
|
var UNATTRIBUTED_ID = 0;
|
|
2921
2888
|
var MAX_REQUEST_BYTES = 1048576;
|
|
2922
2889
|
function requestBytes(value) {
|
|
@@ -2966,7 +2933,7 @@ function isProtocolValue(value) {
|
|
|
2966
2933
|
return Object.values(value).every(isProtocolValue);
|
|
2967
2934
|
}
|
|
2968
2935
|
var statusPayload = obj({
|
|
2969
|
-
protocol: literal(
|
|
2936
|
+
protocol: literal(2),
|
|
2970
2937
|
vault: union(literal("uninitialized"), literal("locked"), literal("unlocked"), literal("corrupted"), literal("unsupported"), literal("unavailable")),
|
|
2971
2938
|
factors: arr(factorInfo, MAX_SNAPSHOT_ITEMS),
|
|
2972
2939
|
wallets: arr(walletInfo, MAX_SNAPSHOT_ITEMS),
|
|
@@ -2991,11 +2958,11 @@ var errorPayload = obj({
|
|
|
2991
2958
|
retryAt: opt(safeTime)
|
|
2992
2959
|
});
|
|
2993
2960
|
var kernelEvent = union(obj({
|
|
2994
|
-
v: literal(
|
|
2961
|
+
v: literal(2),
|
|
2995
2962
|
event: literal("status"),
|
|
2996
2963
|
status: statusPayload
|
|
2997
2964
|
}), obj({
|
|
2998
|
-
v: literal(
|
|
2965
|
+
v: literal(2),
|
|
2999
2966
|
event: literal("locked"),
|
|
3000
2967
|
reason: lockReason
|
|
3001
2968
|
}));
|
|
@@ -3929,14 +3896,8 @@ function asPublicKey(value) {
|
|
|
3929
3896
|
}
|
|
3930
3897
|
return value;
|
|
3931
3898
|
}
|
|
3932
|
-
function
|
|
3933
|
-
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value >
|
|
3934
|
-
throw headerFailure();
|
|
3935
|
-
}
|
|
3936
|
-
return value;
|
|
3937
|
-
}
|
|
3938
|
-
function asBoolean(value) {
|
|
3939
|
-
if (typeof value !== "boolean") {
|
|
3899
|
+
function asIdentityIndex(value) {
|
|
3900
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > 2147483646) {
|
|
3940
3901
|
throw headerFailure();
|
|
3941
3902
|
}
|
|
3942
3903
|
return value;
|
|
@@ -4250,7 +4211,7 @@ var RECORD_KIND_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
|
|
|
4250
4211
|
function isRecordKind(kind) {
|
|
4251
4212
|
return RECORD_KIND_PATTERN.test(kind);
|
|
4252
4213
|
}
|
|
4253
|
-
var VAULT_FORMAT =
|
|
4214
|
+
var VAULT_FORMAT = 3;
|
|
4254
4215
|
|
|
4255
4216
|
// ../wallet-kernel/src/vault/vault.ts
|
|
4256
4217
|
var BACKOFF_MS = [30000, 60000, 300000];
|
|
@@ -6877,6 +6838,14 @@ async function seedFromMnemonic(mnemonic, passphrase, pbkdf2) {
|
|
|
6877
6838
|
async function seedFromEntropy(entropy, pbkdf2) {
|
|
6878
6839
|
return seedFromMnemonic(mnemonicFromEntropy(entropy), "", pbkdf2);
|
|
6879
6840
|
}
|
|
6841
|
+
async function withSeed(pbkdf2, entropy, use) {
|
|
6842
|
+
const seed = await seedFromEntropy(entropy, pbkdf2);
|
|
6843
|
+
try {
|
|
6844
|
+
return await use(seed);
|
|
6845
|
+
} finally {
|
|
6846
|
+
wipe(seed);
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6880
6849
|
|
|
6881
6850
|
// ../wallet-kernel/src/session/session.ts
|
|
6882
6851
|
function wipePendingFactor(pending) {
|
|
@@ -7050,6 +7019,14 @@ class Session {
|
|
|
7050
7019
|
}
|
|
7051
7020
|
|
|
7052
7021
|
// ../wallet-kernel/src/commands/vault.ts
|
|
7022
|
+
async function withWalletSeed(pbkdf2, dek, record, use) {
|
|
7023
|
+
const entropy = openRecord(dek, record);
|
|
7024
|
+
try {
|
|
7025
|
+
return await withSeed(pbkdf2, entropy, use);
|
|
7026
|
+
} finally {
|
|
7027
|
+
wipe(entropy);
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7053
7030
|
var EMPTY_IMAGE = { meta: undefined, records: [], factors: [] };
|
|
7054
7031
|
async function unlockVault(ctx, params) {
|
|
7055
7032
|
await ctx.reload();
|
|
@@ -7134,13 +7111,10 @@ async function removeFactor(ctx, params, requestSession) {
|
|
|
7134
7111
|
|
|
7135
7112
|
// ../wallet-kernel/src/commands/wallets.ts
|
|
7136
7113
|
async function deriveWalletMaterial(platform, entropy) {
|
|
7137
|
-
|
|
7138
|
-
try {
|
|
7114
|
+
return withSeed(platform.pbkdf2, entropy, (seed) => {
|
|
7139
7115
|
const master = masterKey(seed);
|
|
7140
7116
|
return { master, walletId: walletIdOf(master) };
|
|
7141
|
-
}
|
|
7142
|
-
wipe(seed);
|
|
7143
|
-
}
|
|
7117
|
+
});
|
|
7144
7118
|
}
|
|
7145
7119
|
async function walletMaterial(platform, entropy, origin, words) {
|
|
7146
7120
|
const { master, walletId } = await deriveWalletMaterial(platform, entropy);
|
|
@@ -7480,13 +7454,11 @@ function parseHeader(text) {
|
|
|
7480
7454
|
return header;
|
|
7481
7455
|
}
|
|
7482
7456
|
var PAYLOAD_WALLET = 1;
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
function encodePayload(wallets, nostrSecrets) {
|
|
7486
|
-
const size = 1 + wallets.reduce((acc, w) => acc + 3 + w.entropy.length, 0) + nostrSecrets.length * 33;
|
|
7457
|
+
function encodePayload(wallets) {
|
|
7458
|
+
const size = 1 + wallets.reduce((acc, w) => acc + 3 + w.entropy.length, 0);
|
|
7487
7459
|
const out = new Uint8Array(size);
|
|
7488
7460
|
let off = 0;
|
|
7489
|
-
out[off++] =
|
|
7461
|
+
out[off++] = 2;
|
|
7490
7462
|
for (const w of wallets) {
|
|
7491
7463
|
out[off++] = PAYLOAD_WALLET;
|
|
7492
7464
|
out[off++] = ORIGIN_BYTE[w.origin] ?? 0;
|
|
@@ -7494,19 +7466,13 @@ function encodePayload(wallets, nostrSecrets) {
|
|
|
7494
7466
|
out.set(w.entropy, off);
|
|
7495
7467
|
off += w.entropy.length;
|
|
7496
7468
|
}
|
|
7497
|
-
for (const s of nostrSecrets) {
|
|
7498
|
-
out[off++] = PAYLOAD_NOSTR;
|
|
7499
|
-
out.set(s, off);
|
|
7500
|
-
off += s.length;
|
|
7501
|
-
}
|
|
7502
7469
|
return out;
|
|
7503
7470
|
}
|
|
7504
7471
|
function decodePayload2(bytes) {
|
|
7505
|
-
if (bytes.length === 0 || bytes[0] !==
|
|
7472
|
+
if (bytes.length === 0 || bytes[0] !== 2) {
|
|
7506
7473
|
throw new KernelError("integrity", "backup: bad payload version");
|
|
7507
7474
|
}
|
|
7508
7475
|
const wallets = [];
|
|
7509
|
-
const nostrSecrets = [];
|
|
7510
7476
|
let off = 1;
|
|
7511
7477
|
while (off < bytes.length) {
|
|
7512
7478
|
const tag = bytes[off++];
|
|
@@ -7526,17 +7492,6 @@ function decodePayload2(bytes) {
|
|
|
7526
7492
|
}
|
|
7527
7493
|
wallets.push({ origin, entropy: bytes.slice(off, off + len) });
|
|
7528
7494
|
off += len;
|
|
7529
|
-
} else if (tag === PAYLOAD_NOSTR) {
|
|
7530
|
-
if (off + 32 > bytes.length) {
|
|
7531
|
-
throw new KernelError("integrity", "backup: truncated payload");
|
|
7532
|
-
}
|
|
7533
|
-
nostrSecrets.push(bytes.slice(off, off + 32));
|
|
7534
|
-
off += 32;
|
|
7535
|
-
} else if (tag === PAYLOAD_CHAIN) {
|
|
7536
|
-
if (off + 33 > bytes.length) {
|
|
7537
|
-
throw new KernelError("integrity", "backup: truncated payload");
|
|
7538
|
-
}
|
|
7539
|
-
off += 33;
|
|
7540
7495
|
} else {
|
|
7541
7496
|
throw new KernelError("integrity", "backup: unknown payload tag");
|
|
7542
7497
|
}
|
|
@@ -7544,7 +7499,7 @@ function decodePayload2(bytes) {
|
|
|
7544
7499
|
if (off !== bytes.length) {
|
|
7545
7500
|
throw new KernelError("integrity", "backup: payload length mismatch");
|
|
7546
7501
|
}
|
|
7547
|
-
return { wallets
|
|
7502
|
+
return { wallets };
|
|
7548
7503
|
}
|
|
7549
7504
|
function collectContents(ctx, dek) {
|
|
7550
7505
|
const wallets = [];
|
|
@@ -7567,13 +7522,10 @@ function collectContents(ctx, dek) {
|
|
|
7567
7522
|
throw error;
|
|
7568
7523
|
}
|
|
7569
7524
|
}
|
|
7570
|
-
const nostrSecrets = ctx.modules.flatMap((module) => module.backupSecrets(ctx.image, dek));
|
|
7571
7525
|
const header = JSON.stringify({
|
|
7572
|
-
wallets: wallets.map(({ walletId, origin, words }) => ({ walletId, origin, words }))
|
|
7573
|
-
importedNostrKeyCount: nostrSecrets.length,
|
|
7574
|
-
importedChainKeyCount: 0
|
|
7526
|
+
wallets: wallets.map(({ walletId, origin, words }) => ({ walletId, origin, words }))
|
|
7575
7527
|
});
|
|
7576
|
-
return { wallets,
|
|
7528
|
+
return { wallets, header };
|
|
7577
7529
|
} catch (error) {
|
|
7578
7530
|
for (const wallet of wallets) {
|
|
7579
7531
|
wallet.entropy.fill(0);
|
|
@@ -7585,9 +7537,6 @@ function wipeContents(contents) {
|
|
|
7585
7537
|
for (const wallet of contents.wallets) {
|
|
7586
7538
|
wallet.entropy.fill(0);
|
|
7587
7539
|
}
|
|
7588
|
-
for (const secretKey of contents.nostrSecrets) {
|
|
7589
|
-
secretKey.fill(0);
|
|
7590
|
-
}
|
|
7591
7540
|
}
|
|
7592
7541
|
var PURPOSE_PROTECTION = 2;
|
|
7593
7542
|
function backupMaterialOf(result) {
|
|
@@ -7710,7 +7659,7 @@ function updateBackup(ctx, _params, requestSession) {
|
|
|
7710
7659
|
const bek = openRecord(dek, record);
|
|
7711
7660
|
const contents = collectContents(ctx, dek);
|
|
7712
7661
|
try {
|
|
7713
|
-
const plaintext = encodePayload(contents.wallets
|
|
7662
|
+
const plaintext = encodePayload(contents.wallets);
|
|
7714
7663
|
const sealedPayload = seal(bek, plaintext, payloadContext(contents.header), "", ctx.platform.random);
|
|
7715
7664
|
try {
|
|
7716
7665
|
const envelope = {
|
|
@@ -7780,7 +7729,7 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7780
7729
|
}
|
|
7781
7730
|
const header = parseHeader(envelope.header);
|
|
7782
7731
|
const decoded = decodePayload2(plaintext);
|
|
7783
|
-
if (decoded.
|
|
7732
|
+
if (decoded.wallets.length !== header.wallets.length) {
|
|
7784
7733
|
plaintext.fill(0);
|
|
7785
7734
|
throw new KernelError("integrity", "backup: payload does not match header");
|
|
7786
7735
|
}
|
|
@@ -7812,9 +7761,6 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7812
7761
|
records.push(record);
|
|
7813
7762
|
restored.push(walletInfoOf(material, backup, now));
|
|
7814
7763
|
}
|
|
7815
|
-
for (const module of ctx.modules) {
|
|
7816
|
-
records.push(...module.backupRecords(ctx.platform, ctx.image, gated.dek, decoded.nostrSecrets, now));
|
|
7817
|
-
}
|
|
7818
7764
|
if (gated.uninitialized) {
|
|
7819
7765
|
records.push(backupKeyRecord(ctx, gated.dek, bek, envelope.factors));
|
|
7820
7766
|
}
|
|
@@ -7832,9 +7778,6 @@ async function restoreBackup(ctx, params, requestSession) {
|
|
|
7832
7778
|
for (const wallet of decoded.wallets) {
|
|
7833
7779
|
wallet.entropy.fill(0);
|
|
7834
7780
|
}
|
|
7835
|
-
for (const secretKey of decoded.nostrSecrets) {
|
|
7836
|
-
secretKey.fill(0);
|
|
7837
|
-
}
|
|
7838
7781
|
}
|
|
7839
7782
|
} finally {
|
|
7840
7783
|
bek.fill(0);
|
|
@@ -8034,7 +7977,30 @@ var ChainError = class extends Error {
|
|
|
8034
7977
|
}
|
|
8035
7978
|
};
|
|
8036
7979
|
|
|
8037
|
-
// ../wallet-chains/dist/
|
|
7980
|
+
// ../wallet-chains/dist/account-ref-C2qrDbVT.mjs
|
|
7981
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7982
|
+
var isAccountRef = (value) => {
|
|
7983
|
+
if (!isRecord2(value) || typeof value["kind"] !== "string")
|
|
7984
|
+
return false;
|
|
7985
|
+
if (value["kind"] === "hd")
|
|
7986
|
+
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
7987
|
+
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
7988
|
+
};
|
|
7989
|
+
var requestBase = (request) => {
|
|
7990
|
+
if (!isRecord2(request))
|
|
7991
|
+
throw new ChainError("invalid-request", "request must be an object");
|
|
7992
|
+
const { network, account } = request;
|
|
7993
|
+
if (typeof network !== "string")
|
|
7994
|
+
throw new ChainError("invalid-request", "request.network must be a string");
|
|
7995
|
+
if (!isAccountRef(account))
|
|
7996
|
+
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
7997
|
+
return {
|
|
7998
|
+
network,
|
|
7999
|
+
account
|
|
8000
|
+
};
|
|
8001
|
+
};
|
|
8002
|
+
|
|
8003
|
+
// ../wallet-chains/dist/message-DuJ5KSRT.mjs
|
|
8038
8004
|
var MAINNET_BIP32 = {
|
|
8039
8005
|
public: 76067358,
|
|
8040
8006
|
private: 76066276
|
|
@@ -8185,15 +8151,15 @@ var signLegacyMessage = (message, privateKey) => {
|
|
|
8185
8151
|
};
|
|
8186
8152
|
|
|
8187
8153
|
// ../wallet-chains/dist/bitcoin.mjs
|
|
8188
|
-
var isRecord$
|
|
8154
|
+
var isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8189
8155
|
var derivationPaths = (map) => {
|
|
8190
|
-
const entries = map instanceof Map ? [...map.values()] : Array.isArray(map) ? map : isRecord$
|
|
8156
|
+
const entries = map instanceof Map ? [...map.values()] : Array.isArray(map) ? map : isRecord$1(map) ? Object.values(map) : [];
|
|
8191
8157
|
const paths = [];
|
|
8192
8158
|
for (const entry of entries) {
|
|
8193
8159
|
const value = Array.isArray(entry) ? entry[1] : entry;
|
|
8194
|
-
if (!isRecord$
|
|
8160
|
+
if (!isRecord$1(value))
|
|
8195
8161
|
continue;
|
|
8196
|
-
const { path } = isRecord$
|
|
8162
|
+
const { path } = isRecord$1(value["der"]) ? value["der"] : value;
|
|
8197
8163
|
if (Array.isArray(path) && path.every((p) => typeof p === "number"))
|
|
8198
8164
|
paths.push(path);
|
|
8199
8165
|
}
|
|
@@ -8332,26 +8298,10 @@ var decodeBitcoinPsbt = (request, ownScripts = /* @__PURE__ */ new Set) => {
|
|
|
8332
8298
|
verifiability
|
|
8333
8299
|
};
|
|
8334
8300
|
};
|
|
8335
|
-
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8336
|
-
var isAccountRef = (value) => {
|
|
8337
|
-
if (!isRecord2(value) || typeof value["kind"] !== "string")
|
|
8338
|
-
return false;
|
|
8339
|
-
if (value["kind"] === "hd")
|
|
8340
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
8341
|
-
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
8342
|
-
};
|
|
8343
8301
|
var common = (request) => {
|
|
8344
|
-
const
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
8348
|
-
if (!isAccountRef(account))
|
|
8349
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
8350
|
-
bitcoinNetwork(network);
|
|
8351
|
-
return {
|
|
8352
|
-
network,
|
|
8353
|
-
account
|
|
8354
|
-
};
|
|
8302
|
+
const base = requestBase(request);
|
|
8303
|
+
bitcoinNetwork(base.network);
|
|
8304
|
+
return base;
|
|
8355
8305
|
};
|
|
8356
8306
|
var messageTarget = (address, network, format) => {
|
|
8357
8307
|
if (typeof address !== "string")
|
|
@@ -8421,26 +8371,6 @@ var normalizeBitcoin = (request) => {
|
|
|
8421
8371
|
};
|
|
8422
8372
|
var decodeMessageTarget = (request) => messageTarget(request.address, request.network, request.format);
|
|
8423
8373
|
|
|
8424
|
-
// ../wallet-chains/dist/bitcoin-sign.mjs
|
|
8425
|
-
var signBitcoinPsbt = (psbt, inputs, auxRand) => {
|
|
8426
|
-
const tx = Transaction.fromPSBT(psbt);
|
|
8427
|
-
for (const { index, privateKey } of inputs) {
|
|
8428
|
-
if (privateKey.length !== 32)
|
|
8429
|
-
throw new ChainError("invalid-request", `input ${index}: private key must be 32 bytes`);
|
|
8430
|
-
if (!tx.signIdx(privateKey, index, undefined, auxRand(index)))
|
|
8431
|
-
throw new ChainError("invalid-request", `input ${index}: key cannot sign`);
|
|
8432
|
-
}
|
|
8433
|
-
return tx.toPSBT(0);
|
|
8434
|
-
};
|
|
8435
|
-
var signBitcoinMessage = (request, privateKey, auxRand) => {
|
|
8436
|
-
if (privateKey.length !== 32)
|
|
8437
|
-
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
8438
|
-
if (request.format === "legacy")
|
|
8439
|
-
return signLegacyMessage(request.message, privateKey);
|
|
8440
|
-
const scriptPubKey = OutScript.encode(Address(bitcoinNetwork(request.network).params).decode(request.address));
|
|
8441
|
-
return signBip322Simple(request.message, scriptPubKey, privateKey, auxRand);
|
|
8442
|
-
};
|
|
8443
|
-
|
|
8444
8374
|
// ../../node_modules/.bun/@noble+hashes@2.4.0/node_modules/@noble/hashes/sha3.js
|
|
8445
8375
|
var _0n4 = BigInt(0);
|
|
8446
8376
|
var _1n4 = BigInt(1);
|
|
@@ -8664,15 +8594,15 @@ class Keccak {
|
|
|
8664
8594
|
var genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);
|
|
8665
8595
|
var keccak_256 = /* @__PURE__ */ genKeccak(1, 136, 32);
|
|
8666
8596
|
|
|
8667
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8597
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/version.js
|
|
8668
8598
|
var version = "0.1.1";
|
|
8669
8599
|
|
|
8670
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8600
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/errors.js
|
|
8671
8601
|
function getVersion() {
|
|
8672
8602
|
return version;
|
|
8673
8603
|
}
|
|
8674
8604
|
|
|
8675
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8605
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Errors.js
|
|
8676
8606
|
class BaseError extends Error {
|
|
8677
8607
|
details;
|
|
8678
8608
|
docs;
|
|
@@ -8752,7 +8682,7 @@ function walk(err, fn) {
|
|
|
8752
8682
|
return fn ? null : err;
|
|
8753
8683
|
}
|
|
8754
8684
|
|
|
8755
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8685
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/bytes.js
|
|
8756
8686
|
function assertSize(bytes, size_) {
|
|
8757
8687
|
if (size(bytes) > size_)
|
|
8758
8688
|
throw new SizeOverflowError({
|
|
@@ -8821,7 +8751,7 @@ function trim(value, options = {}) {
|
|
|
8821
8751
|
return start === 0 && end === value.length ? value : value.slice(start, end);
|
|
8822
8752
|
}
|
|
8823
8753
|
|
|
8824
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8754
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/hex.js
|
|
8825
8755
|
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, "0"));
|
|
8826
8756
|
var nibbleTable = /* @__PURE__ */ (() => {
|
|
8827
8757
|
const table = new Uint8Array(256).fill(255);
|
|
@@ -8909,7 +8839,7 @@ class InvalidLengthError extends BaseError {
|
|
|
8909
8839
|
}
|
|
8910
8840
|
}
|
|
8911
8841
|
|
|
8912
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8842
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/int.js
|
|
8913
8843
|
function bytesToBigInt(value, signed) {
|
|
8914
8844
|
const len = value.length;
|
|
8915
8845
|
if (len === 0)
|
|
@@ -8966,11 +8896,11 @@ class IntegerOutOfRangeError extends BaseError {
|
|
|
8966
8896
|
}
|
|
8967
8897
|
}
|
|
8968
8898
|
|
|
8969
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8899
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/codec/utf8.js
|
|
8970
8900
|
var encoder = /* @__PURE__ */ new TextEncoder;
|
|
8971
8901
|
var decoder = /* @__PURE__ */ new TextDecoder;
|
|
8972
8902
|
|
|
8973
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8903
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Json.js
|
|
8974
8904
|
var bigIntSuffix = "#__bigint";
|
|
8975
8905
|
function stringify(value, replacer, space) {
|
|
8976
8906
|
return JSON.stringify(value, (key, value) => {
|
|
@@ -8982,9 +8912,9 @@ function stringify(value, replacer, space) {
|
|
|
8982
8912
|
}, space);
|
|
8983
8913
|
}
|
|
8984
8914
|
|
|
8985
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
8915
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Hex.js
|
|
8986
8916
|
function assert(value, options = {}) {
|
|
8987
|
-
const { strict = false } = options;
|
|
8917
|
+
const { even = false, strict = false } = options;
|
|
8988
8918
|
if (typeof value !== "string")
|
|
8989
8919
|
throw new InvalidHexTypeError(value);
|
|
8990
8920
|
if (strict) {
|
|
@@ -8993,6 +8923,8 @@ function assert(value, options = {}) {
|
|
|
8993
8923
|
}
|
|
8994
8924
|
if (!value.startsWith("0x"))
|
|
8995
8925
|
throw new InvalidHexValueError2(value);
|
|
8926
|
+
if (even && value.length % 2 !== 0)
|
|
8927
|
+
throw new InvalidLengthError2(value);
|
|
8996
8928
|
}
|
|
8997
8929
|
function concat2(...values) {
|
|
8998
8930
|
if (values.length === 0)
|
|
@@ -9116,9 +9048,9 @@ function toBytes(hex, options = {}) {
|
|
|
9116
9048
|
return hexToBytes4(value);
|
|
9117
9049
|
}
|
|
9118
9050
|
function validate2(value, options = {}) {
|
|
9119
|
-
const { strict = false } = options;
|
|
9051
|
+
const { even = false, strict = false } = options;
|
|
9120
9052
|
try {
|
|
9121
|
-
assert(value, { strict });
|
|
9053
|
+
assert(value, { even, strict });
|
|
9122
9054
|
return true;
|
|
9123
9055
|
} catch {
|
|
9124
9056
|
return false;
|
|
@@ -9134,6 +9066,8 @@ class InvalidHexTypeError extends BaseError {
|
|
|
9134
9066
|
}
|
|
9135
9067
|
}
|
|
9136
9068
|
var InvalidHexValueError2 = InvalidHexValueError;
|
|
9069
|
+
var InvalidLengthError2 = InvalidLengthError;
|
|
9070
|
+
|
|
9137
9071
|
class SizeOverflowError2 extends BaseError {
|
|
9138
9072
|
name = "Hex.SizeOverflowError";
|
|
9139
9073
|
constructor({ givenSize, maxSize }) {
|
|
@@ -9155,7 +9089,7 @@ class SizeExceedsPaddingSizeError2 extends BaseError {
|
|
|
9155
9089
|
}
|
|
9156
9090
|
}
|
|
9157
9091
|
|
|
9158
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9092
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/hex.js
|
|
9159
9093
|
function assertSize2(hex, size_) {
|
|
9160
9094
|
const len = hex.length - 2;
|
|
9161
9095
|
const size = len + 1 >> 1;
|
|
@@ -9216,7 +9150,7 @@ function trim2(value, options = {}) {
|
|
|
9216
9150
|
return `0x${data.slice(start, end)}`;
|
|
9217
9151
|
}
|
|
9218
9152
|
|
|
9219
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9153
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Bytes.js
|
|
9220
9154
|
function from2(value) {
|
|
9221
9155
|
if (value instanceof Uint8Array)
|
|
9222
9156
|
return value;
|
|
@@ -9327,7 +9261,7 @@ class SizeExceedsPaddingSizeError extends BaseError {
|
|
|
9327
9261
|
}
|
|
9328
9262
|
}
|
|
9329
9263
|
|
|
9330
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9264
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/lru.js
|
|
9331
9265
|
class BoundedMap extends Map {
|
|
9332
9266
|
maxSize;
|
|
9333
9267
|
constructor(size) {
|
|
@@ -9344,20 +9278,20 @@ class BoundedMap extends Map {
|
|
|
9344
9278
|
}
|
|
9345
9279
|
}
|
|
9346
9280
|
|
|
9347
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9281
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Caches.js
|
|
9348
9282
|
var caches = {
|
|
9349
9283
|
checksum: /* @__PURE__ */ new BoundedMap(32768)
|
|
9350
9284
|
};
|
|
9351
9285
|
var checksum = caches.checksum;
|
|
9352
9286
|
|
|
9353
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9287
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/engine.js
|
|
9354
9288
|
var overrides = {};
|
|
9355
9289
|
|
|
9356
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9290
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/hash.js
|
|
9357
9291
|
var keccak256Default = (input) => keccak_256(input);
|
|
9358
9292
|
var keccak256 = (input) => (overrides.Hash?.keccak256 ?? keccak256Default)(input);
|
|
9359
9293
|
|
|
9360
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9294
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Hash.js
|
|
9361
9295
|
function keccak2562(value, options = {}) {
|
|
9362
9296
|
const isBytes = value instanceof Uint8Array;
|
|
9363
9297
|
const { as = isBytes ? "Bytes" : "Hex" } = options;
|
|
@@ -9367,7 +9301,7 @@ function keccak2562(value, options = {}) {
|
|
|
9367
9301
|
return fromBytes(bytes);
|
|
9368
9302
|
}
|
|
9369
9303
|
|
|
9370
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9304
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/address.js
|
|
9371
9305
|
var length = 42;
|
|
9372
9306
|
var ZERO2 = 48;
|
|
9373
9307
|
var NINE = 57;
|
|
@@ -9420,7 +9354,7 @@ function lowercase(value) {
|
|
|
9420
9354
|
return String.fromCharCode.apply(null, out);
|
|
9421
9355
|
}
|
|
9422
9356
|
|
|
9423
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9357
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Address.js
|
|
9424
9358
|
function assert2(value, options = {}) {
|
|
9425
9359
|
const { strict = true } = options;
|
|
9426
9360
|
const kind = classify(value);
|
|
@@ -9500,7 +9434,7 @@ class InvalidChecksumError extends BaseError {
|
|
|
9500
9434
|
}
|
|
9501
9435
|
}
|
|
9502
9436
|
|
|
9503
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9437
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/regex.js
|
|
9504
9438
|
function execTyped(regex, string) {
|
|
9505
9439
|
const match = regex.exec(string);
|
|
9506
9440
|
return match?.groups;
|
|
@@ -9509,7 +9443,7 @@ var bytesRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
|
9509
9443
|
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)?$/;
|
|
9510
9444
|
var isTupleRegex = /^\(.+?\).*?$/;
|
|
9511
9445
|
|
|
9512
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9446
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/formatAbiParameter.js
|
|
9513
9447
|
var tupleRegex = /^tuple(?<array>(\[(\d*)\])*)$/;
|
|
9514
9448
|
function formatAbiParameter(abiParameter) {
|
|
9515
9449
|
let type = abiParameter.type;
|
|
@@ -9536,7 +9470,7 @@ function formatAbiParameter(abiParameter) {
|
|
|
9536
9470
|
return type;
|
|
9537
9471
|
}
|
|
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/formatAbiParameters.js
|
|
9540
9474
|
function formatAbiParameters(abiParameters) {
|
|
9541
9475
|
let params = "";
|
|
9542
9476
|
const length = abiParameters.length;
|
|
@@ -9549,7 +9483,7 @@ function formatAbiParameters(abiParameters) {
|
|
|
9549
9483
|
return params;
|
|
9550
9484
|
}
|
|
9551
9485
|
|
|
9552
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9486
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/errors.js
|
|
9553
9487
|
class InvalidAbiItemError extends BaseError {
|
|
9554
9488
|
name = "AbiItem.InvalidAbiItemError";
|
|
9555
9489
|
constructor({ signature }) {
|
|
@@ -9684,7 +9618,7 @@ class CircularReferenceError extends BaseError {
|
|
|
9684
9618
|
}
|
|
9685
9619
|
}
|
|
9686
9620
|
|
|
9687
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9621
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/signatures.js
|
|
9688
9622
|
var errorSignatureRegex = /^error (?<name>[a-zA-Z$_][a-zA-Z0-9$_]*)\((?<parameters>.*?)\)$/;
|
|
9689
9623
|
function isErrorSignature(signature) {
|
|
9690
9624
|
return errorSignatureRegex.test(signature);
|
|
@@ -9744,7 +9678,7 @@ var functionModifiers = new Set([
|
|
|
9744
9678
|
"storage"
|
|
9745
9679
|
]);
|
|
9746
9680
|
|
|
9747
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9681
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/cache.js
|
|
9748
9682
|
function getParameterCacheKey(param, type, structs) {
|
|
9749
9683
|
let structKey = "";
|
|
9750
9684
|
if (structs)
|
|
@@ -9813,7 +9747,7 @@ var parameterCache = new Map([
|
|
|
9813
9747
|
]
|
|
9814
9748
|
]);
|
|
9815
9749
|
|
|
9816
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9750
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/utils.js
|
|
9817
9751
|
function parseSignature(signature, structs = {}) {
|
|
9818
9752
|
if (isFunctionSignature(signature))
|
|
9819
9753
|
return parseFunctionSignature(signature, structs);
|
|
@@ -10012,7 +9946,7 @@ function isValidDataLocation(type, isArray) {
|
|
|
10012
9946
|
return isArray || type === "bytes" || type === "string" || type === "tuple";
|
|
10013
9947
|
}
|
|
10014
9948
|
|
|
10015
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
9949
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/runtime/structs.js
|
|
10016
9950
|
function parseStructs(signatures) {
|
|
10017
9951
|
const shallowStructs = {};
|
|
10018
9952
|
const signaturesLength = signatures.length;
|
|
@@ -10082,7 +10016,7 @@ function resolveStructs(abiParameters = [], structs = {}, ancestors = new Set) {
|
|
|
10082
10016
|
return components;
|
|
10083
10017
|
}
|
|
10084
10018
|
|
|
10085
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10019
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Solidity.js
|
|
10086
10020
|
var arrayRegex = /^(.*)\[([0-9]*)\]$/;
|
|
10087
10021
|
var bytesRegex2 = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
10088
10022
|
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)?$/;
|
|
@@ -10183,7 +10117,7 @@ var maxUint240 = 2n ** 240n - 1n;
|
|
|
10183
10117
|
var maxUint248 = 2n ** 248n - 1n;
|
|
10184
10118
|
var maxUint256 = 2n ** 256n - 1n;
|
|
10185
10119
|
|
|
10186
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10120
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/abiParameters.js
|
|
10187
10121
|
function decodeParameter(cursor, param, options) {
|
|
10188
10122
|
const { checksumAddress, staticPosition } = options;
|
|
10189
10123
|
const arrayComponents = getArrayComponents(param.type);
|
|
@@ -10725,7 +10659,7 @@ function hasDynamicChild(param) {
|
|
|
10725
10659
|
return false;
|
|
10726
10660
|
}
|
|
10727
10661
|
|
|
10728
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10662
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/cursor.js
|
|
10729
10663
|
var staticCursor = {
|
|
10730
10664
|
bytes: new Uint8Array,
|
|
10731
10665
|
dataView: new DataView(new ArrayBuffer(0)),
|
|
@@ -10916,7 +10850,7 @@ class RecursiveReadLimitExceededError extends BaseError {
|
|
|
10916
10850
|
}
|
|
10917
10851
|
}
|
|
10918
10852
|
|
|
10919
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
10853
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiParameters.js
|
|
10920
10854
|
function decode2(parameters, data, options = {}) {
|
|
10921
10855
|
const { as = "Array", checksumAddress = true } = options;
|
|
10922
10856
|
const bytes = typeof data === "string" ? fromHex(data) : data;
|
|
@@ -11092,7 +11026,7 @@ class InvalidTypeError extends BaseError {
|
|
|
11092
11026
|
}
|
|
11093
11027
|
}
|
|
11094
11028
|
|
|
11095
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11029
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TypedData.js
|
|
11096
11030
|
function assert3(value) {
|
|
11097
11031
|
const { domain, message, primaryType, types } = value;
|
|
11098
11032
|
const validateValue = (type, value, name) => {
|
|
@@ -11204,7 +11138,7 @@ function encodeType(value) {
|
|
|
11204
11138
|
function extractEip712DomainTypes(domain) {
|
|
11205
11139
|
return [
|
|
11206
11140
|
typeof domain?.name === "string" && { name: "name", type: "string" },
|
|
11207
|
-
domain?.version && { name: "version", type: "string" },
|
|
11141
|
+
typeof domain?.version === "string" && { name: "version", type: "string" },
|
|
11208
11142
|
(typeof domain?.chainId === "number" || typeof domain?.chainId === "bigint") && {
|
|
11209
11143
|
name: "chainId",
|
|
11210
11144
|
type: "uint256"
|
|
@@ -11387,7 +11321,7 @@ function validateReference(type) {
|
|
|
11387
11321
|
throw new InvalidStructTypeError({ type });
|
|
11388
11322
|
}
|
|
11389
11323
|
|
|
11390
|
-
// ../wallet-chains/dist/typed-data-
|
|
11324
|
+
// ../wallet-chains/dist/typed-data-Cf1g7JVv.mjs
|
|
11391
11325
|
var isEvmAddress = (value) => /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
11392
11326
|
function checksumEvmAddress(address) {
|
|
11393
11327
|
if (!isEvmAddress(address))
|
|
@@ -11594,7 +11528,7 @@ var typedDataWarnings = (parsed) => parsed.chainIdMismatch ? [{
|
|
|
11594
11528
|
message: "typed-data domain.chainId does not match the request network"
|
|
11595
11529
|
}] : [];
|
|
11596
11530
|
|
|
11597
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11531
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/formatAbiItem.js
|
|
11598
11532
|
function formatAbiItem(abiItem) {
|
|
11599
11533
|
if (abiItem.type === "function")
|
|
11600
11534
|
return `function ${abiItem.name}(${formatAbiParameters(abiItem.inputs)})${abiItem.stateMutability && abiItem.stateMutability !== "nonpayable" ? ` ${abiItem.stateMutability}` : ""}${abiItem.outputs?.length ? ` returns (${formatAbiParameters(abiItem.outputs)})` : ""}`;
|
|
@@ -11609,7 +11543,7 @@ function formatAbiItem(abiItem) {
|
|
|
11609
11543
|
return "receive() external payable";
|
|
11610
11544
|
}
|
|
11611
11545
|
|
|
11612
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11546
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/human-readable/parseAbiItem.js
|
|
11613
11547
|
function parseAbiItem(signature) {
|
|
11614
11548
|
let abiItem;
|
|
11615
11549
|
if (typeof signature === "string")
|
|
@@ -11630,7 +11564,7 @@ function parseAbiItem(signature) {
|
|
|
11630
11564
|
return abiItem;
|
|
11631
11565
|
}
|
|
11632
11566
|
|
|
11633
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11567
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/abiItem.js
|
|
11634
11568
|
function normalizeSignature(signature) {
|
|
11635
11569
|
let active = true;
|
|
11636
11570
|
let current = "";
|
|
@@ -11675,8 +11609,6 @@ function normalizeSignature(signature) {
|
|
|
11675
11609
|
}
|
|
11676
11610
|
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)?$/;
|
|
11677
11611
|
var fixedBytesTypeRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/;
|
|
11678
|
-
var arrayTypeRegex = /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/;
|
|
11679
|
-
var arraySuffixStripRegex = /(\[[0-9]{0,}\])$/;
|
|
11680
11612
|
function isArgOfType(arg, abiParameter) {
|
|
11681
11613
|
const argType = typeof arg;
|
|
11682
11614
|
const abiParameterType = abiParameter.type;
|
|
@@ -11692,16 +11624,18 @@ function isArgOfType(arg, abiParameter) {
|
|
|
11692
11624
|
default: {
|
|
11693
11625
|
if (abiParameterType === "tuple" && "components" in abiParameter)
|
|
11694
11626
|
return Object.values(abiParameter.components).every((component, index) => {
|
|
11695
|
-
return isArgOfType(
|
|
11627
|
+
return argType === "object" && isArgOfType(getComponentValue(arg, component, index), component);
|
|
11696
11628
|
});
|
|
11697
11629
|
if (integerTypeRegex.test(abiParameterType))
|
|
11698
11630
|
return argType === "number" || argType === "bigint";
|
|
11699
11631
|
if (fixedBytesTypeRegex.test(abiParameterType))
|
|
11700
11632
|
return argType === "string" || arg instanceof Uint8Array;
|
|
11701
|
-
|
|
11702
|
-
|
|
11633
|
+
const arrayComponents = getArrayComponents(abiParameterType);
|
|
11634
|
+
if (arrayComponents) {
|
|
11635
|
+
const [length, type] = arrayComponents;
|
|
11636
|
+
return Array.isArray(arg) && (length === null || arg.length === length) && arg.every((x) => isArgOfType(x, {
|
|
11703
11637
|
...abiParameter,
|
|
11704
|
-
type
|
|
11638
|
+
type
|
|
11705
11639
|
}));
|
|
11706
11640
|
}
|
|
11707
11641
|
return false;
|
|
@@ -11712,8 +11646,33 @@ function getAmbiguousTypes(sourceParameters, targetParameters, args) {
|
|
|
11712
11646
|
for (let parameterIndex = 0;parameterIndex < sourceParameters.length; parameterIndex++) {
|
|
11713
11647
|
const sourceParameter = sourceParameters[parameterIndex];
|
|
11714
11648
|
const targetParameter = targetParameters[parameterIndex];
|
|
11715
|
-
if (
|
|
11716
|
-
|
|
11649
|
+
if (!targetParameter)
|
|
11650
|
+
continue;
|
|
11651
|
+
if (sourceParameter.type === "tuple" && targetParameter.type === "tuple" && "components" in sourceParameter && "components" in targetParameter) {
|
|
11652
|
+
const value = args[parameterIndex];
|
|
11653
|
+
const types = getAmbiguousTypes(sourceParameter.components, targetParameter.components, sourceParameter.components.map((component, index) => getComponentValue(value, component, index)));
|
|
11654
|
+
if (types)
|
|
11655
|
+
return types;
|
|
11656
|
+
continue;
|
|
11657
|
+
}
|
|
11658
|
+
const sourceArray = getArrayComponents(sourceParameter.type);
|
|
11659
|
+
const targetArray = getArrayComponents(targetParameter.type);
|
|
11660
|
+
if (sourceArray && targetArray) {
|
|
11661
|
+
const types = getAmbiguousTypes([
|
|
11662
|
+
{
|
|
11663
|
+
...sourceParameter,
|
|
11664
|
+
type: sourceArray[1]
|
|
11665
|
+
}
|
|
11666
|
+
], [
|
|
11667
|
+
{
|
|
11668
|
+
...targetParameter,
|
|
11669
|
+
type: targetArray[1]
|
|
11670
|
+
}
|
|
11671
|
+
], [args[parameterIndex]?.[0]]);
|
|
11672
|
+
if (types)
|
|
11673
|
+
return types;
|
|
11674
|
+
continue;
|
|
11675
|
+
}
|
|
11717
11676
|
const sourceType = sourceParameter.type;
|
|
11718
11677
|
const targetType = targetParameter.type;
|
|
11719
11678
|
const arg = args[parameterIndex];
|
|
@@ -11721,14 +11680,19 @@ function getAmbiguousTypes(sourceParameters, targetParameters, args) {
|
|
|
11721
11680
|
if (sourceType === "address" && targetType === "bytes20" || sourceType === "bytes20" && targetType === "address")
|
|
11722
11681
|
ambiguous = true;
|
|
11723
11682
|
else if (sourceType === "address" && targetType === "string" || sourceType === "string" && targetType === "address" || sourceType === "address" && targetType === "bytes" || sourceType === "bytes" && targetType === "address")
|
|
11724
|
-
ambiguous = validate3(arg, { strict: false });
|
|
11683
|
+
ambiguous = arg === undefined || validate3(arg, { strict: false });
|
|
11725
11684
|
if (ambiguous)
|
|
11726
11685
|
return [sourceType, targetType];
|
|
11727
11686
|
}
|
|
11728
11687
|
return;
|
|
11729
11688
|
}
|
|
11689
|
+
function getComponentValue(arg, component, index) {
|
|
11690
|
+
if (Array.isArray(arg))
|
|
11691
|
+
return arg[index];
|
|
11692
|
+
return arg?.[component.name];
|
|
11693
|
+
}
|
|
11730
11694
|
|
|
11731
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11695
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiItem.js
|
|
11732
11696
|
function from3(abiItem, options = {}) {
|
|
11733
11697
|
const { prepare = true } = options;
|
|
11734
11698
|
const item = (() => {
|
|
@@ -11896,7 +11860,7 @@ class InvalidSelectorSizeError extends BaseError {
|
|
|
11896
11860
|
}
|
|
11897
11861
|
}
|
|
11898
11862
|
|
|
11899
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11863
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AbiFunction.js
|
|
11900
11864
|
function decodeData(...parameters) {
|
|
11901
11865
|
const [abiFunction, data, options] = (() => {
|
|
11902
11866
|
if (Array.isArray(parameters[0])) {
|
|
@@ -11958,7 +11922,7 @@ function getSelector2(abiItem) {
|
|
|
11958
11922
|
return getSelector(abiItem);
|
|
11959
11923
|
}
|
|
11960
11924
|
|
|
11961
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11925
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/PersonalMessage.js
|
|
11962
11926
|
var erc191PrefixHex = "0x19" + fromString(`Ethereum Signed Message:
|
|
11963
11927
|
`).slice(2);
|
|
11964
11928
|
function encode3(data) {
|
|
@@ -11969,7 +11933,7 @@ function getSignPayload2(data) {
|
|
|
11969
11933
|
return keccak2562(encode3(data));
|
|
11970
11934
|
}
|
|
11971
11935
|
|
|
11972
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
11936
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Signature.js
|
|
11973
11937
|
function assert4(signature, options = {}) {
|
|
11974
11938
|
const { recovered } = options;
|
|
11975
11939
|
if (typeof signature.r === "undefined")
|
|
@@ -12093,8 +12057,8 @@ function fromRecoveredBytes(bytes) {
|
|
|
12093
12057
|
}
|
|
12094
12058
|
function toHex(signature) {
|
|
12095
12059
|
assert4(signature);
|
|
12096
|
-
const r = signature.r;
|
|
12097
|
-
const s = signature.s;
|
|
12060
|
+
const r = padLeft(signature.r, 32);
|
|
12061
|
+
const s = padLeft(signature.s, 32);
|
|
12098
12062
|
const signature_ = concat2(r, s, typeof signature.yParity === "number" ? fromNumber(yParityToV(signature.yParity), { size: 1 }) : "0x");
|
|
12099
12063
|
return signature_;
|
|
12100
12064
|
}
|
|
@@ -12166,7 +12130,7 @@ class InvalidVError extends BaseError {
|
|
|
12166
12130
|
}
|
|
12167
12131
|
}
|
|
12168
12132
|
|
|
12169
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12133
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/cryptoIo.js
|
|
12170
12134
|
function formatSignature(signature, as) {
|
|
12171
12135
|
if (as === "Hex")
|
|
12172
12136
|
return toHex(signature);
|
|
@@ -12175,7 +12139,7 @@ function formatSignature(signature, as) {
|
|
|
12175
12139
|
return signature;
|
|
12176
12140
|
}
|
|
12177
12141
|
|
|
12178
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12142
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/secp256k1.js
|
|
12179
12143
|
var signDefault = (payload, privateKey, options) => secp256k1.sign(payload, privateKey, {
|
|
12180
12144
|
...options,
|
|
12181
12145
|
format: "recovered",
|
|
@@ -12183,9 +12147,9 @@ var signDefault = (payload, privateKey, options) => secp256k1.sign(payload, priv
|
|
|
12183
12147
|
});
|
|
12184
12148
|
var sign = (payload, privateKey, options) => (overrides.Secp256k1?.sign ?? signDefault)(payload, privateKey, options);
|
|
12185
12149
|
|
|
12186
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12150
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/entropy.js
|
|
12187
12151
|
var extraEntropy = false;
|
|
12188
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12152
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Secp256k1.js
|
|
12189
12153
|
function sign2(options) {
|
|
12190
12154
|
const { as = "Object", extraEntropy: extraEntropy2 = extraEntropy, hash, payload, privateKey } = options;
|
|
12191
12155
|
const sigBytes = sign(from2(payload), from2(privateKey), {
|
|
@@ -12198,7 +12162,7 @@ function sign2(options) {
|
|
|
12198
12162
|
var fromPrfDomain = fromString2("ox.secp256k1.fromPrf.v1");
|
|
12199
12163
|
var fromSeedDomain = fromString2("ox.secp256k1.fromSeed.v1");
|
|
12200
12164
|
|
|
12201
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12165
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/AccessList.js
|
|
12202
12166
|
function toTupleList(accessList) {
|
|
12203
12167
|
if (!accessList || accessList.length === 0)
|
|
12204
12168
|
return [];
|
|
@@ -12223,7 +12187,7 @@ class InvalidStorageKeySizeError extends BaseError {
|
|
|
12223
12187
|
}
|
|
12224
12188
|
}
|
|
12225
12189
|
|
|
12226
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12190
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/internal/tx.js
|
|
12227
12191
|
function quantityToHex(value) {
|
|
12228
12192
|
if (value === undefined || value === null)
|
|
12229
12193
|
return "0x";
|
|
@@ -12232,7 +12196,7 @@ function quantityToHex(value) {
|
|
|
12232
12196
|
return fromNumber(value);
|
|
12233
12197
|
}
|
|
12234
12198
|
|
|
12235
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12199
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Rlp.js
|
|
12236
12200
|
function from6(value, options) {
|
|
12237
12201
|
const { as } = options;
|
|
12238
12202
|
const ctx = { lengths: [], cursor: 0 };
|
|
@@ -12475,7 +12439,7 @@ function invalidNibble(hex) {
|
|
|
12475
12439
|
return new BaseError(`Invalid hex string \`${hex}\`.`);
|
|
12476
12440
|
}
|
|
12477
12441
|
|
|
12478
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12442
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeEip2930.js
|
|
12479
12443
|
function assert5(envelope) {
|
|
12480
12444
|
const { chainId, gasPrice, to } = envelope;
|
|
12481
12445
|
if (chainId <= 0)
|
|
@@ -12519,7 +12483,7 @@ function serialize(envelope, options = {}) {
|
|
|
12519
12483
|
return concat2("0x01", fromHex3(serialized));
|
|
12520
12484
|
}
|
|
12521
12485
|
|
|
12522
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12486
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeLegacy.js
|
|
12523
12487
|
function assert6(envelope) {
|
|
12524
12488
|
const { chainId, gasPrice, to } = envelope;
|
|
12525
12489
|
if (to)
|
|
@@ -12596,7 +12560,7 @@ function serialize2(envelope, options = {}) {
|
|
|
12596
12560
|
return fromHex3(serialized);
|
|
12597
12561
|
}
|
|
12598
12562
|
|
|
12599
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12563
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/Value.js
|
|
12600
12564
|
var exponents = {
|
|
12601
12565
|
wei: 0,
|
|
12602
12566
|
gwei: 9,
|
|
@@ -12629,7 +12593,7 @@ class InvalidDecimalsError extends BaseError {
|
|
|
12629
12593
|
}
|
|
12630
12594
|
}
|
|
12631
12595
|
|
|
12632
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12596
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelope.js
|
|
12633
12597
|
class FeeCapTooHighError extends BaseError {
|
|
12634
12598
|
name = "TransactionEnvelope.FeeCapTooHighError";
|
|
12635
12599
|
constructor({ feeCap } = {}) {
|
|
@@ -12660,7 +12624,7 @@ class TipAboveFeeCapError extends BaseError {
|
|
|
12660
12624
|
}
|
|
12661
12625
|
}
|
|
12662
12626
|
|
|
12663
|
-
// ../../node_modules/.bun/ox@1.8.
|
|
12627
|
+
// ../../node_modules/.bun/ox@1.8.12+ff0372d108591aba/node_modules/ox/dist/core/TxEnvelopeEip1559.js
|
|
12664
12628
|
var serializedType = "0x02";
|
|
12665
12629
|
function assert7(envelope) {
|
|
12666
12630
|
const { chainId, maxPriorityFeePerGas, maxFeePerGas, to } = envelope;
|
|
@@ -12932,24 +12896,10 @@ var decodeEvm = (request, table = evmTokenTable) => {
|
|
|
12932
12896
|
verifiability: "opaque"
|
|
12933
12897
|
};
|
|
12934
12898
|
};
|
|
12935
|
-
var isAccountRef2 = (value) => {
|
|
12936
|
-
if (!isRecord3(value) || typeof value["kind"] !== "string")
|
|
12937
|
-
return false;
|
|
12938
|
-
if (value["kind"] === "hd")
|
|
12939
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
12940
|
-
if (value["kind"] === "imported")
|
|
12941
|
-
return typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
12942
|
-
return false;
|
|
12943
|
-
};
|
|
12944
12899
|
var normalizeEvm = (request) => {
|
|
12945
12900
|
if (!isRecord3(request) || typeof request["kind"] !== "string")
|
|
12946
12901
|
throw new ChainError("invalid-request", "request must be an object with a kind");
|
|
12947
|
-
const { network } = request;
|
|
12948
|
-
const { account } = request;
|
|
12949
|
-
if (typeof network !== "string")
|
|
12950
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
12951
|
-
if (!isAccountRef2(account))
|
|
12952
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
12902
|
+
const { network, account } = requestBase(request);
|
|
12953
12903
|
const chainId = networkChainId(network);
|
|
12954
12904
|
if (request["kind"] === "evm.transaction") {
|
|
12955
12905
|
const tx = normalizeEvmTransaction(request["tx"]);
|
|
@@ -12988,79 +12938,6 @@ var normalizeEvm = (request) => {
|
|
|
12988
12938
|
throw new ChainError("unsupported", `unsupported sign request kind: ${request["kind"]}`);
|
|
12989
12939
|
};
|
|
12990
12940
|
|
|
12991
|
-
// ../wallet-chains/dist/evm-sign.mjs
|
|
12992
|
-
function assertHex2(value, field) {
|
|
12993
|
-
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value))
|
|
12994
|
-
throw new ChainError("invalid-quantity", `${field} must be 0x-prefixed bytes`);
|
|
12995
|
-
}
|
|
12996
|
-
var hex = (value, field) => {
|
|
12997
|
-
assertHex2(value, field);
|
|
12998
|
-
return value;
|
|
12999
|
-
};
|
|
13000
|
-
var key = (privateKey) => {
|
|
13001
|
-
if (privateKey.length !== 32)
|
|
13002
|
-
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
13003
|
-
return fromBytes(privateKey);
|
|
13004
|
-
};
|
|
13005
|
-
var accessEntry = (entry) => ({
|
|
13006
|
-
address: hex(entry.address, "accessList.address"),
|
|
13007
|
-
storageKeys: entry.storageKeys.map((k) => hex(k, "accessList.storageKeys"))
|
|
13008
|
-
});
|
|
13009
|
-
var sign3 = (payload, privateKey) => sign2({
|
|
13010
|
-
payload,
|
|
13011
|
-
privateKey,
|
|
13012
|
-
as: "Object"
|
|
13013
|
-
});
|
|
13014
|
-
var signEvmTransaction = (tx, privateKey) => {
|
|
13015
|
-
const privateKeyHex = key(privateKey);
|
|
13016
|
-
const base = {
|
|
13017
|
-
chainId: tx.chainId,
|
|
13018
|
-
to: tx.to === undefined ? undefined : hex(tx.to, "to"),
|
|
13019
|
-
data: hex(tx.data, "data"),
|
|
13020
|
-
value: BigInt(tx.value),
|
|
13021
|
-
nonce: BigInt(tx.nonce),
|
|
13022
|
-
gas: BigInt(tx.gas)
|
|
13023
|
-
};
|
|
13024
|
-
if (tx.type === "legacy") {
|
|
13025
|
-
const envelope = {
|
|
13026
|
-
...base,
|
|
13027
|
-
type: "legacy",
|
|
13028
|
-
gasPrice: BigInt(tx.gasPrice)
|
|
13029
|
-
};
|
|
13030
|
-
const signature = sign3(getSignPayload4(envelope), privateKeyHex);
|
|
13031
|
-
return toBytes(serialize2(envelope, { signature }));
|
|
13032
|
-
}
|
|
13033
|
-
if (tx.type === "eip2930") {
|
|
13034
|
-
const envelope = {
|
|
13035
|
-
...base,
|
|
13036
|
-
type: "eip2930",
|
|
13037
|
-
gasPrice: BigInt(tx.gasPrice),
|
|
13038
|
-
accessList: tx.accessList.map(accessEntry)
|
|
13039
|
-
};
|
|
13040
|
-
const signature = sign3(getSignPayload3(envelope), privateKeyHex);
|
|
13041
|
-
return toBytes(serialize(envelope, { signature }));
|
|
13042
|
-
}
|
|
13043
|
-
const envelope = {
|
|
13044
|
-
...base,
|
|
13045
|
-
type: "eip1559",
|
|
13046
|
-
accessList: tx.accessList.map(accessEntry),
|
|
13047
|
-
maxFeePerGas: BigInt(tx.maxFeePerGas),
|
|
13048
|
-
maxPriorityFeePerGas: BigInt(tx.maxPriorityFeePerGas)
|
|
13049
|
-
};
|
|
13050
|
-
const signature = sign3(getSignPayload5(envelope), privateKeyHex);
|
|
13051
|
-
return toBytes(serialize3(envelope, { signature }));
|
|
13052
|
-
};
|
|
13053
|
-
var rs_v = (signature) => toBytes2(signature);
|
|
13054
|
-
var signEvmPersonalMessage = (message, privateKey) => {
|
|
13055
|
-
const payload = getSignPayload2(fromBytes(message));
|
|
13056
|
-
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
13057
|
-
};
|
|
13058
|
-
var signEvmTypedData = (typedData, privateKey) => {
|
|
13059
|
-
const { json } = parseTypedData(typedData, "eip155:1");
|
|
13060
|
-
const payload = getSignPayload(json);
|
|
13061
|
-
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
13062
|
-
};
|
|
13063
|
-
|
|
13064
12941
|
// ../../node_modules/.bun/@solana+errors@8.5.0+ff0372d108591aba/node_modules/@solana/errors/dist/index.node.mjs
|
|
13065
12942
|
var SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED = 1;
|
|
13066
12943
|
var SOLANA_ERROR__INVALID_NONCE = 2;
|
|
@@ -14535,14 +14412,14 @@ var parseCompiledMessage = (bytes) => {
|
|
|
14535
14412
|
lookupAddresses: lookups.map((l) => l.lookupTableAddress)
|
|
14536
14413
|
};
|
|
14537
14414
|
};
|
|
14538
|
-
var
|
|
14415
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14539
14416
|
var isStringArray = (value) => Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
14540
14417
|
var isNumberArray = (value) => Array.isArray(value) && value.every((v) => typeof v === "number");
|
|
14541
|
-
var isArrayLike = (value) =>
|
|
14542
|
-
var isIx = (value) =>
|
|
14543
|
-
var isLookup = (value) =>
|
|
14418
|
+
var isArrayLike = (value) => isRecord4(value) && typeof value["length"] === "number";
|
|
14419
|
+
var isIx = (value) => isRecord4(value) && typeof value["programAddressIndex"] === "number" && (value["accountIndices"] === undefined || isNumberArray(value["accountIndices"]) || isArrayLike(value["accountIndices"])) && value["data"] instanceof Uint8Array;
|
|
14420
|
+
var isLookup = (value) => isRecord4(value) && typeof value["lookupTableAddress"] === "string" && (isNumberArray(value["readonlyIndexes"]) || value["readonlyIndexes"] instanceof Uint8Array) && (isNumberArray(value["writableIndexes"]) || value["writableIndexes"] instanceof Uint8Array);
|
|
14544
14421
|
var asCompiledMessage = (value) => {
|
|
14545
|
-
if (!
|
|
14422
|
+
if (!isRecord4(value) || !isRecord4(value["header"]))
|
|
14546
14423
|
throw new ChainError("invalid-request", "compiled message failed to decode");
|
|
14547
14424
|
const { header } = value;
|
|
14548
14425
|
const { staticAccounts } = value;
|
|
@@ -14763,14 +14640,6 @@ var decodeTransaction2 = (request, signer, table) => {
|
|
|
14763
14640
|
};
|
|
14764
14641
|
};
|
|
14765
14642
|
var decodeSolana = (request, signer, table = solanaTokenTable) => decodeTransaction2(request, signer, table);
|
|
14766
|
-
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14767
|
-
var isAccountRef3 = (value) => {
|
|
14768
|
-
if (!isRecord4(value) || typeof value["kind"] !== "string")
|
|
14769
|
-
return false;
|
|
14770
|
-
if (value["kind"] === "hd")
|
|
14771
|
-
return typeof value["walletId"] === "string" && typeof value["groupIndex"] === "number" && typeof value["template"] === "string";
|
|
14772
|
-
return value["kind"] === "imported" && typeof value["keyId"] === "string" && typeof value["family"] === "string";
|
|
14773
|
-
};
|
|
14774
14643
|
var solanaNetwork = (network) => {
|
|
14775
14644
|
if (!SOLANA_NETWORKS.includes(network))
|
|
14776
14645
|
throw new ChainError("unsupported", `unknown Solana network: ${network}`);
|
|
@@ -14781,7 +14650,7 @@ var validateLookupTablesRaw = (tables) => {
|
|
|
14781
14650
|
if (!Array.isArray(tables))
|
|
14782
14651
|
throw new ChainError("unknown-field", "lookupTables must be an array");
|
|
14783
14652
|
const parsed = tables.map((t) => {
|
|
14784
|
-
if (!
|
|
14653
|
+
if (!isRecord2(t) || typeof t["address"] !== "string" || !Array.isArray(t["addresses"]))
|
|
14785
14654
|
throw new ChainError("unknown-field", "lookupTables entries must be { address, addresses }");
|
|
14786
14655
|
const addresses = t["addresses"].map((a) => {
|
|
14787
14656
|
if (typeof a !== "string")
|
|
@@ -14797,14 +14666,9 @@ var validateLookupTablesRaw = (tables) => {
|
|
|
14797
14666
|
return parsed;
|
|
14798
14667
|
};
|
|
14799
14668
|
var normalizeSolana = (request, signer) => {
|
|
14800
|
-
if (!
|
|
14669
|
+
if (!isRecord2(request) || typeof request["kind"] !== "string")
|
|
14801
14670
|
throw new ChainError("invalid-request", "request must be an object with a kind");
|
|
14802
|
-
const { network } = request;
|
|
14803
|
-
const { account } = request;
|
|
14804
|
-
if (typeof network !== "string")
|
|
14805
|
-
throw new ChainError("invalid-request", "request.network must be a string");
|
|
14806
|
-
if (!isAccountRef3(account))
|
|
14807
|
-
throw new ChainError("invalid-request", "request.account must be an AccountRef");
|
|
14671
|
+
const { network, account } = requestBase(request);
|
|
14808
14672
|
solanaNetwork(network);
|
|
14809
14673
|
if (!isSolanaAddress(signer))
|
|
14810
14674
|
throw new ChainError("invalid-address", "signer is not a base58 address");
|
|
@@ -14850,16 +14714,24 @@ var normalizeSolana = (request, signer) => {
|
|
|
14850
14714
|
throw new ChainError("unsupported", `unsupported sign request kind: ${request["kind"]}`);
|
|
14851
14715
|
};
|
|
14852
14716
|
|
|
14853
|
-
// ../wallet-chains/dist/
|
|
14854
|
-
var
|
|
14717
|
+
// ../wallet-chains/dist/bitcoin-sign.mjs
|
|
14718
|
+
var signBitcoinPsbt = (psbt, inputs, auxRand) => {
|
|
14719
|
+
const tx = Transaction.fromPSBT(psbt);
|
|
14720
|
+
for (const { index, privateKey } of inputs) {
|
|
14721
|
+
if (privateKey.length !== 32)
|
|
14722
|
+
throw new ChainError("invalid-request", `input ${index}: private key must be 32 bytes`);
|
|
14723
|
+
if (!tx.signIdx(privateKey, index, undefined, auxRand(index)))
|
|
14724
|
+
throw new ChainError("invalid-request", `input ${index}: key cannot sign`);
|
|
14725
|
+
}
|
|
14726
|
+
return tx.toPSBT(0);
|
|
14727
|
+
};
|
|
14728
|
+
var signBitcoinMessage = (request, privateKey, auxRand) => {
|
|
14855
14729
|
if (privateKey.length !== 32)
|
|
14856
|
-
throw new ChainError("invalid-request", "private key must be
|
|
14857
|
-
if (
|
|
14858
|
-
|
|
14859
|
-
const
|
|
14860
|
-
|
|
14861
|
-
throw new ChainError("invalid-request", "ed25519 produced a malformed signature");
|
|
14862
|
-
return signature;
|
|
14730
|
+
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
14731
|
+
if (request.format === "legacy")
|
|
14732
|
+
return signLegacyMessage(request.message, privateKey);
|
|
14733
|
+
const scriptPubKey = OutScript.encode(Address(bitcoinNetwork(request.network).params).decode(request.address));
|
|
14734
|
+
return signBip322Simple(request.message, scriptPubKey, privateKey, auxRand);
|
|
14863
14735
|
};
|
|
14864
14736
|
|
|
14865
14737
|
// ../wallet-kernel/src/modules/chains/prompt.ts
|
|
@@ -14926,15 +14798,407 @@ function chainPrompt(locale, intent) {
|
|
|
14926
14798
|
return { title, description: joinLines(lines.length === 0 ? [catalog.generic] : lines) };
|
|
14927
14799
|
}
|
|
14928
14800
|
|
|
14929
|
-
// ../wallet-kernel/src/modules/chains/
|
|
14801
|
+
// ../wallet-kernel/src/modules/chains/shared.ts
|
|
14930
14802
|
var BTC_PURPOSE = {
|
|
14931
14803
|
"btc.bip44": 44,
|
|
14932
14804
|
"btc.bip49": 49,
|
|
14933
14805
|
"btc.bip84": 84,
|
|
14934
14806
|
"btc.bip86": 86
|
|
14935
14807
|
};
|
|
14808
|
+
var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Uint8Array);
|
|
14809
|
+
var deepEqual = (a, b) => {
|
|
14810
|
+
if (a === b) {
|
|
14811
|
+
return true;
|
|
14812
|
+
}
|
|
14813
|
+
if (a instanceof Uint8Array || b instanceof Uint8Array) {
|
|
14814
|
+
return a instanceof Uint8Array && b instanceof Uint8Array && a.length === b.length && a.every((byte, i) => byte === b[i]);
|
|
14815
|
+
}
|
|
14816
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
14817
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
14818
|
+
}
|
|
14819
|
+
if (!isObj(a) || !isObj(b)) {
|
|
14820
|
+
return false;
|
|
14821
|
+
}
|
|
14822
|
+
const ka = Object.keys(a);
|
|
14823
|
+
const kb = new Set(Object.keys(b));
|
|
14824
|
+
return ka.length === kb.size && ka.every((k) => kb.has(k) && deepEqual(a[k], b[k]));
|
|
14825
|
+
};
|
|
14826
|
+
function mapChainError(error) {
|
|
14827
|
+
if (error instanceof ChainError) {
|
|
14828
|
+
throw new KernelError("invalid-input", "invalid sign request");
|
|
14829
|
+
}
|
|
14830
|
+
throw error;
|
|
14831
|
+
}
|
|
14832
|
+
|
|
14833
|
+
// ../wallet-kernel/src/modules/chains/bitcoin.ts
|
|
14936
14834
|
var isPath = (path) => Array.isArray(path) && path.every((p) => typeof p === "number");
|
|
14937
|
-
var
|
|
14835
|
+
var hex = (bytes) => bytes.reduce((acc, b) => acc + b.toString(16).padStart(2, "0"), "");
|
|
14836
|
+
var derivationOf = (owner, fingerprint, purpose) => {
|
|
14837
|
+
if (purpose === 86) {
|
|
14838
|
+
const claimed = (der) => der.fingerprint === fingerprint && isPath(der.path);
|
|
14839
|
+
for (const [key, value] of owner.tapBip32Derivation ?? []) {
|
|
14840
|
+
if (claimed(value.der)) {
|
|
14841
|
+
return { pubkey: key, fingerprint: value.der.fingerprint, path: value.der.path };
|
|
14842
|
+
}
|
|
14843
|
+
}
|
|
14844
|
+
return;
|
|
14845
|
+
}
|
|
14846
|
+
for (const [key, value] of owner.bip32Derivation ?? []) {
|
|
14847
|
+
if (value.fingerprint === fingerprint) {
|
|
14848
|
+
return { pubkey: key, fingerprint: value.fingerprint, path: value.path };
|
|
14849
|
+
}
|
|
14850
|
+
}
|
|
14851
|
+
return;
|
|
14852
|
+
};
|
|
14853
|
+
var expectedPub = (purpose, pub) => purpose === 86 ? pub.slice(1) : pub;
|
|
14854
|
+
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;
|
|
14855
|
+
var childAt = (b, path) => {
|
|
14856
|
+
const [purposePath, coinPath, groupPath, change, index] = path;
|
|
14857
|
+
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) {
|
|
14858
|
+
throw new KernelError("invalid-input", "derivation path is not this account's");
|
|
14859
|
+
}
|
|
14860
|
+
const child = b.accountNode.deriveChild(change).deriveChild(index);
|
|
14861
|
+
b.children.push(child);
|
|
14862
|
+
return child;
|
|
14863
|
+
};
|
|
14864
|
+
var bitcoinInput = (b, tx, idx) => {
|
|
14865
|
+
const input = tx.getInput(idx);
|
|
14866
|
+
const entry = derivationOf(input, b.master.fingerprint, b.purpose);
|
|
14867
|
+
if (entry === undefined) {
|
|
14868
|
+
throw new KernelError("invalid-input", `input ${idx}: derivation entry is not this account's`);
|
|
14869
|
+
}
|
|
14870
|
+
const child = childAt(b, entry.path);
|
|
14871
|
+
const pub = child.publicKey;
|
|
14872
|
+
const priv = child.privateKey;
|
|
14873
|
+
if (pub === null || priv === null) {
|
|
14874
|
+
throw new KernelError("integrity", "no key at derivation path");
|
|
14875
|
+
}
|
|
14876
|
+
if (!deepEqual(entry.pubkey, expectedPub(b.purpose, pub))) {
|
|
14877
|
+
throw new KernelError("invalid-input", `input ${idx}: derivation pubkey is not ours`);
|
|
14878
|
+
}
|
|
14879
|
+
if (b.purpose === 44) {
|
|
14880
|
+
if (input.nonWitnessUtxo === undefined) {
|
|
14881
|
+
throw new KernelError("invalid-input", `input ${idx}: P2PKH spend requires nonWitnessUtxo`);
|
|
14882
|
+
}
|
|
14883
|
+
const vout = input.index;
|
|
14884
|
+
const outs = input.nonWitnessUtxo.outputs;
|
|
14885
|
+
const prevScript = vout === undefined ? undefined : outs[vout]?.script;
|
|
14886
|
+
if (prevScript === undefined || !deepEqual(prevScript, expectedScript(b.purpose, pub))) {
|
|
14887
|
+
throw new KernelError("invalid-input", `input ${idx}: nonWitnessUtxo prevout is not this key's`);
|
|
14888
|
+
}
|
|
14889
|
+
} else {
|
|
14890
|
+
const prevout = input.witnessUtxo;
|
|
14891
|
+
if (prevout === undefined || !deepEqual(prevout.script, expectedScript(b.purpose, pub))) {
|
|
14892
|
+
throw new KernelError("invalid-input", `input ${idx}: prevout script is not this key's`);
|
|
14893
|
+
}
|
|
14894
|
+
if (b.purpose === 49 && (input.redeemScript === undefined || !deepEqual(input.redeemScript, p2wpkh(pub).script))) {
|
|
14895
|
+
throw new KernelError("invalid-input", `input ${idx}: redeemScript is not this key's`);
|
|
14896
|
+
}
|
|
14897
|
+
}
|
|
14898
|
+
return { index: idx, privateKey: priv };
|
|
14899
|
+
};
|
|
14900
|
+
var bitcoinOwnScripts = (b, tx) => {
|
|
14901
|
+
const ownScripts = new Set;
|
|
14902
|
+
for (let i = 0;i < tx.outputsLength; i++) {
|
|
14903
|
+
const output = tx.getOutput(i);
|
|
14904
|
+
if (output.script === undefined) {
|
|
14905
|
+
continue;
|
|
14906
|
+
}
|
|
14907
|
+
const entry = derivationOf(output, b.master.fingerprint, b.purpose);
|
|
14908
|
+
if (entry === undefined) {
|
|
14909
|
+
continue;
|
|
14910
|
+
}
|
|
14911
|
+
try {
|
|
14912
|
+
const child = childAt(b, entry.path);
|
|
14913
|
+
const pub = child.publicKey;
|
|
14914
|
+
if (pub !== null && deepEqual(output.script, expectedScript(b.purpose, pub))) {
|
|
14915
|
+
ownScripts.add(hex(output.script));
|
|
14916
|
+
}
|
|
14917
|
+
} catch {
|
|
14918
|
+
continue;
|
|
14919
|
+
}
|
|
14920
|
+
}
|
|
14921
|
+
return ownScripts;
|
|
14922
|
+
};
|
|
14923
|
+
var executeBitcoinPsbt = (b, request, random, intentOnly) => {
|
|
14924
|
+
const tx = Transaction.fromPSBT(request.psbt);
|
|
14925
|
+
const inputs = request.sign.map((idx) => bitcoinInput(b, tx, idx));
|
|
14926
|
+
const ownScripts = bitcoinOwnScripts(b, tx);
|
|
14927
|
+
let normalized;
|
|
14928
|
+
try {
|
|
14929
|
+
normalized = normalizeBitcoin(request);
|
|
14930
|
+
} catch (error) {
|
|
14931
|
+
mapChainError(error);
|
|
14932
|
+
}
|
|
14933
|
+
if (!deepEqual(normalized, request)) {
|
|
14934
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
14935
|
+
}
|
|
14936
|
+
let intent;
|
|
14937
|
+
try {
|
|
14938
|
+
intent = decodeBitcoinPsbt(request, ownScripts);
|
|
14939
|
+
} catch (error) {
|
|
14940
|
+
mapChainError(error);
|
|
14941
|
+
}
|
|
14942
|
+
if (intentOnly) {
|
|
14943
|
+
return { prompt: intent };
|
|
14944
|
+
}
|
|
14945
|
+
return {
|
|
14946
|
+
kind: "bitcoin.psbt",
|
|
14947
|
+
signedPsbt: signBitcoinPsbt(request.psbt, inputs, () => random(32))
|
|
14948
|
+
};
|
|
14949
|
+
};
|
|
14950
|
+
var executeBitcoinMessage = (b, request, random, intentOnly) => {
|
|
14951
|
+
if (request.format === "legacy" && b.account.template !== "btc.bip44") {
|
|
14952
|
+
throw new KernelError("unsupported", "legacy message format is btc.bip44-only");
|
|
14953
|
+
}
|
|
14954
|
+
const child = childAt(b, [
|
|
14955
|
+
b.purpose + b.hardened,
|
|
14956
|
+
b.coinType + b.hardened,
|
|
14957
|
+
b.account.groupIndex + b.hardened,
|
|
14958
|
+
request.change,
|
|
14959
|
+
request.index
|
|
14960
|
+
]);
|
|
14961
|
+
const pub = child.publicKey;
|
|
14962
|
+
const priv = child.privateKey;
|
|
14963
|
+
if (pub === null || priv === null) {
|
|
14964
|
+
throw new KernelError("integrity", "no key at derivation path");
|
|
14965
|
+
}
|
|
14966
|
+
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;
|
|
14967
|
+
if (derived !== request.address) {
|
|
14968
|
+
throw new KernelError("invalid-input", "address is not ours");
|
|
14969
|
+
}
|
|
14970
|
+
let normalized;
|
|
14971
|
+
try {
|
|
14972
|
+
normalized = normalizeBitcoin(request);
|
|
14973
|
+
} catch (error) {
|
|
14974
|
+
mapChainError(error);
|
|
14975
|
+
}
|
|
14976
|
+
if (!deepEqual(normalized, request)) {
|
|
14977
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
14978
|
+
}
|
|
14979
|
+
try {
|
|
14980
|
+
decodeMessageTarget(request);
|
|
14981
|
+
} catch (error) {
|
|
14982
|
+
mapChainError(error);
|
|
14983
|
+
}
|
|
14984
|
+
if (intentOnly) {
|
|
14985
|
+
return { prompt: MESSAGE_INTENT };
|
|
14986
|
+
}
|
|
14987
|
+
return {
|
|
14988
|
+
kind: "bitcoin.message",
|
|
14989
|
+
signature: signBitcoinMessage(request, priv, () => random(32))
|
|
14990
|
+
};
|
|
14991
|
+
};
|
|
14992
|
+
var executeBitcoin = (random, request, account, seed, intentOnly) => {
|
|
14993
|
+
const net = bitcoinNetwork(request.network);
|
|
14994
|
+
const master = HDKey.fromMasterSeed(seed, net.bip32);
|
|
14995
|
+
try {
|
|
14996
|
+
const purpose = BTC_PURPOSE[account.template] ?? 84;
|
|
14997
|
+
const { coinType } = net;
|
|
14998
|
+
const hardened = 2147483648;
|
|
14999
|
+
const accountNode = master.derive(`m/${purpose}'/${coinType}'/${account.groupIndex}'`);
|
|
15000
|
+
const children = [];
|
|
15001
|
+
const b = {
|
|
15002
|
+
master,
|
|
15003
|
+
accountNode,
|
|
15004
|
+
children,
|
|
15005
|
+
purpose,
|
|
15006
|
+
coinType,
|
|
15007
|
+
hardened,
|
|
15008
|
+
account,
|
|
15009
|
+
net
|
|
15010
|
+
};
|
|
15011
|
+
try {
|
|
15012
|
+
if (request.kind === "bitcoin.psbt") {
|
|
15013
|
+
return executeBitcoinPsbt(b, request, random, intentOnly);
|
|
15014
|
+
}
|
|
15015
|
+
return executeBitcoinMessage(b, request, random, intentOnly);
|
|
15016
|
+
} finally {
|
|
15017
|
+
for (const child of children) {
|
|
15018
|
+
child.wipePrivateData();
|
|
15019
|
+
}
|
|
15020
|
+
accountNode.wipePrivateData();
|
|
15021
|
+
}
|
|
15022
|
+
} finally {
|
|
15023
|
+
master.wipePrivateData();
|
|
15024
|
+
}
|
|
15025
|
+
};
|
|
15026
|
+
|
|
15027
|
+
// ../wallet-chains/dist/evm-sign.mjs
|
|
15028
|
+
function assertHex2(value, field) {
|
|
15029
|
+
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value))
|
|
15030
|
+
throw new ChainError("invalid-quantity", `${field} must be 0x-prefixed bytes`);
|
|
15031
|
+
}
|
|
15032
|
+
var hex2 = (value, field) => {
|
|
15033
|
+
assertHex2(value, field);
|
|
15034
|
+
return value;
|
|
15035
|
+
};
|
|
15036
|
+
var key = (privateKey) => {
|
|
15037
|
+
if (privateKey.length !== 32)
|
|
15038
|
+
throw new ChainError("invalid-request", "private key must be 32 bytes");
|
|
15039
|
+
return fromBytes(privateKey);
|
|
15040
|
+
};
|
|
15041
|
+
var accessEntry = (entry) => ({
|
|
15042
|
+
address: hex2(entry.address, "accessList.address"),
|
|
15043
|
+
storageKeys: entry.storageKeys.map((k) => hex2(k, "accessList.storageKeys"))
|
|
15044
|
+
});
|
|
15045
|
+
var sign3 = (payload, privateKey) => sign2({
|
|
15046
|
+
payload,
|
|
15047
|
+
privateKey,
|
|
15048
|
+
as: "Object"
|
|
15049
|
+
});
|
|
15050
|
+
var signEvmTransaction = (tx, privateKey) => {
|
|
15051
|
+
const privateKeyHex = key(privateKey);
|
|
15052
|
+
const base = {
|
|
15053
|
+
chainId: tx.chainId,
|
|
15054
|
+
to: tx.to === undefined ? undefined : hex2(tx.to, "to"),
|
|
15055
|
+
data: hex2(tx.data, "data"),
|
|
15056
|
+
value: BigInt(tx.value),
|
|
15057
|
+
nonce: BigInt(tx.nonce),
|
|
15058
|
+
gas: BigInt(tx.gas)
|
|
15059
|
+
};
|
|
15060
|
+
if (tx.type === "legacy") {
|
|
15061
|
+
const envelope = {
|
|
15062
|
+
...base,
|
|
15063
|
+
type: "legacy",
|
|
15064
|
+
gasPrice: BigInt(tx.gasPrice)
|
|
15065
|
+
};
|
|
15066
|
+
const signature = sign3(getSignPayload4(envelope), privateKeyHex);
|
|
15067
|
+
return toBytes(serialize2(envelope, { signature }));
|
|
15068
|
+
}
|
|
15069
|
+
if (tx.type === "eip2930") {
|
|
15070
|
+
const envelope = {
|
|
15071
|
+
...base,
|
|
15072
|
+
type: "eip2930",
|
|
15073
|
+
gasPrice: BigInt(tx.gasPrice),
|
|
15074
|
+
accessList: tx.accessList.map(accessEntry)
|
|
15075
|
+
};
|
|
15076
|
+
const signature = sign3(getSignPayload3(envelope), privateKeyHex);
|
|
15077
|
+
return toBytes(serialize(envelope, { signature }));
|
|
15078
|
+
}
|
|
15079
|
+
const envelope = {
|
|
15080
|
+
...base,
|
|
15081
|
+
type: "eip1559",
|
|
15082
|
+
accessList: tx.accessList.map(accessEntry),
|
|
15083
|
+
maxFeePerGas: BigInt(tx.maxFeePerGas),
|
|
15084
|
+
maxPriorityFeePerGas: BigInt(tx.maxPriorityFeePerGas)
|
|
15085
|
+
};
|
|
15086
|
+
const signature = sign3(getSignPayload5(envelope), privateKeyHex);
|
|
15087
|
+
return toBytes(serialize3(envelope, { signature }));
|
|
15088
|
+
};
|
|
15089
|
+
var rs_v = (signature) => toBytes2(signature);
|
|
15090
|
+
var signEvmPersonalMessage = (message, privateKey) => {
|
|
15091
|
+
const payload = getSignPayload2(fromBytes(message));
|
|
15092
|
+
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
15093
|
+
};
|
|
15094
|
+
var signEvmTypedData = (typedData, privateKey) => {
|
|
15095
|
+
const { json } = parseTypedData(typedData, "eip155:1");
|
|
15096
|
+
const payload = getSignPayload(json);
|
|
15097
|
+
return rs_v(from5(sign3(payload, key(privateKey))));
|
|
15098
|
+
};
|
|
15099
|
+
|
|
15100
|
+
// ../wallet-kernel/src/modules/chains/evm.ts
|
|
15101
|
+
var executeEvm = (request, account, seed, intentOnly) => {
|
|
15102
|
+
const master = HDKey.fromMasterSeed(seed);
|
|
15103
|
+
try {
|
|
15104
|
+
const child = master.derive(`m/44'/60'/0'/0/${account.groupIndex}`);
|
|
15105
|
+
try {
|
|
15106
|
+
const priv = child.privateKey;
|
|
15107
|
+
if (priv === null) {
|
|
15108
|
+
throw new KernelError("integrity", "no private key at account path");
|
|
15109
|
+
}
|
|
15110
|
+
let normalized;
|
|
15111
|
+
try {
|
|
15112
|
+
normalized = normalizeEvm(request);
|
|
15113
|
+
} catch (error) {
|
|
15114
|
+
mapChainError(error);
|
|
15115
|
+
}
|
|
15116
|
+
if (!deepEqual(normalized, request)) {
|
|
15117
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
15118
|
+
}
|
|
15119
|
+
let intent;
|
|
15120
|
+
try {
|
|
15121
|
+
intent = decodeEvm(request);
|
|
15122
|
+
} catch (error) {
|
|
15123
|
+
mapChainError(error);
|
|
15124
|
+
}
|
|
15125
|
+
if (intentOnly) {
|
|
15126
|
+
return { prompt: intent };
|
|
15127
|
+
}
|
|
15128
|
+
if (request.kind === "evm.transaction") {
|
|
15129
|
+
return {
|
|
15130
|
+
kind: "evm.transaction",
|
|
15131
|
+
signedTransaction: signEvmTransaction(request.tx, priv)
|
|
15132
|
+
};
|
|
15133
|
+
}
|
|
15134
|
+
if (request.kind === "evm.personal-message") {
|
|
15135
|
+
return {
|
|
15136
|
+
kind: "evm.personal-message",
|
|
15137
|
+
signature: signEvmPersonalMessage(request.message, priv)
|
|
15138
|
+
};
|
|
15139
|
+
}
|
|
15140
|
+
return {
|
|
15141
|
+
kind: "evm.typed-data",
|
|
15142
|
+
signature: signEvmTypedData(request.typedData, priv)
|
|
15143
|
+
};
|
|
15144
|
+
} finally {
|
|
15145
|
+
child.wipePrivateData();
|
|
15146
|
+
}
|
|
15147
|
+
} finally {
|
|
15148
|
+
master.wipePrivateData();
|
|
15149
|
+
}
|
|
15150
|
+
};
|
|
15151
|
+
|
|
15152
|
+
// ../wallet-chains/dist/solana-sign.mjs
|
|
15153
|
+
var signSolanaMessage = (message, privateKey) => {
|
|
15154
|
+
if (privateKey.length !== 32)
|
|
15155
|
+
throw new ChainError("invalid-request", "private key must be a 32-byte seed");
|
|
15156
|
+
if (message.length === 0)
|
|
15157
|
+
throw new ChainError("invalid-request", "message must not be empty");
|
|
15158
|
+
const signature = ed25519.sign(message, privateKey);
|
|
15159
|
+
if (signature.length !== 64)
|
|
15160
|
+
throw new ChainError("invalid-request", "ed25519 produced a malformed signature");
|
|
15161
|
+
return signature;
|
|
15162
|
+
};
|
|
15163
|
+
|
|
15164
|
+
// ../wallet-kernel/src/modules/chains/solana.ts
|
|
15165
|
+
var executeSolana = (request, account, seed, intentOnly) => {
|
|
15166
|
+
const root = HDKey2.fromMasterSeed(seed);
|
|
15167
|
+
const child = root.derive(`m/44'/501'/${account.groupIndex}'/0'`);
|
|
15168
|
+
try {
|
|
15169
|
+
const priv = child.privateKey;
|
|
15170
|
+
const signer = solanaAddressFromPublicKey(ed25519.getPublicKey(priv));
|
|
15171
|
+
let normalized;
|
|
15172
|
+
try {
|
|
15173
|
+
normalized = normalizeSolana(request, signer);
|
|
15174
|
+
} catch (error) {
|
|
15175
|
+
mapChainError(error);
|
|
15176
|
+
}
|
|
15177
|
+
if (!deepEqual(normalized, request)) {
|
|
15178
|
+
throw new KernelError("invalid-input", "request is not normalized");
|
|
15179
|
+
}
|
|
15180
|
+
let intent = MESSAGE_INTENT;
|
|
15181
|
+
if (request.kind === "solana.transaction") {
|
|
15182
|
+
try {
|
|
15183
|
+
intent = decodeSolana(request, signer);
|
|
15184
|
+
} catch (error) {
|
|
15185
|
+
mapChainError(error);
|
|
15186
|
+
}
|
|
15187
|
+
}
|
|
15188
|
+
if (intentOnly) {
|
|
15189
|
+
return { prompt: intent };
|
|
15190
|
+
}
|
|
15191
|
+
return {
|
|
15192
|
+
kind: request.kind,
|
|
15193
|
+
signature: signSolanaMessage(request.message, priv)
|
|
15194
|
+
};
|
|
15195
|
+
} finally {
|
|
15196
|
+
wipe(child.privateKey);
|
|
15197
|
+
wipe(root.privateKey);
|
|
15198
|
+
}
|
|
15199
|
+
};
|
|
15200
|
+
|
|
15201
|
+
// ../wallet-kernel/src/modules/chains/index.ts
|
|
14938
15202
|
var checkNetwork = (template, network) => {
|
|
14939
15203
|
if (template.startsWith("evm.") && !network.startsWith("eip155:")) {
|
|
14940
15204
|
throw new KernelError("invalid-input", "evm.bip44 requires an eip155 network");
|
|
@@ -14991,382 +15255,86 @@ var accountFor = (master, seed, template, network, groupIndex) => {
|
|
|
14991
15255
|
account.wipePrivateData();
|
|
14992
15256
|
}
|
|
14993
15257
|
};
|
|
14994
|
-
var
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
if (a instanceof Uint8Array || b instanceof Uint8Array) {
|
|
15000
|
-
return a instanceof Uint8Array && b instanceof Uint8Array && a.length === b.length && a.every((byte, i) => byte === b[i]);
|
|
15001
|
-
}
|
|
15002
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
15003
|
-
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
15004
|
-
}
|
|
15005
|
-
if (!isObj(a) || !isObj(b)) {
|
|
15006
|
-
return false;
|
|
15007
|
-
}
|
|
15008
|
-
const ka = Object.keys(a);
|
|
15009
|
-
const kb = new Set(Object.keys(b));
|
|
15010
|
-
return ka.length === kb.size && ka.every((k) => kb.has(k) && deepEqual(a[k], b[k]));
|
|
15011
|
-
};
|
|
15012
|
-
function mapChainError(error) {
|
|
15013
|
-
if (error instanceof ChainError) {
|
|
15014
|
-
throw new KernelError("invalid-input", "invalid sign request");
|
|
15258
|
+
var walletAccounts = async (ctx, params, session) => {
|
|
15259
|
+
const { dek } = ctx.session.require(session);
|
|
15260
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.walletId);
|
|
15261
|
+
if (record === undefined) {
|
|
15262
|
+
throw new KernelError("not-found", "no such wallet");
|
|
15015
15263
|
}
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
|
|
15020
|
-
|
|
15021
|
-
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15025
|
-
|
|
15026
|
-
|
|
15027
|
-
|
|
15028
|
-
|
|
15029
|
-
|
|
15030
|
-
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
wipe(entropy);
|
|
15046
|
-
}
|
|
15047
|
-
try {
|
|
15048
|
-
const master = HDKey.fromMasterSeed(seed, params.template.startsWith("btc.") ? bitcoinNetwork(params.network).bip32 : undefined);
|
|
15049
|
-
try {
|
|
15050
|
-
return accountFor(master, seed, params.template, params.network, params.groupIndex);
|
|
15051
|
-
} finally {
|
|
15052
|
-
master.wipePrivateData();
|
|
15053
|
-
}
|
|
15054
|
-
} finally {
|
|
15055
|
-
wipe(seed);
|
|
15056
|
-
}
|
|
15057
|
-
},
|
|
15058
|
-
"chain.sign": async (ctx, params, session) => {
|
|
15059
|
-
const { dek } = ctx.session.require(session);
|
|
15060
|
-
const { request, verify } = params;
|
|
15061
|
-
const { account } = request;
|
|
15062
|
-
if (account.kind !== "hd") {
|
|
15063
|
-
throw new KernelError("unsupported", "imported accounts are not yet supported");
|
|
15064
|
-
}
|
|
15065
|
-
const [family] = request.kind.split(".", 1);
|
|
15066
|
-
const expected = family === "evm" ? ["evm.bip44"] : family === "solana" ? ["solana.bip44-change"] : ["btc.bip44", "btc.bip49", "btc.bip84", "btc.bip86"];
|
|
15067
|
-
if (!expected.includes(account.template)) {
|
|
15068
|
-
throw new KernelError("invalid-input", "account template does not match the request family");
|
|
15069
|
-
}
|
|
15070
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
15071
|
-
if (record === undefined) {
|
|
15072
|
-
throw new KernelError("not-found", "no such wallet");
|
|
15073
|
-
}
|
|
15074
|
-
const execute = (seed, intentOnly) => {
|
|
15075
|
-
if (request.kind === "evm.transaction" || request.kind === "evm.personal-message" || request.kind === "evm.typed-data") {
|
|
15076
|
-
const master = HDKey.fromMasterSeed(seed);
|
|
15077
|
-
try {
|
|
15078
|
-
const child = master.derive(`m/44'/60'/0'/0/${account.groupIndex}`);
|
|
15079
|
-
try {
|
|
15080
|
-
const priv = child.privateKey;
|
|
15081
|
-
if (priv === null) {
|
|
15082
|
-
throw new KernelError("integrity", "no private key at account path");
|
|
15083
|
-
}
|
|
15084
|
-
let normalized;
|
|
15085
|
-
try {
|
|
15086
|
-
normalized = normalizeEvm(request);
|
|
15087
|
-
} catch (error) {
|
|
15088
|
-
mapChainError(error);
|
|
15089
|
-
}
|
|
15090
|
-
if (!deepEqual(normalized, request)) {
|
|
15091
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15092
|
-
}
|
|
15093
|
-
let intent;
|
|
15094
|
-
try {
|
|
15095
|
-
intent = decodeEvm(request);
|
|
15096
|
-
} catch (error) {
|
|
15097
|
-
mapChainError(error);
|
|
15098
|
-
}
|
|
15099
|
-
if (intentOnly) {
|
|
15100
|
-
return { prompt: intent };
|
|
15101
|
-
}
|
|
15102
|
-
if (request.kind === "evm.transaction") {
|
|
15103
|
-
return {
|
|
15104
|
-
kind: "evm.transaction",
|
|
15105
|
-
signedTransaction: signEvmTransaction(request.tx, priv)
|
|
15106
|
-
};
|
|
15107
|
-
}
|
|
15108
|
-
if (request.kind === "evm.personal-message") {
|
|
15109
|
-
return {
|
|
15110
|
-
kind: "evm.personal-message",
|
|
15111
|
-
signature: signEvmPersonalMessage(request.message, priv)
|
|
15112
|
-
};
|
|
15113
|
-
}
|
|
15114
|
-
return {
|
|
15115
|
-
kind: "evm.typed-data",
|
|
15116
|
-
signature: signEvmTypedData(request.typedData, priv)
|
|
15117
|
-
};
|
|
15118
|
-
} finally {
|
|
15119
|
-
child.wipePrivateData();
|
|
15120
|
-
}
|
|
15121
|
-
} finally {
|
|
15122
|
-
master.wipePrivateData();
|
|
15123
|
-
}
|
|
15124
|
-
}
|
|
15125
|
-
if (request.kind === "bitcoin.psbt" || request.kind === "bitcoin.message") {
|
|
15126
|
-
const net = bitcoinNetwork(request.network);
|
|
15127
|
-
const master = HDKey.fromMasterSeed(seed, net.bip32);
|
|
15128
|
-
try {
|
|
15129
|
-
const purpose = BTC_PURPOSE[account.template] ?? 84;
|
|
15130
|
-
const { coinType } = net;
|
|
15131
|
-
const hardened = 2147483648;
|
|
15132
|
-
const accountNode = master.derive(`m/${purpose}'/${coinType}'/${account.groupIndex}'`);
|
|
15133
|
-
const children = [];
|
|
15134
|
-
const derivation = (owner) => {
|
|
15135
|
-
if (purpose === 86) {
|
|
15136
|
-
const claimed = (der) => der.fingerprint === master.fingerprint && isPath(der.path);
|
|
15137
|
-
for (const [key, value] of owner.tapBip32Derivation ?? []) {
|
|
15138
|
-
if (claimed(value.der)) {
|
|
15139
|
-
return {
|
|
15140
|
-
pubkey: key,
|
|
15141
|
-
fingerprint: value.der.fingerprint,
|
|
15142
|
-
path: value.der.path
|
|
15143
|
-
};
|
|
15144
|
-
}
|
|
15145
|
-
}
|
|
15146
|
-
return;
|
|
15147
|
-
}
|
|
15148
|
-
for (const [key, value] of owner.bip32Derivation ?? []) {
|
|
15149
|
-
if (value.fingerprint === master.fingerprint) {
|
|
15150
|
-
return { pubkey: key, fingerprint: value.fingerprint, path: value.path };
|
|
15151
|
-
}
|
|
15152
|
-
}
|
|
15153
|
-
return;
|
|
15154
|
-
};
|
|
15155
|
-
const childAt = (path) => {
|
|
15156
|
-
const [purposePath, coinPath, groupPath, change, index] = path;
|
|
15157
|
-
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) {
|
|
15158
|
-
throw new KernelError("invalid-input", "derivation path is not this account's");
|
|
15159
|
-
}
|
|
15160
|
-
const child = accountNode.deriveChild(change).deriveChild(index);
|
|
15161
|
-
children.push(child);
|
|
15162
|
-
return child;
|
|
15163
|
-
};
|
|
15164
|
-
const expectedPub = (pub) => purpose === 86 ? pub.slice(1) : pub;
|
|
15165
|
-
const expectedScript = (pub) => purpose === 86 ? p2tr(pub.slice(1)).script : purpose === 49 ? p2sh(p2wpkh(pub)).script : purpose === 44 ? p2pkh(pub).script : p2wpkh(pub).script;
|
|
15166
|
-
try {
|
|
15167
|
-
if (request.kind === "bitcoin.psbt") {
|
|
15168
|
-
const tx = Transaction.fromPSBT(request.psbt);
|
|
15169
|
-
const inputs = [];
|
|
15170
|
-
for (const idx of request.sign) {
|
|
15171
|
-
const input = tx.getInput(idx);
|
|
15172
|
-
const entry = derivation(input);
|
|
15173
|
-
if (entry === undefined) {
|
|
15174
|
-
throw new KernelError("invalid-input", `input ${idx}: derivation entry is not this account's`);
|
|
15175
|
-
}
|
|
15176
|
-
const child = childAt(entry.path);
|
|
15177
|
-
const pub = child.publicKey;
|
|
15178
|
-
const priv = child.privateKey;
|
|
15179
|
-
if (pub === null || priv === null) {
|
|
15180
|
-
throw new KernelError("integrity", "no key at derivation path");
|
|
15181
|
-
}
|
|
15182
|
-
if (!deepEqual(entry.pubkey, expectedPub(pub))) {
|
|
15183
|
-
throw new KernelError("invalid-input", `input ${idx}: derivation pubkey is not ours`);
|
|
15184
|
-
}
|
|
15185
|
-
if (purpose === 44) {
|
|
15186
|
-
if (input.nonWitnessUtxo === undefined) {
|
|
15187
|
-
throw new KernelError("invalid-input", `input ${idx}: P2PKH spend requires nonWitnessUtxo`);
|
|
15188
|
-
}
|
|
15189
|
-
const vout = input.index;
|
|
15190
|
-
const outs = input.nonWitnessUtxo.outputs;
|
|
15191
|
-
const prevScript = vout === undefined ? undefined : outs[vout]?.script;
|
|
15192
|
-
if (prevScript === undefined || !deepEqual(prevScript, expectedScript(pub))) {
|
|
15193
|
-
throw new KernelError("invalid-input", `input ${idx}: nonWitnessUtxo prevout is not this key's`);
|
|
15194
|
-
}
|
|
15195
|
-
} else {
|
|
15196
|
-
const prevout = input.witnessUtxo;
|
|
15197
|
-
if (prevout === undefined || !deepEqual(prevout.script, expectedScript(pub))) {
|
|
15198
|
-
throw new KernelError("invalid-input", `input ${idx}: prevout script is not this key's`);
|
|
15199
|
-
}
|
|
15200
|
-
if (purpose === 49 && (input.redeemScript === undefined || !deepEqual(input.redeemScript, p2wpkh(pub).script))) {
|
|
15201
|
-
throw new KernelError("invalid-input", `input ${idx}: redeemScript is not this key's`);
|
|
15202
|
-
}
|
|
15203
|
-
}
|
|
15204
|
-
inputs.push({ index: idx, privateKey: priv });
|
|
15205
|
-
}
|
|
15206
|
-
const ownScripts = new Set;
|
|
15207
|
-
for (let i = 0;i < tx.outputsLength; i++) {
|
|
15208
|
-
const output = tx.getOutput(i);
|
|
15209
|
-
if (output.script === undefined) {
|
|
15210
|
-
continue;
|
|
15211
|
-
}
|
|
15212
|
-
const entry = derivation(output);
|
|
15213
|
-
if (entry === undefined) {
|
|
15214
|
-
continue;
|
|
15215
|
-
}
|
|
15216
|
-
try {
|
|
15217
|
-
const child = childAt(entry.path);
|
|
15218
|
-
const pub = child.publicKey;
|
|
15219
|
-
if (pub !== null && deepEqual(output.script, expectedScript(pub))) {
|
|
15220
|
-
ownScripts.add(hex2(output.script));
|
|
15221
|
-
}
|
|
15222
|
-
} catch {
|
|
15223
|
-
continue;
|
|
15224
|
-
}
|
|
15225
|
-
}
|
|
15226
|
-
let normalized;
|
|
15227
|
-
try {
|
|
15228
|
-
normalized = normalizeBitcoin(request);
|
|
15229
|
-
} catch (error) {
|
|
15230
|
-
mapChainError(error);
|
|
15231
|
-
}
|
|
15232
|
-
if (!deepEqual(normalized, request)) {
|
|
15233
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15234
|
-
}
|
|
15235
|
-
let intent;
|
|
15236
|
-
try {
|
|
15237
|
-
intent = decodeBitcoinPsbt(request, ownScripts);
|
|
15238
|
-
} catch (error) {
|
|
15239
|
-
mapChainError(error);
|
|
15240
|
-
}
|
|
15241
|
-
if (intentOnly) {
|
|
15242
|
-
return { prompt: intent };
|
|
15243
|
-
}
|
|
15244
|
-
return {
|
|
15245
|
-
kind: "bitcoin.psbt",
|
|
15246
|
-
signedPsbt: signBitcoinPsbt(request.psbt, inputs, () => ctx.platform.random(32))
|
|
15247
|
-
};
|
|
15248
|
-
}
|
|
15249
|
-
if (request.format === "legacy" && account.template !== "btc.bip44") {
|
|
15250
|
-
throw new KernelError("unsupported", "legacy message format is btc.bip44-only");
|
|
15251
|
-
}
|
|
15252
|
-
const child = childAt([
|
|
15253
|
-
purpose + hardened,
|
|
15254
|
-
coinType + hardened,
|
|
15255
|
-
account.groupIndex + hardened,
|
|
15256
|
-
request.change,
|
|
15257
|
-
request.index
|
|
15258
|
-
]);
|
|
15259
|
-
const pub = child.publicKey;
|
|
15260
|
-
const priv = child.privateKey;
|
|
15261
|
-
if (pub === null || priv === null) {
|
|
15262
|
-
throw new KernelError("integrity", "no key at derivation path");
|
|
15263
|
-
}
|
|
15264
|
-
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;
|
|
15265
|
-
if (derived !== request.address) {
|
|
15266
|
-
throw new KernelError("invalid-input", "address is not ours");
|
|
15267
|
-
}
|
|
15268
|
-
let normalized;
|
|
15269
|
-
try {
|
|
15270
|
-
normalized = normalizeBitcoin(request);
|
|
15271
|
-
} catch (error) {
|
|
15272
|
-
mapChainError(error);
|
|
15273
|
-
}
|
|
15274
|
-
if (!deepEqual(normalized, request)) {
|
|
15275
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15276
|
-
}
|
|
15277
|
-
try {
|
|
15278
|
-
decodeMessageTarget(request);
|
|
15279
|
-
} catch (error) {
|
|
15280
|
-
mapChainError(error);
|
|
15281
|
-
}
|
|
15282
|
-
if (intentOnly) {
|
|
15283
|
-
return { prompt: MESSAGE_INTENT };
|
|
15284
|
-
}
|
|
15285
|
-
return {
|
|
15286
|
-
kind: "bitcoin.message",
|
|
15287
|
-
signature: signBitcoinMessage(request, priv, () => ctx.platform.random(32))
|
|
15288
|
-
};
|
|
15289
|
-
} finally {
|
|
15290
|
-
for (const child of children) {
|
|
15291
|
-
child.wipePrivateData();
|
|
15292
|
-
}
|
|
15293
|
-
accountNode.wipePrivateData();
|
|
15294
|
-
}
|
|
15295
|
-
} finally {
|
|
15296
|
-
master.wipePrivateData();
|
|
15297
|
-
}
|
|
15298
|
-
}
|
|
15299
|
-
const root = HDKey2.fromMasterSeed(seed);
|
|
15300
|
-
const child = root.derive(`m/44'/501'/${account.groupIndex}'/0'`);
|
|
15301
|
-
try {
|
|
15302
|
-
const priv = child.privateKey;
|
|
15303
|
-
const signer = solanaAddressFromPublicKey(ed25519.getPublicKey(priv));
|
|
15304
|
-
let normalized;
|
|
15305
|
-
try {
|
|
15306
|
-
normalized = normalizeSolana(request, signer);
|
|
15307
|
-
} catch (error) {
|
|
15308
|
-
mapChainError(error);
|
|
15309
|
-
}
|
|
15310
|
-
if (!deepEqual(normalized, request)) {
|
|
15311
|
-
throw new KernelError("invalid-input", "request is not normalized");
|
|
15312
|
-
}
|
|
15313
|
-
let intent = MESSAGE_INTENT;
|
|
15314
|
-
if (request.kind === "solana.transaction") {
|
|
15315
|
-
try {
|
|
15316
|
-
intent = decodeSolana(request, signer);
|
|
15317
|
-
} catch (error) {
|
|
15318
|
-
mapChainError(error);
|
|
15319
|
-
}
|
|
15320
|
-
}
|
|
15321
|
-
if (intentOnly) {
|
|
15322
|
-
return { prompt: intent };
|
|
15323
|
-
}
|
|
15324
|
-
return {
|
|
15325
|
-
kind: request.kind,
|
|
15326
|
-
signature: signSolanaMessage(request.message, priv)
|
|
15327
|
-
};
|
|
15328
|
-
} finally {
|
|
15329
|
-
wipe(child.privateKey);
|
|
15330
|
-
wipe(root.privateKey);
|
|
15331
|
-
}
|
|
15332
|
-
};
|
|
15333
|
-
const withSeed = async (run) => {
|
|
15334
|
-
const entropy = openRecord(dek, record);
|
|
15335
|
-
let seed;
|
|
15336
|
-
try {
|
|
15337
|
-
seed = await seedFromEntropy(entropy, ctx.platform.pbkdf2);
|
|
15338
|
-
} finally {
|
|
15339
|
-
wipe(entropy);
|
|
15340
|
-
}
|
|
15341
|
-
try {
|
|
15342
|
-
return run(seed);
|
|
15343
|
-
} finally {
|
|
15344
|
-
wipe(seed);
|
|
15345
|
-
}
|
|
15346
|
-
};
|
|
15347
|
-
const prepared = await withSeed((seed) => execute(seed, true));
|
|
15348
|
-
if (!("prompt" in prepared)) {
|
|
15349
|
-
throw new KernelError("integrity", "unreachable: prepare pass signed");
|
|
15350
|
-
}
|
|
15351
|
-
await verifyFactor(ctx.platform, ctx.image, verify, dek, () => chainPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), prepared.prompt));
|
|
15352
|
-
ctx.session.require(session);
|
|
15353
|
-
const signed = await withSeed((seed) => execute(seed, false));
|
|
15354
|
-
if ("prompt" in signed) {
|
|
15355
|
-
throw new KernelError("integrity", "unreachable: sign pass did not sign");
|
|
15356
|
-
}
|
|
15357
|
-
return signed;
|
|
15264
|
+
checkNetwork(params.template, params.network);
|
|
15265
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => {
|
|
15266
|
+
const master = HDKey.fromMasterSeed(seed, params.template.startsWith("btc.") ? bitcoinNetwork(params.network).bip32 : undefined);
|
|
15267
|
+
try {
|
|
15268
|
+
return accountFor(master, seed, params.template, params.network, params.groupIndex);
|
|
15269
|
+
} finally {
|
|
15270
|
+
master.wipePrivateData();
|
|
15271
|
+
}
|
|
15272
|
+
});
|
|
15273
|
+
};
|
|
15274
|
+
var chainSign = async (ctx, params, session) => {
|
|
15275
|
+
const { dek } = ctx.session.require(session);
|
|
15276
|
+
const { request, verify } = params;
|
|
15277
|
+
const { account } = request;
|
|
15278
|
+
if (account.kind !== "hd") {
|
|
15279
|
+
throw new KernelError("unsupported", "imported accounts are not yet supported");
|
|
15280
|
+
}
|
|
15281
|
+
const [family] = request.kind.split(".", 1);
|
|
15282
|
+
const expected = family === "evm" ? ["evm.bip44"] : family === "solana" ? ["solana.bip44-change"] : ["btc.bip44", "btc.bip49", "btc.bip84", "btc.bip86"];
|
|
15283
|
+
if (!expected.includes(account.template)) {
|
|
15284
|
+
throw new KernelError("invalid-input", "account template does not match the request family");
|
|
15285
|
+
}
|
|
15286
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
15287
|
+
if (record === undefined) {
|
|
15288
|
+
throw new KernelError("not-found", "no such wallet");
|
|
15289
|
+
}
|
|
15290
|
+
const execute = (seed, intentOnly) => {
|
|
15291
|
+
if (request.kind === "evm.transaction" || request.kind === "evm.personal-message" || request.kind === "evm.typed-data") {
|
|
15292
|
+
return executeEvm(request, account, seed, intentOnly);
|
|
15358
15293
|
}
|
|
15294
|
+
if (request.kind === "bitcoin.psbt" || request.kind === "bitcoin.message") {
|
|
15295
|
+
return executeBitcoin(ctx.platform.random, request, account, seed, intentOnly);
|
|
15296
|
+
}
|
|
15297
|
+
return executeSolana(request, account, seed, intentOnly);
|
|
15298
|
+
};
|
|
15299
|
+
const withSeed = async (run) => withWalletSeed(ctx.platform.pbkdf2, dek, record, run);
|
|
15300
|
+
const prepared = await withSeed((seed) => execute(seed, true));
|
|
15301
|
+
if (!("prompt" in prepared)) {
|
|
15302
|
+
throw new KernelError("integrity", "unreachable: prepare pass signed");
|
|
15303
|
+
}
|
|
15304
|
+
await verifyFactor(ctx.platform, ctx.image, verify, dek, () => chainPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), prepared.prompt));
|
|
15305
|
+
ctx.session.require(session);
|
|
15306
|
+
const signed = await withSeed((seed) => execute(seed, false));
|
|
15307
|
+
if ("prompt" in signed) {
|
|
15308
|
+
throw new KernelError("integrity", "unreachable: sign pass did not sign");
|
|
15309
|
+
}
|
|
15310
|
+
return signed;
|
|
15311
|
+
};
|
|
15312
|
+
function createChainsModule() {
|
|
15313
|
+
const vault = {
|
|
15314
|
+
ownsRecord: () => false,
|
|
15315
|
+
claimUnlocked: (records) => records,
|
|
15316
|
+
forget: () => {
|
|
15317
|
+
return;
|
|
15318
|
+
},
|
|
15319
|
+
lock: () => {
|
|
15320
|
+
return;
|
|
15321
|
+
},
|
|
15322
|
+
walletDeleteOps: () => []
|
|
15323
|
+
};
|
|
15324
|
+
const handlers = {
|
|
15325
|
+
"wallet.accounts": walletAccounts,
|
|
15326
|
+
"chain.sign": chainSign
|
|
15359
15327
|
};
|
|
15360
15328
|
return { vault, handlers };
|
|
15361
15329
|
}
|
|
15362
15330
|
|
|
15363
15331
|
// ../wallet-kernel/src/modules/nostr/derive.ts
|
|
15364
15332
|
var NIP06_PATH = "m/44'/1237'/i'/0/0";
|
|
15365
|
-
function nostrKeyAt(master,
|
|
15366
|
-
if (!Number.isSafeInteger(
|
|
15367
|
-
throw new KernelError("invalid-input", "
|
|
15333
|
+
function nostrKeyAt(master, index) {
|
|
15334
|
+
if (!Number.isSafeInteger(index) || index < 0 || index > 2147483647) {
|
|
15335
|
+
throw new KernelError("invalid-input", "identity index out of range");
|
|
15368
15336
|
}
|
|
15369
|
-
const path = NIP06_PATH.split("/").map((segment) => segment === "i'" ? `${
|
|
15337
|
+
const path = NIP06_PATH.split("/").map((segment) => segment === "i'" ? `${index}'` : segment).join("/");
|
|
15370
15338
|
const node = master.derive(path);
|
|
15371
15339
|
try {
|
|
15372
15340
|
const key = node.privateKey;
|
|
@@ -15381,32 +15349,6 @@ function nostrKeyAt(master, groupIndex) {
|
|
|
15381
15349
|
|
|
15382
15350
|
// ../../node_modules/.bun/@qntx+nostr@0.15.3+ea9f70ecde856c26/node_modules/@qntx/nostr/dist/nips/nip19.mjs
|
|
15383
15351
|
var Bech32MaxSize2 = 5000;
|
|
15384
|
-
var Nip19Error2 = class extends NostrError {
|
|
15385
|
-
name = "Nip19Error";
|
|
15386
|
-
};
|
|
15387
|
-
function parseTLV(data) {
|
|
15388
|
-
const result = {};
|
|
15389
|
-
let rest = data;
|
|
15390
|
-
while (rest.length > 0) {
|
|
15391
|
-
if (rest.length < 2)
|
|
15392
|
-
throw new Nip19Error2("not enough data to read TLV");
|
|
15393
|
-
const t = rest.at(0);
|
|
15394
|
-
const l = rest.at(1);
|
|
15395
|
-
if (t === undefined || l === undefined)
|
|
15396
|
-
throw new Nip19Error2("not enough data to read TLV");
|
|
15397
|
-
const v = rest.slice(2, 2 + l);
|
|
15398
|
-
rest = rest.slice(2 + l);
|
|
15399
|
-
if (v.length < l)
|
|
15400
|
-
throw new Nip19Error2(`not enough data to read on TLV ${t}`);
|
|
15401
|
-
result[t] = result[t] ?? [];
|
|
15402
|
-
result[t].push(v);
|
|
15403
|
-
}
|
|
15404
|
-
return result;
|
|
15405
|
-
}
|
|
15406
|
-
function assertNip19Kind(kind) {
|
|
15407
|
-
if (!Number.isInteger(kind) || kind < 0 || kind > 65535)
|
|
15408
|
-
throw new Nip19Error2(`invalid kind: ${kind}`);
|
|
15409
|
-
}
|
|
15410
15352
|
function encodeBech32(prefix, data) {
|
|
15411
15353
|
const words = bech32.toWords(data);
|
|
15412
15354
|
return bech32.encode(prefix, words, Bech32MaxSize2);
|
|
@@ -15418,106 +15360,6 @@ function nsecEncode2(key) {
|
|
|
15418
15360
|
assertByteLength(key, 32, "secret key");
|
|
15419
15361
|
return encodeBytes("nsec", key);
|
|
15420
15362
|
}
|
|
15421
|
-
function readUint32(bytes) {
|
|
15422
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);
|
|
15423
|
-
}
|
|
15424
|
-
function decode3(code) {
|
|
15425
|
-
let prefix;
|
|
15426
|
-
let data;
|
|
15427
|
-
try {
|
|
15428
|
-
const { prefix: hrp, words } = bech32.decode(code, Bech32MaxSize2);
|
|
15429
|
-
prefix = hrp;
|
|
15430
|
-
data = new Uint8Array(bech32.fromWords(words));
|
|
15431
|
-
} catch (error) {
|
|
15432
|
-
throw new Nip19Error2(`invalid bech32: ${errorMessage(error)}`, { cause: error });
|
|
15433
|
-
}
|
|
15434
|
-
switch (prefix) {
|
|
15435
|
-
case "nprofile": {
|
|
15436
|
-
const tlv = parseTLV(data);
|
|
15437
|
-
if (!tlv[0]?.[0])
|
|
15438
|
-
throw new Nip19Error2("missing TLV 0 for nprofile");
|
|
15439
|
-
if (tlv[0][0].length !== 32)
|
|
15440
|
-
throw new Nip19Error2("TLV 0 should be 32 bytes");
|
|
15441
|
-
return {
|
|
15442
|
-
type: "nprofile",
|
|
15443
|
-
data: {
|
|
15444
|
-
pubkey: bytesToHex$1(tlv[0][0]),
|
|
15445
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15446
|
-
}
|
|
15447
|
-
};
|
|
15448
|
-
}
|
|
15449
|
-
case "nevent": {
|
|
15450
|
-
const tlv = parseTLV(data);
|
|
15451
|
-
if (!tlv[0]?.[0])
|
|
15452
|
-
throw new Nip19Error2("missing TLV 0 for nevent");
|
|
15453
|
-
if (tlv[0][0].length !== 32)
|
|
15454
|
-
throw new Nip19Error2("TLV 0 should be 32 bytes");
|
|
15455
|
-
if (tlv[2]?.[0] && tlv[2][0].length !== 32)
|
|
15456
|
-
throw new Nip19Error2("TLV 2 should be 32 bytes");
|
|
15457
|
-
if (tlv[3]?.[0] && tlv[3][0].length !== 4)
|
|
15458
|
-
throw new Nip19Error2("TLV 3 should be 4 bytes");
|
|
15459
|
-
const pointer = {
|
|
15460
|
-
id: bytesToHex$1(tlv[0][0]),
|
|
15461
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15462
|
-
};
|
|
15463
|
-
const author = tlv[2]?.[0];
|
|
15464
|
-
if (author !== undefined)
|
|
15465
|
-
pointer.author = bytesToHex$1(author);
|
|
15466
|
-
const kind = tlv[3]?.[0];
|
|
15467
|
-
if (kind !== undefined) {
|
|
15468
|
-
pointer.kind = readUint32(kind);
|
|
15469
|
-
assertNip19Kind(pointer.kind);
|
|
15470
|
-
}
|
|
15471
|
-
return {
|
|
15472
|
-
type: "nevent",
|
|
15473
|
-
data: pointer
|
|
15474
|
-
};
|
|
15475
|
-
}
|
|
15476
|
-
case "naddr": {
|
|
15477
|
-
const tlv = parseTLV(data);
|
|
15478
|
-
if (!tlv[0]?.[0])
|
|
15479
|
-
throw new Nip19Error2("missing TLV 0 for naddr");
|
|
15480
|
-
if (!tlv[2]?.[0])
|
|
15481
|
-
throw new Nip19Error2("missing TLV 2 for naddr");
|
|
15482
|
-
if (tlv[2][0].length !== 32)
|
|
15483
|
-
throw new Nip19Error2("TLV 2 should be 32 bytes");
|
|
15484
|
-
if (!tlv[3]?.[0])
|
|
15485
|
-
throw new Nip19Error2("missing TLV 3 for naddr");
|
|
15486
|
-
if (tlv[3][0].length !== 4)
|
|
15487
|
-
throw new Nip19Error2("TLV 3 should be 4 bytes");
|
|
15488
|
-
const naddrKind = readUint32(tlv[3][0]);
|
|
15489
|
-
assertNip19Kind(naddrKind);
|
|
15490
|
-
return {
|
|
15491
|
-
type: "naddr",
|
|
15492
|
-
data: {
|
|
15493
|
-
identifier: utf8Decoder.decode(tlv[0][0]),
|
|
15494
|
-
pubkey: bytesToHex$1(tlv[2][0]),
|
|
15495
|
-
kind: naddrKind,
|
|
15496
|
-
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
15497
|
-
}
|
|
15498
|
-
};
|
|
15499
|
-
}
|
|
15500
|
-
case "nsec":
|
|
15501
|
-
if (data.length !== 32)
|
|
15502
|
-
throw new Nip19Error2("nsec must be 32 bytes");
|
|
15503
|
-
if (!secp256k1.utils.isValidSecretKey(data))
|
|
15504
|
-
throw new Nip19Error2("invalid nsec secret key");
|
|
15505
|
-
return {
|
|
15506
|
-
type: "nsec",
|
|
15507
|
-
data
|
|
15508
|
-
};
|
|
15509
|
-
case "npub":
|
|
15510
|
-
case "note":
|
|
15511
|
-
if (data.length !== 32)
|
|
15512
|
-
throw new Nip19Error2(`${prefix} must be 32 bytes`);
|
|
15513
|
-
return {
|
|
15514
|
-
type: prefix,
|
|
15515
|
-
data: bytesToHex$1(data)
|
|
15516
|
-
};
|
|
15517
|
-
default:
|
|
15518
|
-
throw new Nip19Error2(`unknown prefix ${prefix}`);
|
|
15519
|
-
}
|
|
15520
|
-
}
|
|
15521
15363
|
|
|
15522
15364
|
// ../../node_modules/.bun/@noble+hashes@2.4.0/node_modules/@noble/hashes/scrypt.js
|
|
15523
15365
|
function XorAndSalsa(prev, pi, input, ii, out, oi) {
|
|
@@ -15682,7 +15524,6 @@ async function scryptAsync(password, salt, opts) {
|
|
|
15682
15524
|
var VERSION2 = 2;
|
|
15683
15525
|
var SALT_LEN = 16;
|
|
15684
15526
|
var NONCE_LEN = 24;
|
|
15685
|
-
var PAYLOAD_LEN = 91;
|
|
15686
15527
|
var LOGN_MIN = 1;
|
|
15687
15528
|
var LOGN_MAX = 22;
|
|
15688
15529
|
var SCRYPT_R = 8;
|
|
@@ -15726,60 +15567,6 @@ async function encrypt4(secretKey, password, opts) {
|
|
|
15726
15567
|
const bytes = concatBytes(Uint8Array.from([VERSION2]), Uint8Array.from([logn]), salt, nonce, aad, ciphertext);
|
|
15727
15568
|
return encodeBytes("ncryptsec", bytes);
|
|
15728
15569
|
}
|
|
15729
|
-
async function decrypt4(ncryptsec, password, opts) {
|
|
15730
|
-
const { maxLogN } = opts;
|
|
15731
|
-
if (!Number.isInteger(maxLogN) || maxLogN < LOGN_MIN || maxLogN > LOGN_MAX)
|
|
15732
|
-
throw new Nip49Error(`invalid maxLogN ${maxLogN}, expected integer ${LOGN_MIN}..${LOGN_MAX}`);
|
|
15733
|
-
let prefix;
|
|
15734
|
-
let b;
|
|
15735
|
-
try {
|
|
15736
|
-
const decoded = bech32.decode(ncryptsec, Bech32MaxSize2);
|
|
15737
|
-
({ prefix } = decoded);
|
|
15738
|
-
b = new Uint8Array(bech32.fromWords(decoded.words));
|
|
15739
|
-
} catch (error) {
|
|
15740
|
-
throw new Nip49Error("invalid ncryptsec", { cause: error });
|
|
15741
|
-
}
|
|
15742
|
-
if (prefix !== "ncryptsec")
|
|
15743
|
-
throw new Nip49Error(`invalid prefix ${prefix}, expected 'ncryptsec'`);
|
|
15744
|
-
if (b.length !== PAYLOAD_LEN)
|
|
15745
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15746
|
-
const version = b.at(0);
|
|
15747
|
-
if (version === undefined)
|
|
15748
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15749
|
-
if (version !== VERSION2)
|
|
15750
|
-
throw new Nip49Error(`invalid version ${version}, expected 0x02`);
|
|
15751
|
-
const logn = b.at(1);
|
|
15752
|
-
if (logn === undefined)
|
|
15753
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15754
|
-
if (logn > maxLogN)
|
|
15755
|
-
throw new Nip49Error(`logn ${logn} exceeds maxLogN ${maxLogN}`);
|
|
15756
|
-
const salt = b.subarray(2, 18);
|
|
15757
|
-
const nonce = b.subarray(18, 42);
|
|
15758
|
-
const ksb = b.at(42);
|
|
15759
|
-
if (ksb === undefined)
|
|
15760
|
-
throw new Nip49Error("invalid ncryptsec length");
|
|
15761
|
-
if (ksb !== 0 && ksb !== 1 && ksb !== 2)
|
|
15762
|
-
throw new Nip49Error(`invalid key security byte ${ksb}, expected 0x00, 0x01, or 0x02`);
|
|
15763
|
-
const aad = Uint8Array.from([ksb]);
|
|
15764
|
-
const ciphertext = b.subarray(43);
|
|
15765
|
-
try {
|
|
15766
|
-
const key = await deriveKey(password, salt, logn, opts.scrypt ?? nobleScrypt);
|
|
15767
|
-
try {
|
|
15768
|
-
const secret = xchacha20poly1305(key, nonce, aad).decrypt(ciphertext);
|
|
15769
|
-
if (!secp256k1.utils.isValidSecretKey(secret)) {
|
|
15770
|
-
secret.fill(0);
|
|
15771
|
-
throw new Nip49Error("invalid secret key");
|
|
15772
|
-
}
|
|
15773
|
-
return secret;
|
|
15774
|
-
} finally {
|
|
15775
|
-
key.fill(0);
|
|
15776
|
-
}
|
|
15777
|
-
} catch (error) {
|
|
15778
|
-
if (error instanceof Nip49Error)
|
|
15779
|
-
throw error;
|
|
15780
|
-
throw new Nip49Error("failed to decrypt", { cause: error });
|
|
15781
|
-
}
|
|
15782
|
-
}
|
|
15783
15570
|
|
|
15784
15571
|
// ../wallet-kernel/src/modules/nostr/pool.ts
|
|
15785
15572
|
class SignerPool {
|
|
@@ -15822,63 +15609,6 @@ class SignerPool {
|
|
|
15822
15609
|
this.signers.clear();
|
|
15823
15610
|
}
|
|
15824
15611
|
}
|
|
15825
|
-
function generateSecretKey(random, backend) {
|
|
15826
|
-
for (;; ) {
|
|
15827
|
-
const candidate = random(32);
|
|
15828
|
-
try {
|
|
15829
|
-
Keys.fromSecretKey(candidate, backend);
|
|
15830
|
-
return candidate;
|
|
15831
|
-
} catch {
|
|
15832
|
-
wipe(candidate);
|
|
15833
|
-
}
|
|
15834
|
-
}
|
|
15835
|
-
}
|
|
15836
|
-
function secretKeyFromNsec(nsec) {
|
|
15837
|
-
const text = decodeUtf8Secret(nsec);
|
|
15838
|
-
try {
|
|
15839
|
-
const decoded = decode3(text);
|
|
15840
|
-
if (decoded.type !== "nsec") {
|
|
15841
|
-
throw new KernelError("invalid-input", "expected an nsec bech32 string");
|
|
15842
|
-
}
|
|
15843
|
-
return new Uint8Array(decoded.data);
|
|
15844
|
-
} catch (error) {
|
|
15845
|
-
if (error instanceof KernelError) {
|
|
15846
|
-
throw error;
|
|
15847
|
-
}
|
|
15848
|
-
throw new KernelError("invalid-input", "invalid nsec");
|
|
15849
|
-
}
|
|
15850
|
-
}
|
|
15851
|
-
async function secretKeyFromNcryptsec(ncryptsec, password, maxLogN, scrypt) {
|
|
15852
|
-
const text = decodeUtf8Secret(password);
|
|
15853
|
-
let payload;
|
|
15854
|
-
try {
|
|
15855
|
-
const decoded = bech32.decode(ncryptsec, Bech32MaxSize2);
|
|
15856
|
-
payload = new Uint8Array(bech32.fromWords(decoded.words));
|
|
15857
|
-
if (decoded.prefix !== "ncryptsec" || payload.length !== 91 || payload.at(0) !== 2) {
|
|
15858
|
-
throw new KernelError("invalid-input", "malformed ncryptsec");
|
|
15859
|
-
}
|
|
15860
|
-
} catch (error) {
|
|
15861
|
-
if (error instanceof KernelError) {
|
|
15862
|
-
throw error;
|
|
15863
|
-
}
|
|
15864
|
-
throw new KernelError("invalid-input", "malformed ncryptsec");
|
|
15865
|
-
}
|
|
15866
|
-
const logN = payload.at(1) ?? 0;
|
|
15867
|
-
if (logN > maxLogN) {
|
|
15868
|
-
throw new KernelError("unsupported", "ncryptsec scrypt logN exceeds the policy limit");
|
|
15869
|
-
}
|
|
15870
|
-
try {
|
|
15871
|
-
return await decrypt4(ncryptsec, text, {
|
|
15872
|
-
maxLogN,
|
|
15873
|
-
...scrypt === undefined ? {} : { scrypt }
|
|
15874
|
-
});
|
|
15875
|
-
} catch (error) {
|
|
15876
|
-
if (error instanceof Nip49Error && error.cause instanceof RangeError) {
|
|
15877
|
-
throw new KernelError("unavailable", "ncryptsec scrypt allocation failed");
|
|
15878
|
-
}
|
|
15879
|
-
throw new KernelError("wrong-password", "invalid ncryptsec or wrong password");
|
|
15880
|
-
}
|
|
15881
|
-
}
|
|
15882
15612
|
function nsecFromSecretKey(secretKey) {
|
|
15883
15613
|
return new TextEncoder().encode(nsecEncode2(secretKey));
|
|
15884
15614
|
}
|
|
@@ -15918,58 +15648,27 @@ async function unwrapGiftWrap(pool, publicKey, event, backend) {
|
|
|
15918
15648
|
// ../wallet-kernel/src/modules/nostr/record.ts
|
|
15919
15649
|
var NOSTR_KEY_KIND = "nostr-key";
|
|
15920
15650
|
function encodeNostrKeyHeader(header) {
|
|
15921
|
-
|
|
15922
|
-
return JSON.stringify({
|
|
15923
|
-
publicKey: header.publicKey,
|
|
15924
|
-
origin: header.origin,
|
|
15925
|
-
walletId: header.walletId,
|
|
15926
|
-
groupIndex: header.groupIndex,
|
|
15927
|
-
createdAt: header.createdAt
|
|
15928
|
-
});
|
|
15929
|
-
}
|
|
15930
|
-
return header.origin === "nip46-client" ? JSON.stringify({
|
|
15931
|
-
publicKey: header.publicKey,
|
|
15932
|
-
origin: header.origin,
|
|
15933
|
-
createdAt: header.createdAt
|
|
15934
|
-
}) : JSON.stringify({
|
|
15651
|
+
return JSON.stringify({
|
|
15935
15652
|
publicKey: header.publicKey,
|
|
15936
|
-
|
|
15937
|
-
|
|
15653
|
+
walletId: header.walletId,
|
|
15654
|
+
index: header.index,
|
|
15938
15655
|
createdAt: header.createdAt
|
|
15939
15656
|
});
|
|
15940
15657
|
}
|
|
15941
15658
|
function parseNostrKeyHeader(text) {
|
|
15942
15659
|
const object = headerObject(text);
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
15946
|
-
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
walletId: asWalletId(object["walletId"]),
|
|
15951
|
-
groupIndex: asGroupIndex(object["groupIndex"]),
|
|
15952
|
-
createdAt
|
|
15953
|
-
};
|
|
15954
|
-
}
|
|
15955
|
-
if (object["origin"] === "nip46-client") {
|
|
15956
|
-
expectKeys(object, ["publicKey", "origin", "createdAt"]);
|
|
15957
|
-
return { publicKey, origin: "nip46-client", createdAt };
|
|
15958
|
-
}
|
|
15959
|
-
expectKeys(object, ["publicKey", "origin", "backedUp", "createdAt"]);
|
|
15960
|
-
const { origin } = object;
|
|
15961
|
-
if (origin !== "nsec" && origin !== "ncryptsec" && origin !== "generated") {
|
|
15962
|
-
throw headerFailure();
|
|
15963
|
-
}
|
|
15964
|
-
return { publicKey, origin, backedUp: asBoolean(object["backedUp"]), createdAt };
|
|
15660
|
+
expectKeys(object, ["publicKey", "walletId", "index", "createdAt"]);
|
|
15661
|
+
return {
|
|
15662
|
+
publicKey: asPublicKey(object["publicKey"]),
|
|
15663
|
+
walletId: asWalletId(object["walletId"]),
|
|
15664
|
+
index: asIdentityIndex(object["index"]),
|
|
15665
|
+
createdAt: asCreatedAt(object["createdAt"])
|
|
15666
|
+
};
|
|
15965
15667
|
}
|
|
15966
15668
|
function nostrKeyInfo2(header) {
|
|
15967
|
-
const standalone = header.origin !== "derived" && header.origin !== "nip46-client";
|
|
15968
15669
|
return {
|
|
15969
|
-
ref:
|
|
15670
|
+
ref: { kind: "derived", walletId: header.walletId, index: header.index },
|
|
15970
15671
|
publicKey: header.publicKey,
|
|
15971
|
-
origin: header.origin,
|
|
15972
|
-
...standalone ? { backedUp: header.backedUp } : {},
|
|
15973
15672
|
createdAt: header.createdAt
|
|
15974
15673
|
};
|
|
15975
15674
|
}
|
|
@@ -15977,14 +15676,39 @@ function nostrStatus2(records) {
|
|
|
15977
15676
|
const keys = [];
|
|
15978
15677
|
let corrupted = false;
|
|
15979
15678
|
for (const record of records) {
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15679
|
+
if (record.kind === NOSTR_KEY_KIND) {
|
|
15680
|
+
try {
|
|
15681
|
+
keys.push(nostrKeyInfo2(parseNostrKeyHeader(record.header)));
|
|
15682
|
+
} catch {
|
|
15683
|
+
corrupted = true;
|
|
15684
|
+
}
|
|
15685
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15686
|
+
try {
|
|
15687
|
+
parseSyncKeyHeader(record.header);
|
|
15688
|
+
} catch {
|
|
15689
|
+
corrupted = true;
|
|
15690
|
+
}
|
|
15984
15691
|
}
|
|
15985
15692
|
}
|
|
15986
15693
|
return { keys, corrupted };
|
|
15987
15694
|
}
|
|
15695
|
+
var NOSTR_SYNC_KEY_KIND = "nostr-sync-key";
|
|
15696
|
+
function encodeSyncKeyHeader(header) {
|
|
15697
|
+
return JSON.stringify({
|
|
15698
|
+
publicKey: header.publicKey,
|
|
15699
|
+
walletId: header.walletId,
|
|
15700
|
+
createdAt: header.createdAt
|
|
15701
|
+
});
|
|
15702
|
+
}
|
|
15703
|
+
function parseSyncKeyHeader(text) {
|
|
15704
|
+
const object = headerObject(text);
|
|
15705
|
+
expectKeys(object, ["publicKey", "walletId", "createdAt"]);
|
|
15706
|
+
return {
|
|
15707
|
+
publicKey: asPublicKey(object["publicKey"]),
|
|
15708
|
+
walletId: asWalletId(object["walletId"]),
|
|
15709
|
+
createdAt: asCreatedAt(object["createdAt"])
|
|
15710
|
+
};
|
|
15711
|
+
}
|
|
15988
15712
|
|
|
15989
15713
|
// ../wallet-kernel/src/modules/nostr/keys.ts
|
|
15990
15714
|
function keyRecord(ctx, dek, secretKey, header) {
|
|
@@ -15995,114 +15719,57 @@ function ensureNewKey(ctx, publicKey) {
|
|
|
15995
15719
|
throw new KernelError("already-exists", "nostr key already exists");
|
|
15996
15720
|
}
|
|
15997
15721
|
}
|
|
15998
|
-
async function addKey(ctx, secretKey, origin, backedUp, factor, requestSession) {
|
|
15999
|
-
const gated = gate(ctx, factor, requestSession);
|
|
16000
|
-
const publicKey = getPublicKey(secretKey);
|
|
16001
|
-
ensureNewKey(ctx, publicKey);
|
|
16002
|
-
const header = {
|
|
16003
|
-
publicKey,
|
|
16004
|
-
origin,
|
|
16005
|
-
backedUp,
|
|
16006
|
-
createdAt: ctx.platform.now()
|
|
16007
|
-
};
|
|
16008
|
-
const record = keyRecord(ctx, gated.dek, secretKey, header);
|
|
16009
|
-
const session = await commitRecords(ctx, gated, factor, [record]);
|
|
16010
|
-
return { key: nostrKeyInfo2(header), session };
|
|
16011
|
-
}
|
|
16012
|
-
async function importKey(ctx, params, requestSession) {
|
|
16013
|
-
const { input } = params;
|
|
16014
|
-
const secretKey = input.kind === "nsec" ? secretKeyFromNsec(input.nsec) : await secretKeyFromNcryptsec(input.ncryptsec, input.password, ctx.platform.policy.maxScryptLogN);
|
|
16015
|
-
try {
|
|
16016
|
-
return await addKey(ctx, secretKey, input.kind, true, params.factor, requestSession);
|
|
16017
|
-
} finally {
|
|
16018
|
-
wipe(secretKey);
|
|
16019
|
-
}
|
|
16020
|
-
}
|
|
16021
|
-
async function generateKey(ctx, params, requestSession) {
|
|
16022
|
-
const secretKey = generateSecretKey(ctx.platform.random, ctx.platform.backends.nostr);
|
|
16023
|
-
try {
|
|
16024
|
-
return await addKey(ctx, secretKey, "generated", false, params.factor, requestSession);
|
|
16025
|
-
} finally {
|
|
16026
|
-
wipe(secretKey);
|
|
16027
|
-
}
|
|
16028
|
-
}
|
|
16029
|
-
async function createNip46ClientKey(ctx, requestSession) {
|
|
16030
|
-
const { dek } = ctx.session.require(requestSession);
|
|
16031
|
-
const secretKey = generateSecretKey(ctx.platform.random, ctx.platform.backends.nostr);
|
|
16032
|
-
try {
|
|
16033
|
-
const publicKey = getPublicKey(secretKey);
|
|
16034
|
-
ensureNewKey(ctx, publicKey);
|
|
16035
|
-
const header = {
|
|
16036
|
-
publicKey,
|
|
16037
|
-
origin: "nip46-client",
|
|
16038
|
-
createdAt: ctx.platform.now()
|
|
16039
|
-
};
|
|
16040
|
-
await ctx.commit([{ op: "put-record", record: keyRecord(ctx, dek, secretKey, header) }]);
|
|
16041
|
-
return nostrKeyInfo2(header);
|
|
16042
|
-
} finally {
|
|
16043
|
-
wipe(secretKey);
|
|
16044
|
-
}
|
|
16045
|
-
}
|
|
16046
15722
|
async function deriveKey2(ctx, params, requestSession) {
|
|
16047
15723
|
const { dek } = ctx.session.require(requestSession);
|
|
16048
15724
|
const record = findRecord(ctx.image, "entropy", params.walletId);
|
|
16049
|
-
|
|
16050
|
-
|
|
16051
|
-
wipe(entropy);
|
|
16052
|
-
const master = masterKey(seed);
|
|
16053
|
-
wipe(seed);
|
|
16054
|
-
try {
|
|
16055
|
-
const secretKey = nostrKeyAt(master, params.groupIndex);
|
|
15725
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, async (seed) => {
|
|
15726
|
+
const master = masterKey(seed);
|
|
16056
15727
|
try {
|
|
16057
|
-
const
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
publicKey
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
15728
|
+
const secretKey = nostrKeyAt(master, params.index);
|
|
15729
|
+
try {
|
|
15730
|
+
const publicKey = getPublicKey(secretKey);
|
|
15731
|
+
ensureNewKey(ctx, publicKey);
|
|
15732
|
+
const header = {
|
|
15733
|
+
publicKey,
|
|
15734
|
+
walletId: params.walletId,
|
|
15735
|
+
index: params.index,
|
|
15736
|
+
createdAt: ctx.platform.now()
|
|
15737
|
+
};
|
|
15738
|
+
await ctx.commit([{ op: "put-record", record: keyRecord(ctx, dek, secretKey, header) }]);
|
|
15739
|
+
return nostrKeyInfo2(header);
|
|
15740
|
+
} finally {
|
|
15741
|
+
wipe(secretKey);
|
|
15742
|
+
}
|
|
16068
15743
|
} finally {
|
|
16069
|
-
|
|
15744
|
+
master.wipePrivateData();
|
|
16070
15745
|
}
|
|
16071
|
-
}
|
|
16072
|
-
master.wipePrivateData();
|
|
16073
|
-
}
|
|
15746
|
+
});
|
|
16074
15747
|
}
|
|
16075
15748
|
async function discover(ctx, params, requestSession) {
|
|
16076
15749
|
const { dek } = ctx.session.require(requestSession);
|
|
16077
15750
|
const record = findRecord(ctx.image, "entropy", params.walletId);
|
|
16078
|
-
|
|
15751
|
+
if (params.from + params.count - 1 > 2147483646) {
|
|
15752
|
+
throw new KernelError("invalid-input", "identity range exceeds 0x7ffffffe");
|
|
15753
|
+
}
|
|
16079
15754
|
const keys = [];
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
|
|
16083
|
-
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
15755
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => {
|
|
15756
|
+
const master = masterKey(seed);
|
|
15757
|
+
try {
|
|
15758
|
+
for (let i = 0;i < params.count; i++) {
|
|
15759
|
+
const index = params.from + i;
|
|
15760
|
+
const secretKey = nostrKeyAt(master, index);
|
|
15761
|
+
keys.push({ index, publicKey: getPublicKey(secretKey) });
|
|
15762
|
+
wipe(secretKey);
|
|
15763
|
+
}
|
|
15764
|
+
return { keys };
|
|
15765
|
+
} finally {
|
|
15766
|
+
master.wipePrivateData();
|
|
16090
15767
|
}
|
|
16091
|
-
|
|
16092
|
-
} finally {
|
|
16093
|
-
master.wipePrivateData();
|
|
16094
|
-
}
|
|
15768
|
+
});
|
|
16095
15769
|
}
|
|
16096
15770
|
async function removeKey(ctx, params, requestSession) {
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16100
|
-
if (header.origin !== "nip46-client") {
|
|
16101
|
-
if (params.verify === undefined) {
|
|
16102
|
-
throw new KernelError("invalid-input", "factor verification is required");
|
|
16103
|
-
}
|
|
16104
|
-
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, corePromptFor(ctx.platform.keystore, "remove-key"));
|
|
16105
|
-
}
|
|
15771
|
+
ctx.session.require(requestSession);
|
|
15772
|
+
findRecord(ctx.image, NOSTR_KEY_KIND, params.publicKey);
|
|
16106
15773
|
await ctx.commit([{ op: "delete-record", kind: NOSTR_KEY_KIND, id: params.publicKey }]);
|
|
16107
15774
|
return null;
|
|
16108
15775
|
}
|
|
@@ -16110,60 +15777,132 @@ async function exportKey(ctx, params, requestSession) {
|
|
|
16110
15777
|
const { dek } = ctx.session.require(requestSession);
|
|
16111
15778
|
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, corePromptFor(ctx.platform.keystore, "export-key"));
|
|
16112
15779
|
const record = findRecord(ctx.image, NOSTR_KEY_KIND, params.publicKey);
|
|
16113
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16114
15780
|
const secretKey = openRecord(dek, record);
|
|
16115
15781
|
try {
|
|
16116
15782
|
const exported = params.format.kind === "nsec" ? nsecFromSecretKey(secretKey) : await ncryptsecFromSecretKey(secretKey, params.format.password);
|
|
16117
|
-
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
15783
|
+
return exported;
|
|
15784
|
+
} finally {
|
|
15785
|
+
wipe(secretKey);
|
|
15786
|
+
}
|
|
15787
|
+
}
|
|
15788
|
+
|
|
15789
|
+
// ../wallet-kernel/src/modules/nostr/ops.ts
|
|
15790
|
+
async function sign4(ctx, pool, params, requestSession) {
|
|
15791
|
+
ctx.session.require(requestSession);
|
|
15792
|
+
return signEvent2(pool, params.publicKey, params.event);
|
|
15793
|
+
}
|
|
15794
|
+
async function nip04Encrypt(ctx, pool, params, requestSession) {
|
|
15795
|
+
ctx.session.require(requestSession);
|
|
15796
|
+
return pool.get(params.publicKey).nip04Encrypt(params.peer, params.text);
|
|
15797
|
+
}
|
|
15798
|
+
async function nip04Decrypt(ctx, pool, params, requestSession) {
|
|
15799
|
+
ctx.session.require(requestSession);
|
|
15800
|
+
return pool.get(params.publicKey).nip04Decrypt(params.peer, params.text);
|
|
15801
|
+
}
|
|
15802
|
+
async function nip44Encrypt(ctx, pool, params, requestSession) {
|
|
15803
|
+
ctx.session.require(requestSession);
|
|
15804
|
+
return pool.get(params.publicKey).nip44Encrypt(params.peer, params.text);
|
|
15805
|
+
}
|
|
15806
|
+
async function nip44Decrypt(ctx, pool, params, requestSession) {
|
|
15807
|
+
ctx.session.require(requestSession);
|
|
15808
|
+
return pool.get(params.publicKey).nip44Decrypt(params.peer, params.text);
|
|
15809
|
+
}
|
|
15810
|
+
async function unwrapGiftWraps(ctx, pool, params, requestSession) {
|
|
15811
|
+
ctx.session.require(requestSession);
|
|
15812
|
+
const results = [];
|
|
15813
|
+
for (const event of params.events) {
|
|
15814
|
+
results.push(await unwrapGiftWrap(pool, params.publicKey, event, ctx.platform.backends.nostr));
|
|
15815
|
+
}
|
|
15816
|
+
return { results };
|
|
15817
|
+
}
|
|
15818
|
+
|
|
15819
|
+
// ../wallet-kernel/src/modules/nostr/sync.ts
|
|
15820
|
+
var SYNC_INDEX = 2147483647;
|
|
15821
|
+
function syncRecord(ctx, walletId) {
|
|
15822
|
+
findRecord(ctx.image, "entropy", walletId);
|
|
15823
|
+
for (const record of ctx.image.records) {
|
|
15824
|
+
if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15825
|
+
const header = parseSyncKeyHeader(record.header);
|
|
15826
|
+
if (header.walletId === walletId) {
|
|
15827
|
+
return record;
|
|
15828
|
+
}
|
|
15829
|
+
}
|
|
15830
|
+
}
|
|
15831
|
+
throw new KernelError("not-found", "no sync key for this wallet");
|
|
15832
|
+
}
|
|
15833
|
+
async function syncKey(ctx, params, requestSession) {
|
|
15834
|
+
const { dek } = ctx.session.require(requestSession);
|
|
15835
|
+
try {
|
|
15836
|
+
return { publicKey: parseSyncKeyHeader(syncRecord(ctx, params.walletId).header).publicKey };
|
|
15837
|
+
} catch (error) {
|
|
15838
|
+
if (!(error instanceof KernelError && error.code === "not-found")) {
|
|
15839
|
+
throw error;
|
|
15840
|
+
}
|
|
15841
|
+
}
|
|
15842
|
+
const wallet = findRecord(ctx.image, "entropy", params.walletId);
|
|
15843
|
+
return withWalletSeed(ctx.platform.pbkdf2, dek, wallet, async (seed) => {
|
|
15844
|
+
const master = masterKey(seed);
|
|
15845
|
+
try {
|
|
15846
|
+
const secretKey = nostrKeyAt(master, SYNC_INDEX);
|
|
15847
|
+
try {
|
|
15848
|
+
const publicKey = getPublicKey(secretKey);
|
|
15849
|
+
const header = {
|
|
15850
|
+
publicKey,
|
|
15851
|
+
walletId: params.walletId,
|
|
15852
|
+
createdAt: ctx.platform.now()
|
|
15853
|
+
};
|
|
15854
|
+
const record = sealRecord(ctx.platform, dek, NOSTR_SYNC_KEY_KIND, publicKey, encodeSyncKeyHeader(header), new Uint8Array(secretKey));
|
|
15855
|
+
try {
|
|
15856
|
+
await ctx.commit([{ op: "put-record", record }]);
|
|
15857
|
+
} catch (error) {
|
|
15858
|
+
if (!(error instanceof KernelError && error.code === "conflict")) {
|
|
15859
|
+
throw error;
|
|
15860
|
+
}
|
|
15861
|
+
return {
|
|
15862
|
+
publicKey: parseSyncKeyHeader(syncRecord(ctx, params.walletId).header).publicKey
|
|
15863
|
+
};
|
|
16123
15864
|
}
|
|
16124
|
-
|
|
15865
|
+
return { publicKey };
|
|
15866
|
+
} finally {
|
|
15867
|
+
wipe(secretKey);
|
|
15868
|
+
}
|
|
15869
|
+
} finally {
|
|
15870
|
+
master.wipePrivateData();
|
|
16125
15871
|
}
|
|
16126
|
-
|
|
16127
|
-
} finally {
|
|
16128
|
-
wipe(secretKey);
|
|
16129
|
-
}
|
|
16130
|
-
}
|
|
16131
|
-
|
|
16132
|
-
// ../wallet-kernel/src/modules/nostr/ops.ts
|
|
16133
|
-
async function sign4(ctx, pool, params, requestSession) {
|
|
16134
|
-
ctx.session.require(requestSession);
|
|
16135
|
-
return signEvent2(pool, params.publicKey, params.event);
|
|
16136
|
-
}
|
|
16137
|
-
async function nip04Encrypt(ctx, pool, params, requestSession) {
|
|
16138
|
-
ctx.session.require(requestSession);
|
|
16139
|
-
return pool.get(params.publicKey).nip04Encrypt(params.peer, params.text);
|
|
15872
|
+
});
|
|
16140
15873
|
}
|
|
16141
|
-
|
|
16142
|
-
ctx
|
|
16143
|
-
|
|
15874
|
+
function requireSyncSigner(ctx, pool, walletId) {
|
|
15875
|
+
const record = syncRecord(ctx, walletId);
|
|
15876
|
+
const { publicKey } = parseSyncKeyHeader(record.header);
|
|
15877
|
+
return pool.get(publicKey);
|
|
16144
15878
|
}
|
|
16145
|
-
async function
|
|
15879
|
+
async function syncSign(ctx, pool, params, requestSession) {
|
|
16146
15880
|
ctx.session.require(requestSession);
|
|
16147
|
-
|
|
15881
|
+
if (params.event.kind !== 30078) {
|
|
15882
|
+
throw new KernelError("invalid-input", "sync signer authors kind-30078 events only");
|
|
15883
|
+
}
|
|
15884
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15885
|
+
return signEvent2(pool, signer.keys.publicKey, params.event);
|
|
16148
15886
|
}
|
|
16149
|
-
async function
|
|
15887
|
+
async function syncEncrypt(ctx, pool, params, requestSession) {
|
|
16150
15888
|
ctx.session.require(requestSession);
|
|
16151
|
-
|
|
15889
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15890
|
+
const { publicKey } = signer.keys;
|
|
15891
|
+
return signer.nip44Encrypt(publicKey, params.text);
|
|
16152
15892
|
}
|
|
16153
|
-
async function
|
|
15893
|
+
async function syncDecrypt(ctx, pool, params, requestSession) {
|
|
16154
15894
|
ctx.session.require(requestSession);
|
|
16155
|
-
const
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
}
|
|
16159
|
-
return { results };
|
|
15895
|
+
const signer = requireSyncSigner(ctx, pool, params.walletId);
|
|
15896
|
+
const { publicKey } = signer.keys;
|
|
15897
|
+
return signer.nip44Decrypt(publicKey, params.text);
|
|
16160
15898
|
}
|
|
16161
15899
|
|
|
16162
15900
|
// ../wallet-kernel/src/modules/nostr/index.ts
|
|
16163
15901
|
function createNostrModule(backend) {
|
|
16164
15902
|
const pool = new SignerPool(backend);
|
|
15903
|
+
const syncPool = new SignerPool(backend);
|
|
16165
15904
|
const vault = {
|
|
16166
|
-
ownsRecord: (kind) => kind === NOSTR_KEY_KIND,
|
|
15905
|
+
ownsRecord: (kind) => kind === NOSTR_KEY_KIND || kind === NOSTR_SYNC_KEY_KIND,
|
|
16167
15906
|
claimUnlocked: (records) => {
|
|
16168
15907
|
const unclaimed = [];
|
|
16169
15908
|
for (const record of records) {
|
|
@@ -16172,6 +15911,11 @@ function createNostrModule(backend) {
|
|
|
16172
15911
|
if (claimed !== record.id) {
|
|
16173
15912
|
throw new KernelError("integrity", "nostr key does not match its record", undefined, true);
|
|
16174
15913
|
}
|
|
15914
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15915
|
+
const claimed = syncPool.add(record.plaintext);
|
|
15916
|
+
if (claimed !== record.id) {
|
|
15917
|
+
throw new KernelError("integrity", "sync key does not match its record", undefined, true);
|
|
15918
|
+
}
|
|
16175
15919
|
} else {
|
|
16176
15920
|
unclaimed.push(record);
|
|
16177
15921
|
}
|
|
@@ -16181,61 +15925,35 @@ function createNostrModule(backend) {
|
|
|
16181
15925
|
forget: (kind, id) => {
|
|
16182
15926
|
if (kind === NOSTR_KEY_KIND) {
|
|
16183
15927
|
pool.remove(id);
|
|
15928
|
+
} else if (kind === NOSTR_SYNC_KEY_KIND) {
|
|
15929
|
+
syncPool.remove(id);
|
|
16184
15930
|
}
|
|
16185
15931
|
},
|
|
16186
15932
|
lock: () => {
|
|
16187
15933
|
pool.dispose();
|
|
15934
|
+
syncPool.dispose();
|
|
16188
15935
|
},
|
|
16189
15936
|
walletDeleteOps: (image, walletId) => {
|
|
16190
15937
|
const ops = [];
|
|
16191
15938
|
for (const record of image.records) {
|
|
16192
|
-
if (record.kind
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
|
|
15939
|
+
if (record.kind === NOSTR_KEY_KIND) {
|
|
15940
|
+
const header = parseNostrKeyHeader(record.header);
|
|
15941
|
+
if (header.walletId === walletId) {
|
|
15942
|
+
ops.push({ op: "delete-record", kind: NOSTR_KEY_KIND, id: record.id });
|
|
15943
|
+
}
|
|
15944
|
+
} else if (record.kind === NOSTR_SYNC_KEY_KIND) {
|
|
15945
|
+
const header = parseSyncKeyHeader(record.header);
|
|
15946
|
+
if (header.walletId === walletId) {
|
|
15947
|
+
ops.push({ op: "delete-record", kind: NOSTR_SYNC_KEY_KIND, id: record.id });
|
|
15948
|
+
}
|
|
16198
15949
|
}
|
|
16199
15950
|
}
|
|
16200
15951
|
return ops;
|
|
16201
|
-
},
|
|
16202
|
-
backupSecrets: (image, dek) => {
|
|
16203
|
-
const secrets = [];
|
|
16204
|
-
for (const record of image.records) {
|
|
16205
|
-
if (record.kind !== NOSTR_KEY_KIND) {
|
|
16206
|
-
continue;
|
|
16207
|
-
}
|
|
16208
|
-
const header = parseNostrKeyHeader(record.header);
|
|
16209
|
-
if (header.origin === "derived" || header.origin === "nip46-client") {
|
|
16210
|
-
continue;
|
|
16211
|
-
}
|
|
16212
|
-
secrets.push(openRecord(dek, record));
|
|
16213
|
-
}
|
|
16214
|
-
return secrets;
|
|
16215
|
-
},
|
|
16216
|
-
backupRecords: (platform, image, dek, secrets, now) => {
|
|
16217
|
-
const records = [];
|
|
16218
|
-
for (const secretKey of secrets) {
|
|
16219
|
-
const publicKey = getPublicKey(secretKey);
|
|
16220
|
-
if (image.records.some((r) => r.kind === NOSTR_KEY_KIND && r.id === publicKey)) {
|
|
16221
|
-
continue;
|
|
16222
|
-
}
|
|
16223
|
-
records.push(sealRecord(platform, dek, NOSTR_KEY_KIND, publicKey, encodeNostrKeyHeader({
|
|
16224
|
-
publicKey,
|
|
16225
|
-
origin: "nsec",
|
|
16226
|
-
backedUp: true,
|
|
16227
|
-
createdAt: now
|
|
16228
|
-
}), secretKey));
|
|
16229
|
-
}
|
|
16230
|
-
return records;
|
|
16231
15952
|
}
|
|
16232
15953
|
};
|
|
16233
15954
|
const handlers = {
|
|
16234
15955
|
"nostr.discover": async (ctx, params, session) => discover(ctx, params, session),
|
|
16235
15956
|
"nostr.deriveKey": async (ctx, params, session) => deriveKey2(ctx, params, session),
|
|
16236
|
-
"nostr.importKey": async (ctx, params, session) => importKey(ctx, params, session),
|
|
16237
|
-
"nostr.generateKey": async (ctx, params, session) => generateKey(ctx, params, session),
|
|
16238
|
-
"nostr.createNip46ClientKey": async (ctx, _params, session) => createNip46ClientKey(ctx, session),
|
|
16239
15957
|
"nostr.removeKey": async (ctx, params, session) => removeKey(ctx, params, session),
|
|
16240
15958
|
"nostr.exportKey": async (ctx, params, session) => exportKey(ctx, params, session),
|
|
16241
15959
|
"nostr.signEvent": async (ctx, params, session) => sign4(ctx, pool, params, session),
|
|
@@ -16243,7 +15961,11 @@ function createNostrModule(backend) {
|
|
|
16243
15961
|
"nostr.nip04Decrypt": async (ctx, params, session) => nip04Decrypt(ctx, pool, params, session),
|
|
16244
15962
|
"nostr.nip44Encrypt": async (ctx, params, session) => nip44Encrypt(ctx, pool, params, session),
|
|
16245
15963
|
"nostr.nip44Decrypt": async (ctx, params, session) => nip44Decrypt(ctx, pool, params, session),
|
|
16246
|
-
"nostr.unwrapGiftWraps": async (ctx, params, session) => unwrapGiftWraps(ctx, pool, params, session)
|
|
15964
|
+
"nostr.unwrapGiftWraps": async (ctx, params, session) => unwrapGiftWraps(ctx, pool, params, session),
|
|
15965
|
+
"nostr.syncKey": async (ctx, params, session) => syncKey(ctx, params, session),
|
|
15966
|
+
"nostr.syncSign": async (ctx, params, session) => syncSign(ctx, syncPool, params, session),
|
|
15967
|
+
"nostr.syncEncrypt": async (ctx, params, session) => syncEncrypt(ctx, syncPool, params, session),
|
|
15968
|
+
"nostr.syncDecrypt": async (ctx, params, session) => syncDecrypt(ctx, syncPool, params, session)
|
|
16247
15969
|
};
|
|
16248
15970
|
return {
|
|
16249
15971
|
vault,
|
|
@@ -16427,228 +16149,241 @@ var decodeIntent = (rt, account, intent) => {
|
|
|
16427
16149
|
}
|
|
16428
16150
|
return result;
|
|
16429
16151
|
};
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
const approvals = new Map;
|
|
16433
|
-
let backendPromise;
|
|
16434
|
-
let runtimePromise;
|
|
16435
|
-
const sparkRuntime = async () => {
|
|
16436
|
-
runtimePromise ??= (async () => {
|
|
16437
|
-
try {
|
|
16438
|
-
return await loadSparkRuntime();
|
|
16439
|
-
} catch (error) {
|
|
16440
|
-
runtimePromise = undefined;
|
|
16441
|
-
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark runtime failed to load");
|
|
16442
|
-
}
|
|
16443
|
-
})();
|
|
16444
|
-
return runtimePromise;
|
|
16445
|
-
};
|
|
16446
|
-
const liveApprovals = (ctx, key) => {
|
|
16447
|
-
const now = ctx.platform.elapsed();
|
|
16448
|
-
const live = (approvals.get(key) ?? []).filter((approval) => approval.deadline > now);
|
|
16449
|
-
if (live.length === 0) {
|
|
16450
|
-
approvals.delete(key);
|
|
16451
|
-
} else {
|
|
16452
|
-
approvals.set(key, live);
|
|
16453
|
-
}
|
|
16454
|
-
return live;
|
|
16455
|
-
};
|
|
16456
|
-
const backend = async (ctx) => {
|
|
16457
|
-
backendPromise ??= (async () => {
|
|
16458
|
-
try {
|
|
16459
|
-
return await ctx.platform.backends.spark();
|
|
16460
|
-
} catch (error) {
|
|
16461
|
-
backendPromise = undefined;
|
|
16462
|
-
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark backend failed to load");
|
|
16463
|
-
}
|
|
16464
|
-
})();
|
|
16465
|
-
return backendPromise;
|
|
16466
|
-
};
|
|
16467
|
-
const disposeAll = () => {
|
|
16468
|
-
for (const signer of signers.values()) {
|
|
16469
|
-
signer.dispose();
|
|
16470
|
-
}
|
|
16471
|
-
signers.clear();
|
|
16472
|
-
approvals.clear();
|
|
16473
|
-
};
|
|
16474
|
-
const disposeWallet = (walletId) => {
|
|
16475
|
-
for (const [key, signer] of signers) {
|
|
16476
|
-
if (key.startsWith(`${walletId}/`)) {
|
|
16477
|
-
signer.dispose();
|
|
16478
|
-
signers.delete(key);
|
|
16479
|
-
}
|
|
16480
|
-
}
|
|
16481
|
-
for (const key of approvals.keys()) {
|
|
16482
|
-
if (key.startsWith(`${walletId}/`)) {
|
|
16483
|
-
approvals.delete(key);
|
|
16484
|
-
}
|
|
16485
|
-
}
|
|
16486
|
-
};
|
|
16487
|
-
const poison = () => {
|
|
16488
|
-
backendPromise = undefined;
|
|
16489
|
-
disposeAll();
|
|
16490
|
-
return new KernelError("unavailable", "spark backend was disposed after a wasm fault");
|
|
16491
|
-
};
|
|
16492
|
-
const mapError = (error) => {
|
|
16493
|
-
if (error instanceof KernelError) {
|
|
16494
|
-
return error;
|
|
16495
|
-
}
|
|
16496
|
-
if (isNamed(error, "WasmPoisonedError")) {
|
|
16497
|
-
return poison();
|
|
16498
|
-
}
|
|
16499
|
-
if (isNamed(error, "SparkInputError")) {
|
|
16500
|
-
return new KernelError("invalid-input", "spark signer rejected the request");
|
|
16501
|
-
}
|
|
16502
|
-
return new KernelError("integrity", "spark signer call failed");
|
|
16503
|
-
};
|
|
16504
|
-
const signerFor = async (ctx, account, requestSession) => {
|
|
16505
|
-
const { dek } = ctx.session.require(requestSession);
|
|
16506
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
16507
|
-
if (record === undefined) {
|
|
16508
|
-
disposeWallet(account.walletId);
|
|
16509
|
-
throw new KernelError("not-found", "no such wallet");
|
|
16510
|
-
}
|
|
16511
|
-
const existing = signers.get(poolKey(account));
|
|
16512
|
-
if (existing !== undefined) {
|
|
16513
|
-
return existing;
|
|
16514
|
-
}
|
|
16515
|
-
const entropy = openRecord(dek, record);
|
|
16516
|
-
const seed = await seedFromEntropy(entropy, ctx.platform.pbkdf2);
|
|
16517
|
-
wipe(entropy);
|
|
16518
|
-
let accountKey;
|
|
16519
|
-
const rt = await sparkRuntime();
|
|
16152
|
+
var sparkRuntime = async (state) => {
|
|
16153
|
+
state.runtimePromise ??= (async () => {
|
|
16520
16154
|
try {
|
|
16521
|
-
|
|
16155
|
+
return await loadSparkRuntime();
|
|
16522
16156
|
} catch (error) {
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
wipe(seed);
|
|
16157
|
+
state.runtimePromise = undefined;
|
|
16158
|
+
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark runtime failed to load");
|
|
16526
16159
|
}
|
|
16527
|
-
|
|
16160
|
+
})();
|
|
16161
|
+
return state.runtimePromise;
|
|
16162
|
+
};
|
|
16163
|
+
var liveApprovals = (state, ctx, key) => {
|
|
16164
|
+
const now = ctx.platform.elapsed();
|
|
16165
|
+
const live = (state.approvals.get(key) ?? []).filter((approval) => approval.deadline > now);
|
|
16166
|
+
if (live.length === 0) {
|
|
16167
|
+
state.approvals.delete(key);
|
|
16168
|
+
} else {
|
|
16169
|
+
state.approvals.set(key, live);
|
|
16170
|
+
}
|
|
16171
|
+
return live;
|
|
16172
|
+
};
|
|
16173
|
+
var backend = async (state, ctx) => {
|
|
16174
|
+
state.backendPromise ??= (async () => {
|
|
16528
16175
|
try {
|
|
16529
|
-
|
|
16530
|
-
crypto: crypto2,
|
|
16531
|
-
accountKey,
|
|
16532
|
-
network: account.network,
|
|
16533
|
-
random: ctx.platform.random,
|
|
16534
|
-
authorize: async (outflow) => authorizeWithCtx(ctx, account, outflow)
|
|
16535
|
-
});
|
|
16536
|
-
signers.set(poolKey(account), signer);
|
|
16537
|
-
return signer;
|
|
16176
|
+
return await ctx.platform.backends.spark();
|
|
16538
16177
|
} catch (error) {
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
wipe(accountKey);
|
|
16178
|
+
state.backendPromise = undefined;
|
|
16179
|
+
throw error instanceof KernelError ? error : new KernelError("unavailable", "spark backend failed to load");
|
|
16542
16180
|
}
|
|
16543
|
-
};
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16181
|
+
})();
|
|
16182
|
+
return state.backendPromise;
|
|
16183
|
+
};
|
|
16184
|
+
var disposeAll = (state) => {
|
|
16185
|
+
for (const signer of state.signers.values()) {
|
|
16186
|
+
signer.dispose();
|
|
16187
|
+
}
|
|
16188
|
+
state.signers.clear();
|
|
16189
|
+
state.approvals.clear();
|
|
16190
|
+
};
|
|
16191
|
+
var disposeWallet = (state, walletId) => {
|
|
16192
|
+
for (const [key, signer] of state.signers) {
|
|
16193
|
+
if (key.startsWith(`${walletId}/`)) {
|
|
16194
|
+
signer.dispose();
|
|
16195
|
+
state.signers.delete(key);
|
|
16548
16196
|
}
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
if (outflow.kind === "transfer" && intent.kind === "transfer") {
|
|
16554
|
-
const covered = outflow.receivers.every((receiver) => intent.receivers.some((wanted) => equalBytes(wanted.identityPublicKey, receiver.identityPublicKey) && receiver.amountSats <= wanted.amountSats));
|
|
16555
|
-
if (covered) {
|
|
16556
|
-
live.splice(live.indexOf(approval), 1);
|
|
16557
|
-
return;
|
|
16558
|
-
}
|
|
16559
|
-
continue;
|
|
16560
|
-
}
|
|
16561
|
-
if (outflow.kind === "lightning" && intent.kind === "lightning") {
|
|
16562
|
-
const signer = signers.get(key);
|
|
16563
|
-
const { paymentHash } = approval.decoded;
|
|
16564
|
-
const budget = approval.decoded.invoiceAmountSats;
|
|
16565
|
-
if (signer === undefined || paymentHash === undefined || budget === undefined) {
|
|
16566
|
-
continue;
|
|
16567
|
-
}
|
|
16568
|
-
const expected = rt.lightningSendHtlcScript({
|
|
16569
|
-
paymentHash,
|
|
16570
|
-
sspIdentityPublicKey: rt.sparkNetworkConfig(account.network).ssp.identityPublicKey,
|
|
16571
|
-
identityPublicKey: await signer.identityPublicKey()
|
|
16572
|
-
});
|
|
16573
|
-
if (!equalBytes(expected, outflow.htlcOutputScript)) {
|
|
16574
|
-
continue;
|
|
16575
|
-
}
|
|
16576
|
-
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16577
|
-
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16578
|
-
if (total > budget + intent.maxFeeSats) {
|
|
16579
|
-
continue;
|
|
16580
|
-
}
|
|
16581
|
-
for (const leaf of fresh) {
|
|
16582
|
-
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16583
|
-
}
|
|
16584
|
-
return;
|
|
16585
|
-
}
|
|
16586
|
-
if (outflow.kind === "exit" && intent.kind === "exit") {
|
|
16587
|
-
const { addressScript } = approval.decoded;
|
|
16588
|
-
if (addressScript === undefined) {
|
|
16589
|
-
continue;
|
|
16590
|
-
}
|
|
16591
|
-
const pays = outflow.exitOutputs.some((output) => equalBytes(output.script, addressScript) && output.amountSats >= intent.amountSats);
|
|
16592
|
-
if (!pays) {
|
|
16593
|
-
continue;
|
|
16594
|
-
}
|
|
16595
|
-
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16596
|
-
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16597
|
-
if (total > intent.amountSats + intent.maxFeeSats) {
|
|
16598
|
-
continue;
|
|
16599
|
-
}
|
|
16600
|
-
for (const leaf of fresh) {
|
|
16601
|
-
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16602
|
-
}
|
|
16603
|
-
return;
|
|
16604
|
-
}
|
|
16605
|
-
if (outflow.kind === "onchain" && intent.kind === "onchain") {
|
|
16606
|
-
const { addressScript } = approval.decoded;
|
|
16607
|
-
if (addressScript === undefined) {
|
|
16608
|
-
continue;
|
|
16609
|
-
}
|
|
16610
|
-
const every = outflow.outputs.every((output) => equalBytes(output.script, rt.EPHEMERAL_ANCHOR_SCRIPT) || equalBytes(output.script, addressScript));
|
|
16611
|
-
if (!every) {
|
|
16612
|
-
continue;
|
|
16613
|
-
}
|
|
16614
|
-
const fee = outflow.inputSats - outflow.totalSats;
|
|
16615
|
-
if (fee > intent.maxFeeSats) {
|
|
16616
|
-
continue;
|
|
16617
|
-
}
|
|
16618
|
-
live.splice(live.indexOf(approval), 1);
|
|
16619
|
-
return;
|
|
16620
|
-
}
|
|
16621
|
-
if (outflow.kind === "token" && intent.kind === "token") {
|
|
16622
|
-
const signer = signers.get(key);
|
|
16623
|
-
if (signer === undefined) {
|
|
16624
|
-
continue;
|
|
16625
|
-
}
|
|
16626
|
-
const identity = await signer.identityPublicKey();
|
|
16627
|
-
const covered = outflow.outputs.every((output) => {
|
|
16628
|
-
if (equalBytes(output.ownerPublicKey, identity)) {
|
|
16629
|
-
return true;
|
|
16630
|
-
}
|
|
16631
|
-
if (!equalBytes(output.tokenIdentifier, intent.tokenIdentifier)) {
|
|
16632
|
-
return false;
|
|
16633
|
-
}
|
|
16634
|
-
return intent.receivers.some((wanted) => equalBytes(wanted.ownerPublicKey, output.ownerPublicKey) && output.amount <= BigInt(wanted.amount));
|
|
16635
|
-
});
|
|
16636
|
-
if (!covered) {
|
|
16637
|
-
continue;
|
|
16638
|
-
}
|
|
16639
|
-
live.splice(live.indexOf(approval), 1);
|
|
16640
|
-
return;
|
|
16641
|
-
}
|
|
16197
|
+
}
|
|
16198
|
+
for (const key of state.approvals.keys()) {
|
|
16199
|
+
if (key.startsWith(`${walletId}/`)) {
|
|
16200
|
+
state.approvals.delete(key);
|
|
16642
16201
|
}
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16648
|
-
|
|
16649
|
-
|
|
16650
|
-
|
|
16202
|
+
}
|
|
16203
|
+
};
|
|
16204
|
+
var poison = (state) => {
|
|
16205
|
+
state.backendPromise = undefined;
|
|
16206
|
+
disposeAll(state);
|
|
16207
|
+
return new KernelError("unavailable", "spark backend was disposed after a wasm fault");
|
|
16208
|
+
};
|
|
16209
|
+
var mapError = (state, error) => {
|
|
16210
|
+
if (error instanceof KernelError) {
|
|
16211
|
+
return error;
|
|
16212
|
+
}
|
|
16213
|
+
if (isNamed(error, "WasmPoisonedError")) {
|
|
16214
|
+
return poison(state);
|
|
16215
|
+
}
|
|
16216
|
+
if (isNamed(error, "SparkInputError")) {
|
|
16217
|
+
return new KernelError("invalid-input", "spark signer rejected the request");
|
|
16218
|
+
}
|
|
16219
|
+
return new KernelError("integrity", "spark signer call failed");
|
|
16220
|
+
};
|
|
16221
|
+
var signerFor = async (state, ctx, account, requestSession) => {
|
|
16222
|
+
const { dek } = ctx.session.require(requestSession);
|
|
16223
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === account.walletId);
|
|
16224
|
+
if (record === undefined) {
|
|
16225
|
+
disposeWallet(state, account.walletId);
|
|
16226
|
+
throw new KernelError("not-found", "no such wallet");
|
|
16227
|
+
}
|
|
16228
|
+
const existing = state.signers.get(poolKey(account));
|
|
16229
|
+
if (existing !== undefined) {
|
|
16230
|
+
return existing;
|
|
16231
|
+
}
|
|
16232
|
+
let accountKey;
|
|
16233
|
+
const rt = await sparkRuntime(state);
|
|
16234
|
+
try {
|
|
16235
|
+
accountKey = await withWalletSeed(ctx.platform.pbkdf2, dek, record, (seed) => rt.sparkAccountKey(seed, account.network, account.network === "mainnet" ? account.groupIndex + 1 : account.groupIndex));
|
|
16236
|
+
} catch (error) {
|
|
16237
|
+
throw mapError(state, error);
|
|
16238
|
+
}
|
|
16239
|
+
const crypto2 = await backend(state, ctx);
|
|
16240
|
+
try {
|
|
16241
|
+
const signer = rt.createSparkSigner({
|
|
16242
|
+
crypto: crypto2,
|
|
16243
|
+
accountKey,
|
|
16244
|
+
network: account.network,
|
|
16245
|
+
random: ctx.platform.random,
|
|
16246
|
+
authorize: async (outflow) => authorizeWithCtx(state, ctx, account, outflow)
|
|
16247
|
+
});
|
|
16248
|
+
state.signers.set(poolKey(account), signer);
|
|
16249
|
+
return signer;
|
|
16250
|
+
} catch (error) {
|
|
16251
|
+
throw mapError(state, error);
|
|
16252
|
+
} finally {
|
|
16253
|
+
wipe(accountKey);
|
|
16254
|
+
}
|
|
16255
|
+
};
|
|
16256
|
+
var transferCovered = (outflow, intent) => outflow.receivers.every((receiver) => intent.receivers.some((wanted) => equalBytes(wanted.identityPublicKey, receiver.identityPublicKey) && receiver.amountSats <= wanted.amountSats));
|
|
16257
|
+
var lightningCovered = async (state, rt, key, network, outflow, approval, intent) => {
|
|
16258
|
+
const signer = state.signers.get(key);
|
|
16259
|
+
const { paymentHash } = approval.decoded;
|
|
16260
|
+
const budget = approval.decoded.invoiceAmountSats;
|
|
16261
|
+
if (signer === undefined || paymentHash === undefined || budget === undefined) {
|
|
16262
|
+
return false;
|
|
16263
|
+
}
|
|
16264
|
+
const expected = rt.lightningSendHtlcScript({
|
|
16265
|
+
paymentHash,
|
|
16266
|
+
sspIdentityPublicKey: rt.sparkNetworkConfig(network).ssp.identityPublicKey,
|
|
16267
|
+
identityPublicKey: await signer.identityPublicKey()
|
|
16268
|
+
});
|
|
16269
|
+
if (!equalBytes(expected, outflow.htlcOutputScript)) {
|
|
16270
|
+
return false;
|
|
16271
|
+
}
|
|
16272
|
+
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16273
|
+
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16274
|
+
if (total > budget + intent.maxFeeSats) {
|
|
16275
|
+
return false;
|
|
16276
|
+
}
|
|
16277
|
+
for (const leaf of fresh) {
|
|
16278
|
+
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16279
|
+
}
|
|
16280
|
+
return true;
|
|
16281
|
+
};
|
|
16282
|
+
var exitCovered = (outflow, approval, intent) => {
|
|
16283
|
+
const { addressScript } = approval.decoded;
|
|
16284
|
+
if (addressScript === undefined) {
|
|
16285
|
+
return false;
|
|
16286
|
+
}
|
|
16287
|
+
const pays = outflow.exitOutputs.some((output) => equalBytes(output.script, addressScript) && output.amountSats >= intent.amountSats);
|
|
16288
|
+
if (!pays) {
|
|
16289
|
+
return false;
|
|
16290
|
+
}
|
|
16291
|
+
const fresh = outflow.leaves.filter((leaf) => !approval.spentLeaves.has(bytesToHex(leaf.publicKey)));
|
|
16292
|
+
const total = fresh.reduce((sum, leaf) => sum + leaf.amountSats, 0) + [...approval.spentLeaves.values()].reduce((sum, v) => sum + v, 0);
|
|
16293
|
+
if (total > intent.amountSats + intent.maxFeeSats) {
|
|
16294
|
+
return false;
|
|
16295
|
+
}
|
|
16296
|
+
for (const leaf of fresh) {
|
|
16297
|
+
approval.spentLeaves.set(bytesToHex(leaf.publicKey), leaf.amountSats);
|
|
16298
|
+
}
|
|
16299
|
+
return true;
|
|
16300
|
+
};
|
|
16301
|
+
var onchainCovered = (rt, outflow, approval, intent) => {
|
|
16302
|
+
const { addressScript } = approval.decoded;
|
|
16303
|
+
if (addressScript === undefined) {
|
|
16304
|
+
return false;
|
|
16305
|
+
}
|
|
16306
|
+
const every = outflow.outputs.every((output) => equalBytes(output.script, rt.EPHEMERAL_ANCHOR_SCRIPT) || equalBytes(output.script, addressScript));
|
|
16307
|
+
if (!every) {
|
|
16308
|
+
return false;
|
|
16309
|
+
}
|
|
16310
|
+
const fee = outflow.inputSats - outflow.totalSats;
|
|
16311
|
+
return fee <= intent.maxFeeSats;
|
|
16312
|
+
};
|
|
16313
|
+
var tokenCovered = async (state, key, outflow, intent) => {
|
|
16314
|
+
const signer = state.signers.get(key);
|
|
16315
|
+
if (signer === undefined) {
|
|
16316
|
+
return false;
|
|
16317
|
+
}
|
|
16318
|
+
const identity = await signer.identityPublicKey();
|
|
16319
|
+
return outflow.outputs.every((output) => {
|
|
16320
|
+
if (equalBytes(output.ownerPublicKey, identity)) {
|
|
16321
|
+
return true;
|
|
16322
|
+
}
|
|
16323
|
+
if (!equalBytes(output.tokenIdentifier, intent.tokenIdentifier)) {
|
|
16324
|
+
return false;
|
|
16325
|
+
}
|
|
16326
|
+
return intent.receivers.some((wanted) => equalBytes(wanted.ownerPublicKey, output.ownerPublicKey) && output.amount <= BigInt(wanted.amount));
|
|
16327
|
+
});
|
|
16328
|
+
};
|
|
16329
|
+
var authorizeWithCtx = async (state, ctx, account, outflow) => {
|
|
16330
|
+
const rt = await sparkRuntime(state);
|
|
16331
|
+
if (outflow.kind === "swap") {
|
|
16332
|
+
return;
|
|
16333
|
+
}
|
|
16334
|
+
const key = poolKey(account);
|
|
16335
|
+
const live = liveApprovals(state, ctx, key);
|
|
16336
|
+
for (const approval of live) {
|
|
16337
|
+
const { intent } = approval;
|
|
16338
|
+
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;
|
|
16339
|
+
if (covered) {
|
|
16340
|
+
live.splice(live.indexOf(approval), 1);
|
|
16341
|
+
return;
|
|
16651
16342
|
}
|
|
16343
|
+
}
|
|
16344
|
+
throw approvalRequired();
|
|
16345
|
+
};
|
|
16346
|
+
var call = async (state, ctx, account, requestSession, run) => {
|
|
16347
|
+
const signer = await signerFor(state, ctx, account, requestSession);
|
|
16348
|
+
try {
|
|
16349
|
+
return await run(signer);
|
|
16350
|
+
} catch (error) {
|
|
16351
|
+
throw mapError(state, error);
|
|
16352
|
+
}
|
|
16353
|
+
};
|
|
16354
|
+
var sparkApprove = async (state, ctx, params, session) => {
|
|
16355
|
+
const { dek } = ctx.session.require(session);
|
|
16356
|
+
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.account.walletId);
|
|
16357
|
+
if (record === undefined) {
|
|
16358
|
+
throw new KernelError("not-found", "no such wallet");
|
|
16359
|
+
}
|
|
16360
|
+
const key = poolKey(params.account);
|
|
16361
|
+
if (liveApprovals(state, ctx, key).length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16362
|
+
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16363
|
+
}
|
|
16364
|
+
const { summary, decoded } = decodeIntent(await sparkRuntime(state), params.account, params.intent);
|
|
16365
|
+
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, () => sparkPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), summary));
|
|
16366
|
+
ctx.session.require(session);
|
|
16367
|
+
const live = liveApprovals(state, ctx, key);
|
|
16368
|
+
if (live.length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16369
|
+
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16370
|
+
}
|
|
16371
|
+
live.push({
|
|
16372
|
+
intent: params.intent,
|
|
16373
|
+
deadline: ctx.platform.elapsed() + APPROVAL_TTL_MS,
|
|
16374
|
+
decoded,
|
|
16375
|
+
summary,
|
|
16376
|
+
spentLeaves: new Map
|
|
16377
|
+
});
|
|
16378
|
+
state.approvals.set(key, live);
|
|
16379
|
+
return summary;
|
|
16380
|
+
};
|
|
16381
|
+
function createSparkModule() {
|
|
16382
|
+
const state = {
|
|
16383
|
+
signers: new Map,
|
|
16384
|
+
approvals: new Map,
|
|
16385
|
+
backendPromise: undefined,
|
|
16386
|
+
runtimePromise: undefined
|
|
16652
16387
|
};
|
|
16653
16388
|
const vault = {
|
|
16654
16389
|
ownsRecord: () => false,
|
|
@@ -16657,56 +16392,28 @@ function createSparkModule() {
|
|
|
16657
16392
|
return;
|
|
16658
16393
|
},
|
|
16659
16394
|
lock: () => {
|
|
16660
|
-
disposeAll();
|
|
16395
|
+
disposeAll(state);
|
|
16661
16396
|
},
|
|
16662
|
-
backupSecrets: () => [],
|
|
16663
|
-
backupRecords: () => [],
|
|
16664
16397
|
walletDeleteOps: (_image, walletId) => {
|
|
16665
|
-
disposeWallet(walletId);
|
|
16398
|
+
disposeWallet(state, walletId);
|
|
16666
16399
|
return [];
|
|
16667
16400
|
}
|
|
16668
16401
|
};
|
|
16669
16402
|
const handlers = {
|
|
16670
|
-
"spark.identityPublicKey": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.identityPublicKey()),
|
|
16671
|
-
"spark.publicKeys": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.publicKeys(params.keys)),
|
|
16672
|
-
"spark.receivedPublicKeys": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.receivedPublicKeys(params.ciphertexts)),
|
|
16673
|
-
"spark.newCommitments": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.newCommitments(params.count)),
|
|
16674
|
-
"spark.signFrost": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signFrost(params.jobs)),
|
|
16675
|
-
"spark.aggregateFrost": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.aggregateFrost(params.jobs)),
|
|
16676
|
-
"spark.signIdentity": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signIdentity(params.statement)),
|
|
16677
|
-
"spark.signKeySpend": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signKeySpend(params.key, params.target)),
|
|
16678
|
-
"spark.signHtlcTimeout": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.signHtlcTimeout(params.request)),
|
|
16679
|
-
"spark.prepareTransfer": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareTransfer(params.request)),
|
|
16680
|
-
"spark.prepareClaim": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareClaim(params.request)),
|
|
16681
|
-
"spark.prepareLightningReceive": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.prepareLightningReceive()),
|
|
16682
|
-
"spark.claimStaticDeposit": async (ctx, params, session) => call(ctx, params.account, session, async (signer) => signer.claimStaticDeposit(params.request)),
|
|
16683
|
-
"spark.approve": async (ctx, params, session) =>
|
|
16684
|
-
const { dek } = ctx.session.require(session);
|
|
16685
|
-
const record = ctx.image.records.find((entry) => entry.kind === "entropy" && entry.id === params.account.walletId);
|
|
16686
|
-
if (record === undefined) {
|
|
16687
|
-
throw new KernelError("not-found", "no such wallet");
|
|
16688
|
-
}
|
|
16689
|
-
const key = poolKey(params.account);
|
|
16690
|
-
if (liveApprovals(ctx, key).length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16691
|
-
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16692
|
-
}
|
|
16693
|
-
const { summary, decoded } = decodeIntent(await sparkRuntime(), params.account, params.intent);
|
|
16694
|
-
await verifyFactor(ctx.platform, ctx.image, params.verify, dek, () => sparkPrompt(promptLocale(ctx.platform.keystore?.locale ?? "en"), summary));
|
|
16695
|
-
ctx.session.require(session);
|
|
16696
|
-
const live = liveApprovals(ctx, key);
|
|
16697
|
-
if (live.length >= APPROVAL_MAX_PER_ACCOUNT) {
|
|
16698
|
-
throw new KernelError("invalid-input", "approval cap reached for this account");
|
|
16699
|
-
}
|
|
16700
|
-
live.push({
|
|
16701
|
-
intent: params.intent,
|
|
16702
|
-
deadline: ctx.platform.elapsed() + APPROVAL_TTL_MS,
|
|
16703
|
-
decoded,
|
|
16704
|
-
summary,
|
|
16705
|
-
spentLeaves: new Map
|
|
16706
|
-
});
|
|
16707
|
-
approvals.set(key, live);
|
|
16708
|
-
return summary;
|
|
16709
|
-
}
|
|
16403
|
+
"spark.identityPublicKey": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.identityPublicKey()),
|
|
16404
|
+
"spark.publicKeys": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.publicKeys(params.keys)),
|
|
16405
|
+
"spark.receivedPublicKeys": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.receivedPublicKeys(params.ciphertexts)),
|
|
16406
|
+
"spark.newCommitments": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.newCommitments(params.count)),
|
|
16407
|
+
"spark.signFrost": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signFrost(params.jobs)),
|
|
16408
|
+
"spark.aggregateFrost": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.aggregateFrost(params.jobs)),
|
|
16409
|
+
"spark.signIdentity": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signIdentity(params.statement)),
|
|
16410
|
+
"spark.signKeySpend": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signKeySpend(params.key, params.target)),
|
|
16411
|
+
"spark.signHtlcTimeout": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.signHtlcTimeout(params.request)),
|
|
16412
|
+
"spark.prepareTransfer": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareTransfer(params.request)),
|
|
16413
|
+
"spark.prepareClaim": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareClaim(params.request)),
|
|
16414
|
+
"spark.prepareLightningReceive": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.prepareLightningReceive()),
|
|
16415
|
+
"spark.claimStaticDeposit": async (ctx, params, session) => call(state, ctx, params.account, session, async (signer) => signer.claimStaticDeposit(params.request)),
|
|
16416
|
+
"spark.approve": async (ctx, params, session) => sparkApprove(state, ctx, params, session)
|
|
16710
16417
|
};
|
|
16711
16418
|
return { vault, handlers };
|
|
16712
16419
|
}
|
|
@@ -17232,6 +16939,39 @@ function isNodeWorkerData(value) {
|
|
|
17232
16939
|
return data !== undefined && Object.keys(data).sort().join(",") === "idleMinutes,storePort" && isIdleMinutes(data["idleMinutes"]) && typeof data["storePort"] === "object" && data["storePort"] !== null;
|
|
17233
16940
|
}
|
|
17234
16941
|
|
|
16942
|
+
// src/worker/subtle.ts
|
|
16943
|
+
var SUBTLE_HASH = {
|
|
16944
|
+
sha256: "SHA-256",
|
|
16945
|
+
sha512: "SHA-512"
|
|
16946
|
+
};
|
|
16947
|
+
var subtlePbkdf2 = async (hash, password, salt, iterations, length) => {
|
|
16948
|
+
const passwordCopy = new Uint8Array(password);
|
|
16949
|
+
const saltCopy = new Uint8Array(salt);
|
|
16950
|
+
try {
|
|
16951
|
+
const key = await crypto.subtle.importKey("raw", passwordCopy, "PBKDF2", false, ["deriveBits"]);
|
|
16952
|
+
const bits = await crypto.subtle.deriveBits({ name: "PBKDF2", hash: SUBTLE_HASH[hash] ?? "SHA-256", salt: saltCopy, iterations }, key, length * 8);
|
|
16953
|
+
return new Uint8Array(bits);
|
|
16954
|
+
} finally {
|
|
16955
|
+
passwordCopy.fill(0);
|
|
16956
|
+
}
|
|
16957
|
+
};
|
|
16958
|
+
|
|
16959
|
+
// src/worker/platform.ts
|
|
16960
|
+
var basePlatform = () => ({
|
|
16961
|
+
random: (length) => crypto.getRandomValues(new Uint8Array(length)),
|
|
16962
|
+
now: () => Date.now(),
|
|
16963
|
+
elapsed: () => performance.now(),
|
|
16964
|
+
setTimer: (delayMs, fn) => {
|
|
16965
|
+
const timer = setTimeout(fn, delayMs);
|
|
16966
|
+
return () => {
|
|
16967
|
+
clearTimeout(timer);
|
|
16968
|
+
};
|
|
16969
|
+
},
|
|
16970
|
+
pbkdf2: subtlePbkdf2,
|
|
16971
|
+
keystore: undefined,
|
|
16972
|
+
passkey: undefined
|
|
16973
|
+
});
|
|
16974
|
+
|
|
17235
16975
|
// src/worker/spark.ts
|
|
17236
16976
|
async function loadSparkBackend(readWasm) {
|
|
17237
16977
|
const { loadSparkWasm, SPARK_WASM_INTEGRITY } = await import("./browser-1vpxmqwn.js");
|
|
@@ -17317,23 +17057,6 @@ function createStoreClient(port) {
|
|
|
17317
17057
|
};
|
|
17318
17058
|
}
|
|
17319
17059
|
|
|
17320
|
-
// src/worker/subtle.ts
|
|
17321
|
-
var SUBTLE_HASH = {
|
|
17322
|
-
sha256: "SHA-256",
|
|
17323
|
-
sha512: "SHA-512"
|
|
17324
|
-
};
|
|
17325
|
-
var subtlePbkdf2 = async (hash, password, salt, iterations, length) => {
|
|
17326
|
-
const passwordCopy = new Uint8Array(password);
|
|
17327
|
-
const saltCopy = new Uint8Array(salt);
|
|
17328
|
-
try {
|
|
17329
|
-
const key = await crypto.subtle.importKey("raw", passwordCopy, "PBKDF2", false, ["deriveBits"]);
|
|
17330
|
-
const bits = await crypto.subtle.deriveBits({ name: "PBKDF2", hash: SUBTLE_HASH[hash] ?? "SHA-256", salt: saltCopy, iterations }, key, length * 8);
|
|
17331
|
-
return new Uint8Array(bits);
|
|
17332
|
-
} finally {
|
|
17333
|
-
passwordCopy.fill(0);
|
|
17334
|
-
}
|
|
17335
|
-
};
|
|
17336
|
-
|
|
17337
17060
|
// src/worker/node.ts
|
|
17338
17061
|
var main = parentPort;
|
|
17339
17062
|
if (main === null) {
|
|
@@ -17348,18 +17071,7 @@ var data = {
|
|
|
17348
17071
|
};
|
|
17349
17072
|
data.storePort.start();
|
|
17350
17073
|
var platform = {
|
|
17351
|
-
|
|
17352
|
-
now: () => Date.now(),
|
|
17353
|
-
elapsed: () => performance.now(),
|
|
17354
|
-
setTimer: (delayMs, fn) => {
|
|
17355
|
-
const timer = setTimeout(fn, delayMs);
|
|
17356
|
-
return () => {
|
|
17357
|
-
clearTimeout(timer);
|
|
17358
|
-
};
|
|
17359
|
-
},
|
|
17360
|
-
pbkdf2: subtlePbkdf2,
|
|
17361
|
-
keystore: undefined,
|
|
17362
|
-
passkey: undefined,
|
|
17074
|
+
...basePlatform(),
|
|
17363
17075
|
store: createStoreClient({
|
|
17364
17076
|
post: (message) => {
|
|
17365
17077
|
data.storePort.postMessage(message);
|