@kehto/paja 0.3.7 → 0.4.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/README.md +4 -0
- package/dist/browser-host.js +2096 -344
- package/dist/browser-host.js.map +1 -1
- package/dist/{chunk-WYIXZLDJ.js → chunk-BK4UY76F.js} +237 -18
- package/dist/chunk-BK4UY76F.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +52 -3
- package/dist/index.js +13 -1
- package/dist/{server-Ca1k_vlt.d.ts → server-DwuF7bjQ.d.ts} +19 -2
- package/package.json +3 -3
- package/dist/chunk-WYIXZLDJ.js.map +0 -1
package/dist/browser-host.js
CHANGED
|
@@ -1697,13 +1697,13 @@ function legacyScopedKey(pubkey, dTag, aggregateHash, userKey) {
|
|
|
1697
1697
|
}
|
|
1698
1698
|
function byteLength(str) {
|
|
1699
1699
|
let bytes = 0;
|
|
1700
|
-
for (let
|
|
1701
|
-
const c = str.charCodeAt(
|
|
1700
|
+
for (let i4 = 0; i4 < str.length; i4++) {
|
|
1701
|
+
const c = str.charCodeAt(i4);
|
|
1702
1702
|
if (c < 128) bytes += 1;
|
|
1703
1703
|
else if (c < 2048) bytes += 2;
|
|
1704
1704
|
else if (c < 55296 || c >= 57344) bytes += 3;
|
|
1705
1705
|
else {
|
|
1706
|
-
|
|
1706
|
+
i4++;
|
|
1707
1707
|
bytes += 4;
|
|
1708
1708
|
}
|
|
1709
1709
|
}
|
|
@@ -2003,13 +2003,13 @@ function createNapEnvelopeDispatcher(handlers) {
|
|
|
2003
2003
|
}
|
|
2004
2004
|
function utf8ByteLength(str) {
|
|
2005
2005
|
let bytes = 0;
|
|
2006
|
-
for (let
|
|
2007
|
-
const c = str.charCodeAt(
|
|
2006
|
+
for (let i4 = 0; i4 < str.length; i4++) {
|
|
2007
|
+
const c = str.charCodeAt(i4);
|
|
2008
2008
|
if (c < 128) bytes += 1;
|
|
2009
2009
|
else if (c < 2048) bytes += 2;
|
|
2010
2010
|
else if (c < 55296 || c >= 57344) bytes += 3;
|
|
2011
2011
|
else {
|
|
2012
|
-
|
|
2012
|
+
i4++;
|
|
2013
2013
|
bytes += 4;
|
|
2014
2014
|
}
|
|
2015
2015
|
}
|
|
@@ -2252,8 +2252,8 @@ function bytesToHex(bytes) {
|
|
|
2252
2252
|
}
|
|
2253
2253
|
function hexToBytes(hex) {
|
|
2254
2254
|
const bytes = new Uint8Array(hex.length / 2);
|
|
2255
|
-
for (let
|
|
2256
|
-
bytes[
|
|
2255
|
+
for (let i4 = 0; i4 < hex.length; i4 += 2) {
|
|
2256
|
+
bytes[i4 / 2] = parseInt(hex.substring(i4, i4 + 2), 16);
|
|
2257
2257
|
}
|
|
2258
2258
|
return bytes;
|
|
2259
2259
|
}
|
|
@@ -2427,8 +2427,8 @@ function createStatePersistence() {
|
|
|
2427
2427
|
clear(prefix) {
|
|
2428
2428
|
try {
|
|
2429
2429
|
const keysToRemove = [];
|
|
2430
|
-
for (let
|
|
2431
|
-
const key = localStorage.key(
|
|
2430
|
+
for (let i4 = 0; i4 < localStorage.length; i4++) {
|
|
2431
|
+
const key = localStorage.key(i4);
|
|
2432
2432
|
if (key?.startsWith(prefix)) keysToRemove.push(key);
|
|
2433
2433
|
}
|
|
2434
2434
|
for (const key of keysToRemove) localStorage.removeItem(key);
|
|
@@ -2438,8 +2438,8 @@ function createStatePersistence() {
|
|
|
2438
2438
|
keys(prefix) {
|
|
2439
2439
|
try {
|
|
2440
2440
|
const result = [];
|
|
2441
|
-
for (let
|
|
2442
|
-
const key = localStorage.key(
|
|
2441
|
+
for (let i4 = 0; i4 < localStorage.length; i4++) {
|
|
2442
|
+
const key = localStorage.key(i4);
|
|
2443
2443
|
if (key?.startsWith(prefix)) result.push(key);
|
|
2444
2444
|
}
|
|
2445
2445
|
return result;
|
|
@@ -2450,8 +2450,8 @@ function createStatePersistence() {
|
|
|
2450
2450
|
calculateBytes(prefix, excludeKey) {
|
|
2451
2451
|
try {
|
|
2452
2452
|
let total = 0;
|
|
2453
|
-
for (let
|
|
2454
|
-
const key = localStorage.key(
|
|
2453
|
+
for (let i4 = 0; i4 < localStorage.length; i4++) {
|
|
2454
|
+
const key = localStorage.key(i4);
|
|
2455
2455
|
if (!key?.startsWith(prefix)) continue;
|
|
2456
2456
|
if (excludeKey && key === excludeKey) continue;
|
|
2457
2457
|
const value = localStorage.getItem(key) ?? "";
|
|
@@ -3503,8 +3503,8 @@ function aoutput(out, instance) {
|
|
|
3503
3503
|
}
|
|
3504
3504
|
}
|
|
3505
3505
|
function clean(...arrays) {
|
|
3506
|
-
for (let
|
|
3507
|
-
arrays[
|
|
3506
|
+
for (let i4 = 0; i4 < arrays.length; i4++) {
|
|
3507
|
+
arrays[i4].fill(0);
|
|
3508
3508
|
}
|
|
3509
3509
|
}
|
|
3510
3510
|
function createView(arr) {
|
|
@@ -3517,14 +3517,14 @@ var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
|
3517
3517
|
// @ts-ignore
|
|
3518
3518
|
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
3519
3519
|
))();
|
|
3520
|
-
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_,
|
|
3520
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i4) => i4.toString(16).padStart(2, "0"));
|
|
3521
3521
|
function bytesToHex2(bytes) {
|
|
3522
3522
|
abytes(bytes);
|
|
3523
3523
|
if (hasHexBuiltin)
|
|
3524
3524
|
return bytes.toHex();
|
|
3525
3525
|
let hex = "";
|
|
3526
|
-
for (let
|
|
3527
|
-
hex += hexes[bytes[
|
|
3526
|
+
for (let i4 = 0; i4 < bytes.length; i4++) {
|
|
3527
|
+
hex += hexes[bytes[i4]];
|
|
3528
3528
|
}
|
|
3529
3529
|
return hex;
|
|
3530
3530
|
}
|
|
@@ -3561,14 +3561,14 @@ function hexToBytes2(hex) {
|
|
|
3561
3561
|
}
|
|
3562
3562
|
function concatBytes(...arrays) {
|
|
3563
3563
|
let sum = 0;
|
|
3564
|
-
for (let
|
|
3565
|
-
const a = arrays[
|
|
3564
|
+
for (let i4 = 0; i4 < arrays.length; i4++) {
|
|
3565
|
+
const a = arrays[i4];
|
|
3566
3566
|
abytes(a);
|
|
3567
3567
|
sum += a.length;
|
|
3568
3568
|
}
|
|
3569
3569
|
const res = new Uint8Array(sum);
|
|
3570
|
-
for (let
|
|
3571
|
-
const a = arrays[
|
|
3570
|
+
for (let i4 = 0, pad2 = 0; i4 < arrays.length; i4++) {
|
|
3571
|
+
const a = arrays[i4];
|
|
3572
3572
|
res.set(a, pad2);
|
|
3573
3573
|
pad2 += a.length;
|
|
3574
3574
|
}
|
|
@@ -3651,24 +3651,24 @@ function alphabet(letters) {
|
|
|
3651
3651
|
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
3652
3652
|
const len = lettersA.length;
|
|
3653
3653
|
astrArr("alphabet", lettersA);
|
|
3654
|
-
const indexes = new Map(lettersA.map((l,
|
|
3654
|
+
const indexes = new Map(lettersA.map((l, i4) => [l, i4]));
|
|
3655
3655
|
return {
|
|
3656
3656
|
encode: (digits) => {
|
|
3657
3657
|
aArr(digits);
|
|
3658
|
-
return digits.map((
|
|
3659
|
-
if (!Number.isSafeInteger(
|
|
3660
|
-
throw new Error(`alphabet.encode: digit index outside alphabet "${
|
|
3661
|
-
return lettersA[
|
|
3658
|
+
return digits.map((i4) => {
|
|
3659
|
+
if (!Number.isSafeInteger(i4) || i4 < 0 || i4 >= len)
|
|
3660
|
+
throw new Error(`alphabet.encode: digit index outside alphabet "${i4}". Allowed: ${letters}`);
|
|
3661
|
+
return lettersA[i4];
|
|
3662
3662
|
});
|
|
3663
3663
|
},
|
|
3664
3664
|
decode: (input) => {
|
|
3665
3665
|
aArr(input);
|
|
3666
3666
|
return input.map((letter) => {
|
|
3667
3667
|
astr("alphabet.decode", letter);
|
|
3668
|
-
const
|
|
3669
|
-
if (
|
|
3668
|
+
const i4 = indexes.get(letter);
|
|
3669
|
+
if (i4 === void 0)
|
|
3670
3670
|
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
3671
|
-
return
|
|
3671
|
+
return i4;
|
|
3672
3672
|
});
|
|
3673
3673
|
}
|
|
3674
3674
|
};
|
|
@@ -3717,8 +3717,8 @@ var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
|
3717
3717
|
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
3718
3718
|
var powers = /* @__PURE__ */ (() => {
|
|
3719
3719
|
let res = [];
|
|
3720
|
-
for (let
|
|
3721
|
-
res.push(2 **
|
|
3720
|
+
for (let i4 = 0; i4 < 40; i4++)
|
|
3721
|
+
res.push(2 ** i4);
|
|
3722
3722
|
return res;
|
|
3723
3723
|
})();
|
|
3724
3724
|
function convertRadix2(data, from, to, padding2) {
|
|
@@ -3810,27 +3810,27 @@ var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059
|
|
|
3810
3810
|
function bech32Polymod(pre) {
|
|
3811
3811
|
const b = pre >> 25;
|
|
3812
3812
|
let chk = (pre & 33554431) << 5;
|
|
3813
|
-
for (let
|
|
3814
|
-
if ((b >>
|
|
3815
|
-
chk ^= POLYMOD_GENERATORS[
|
|
3813
|
+
for (let i4 = 0; i4 < POLYMOD_GENERATORS.length; i4++) {
|
|
3814
|
+
if ((b >> i4 & 1) === 1)
|
|
3815
|
+
chk ^= POLYMOD_GENERATORS[i4];
|
|
3816
3816
|
}
|
|
3817
3817
|
return chk;
|
|
3818
3818
|
}
|
|
3819
3819
|
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
3820
3820
|
const len = prefix.length;
|
|
3821
3821
|
let chk = 1;
|
|
3822
|
-
for (let
|
|
3823
|
-
const c = prefix.charCodeAt(
|
|
3822
|
+
for (let i4 = 0; i4 < len; i4++) {
|
|
3823
|
+
const c = prefix.charCodeAt(i4);
|
|
3824
3824
|
if (c < 33 || c > 126)
|
|
3825
3825
|
throw new Error(`Invalid prefix (${prefix})`);
|
|
3826
3826
|
chk = bech32Polymod(chk) ^ c >> 5;
|
|
3827
3827
|
}
|
|
3828
3828
|
chk = bech32Polymod(chk);
|
|
3829
|
-
for (let
|
|
3830
|
-
chk = bech32Polymod(chk) ^ prefix.charCodeAt(
|
|
3829
|
+
for (let i4 = 0; i4 < len; i4++)
|
|
3830
|
+
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i4) & 31;
|
|
3831
3831
|
for (let v of words)
|
|
3832
3832
|
chk = bech32Polymod(chk) ^ v;
|
|
3833
|
-
for (let
|
|
3833
|
+
for (let i4 = 0; i4 < 6; i4++)
|
|
3834
3834
|
chk = bech32Polymod(chk);
|
|
3835
3835
|
chk ^= encodingConst;
|
|
3836
3836
|
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
@@ -4117,8 +4117,8 @@ var HashMD = class {
|
|
|
4117
4117
|
this.process(view, 0);
|
|
4118
4118
|
pos = 0;
|
|
4119
4119
|
}
|
|
4120
|
-
for (let
|
|
4121
|
-
buffer[
|
|
4120
|
+
for (let i4 = pos; i4 < blockLen; i4++)
|
|
4121
|
+
buffer[i4] = 0;
|
|
4122
4122
|
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE2);
|
|
4123
4123
|
this.process(view, 0);
|
|
4124
4124
|
const oview = createView(out);
|
|
@@ -4129,8 +4129,8 @@ var HashMD = class {
|
|
|
4129
4129
|
const state = this.get();
|
|
4130
4130
|
if (outLen > state.length)
|
|
4131
4131
|
throw new Error("_sha2: outputLen bigger than state");
|
|
4132
|
-
for (let
|
|
4133
|
-
oview.setUint32(4 *
|
|
4132
|
+
for (let i4 = 0; i4 < outLen; i4++)
|
|
4133
|
+
oview.setUint32(4 * i4, state[i4], isLE2);
|
|
4134
4134
|
}
|
|
4135
4135
|
digest() {
|
|
4136
4136
|
const { buffer, outputLen } = this;
|
|
@@ -4254,19 +4254,19 @@ var SHA2_32B = class extends HashMD {
|
|
|
4254
4254
|
this.H = H | 0;
|
|
4255
4255
|
}
|
|
4256
4256
|
process(view, offset) {
|
|
4257
|
-
for (let
|
|
4258
|
-
SHA256_W[
|
|
4259
|
-
for (let
|
|
4260
|
-
const W15 = SHA256_W[
|
|
4261
|
-
const W2 = SHA256_W[
|
|
4257
|
+
for (let i4 = 0; i4 < 16; i4++, offset += 4)
|
|
4258
|
+
SHA256_W[i4] = view.getUint32(offset, false);
|
|
4259
|
+
for (let i4 = 16; i4 < 64; i4++) {
|
|
4260
|
+
const W15 = SHA256_W[i4 - 15];
|
|
4261
|
+
const W2 = SHA256_W[i4 - 2];
|
|
4262
4262
|
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
4263
4263
|
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
4264
|
-
SHA256_W[
|
|
4264
|
+
SHA256_W[i4] = s1 + SHA256_W[i4 - 7] + s0 + SHA256_W[i4 - 16] | 0;
|
|
4265
4265
|
}
|
|
4266
4266
|
let { A, B, C, D, E, F, G, H } = this;
|
|
4267
|
-
for (let
|
|
4267
|
+
for (let i4 = 0; i4 < 64; i4++) {
|
|
4268
4268
|
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
4269
|
-
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[
|
|
4269
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i4] + SHA256_W[i4] | 0;
|
|
4270
4270
|
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
4271
4271
|
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
4272
4272
|
H = G;
|
|
@@ -4364,10 +4364,10 @@ function copyBytes(bytes) {
|
|
|
4364
4364
|
return Uint8Array.from(bytes);
|
|
4365
4365
|
}
|
|
4366
4366
|
function asciiToBytes(ascii) {
|
|
4367
|
-
return Uint8Array.from(ascii, (c,
|
|
4367
|
+
return Uint8Array.from(ascii, (c, i4) => {
|
|
4368
4368
|
const charCode = c.charCodeAt(0);
|
|
4369
4369
|
if (c.length !== 1 || charCode > 127) {
|
|
4370
|
-
throw new Error(`string contains non-ASCII character "${ascii[
|
|
4370
|
+
throw new Error(`string contains non-ASCII character "${ascii[i4]}" with code ${charCode} at position ${i4}`);
|
|
4371
4371
|
}
|
|
4372
4372
|
return charCode;
|
|
4373
4373
|
});
|
|
@@ -4399,11 +4399,11 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
4399
4399
|
const _maxDrbgIters = 1e3;
|
|
4400
4400
|
let v = u8n(hashLen);
|
|
4401
4401
|
let k = u8n(hashLen);
|
|
4402
|
-
let
|
|
4402
|
+
let i4 = 0;
|
|
4403
4403
|
const reset = () => {
|
|
4404
4404
|
v.fill(1);
|
|
4405
4405
|
k.fill(0);
|
|
4406
|
-
|
|
4406
|
+
i4 = 0;
|
|
4407
4407
|
};
|
|
4408
4408
|
const h = (...msgs) => hmacFn(k, concatBytes(v, ...msgs));
|
|
4409
4409
|
const reseed = (seed = NULL) => {
|
|
@@ -4415,7 +4415,7 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
4415
4415
|
v = h();
|
|
4416
4416
|
};
|
|
4417
4417
|
const gen = () => {
|
|
4418
|
-
if (
|
|
4418
|
+
if (i4++ >= _maxDrbgIters)
|
|
4419
4419
|
throw new Error("drbg: tried max amount of iterations");
|
|
4420
4420
|
let len = 0;
|
|
4421
4421
|
const out = [];
|
|
@@ -4523,8 +4523,8 @@ function sqrt5mod8(Fp, n) {
|
|
|
4523
4523
|
const n2 = Fp.mul(n, _2n);
|
|
4524
4524
|
const v = Fp.pow(n2, p5div8);
|
|
4525
4525
|
const nv = Fp.mul(n, v);
|
|
4526
|
-
const
|
|
4527
|
-
const root = Fp.mul(nv, Fp.sub(
|
|
4526
|
+
const i4 = Fp.mul(Fp.mul(nv, _2n), v);
|
|
4527
|
+
const root = Fp.mul(nv, Fp.sub(i4, Fp.ONE));
|
|
4528
4528
|
assertIsSquare(Fp, root, n);
|
|
4529
4529
|
return root;
|
|
4530
4530
|
}
|
|
@@ -4581,17 +4581,17 @@ function tonelliShanks(P) {
|
|
|
4581
4581
|
while (!Fp.eql(t, Fp.ONE)) {
|
|
4582
4582
|
if (Fp.is0(t))
|
|
4583
4583
|
return Fp.ZERO;
|
|
4584
|
-
let
|
|
4584
|
+
let i4 = 1;
|
|
4585
4585
|
let t_tmp = Fp.sqr(t);
|
|
4586
4586
|
while (!Fp.eql(t_tmp, Fp.ONE)) {
|
|
4587
|
-
|
|
4587
|
+
i4++;
|
|
4588
4588
|
t_tmp = Fp.sqr(t_tmp);
|
|
4589
|
-
if (
|
|
4589
|
+
if (i4 === M)
|
|
4590
4590
|
throw new Error("Cannot find square root");
|
|
4591
4591
|
}
|
|
4592
|
-
const exponent = _1n2 << BigInt(M -
|
|
4592
|
+
const exponent = _1n2 << BigInt(M - i4 - 1);
|
|
4593
4593
|
const b = Fp.pow(c, exponent);
|
|
4594
|
-
M =
|
|
4594
|
+
M = i4;
|
|
4595
4595
|
c = Fp.sqr(b);
|
|
4596
4596
|
t = Fp.mul(t, c);
|
|
4597
4597
|
R = Fp.mul(R, b);
|
|
@@ -4659,17 +4659,17 @@ function FpPow(Fp, num2, power) {
|
|
|
4659
4659
|
}
|
|
4660
4660
|
function FpInvertBatch(Fp, nums, passZero = false) {
|
|
4661
4661
|
const inverted = new Array(nums.length).fill(passZero ? Fp.ZERO : void 0);
|
|
4662
|
-
const multipliedAcc = nums.reduce((acc, num2,
|
|
4662
|
+
const multipliedAcc = nums.reduce((acc, num2, i4) => {
|
|
4663
4663
|
if (Fp.is0(num2))
|
|
4664
4664
|
return acc;
|
|
4665
|
-
inverted[
|
|
4665
|
+
inverted[i4] = acc;
|
|
4666
4666
|
return Fp.mul(acc, num2);
|
|
4667
4667
|
}, Fp.ONE);
|
|
4668
4668
|
const invertedAcc = Fp.inv(multipliedAcc);
|
|
4669
|
-
nums.reduceRight((acc, num2,
|
|
4669
|
+
nums.reduceRight((acc, num2, i4) => {
|
|
4670
4670
|
if (Fp.is0(num2))
|
|
4671
4671
|
return acc;
|
|
4672
|
-
inverted[
|
|
4672
|
+
inverted[i4] = Fp.mul(acc, inverted[i4]);
|
|
4673
4673
|
return Fp.mul(acc, num2);
|
|
4674
4674
|
}, invertedAcc);
|
|
4675
4675
|
return inverted;
|
|
@@ -4860,7 +4860,7 @@ function negateCt(condition, item) {
|
|
|
4860
4860
|
}
|
|
4861
4861
|
function normalizeZ(c, points) {
|
|
4862
4862
|
const invertedZs = FpInvertBatch(c.Fp, points.map((p) => p.Z));
|
|
4863
|
-
return points.map((p,
|
|
4863
|
+
return points.map((p, i4) => c.fromAffine(p.toAffine(invertedZs[i4])));
|
|
4864
4864
|
}
|
|
4865
4865
|
function validateW(W, bits) {
|
|
4866
4866
|
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
|
@@ -4943,7 +4943,7 @@ var wNAF = class {
|
|
|
4943
4943
|
for (let window2 = 0; window2 < windows; window2++) {
|
|
4944
4944
|
base = p;
|
|
4945
4945
|
points.push(base);
|
|
4946
|
-
for (let
|
|
4946
|
+
for (let i4 = 1; i4 < windowSize; i4++) {
|
|
4947
4947
|
base = base.add(p);
|
|
4948
4948
|
points.push(base);
|
|
4949
4949
|
}
|
|
@@ -5077,10 +5077,10 @@ function createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
|
|
5077
5077
|
CURVE = Object.freeze(Object.assign({}, CURVE));
|
|
5078
5078
|
return { CURVE, Fp, Fn };
|
|
5079
5079
|
}
|
|
5080
|
-
function createKeygen(randomSecretKey,
|
|
5080
|
+
function createKeygen(randomSecretKey, getPublicKey4) {
|
|
5081
5081
|
return function keygen(seed) {
|
|
5082
5082
|
const secretKey = randomSecretKey(seed);
|
|
5083
|
-
return { secretKey, publicKey:
|
|
5083
|
+
return { secretKey, publicKey: getPublicKey4(secretKey) };
|
|
5084
5084
|
};
|
|
5085
5085
|
}
|
|
5086
5086
|
|
|
@@ -5103,12 +5103,12 @@ var _HMAC = class {
|
|
|
5103
5103
|
const blockLen = this.blockLen;
|
|
5104
5104
|
const pad2 = new Uint8Array(blockLen);
|
|
5105
5105
|
pad2.set(key.length > blockLen ? hash.create().update(key).digest() : key);
|
|
5106
|
-
for (let
|
|
5107
|
-
pad2[
|
|
5106
|
+
for (let i4 = 0; i4 < pad2.length; i4++)
|
|
5107
|
+
pad2[i4] ^= 54;
|
|
5108
5108
|
this.iHash.update(pad2);
|
|
5109
5109
|
this.oHash = hash.create();
|
|
5110
|
-
for (let
|
|
5111
|
-
pad2[
|
|
5110
|
+
for (let i4 = 0; i4 < pad2.length; i4++)
|
|
5111
|
+
pad2[i4] ^= 54 ^ 92;
|
|
5112
5112
|
this.oHash.update(pad2);
|
|
5113
5113
|
clean(pad2);
|
|
5114
5114
|
}
|
|
@@ -5765,7 +5765,7 @@ function ecdh(Point, ecdhOpts = {}) {
|
|
|
5765
5765
|
function randomSecretKey(seed = randomBytes_(lengths.seed)) {
|
|
5766
5766
|
return mapHashToField(abytes(seed, lengths.seed, "seed"), Fn.ORDER);
|
|
5767
5767
|
}
|
|
5768
|
-
function
|
|
5768
|
+
function getPublicKey4(secretKey, isCompressed = true) {
|
|
5769
5769
|
return Point.BASE.multiply(Fn.fromBytes(secretKey)).toBytes(isCompressed);
|
|
5770
5770
|
}
|
|
5771
5771
|
function isProbPub(item) {
|
|
@@ -5791,8 +5791,8 @@ function ecdh(Point, ecdhOpts = {}) {
|
|
|
5791
5791
|
isValidPublicKey,
|
|
5792
5792
|
randomSecretKey
|
|
5793
5793
|
};
|
|
5794
|
-
const keygen = createKeygen(randomSecretKey,
|
|
5795
|
-
return Object.freeze({ getPublicKey:
|
|
5794
|
+
const keygen = createKeygen(randomSecretKey, getPublicKey4);
|
|
5795
|
+
return Object.freeze({ getPublicKey: getPublicKey4, getSharedSecret, keygen, Point, utils, lengths });
|
|
5796
5796
|
}
|
|
5797
5797
|
function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
5798
5798
|
ahash(hash);
|
|
@@ -5808,7 +5808,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
5808
5808
|
const hmac2 = ecdsaOpts.hmac || ((key, msg) => hmac(hash, key, msg));
|
|
5809
5809
|
const { Fp, Fn } = Point;
|
|
5810
5810
|
const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
|
|
5811
|
-
const { keygen, getPublicKey:
|
|
5811
|
+
const { keygen, getPublicKey: getPublicKey4, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);
|
|
5812
5812
|
const defaultSigOpts = {
|
|
5813
5813
|
prehash: true,
|
|
5814
5814
|
lowS: typeof ecdsaOpts.lowS === "boolean" ? ecdsaOpts.lowS : true,
|
|
@@ -6014,7 +6014,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
6014
6014
|
}
|
|
6015
6015
|
return Object.freeze({
|
|
6016
6016
|
keygen,
|
|
6017
|
-
getPublicKey:
|
|
6017
|
+
getPublicKey: getPublicKey4,
|
|
6018
6018
|
getSharedSecret,
|
|
6019
6019
|
utils,
|
|
6020
6020
|
lengths,
|
|
@@ -6300,8 +6300,8 @@ function u32(arr) {
|
|
|
6300
6300
|
return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
|
6301
6301
|
}
|
|
6302
6302
|
function clean2(...arrays) {
|
|
6303
|
-
for (let
|
|
6304
|
-
arrays[
|
|
6303
|
+
for (let i4 = 0; i4 < arrays.length; i4++) {
|
|
6304
|
+
arrays[i4].fill(0);
|
|
6305
6305
|
}
|
|
6306
6306
|
}
|
|
6307
6307
|
function createView2(arr) {
|
|
@@ -6327,8 +6327,8 @@ function equalBytes(a, b) {
|
|
|
6327
6327
|
if (a.length !== b.length)
|
|
6328
6328
|
return false;
|
|
6329
6329
|
let diff = 0;
|
|
6330
|
-
for (let
|
|
6331
|
-
diff |= a[
|
|
6330
|
+
for (let i4 = 0; i4 < a.length; i4++)
|
|
6331
|
+
diff |= a[i4] ^ b[i4];
|
|
6332
6332
|
return diff === 0;
|
|
6333
6333
|
}
|
|
6334
6334
|
var wrapCipher = /* @__NO_SIDE_EFFECTS__ */ (params, constructor) => {
|
|
@@ -6508,8 +6508,8 @@ function createCipher(core, opts) {
|
|
|
6508
6508
|
}
|
|
6509
6509
|
|
|
6510
6510
|
// ../../node_modules/.pnpm/@noble+ciphers@2.1.1/node_modules/@noble/ciphers/_poly1305.js
|
|
6511
|
-
function u8to16(a,
|
|
6512
|
-
return a[
|
|
6511
|
+
function u8to16(a, i4) {
|
|
6512
|
+
return a[i4++] & 255 | (a[i4++] & 255) << 8;
|
|
6513
6513
|
}
|
|
6514
6514
|
var Poly1305 = class {
|
|
6515
6515
|
blockLen = 16;
|
|
@@ -6542,8 +6542,8 @@ var Poly1305 = class {
|
|
|
6542
6542
|
this.r[7] = (t5 >>> 11 | t6 << 5) & 8065;
|
|
6543
6543
|
this.r[8] = (t6 >>> 8 | t7 << 8) & 8191;
|
|
6544
6544
|
this.r[9] = t7 >>> 5 & 127;
|
|
6545
|
-
for (let
|
|
6546
|
-
this.pad[
|
|
6545
|
+
for (let i4 = 0; i4 < 8; i4++)
|
|
6546
|
+
this.pad[i4] = u8to16(key, 16 + 2 * i4);
|
|
6547
6547
|
}
|
|
6548
6548
|
process(data, offset, isLast = false) {
|
|
6549
6549
|
const hibit = isLast ? 0 : 1 << 11;
|
|
@@ -6658,10 +6658,10 @@ var Poly1305 = class {
|
|
|
6658
6658
|
const g = new Uint16Array(10);
|
|
6659
6659
|
let c = h[1] >>> 13;
|
|
6660
6660
|
h[1] &= 8191;
|
|
6661
|
-
for (let
|
|
6662
|
-
h[
|
|
6663
|
-
c = h[
|
|
6664
|
-
h[
|
|
6661
|
+
for (let i4 = 2; i4 < 10; i4++) {
|
|
6662
|
+
h[i4] += c;
|
|
6663
|
+
c = h[i4] >>> 13;
|
|
6664
|
+
h[i4] &= 8191;
|
|
6665
6665
|
}
|
|
6666
6666
|
h[0] += c * 5;
|
|
6667
6667
|
c = h[0] >>> 13;
|
|
@@ -6673,18 +6673,18 @@ var Poly1305 = class {
|
|
|
6673
6673
|
g[0] = h[0] + 5;
|
|
6674
6674
|
c = g[0] >>> 13;
|
|
6675
6675
|
g[0] &= 8191;
|
|
6676
|
-
for (let
|
|
6677
|
-
g[
|
|
6678
|
-
c = g[
|
|
6679
|
-
g[
|
|
6676
|
+
for (let i4 = 1; i4 < 10; i4++) {
|
|
6677
|
+
g[i4] = h[i4] + c;
|
|
6678
|
+
c = g[i4] >>> 13;
|
|
6679
|
+
g[i4] &= 8191;
|
|
6680
6680
|
}
|
|
6681
6681
|
g[9] -= 1 << 13;
|
|
6682
6682
|
let mask = (c ^ 1) - 1;
|
|
6683
|
-
for (let
|
|
6684
|
-
g[
|
|
6683
|
+
for (let i4 = 0; i4 < 10; i4++)
|
|
6684
|
+
g[i4] &= mask;
|
|
6685
6685
|
mask = ~mask;
|
|
6686
|
-
for (let
|
|
6687
|
-
h[
|
|
6686
|
+
for (let i4 = 0; i4 < 10; i4++)
|
|
6687
|
+
h[i4] = h[i4] & mask | g[i4];
|
|
6688
6688
|
h[0] = (h[0] | h[1] << 13) & 65535;
|
|
6689
6689
|
h[1] = (h[1] >>> 3 | h[2] << 10) & 65535;
|
|
6690
6690
|
h[2] = (h[2] >>> 6 | h[3] << 7) & 65535;
|
|
@@ -6695,9 +6695,9 @@ var Poly1305 = class {
|
|
|
6695
6695
|
h[7] = (h[8] >>> 8 | h[9] << 5) & 65535;
|
|
6696
6696
|
let f = h[0] + pad2[0];
|
|
6697
6697
|
h[0] = f & 65535;
|
|
6698
|
-
for (let
|
|
6699
|
-
f = (h[
|
|
6700
|
-
h[
|
|
6698
|
+
for (let i4 = 1; i4 < 8; i4++) {
|
|
6699
|
+
f = (h[i4] + pad2[i4] | 0) + (f >>> 16) | 0;
|
|
6700
|
+
h[i4] = f & 65535;
|
|
6701
6701
|
}
|
|
6702
6702
|
clean2(g);
|
|
6703
6703
|
}
|
|
@@ -6741,9 +6741,9 @@ var Poly1305 = class {
|
|
|
6741
6741
|
}
|
|
6742
6742
|
this.finalize();
|
|
6743
6743
|
let opos = 0;
|
|
6744
|
-
for (let
|
|
6745
|
-
out[opos++] = h[
|
|
6746
|
-
out[opos++] = h[
|
|
6744
|
+
for (let i4 = 0; i4 < 8; i4++) {
|
|
6745
|
+
out[opos++] = h[i4] >>> 0;
|
|
6746
|
+
out[opos++] = h[i4] >>> 8;
|
|
6747
6747
|
}
|
|
6748
6748
|
return out;
|
|
6749
6749
|
}
|
|
@@ -6853,8 +6853,8 @@ function chachaCore(s, k, n, out, cnt, rounds = 20) {
|
|
|
6853
6853
|
out[oi++] = y14 + x14 | 0;
|
|
6854
6854
|
out[oi++] = y15 + x15 | 0;
|
|
6855
6855
|
}
|
|
6856
|
-
function hchacha(s, k,
|
|
6857
|
-
let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 =
|
|
6856
|
+
function hchacha(s, k, i4, out) {
|
|
6857
|
+
let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i4[0], x13 = i4[1], x14 = i4[2], x15 = i4[3];
|
|
6858
6858
|
for (let r = 0; r < 20; r += 2) {
|
|
6859
6859
|
x00 = x00 + x04 | 0;
|
|
6860
6860
|
x12 = rotl(x12 ^ x00, 16);
|
|
@@ -7492,11 +7492,11 @@ function parseChord(chord) {
|
|
|
7492
7492
|
if (chord.length === 0) throw new Error("empty chord");
|
|
7493
7493
|
const parts = chord.split("+");
|
|
7494
7494
|
const out = { ctrl: false, alt: false, shift: false, meta: false, key: "" };
|
|
7495
|
-
for (let
|
|
7496
|
-
const tok = parts[
|
|
7495
|
+
for (let i4 = 0; i4 < parts.length - 1; i4++) {
|
|
7496
|
+
const tok = parts[i4].trim().toLowerCase();
|
|
7497
7497
|
if (tok.length === 0) continue;
|
|
7498
7498
|
const slot = MODIFIER_ALIASES[tok];
|
|
7499
|
-
if (!slot) throw new Error(`unknown modifier: ${parts[
|
|
7499
|
+
if (!slot) throw new Error(`unknown modifier: ${parts[i4]}`);
|
|
7500
7500
|
out[slot] = true;
|
|
7501
7501
|
}
|
|
7502
7502
|
const keyTok = parts[parts.length - 1].trim();
|
|
@@ -8393,8 +8393,8 @@ function arrayBufferToBase64(buf) {
|
|
|
8393
8393
|
const bytes = new Uint8Array(buf);
|
|
8394
8394
|
const CHUNK = 32768;
|
|
8395
8395
|
let binary = "";
|
|
8396
|
-
for (let
|
|
8397
|
-
binary += String.fromCharCode(...bytes.subarray(
|
|
8396
|
+
for (let i4 = 0; i4 < bytes.length; i4 += CHUNK) {
|
|
8397
|
+
binary += String.fromCharCode(...bytes.subarray(i4, i4 + CHUNK));
|
|
8398
8398
|
}
|
|
8399
8399
|
return btoa(binary);
|
|
8400
8400
|
}
|
|
@@ -10500,7 +10500,7 @@ function createDevServices(pool, getSimulation, onThemeService, confirmRequest,
|
|
|
10500
10500
|
}
|
|
10501
10501
|
return services;
|
|
10502
10502
|
}
|
|
10503
|
-
function createPajaAdapter(config, getSimulation, onThemeService, confirmRequest, signerProvider) {
|
|
10503
|
+
function createPajaAdapter(config, getSimulation, onThemeService, confirmRequest, signerProvider, getIdentity) {
|
|
10504
10504
|
const pool = createMemoryRelayPool(getSimulation, confirmRequest);
|
|
10505
10505
|
const workerRelayEvents = [];
|
|
10506
10506
|
return {
|
|
@@ -10540,10 +10540,13 @@ function createPajaAdapter(config, getSimulation, onThemeService, confirmRequest
|
|
|
10540
10540
|
crypto: {
|
|
10541
10541
|
verifyEvent: async () => true
|
|
10542
10542
|
},
|
|
10543
|
-
onNip5dIframeCreate: () =>
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10543
|
+
onNip5dIframeCreate: () => {
|
|
10544
|
+
const identity = getIdentity?.();
|
|
10545
|
+
return {
|
|
10546
|
+
dTag: identity?.dTag ?? config.window.dTag,
|
|
10547
|
+
aggregateHash: identity?.aggregateHash ?? config.window.aggregateHash
|
|
10548
|
+
};
|
|
10549
|
+
}
|
|
10547
10550
|
};
|
|
10548
10551
|
}
|
|
10549
10552
|
|
|
@@ -10567,14 +10570,14 @@ function mul(a, b) {
|
|
|
10567
10570
|
}
|
|
10568
10571
|
var sbox = /* @__PURE__ */ (() => {
|
|
10569
10572
|
const t = new Uint8Array(256);
|
|
10570
|
-
for (let
|
|
10571
|
-
t[
|
|
10573
|
+
for (let i4 = 0, x = 1; i4 < 256; i4++, x ^= mul2(x))
|
|
10574
|
+
t[i4] = x;
|
|
10572
10575
|
const box = new Uint8Array(256);
|
|
10573
10576
|
box[0] = 99;
|
|
10574
|
-
for (let
|
|
10575
|
-
let x = t[255 -
|
|
10577
|
+
for (let i4 = 0; i4 < 255; i4++) {
|
|
10578
|
+
let x = t[255 - i4];
|
|
10576
10579
|
x |= x << 8;
|
|
10577
|
-
box[t[
|
|
10580
|
+
box[t[i4]] = (x ^ x >> 4 ^ x >> 5 ^ x >> 6 ^ x >> 7 ^ 99) & 255;
|
|
10578
10581
|
}
|
|
10579
10582
|
clean2(t);
|
|
10580
10583
|
return box;
|
|
@@ -10592,12 +10595,12 @@ function genTtable(sbox2, fn) {
|
|
|
10592
10595
|
const T01 = new Uint32Array(256 * 256);
|
|
10593
10596
|
const T23 = new Uint32Array(256 * 256);
|
|
10594
10597
|
const sbox22 = new Uint16Array(256 * 256);
|
|
10595
|
-
for (let
|
|
10598
|
+
for (let i4 = 0; i4 < 256; i4++) {
|
|
10596
10599
|
for (let j = 0; j < 256; j++) {
|
|
10597
|
-
const idx =
|
|
10598
|
-
T01[idx] = T0[
|
|
10599
|
-
T23[idx] = T2[
|
|
10600
|
-
sbox22[idx] = sbox2[
|
|
10600
|
+
const idx = i4 * 256 + j;
|
|
10601
|
+
T01[idx] = T0[i4] ^ T1[j];
|
|
10602
|
+
T23[idx] = T2[i4] ^ T3[j];
|
|
10603
|
+
sbox22[idx] = sbox2[i4] << 8 | sbox2[j];
|
|
10601
10604
|
}
|
|
10602
10605
|
}
|
|
10603
10606
|
return { sbox: sbox2, sbox2: sbox22, T0, T1, T2, T3, T01, T23 };
|
|
@@ -10606,8 +10609,8 @@ var tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => mul(s, 3) << 24 | s <
|
|
|
10606
10609
|
var tableDecoding = /* @__PURE__ */ genTtable(invSbox, (s) => mul(s, 11) << 24 | mul(s, 13) << 16 | mul(s, 9) << 8 | mul(s, 14));
|
|
10607
10610
|
var xPowers = /* @__PURE__ */ (() => {
|
|
10608
10611
|
const p = new Uint8Array(16);
|
|
10609
|
-
for (let
|
|
10610
|
-
p[
|
|
10612
|
+
for (let i4 = 0, x = 1; i4 < 16; i4++, x = mul2(x))
|
|
10613
|
+
p[i4] = x;
|
|
10611
10614
|
return p;
|
|
10612
10615
|
})();
|
|
10613
10616
|
function expandKeyLE(key) {
|
|
@@ -10623,13 +10626,13 @@ function expandKeyLE(key) {
|
|
|
10623
10626
|
const subByte = (n) => applySbox(sbox2, n, n, n, n);
|
|
10624
10627
|
const xk = new Uint32Array(len + 28);
|
|
10625
10628
|
xk.set(k32);
|
|
10626
|
-
for (let
|
|
10627
|
-
let t = xk[
|
|
10628
|
-
if (
|
|
10629
|
-
t = subByte(rotr32_8(t)) ^ xPowers[
|
|
10630
|
-
else if (Nk > 6 &&
|
|
10629
|
+
for (let i4 = Nk; i4 < xk.length; i4++) {
|
|
10630
|
+
let t = xk[i4 - 1];
|
|
10631
|
+
if (i4 % Nk === 0)
|
|
10632
|
+
t = subByte(rotr32_8(t)) ^ xPowers[i4 / Nk - 1];
|
|
10633
|
+
else if (Nk > 6 && i4 % Nk === 4)
|
|
10631
10634
|
t = subByte(t);
|
|
10632
|
-
xk[
|
|
10635
|
+
xk[i4] = xk[i4 - Nk] ^ t;
|
|
10633
10636
|
}
|
|
10634
10637
|
clean2(...toClean);
|
|
10635
10638
|
return xk;
|
|
@@ -10640,15 +10643,15 @@ function expandKeyDecLE(key) {
|
|
|
10640
10643
|
const Nk = encKey.length;
|
|
10641
10644
|
const { sbox2 } = tableEncoding;
|
|
10642
10645
|
const { T0, T1, T2, T3 } = tableDecoding;
|
|
10643
|
-
for (let
|
|
10646
|
+
for (let i4 = 0; i4 < Nk; i4 += 4) {
|
|
10644
10647
|
for (let j = 0; j < 4; j++)
|
|
10645
|
-
xk[
|
|
10648
|
+
xk[i4 + j] = encKey[Nk - i4 - 4 + j];
|
|
10646
10649
|
}
|
|
10647
10650
|
clean2(encKey);
|
|
10648
|
-
for (let
|
|
10649
|
-
const x = xk[
|
|
10651
|
+
for (let i4 = 4; i4 < Nk - 4; i4++) {
|
|
10652
|
+
const x = xk[i4];
|
|
10650
10653
|
const w = applySbox(sbox2, x, x, x, x);
|
|
10651
|
-
xk[
|
|
10654
|
+
xk[i4] = T0[w & 255] ^ T1[w >>> 8 & 255] ^ T2[w >>> 16 & 255] ^ T3[w >>> 24];
|
|
10652
10655
|
}
|
|
10653
10656
|
return xk;
|
|
10654
10657
|
}
|
|
@@ -10663,7 +10666,7 @@ function encrypt(xk, s0, s1, s2, s3) {
|
|
|
10663
10666
|
let k = 0;
|
|
10664
10667
|
s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
|
|
10665
10668
|
const rounds = xk.length / 4 - 2;
|
|
10666
|
-
for (let
|
|
10669
|
+
for (let i4 = 0; i4 < rounds; i4++) {
|
|
10667
10670
|
const t02 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);
|
|
10668
10671
|
const t12 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);
|
|
10669
10672
|
const t22 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);
|
|
@@ -10681,7 +10684,7 @@ function decrypt(xk, s0, s1, s2, s3) {
|
|
|
10681
10684
|
let k = 0;
|
|
10682
10685
|
s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
|
|
10683
10686
|
const rounds = xk.length / 4 - 2;
|
|
10684
|
-
for (let
|
|
10687
|
+
for (let i4 = 0; i4 < rounds; i4++) {
|
|
10685
10688
|
const t02 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);
|
|
10686
10689
|
const t12 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);
|
|
10687
10690
|
const t22 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);
|
|
@@ -10730,8 +10733,8 @@ function validatePCKS(data, pcks5) {
|
|
|
10730
10733
|
if (lastByte <= 0 || lastByte > 16)
|
|
10731
10734
|
throw new Error("aes/pcks5: wrong padding");
|
|
10732
10735
|
const out = data.subarray(0, -lastByte);
|
|
10733
|
-
for (let
|
|
10734
|
-
if (data[len -
|
|
10736
|
+
for (let i4 = 0; i4 < lastByte; i4++)
|
|
10737
|
+
if (data[len - i4 - 1] !== lastByte)
|
|
10735
10738
|
throw new Error("aes/pcks5: wrong padding");
|
|
10736
10739
|
return out;
|
|
10737
10740
|
}
|
|
@@ -10740,8 +10743,8 @@ function padPCKS(left) {
|
|
|
10740
10743
|
const tmp32 = u32(tmp);
|
|
10741
10744
|
tmp.set(left);
|
|
10742
10745
|
const paddingByte = BLOCK_SIZE - left.length;
|
|
10743
|
-
for (let
|
|
10744
|
-
tmp[
|
|
10746
|
+
for (let i4 = BLOCK_SIZE - paddingByte; i4 < BLOCK_SIZE; i4++)
|
|
10747
|
+
tmp[i4] = paddingByte;
|
|
10745
10748
|
return tmp32;
|
|
10746
10749
|
}
|
|
10747
10750
|
var cbc = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 16 }, function aescbc(key, iv, opts = {}) {
|
|
@@ -10756,17 +10759,17 @@ var cbc = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 16 }, functio
|
|
|
10756
10759
|
toClean.push(_iv = copyBytes2(_iv));
|
|
10757
10760
|
const n32 = u32(_iv);
|
|
10758
10761
|
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
|
10759
|
-
let
|
|
10760
|
-
for (;
|
|
10761
|
-
s0 ^= b[
|
|
10762
|
+
let i4 = 0;
|
|
10763
|
+
for (; i4 + 4 <= b.length; ) {
|
|
10764
|
+
s0 ^= b[i4 + 0], s1 ^= b[i4 + 1], s2 ^= b[i4 + 2], s3 ^= b[i4 + 3];
|
|
10762
10765
|
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
|
10763
|
-
o[
|
|
10766
|
+
o[i4++] = s0, o[i4++] = s1, o[i4++] = s2, o[i4++] = s3;
|
|
10764
10767
|
}
|
|
10765
10768
|
if (pcks5) {
|
|
10766
|
-
const tmp32 = padPCKS(plaintext.subarray(
|
|
10769
|
+
const tmp32 = padPCKS(plaintext.subarray(i4 * 4));
|
|
10767
10770
|
s0 ^= tmp32[0], s1 ^= tmp32[1], s2 ^= tmp32[2], s3 ^= tmp32[3];
|
|
10768
10771
|
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
|
10769
|
-
o[
|
|
10772
|
+
o[i4++] = s0, o[i4++] = s1, o[i4++] = s2, o[i4++] = s3;
|
|
10770
10773
|
}
|
|
10771
10774
|
clean2(...toClean);
|
|
10772
10775
|
return _out;
|
|
@@ -10786,11 +10789,11 @@ var cbc = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 16 }, functio
|
|
|
10786
10789
|
const b = u32(ciphertext);
|
|
10787
10790
|
const o = u32(dst);
|
|
10788
10791
|
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
|
10789
|
-
for (let
|
|
10792
|
+
for (let i4 = 0; i4 + 4 <= b.length; ) {
|
|
10790
10793
|
const ps0 = s0, ps1 = s1, ps2 = s2, ps3 = s3;
|
|
10791
|
-
s0 = b[
|
|
10794
|
+
s0 = b[i4 + 0], s1 = b[i4 + 1], s2 = b[i4 + 2], s3 = b[i4 + 3];
|
|
10792
10795
|
const { s0: o0, s1: o1, s2: o2, s3: o3 } = decrypt(xk, s0, s1, s2, s3);
|
|
10793
|
-
o[
|
|
10796
|
+
o[i4++] = o0 ^ ps0, o[i4++] = o1 ^ ps1, o[i4++] = o2 ^ ps2, o[i4++] = o3 ^ ps3;
|
|
10794
10797
|
}
|
|
10795
10798
|
clean2(...toClean);
|
|
10796
10799
|
return validatePCKS(dst, pcks5);
|
|
@@ -10811,9 +10814,9 @@ function encryptBlock(xk, block2) {
|
|
|
10811
10814
|
}
|
|
10812
10815
|
function dbl(block2) {
|
|
10813
10816
|
let carry = 0;
|
|
10814
|
-
for (let
|
|
10815
|
-
const newCarry = (block2[
|
|
10816
|
-
block2[
|
|
10817
|
+
for (let i4 = BLOCK_SIZE - 1; i4 >= 0; i4--) {
|
|
10818
|
+
const newCarry = (block2[i4] & 128) >>> 7;
|
|
10819
|
+
block2[i4] = block2[i4] << 1 | carry;
|
|
10817
10820
|
carry = newCarry;
|
|
10818
10821
|
}
|
|
10819
10822
|
if (carry) {
|
|
@@ -10824,8 +10827,8 @@ function dbl(block2) {
|
|
|
10824
10827
|
function xorBlock(a, b) {
|
|
10825
10828
|
if (a.length !== b.length)
|
|
10826
10829
|
throw new Error("xorBlock: blocks must have same length");
|
|
10827
|
-
for (let
|
|
10828
|
-
a[
|
|
10830
|
+
for (let i4 = 0; i4 < a.length; i4++) {
|
|
10831
|
+
a[i4] = a[i4] ^ b[i4];
|
|
10829
10832
|
}
|
|
10830
10833
|
return a;
|
|
10831
10834
|
}
|
|
@@ -10883,8 +10886,8 @@ var _CMAC = class {
|
|
|
10883
10886
|
m_last = xorBlock(padded, this.k2);
|
|
10884
10887
|
}
|
|
10885
10888
|
let x = new Uint8Array(BLOCK_SIZE);
|
|
10886
|
-
for (let
|
|
10887
|
-
const m_i = buffer.subarray(
|
|
10889
|
+
for (let i4 = 0; i4 < n - 1; i4++) {
|
|
10890
|
+
const m_i = buffer.subarray(i4 * BLOCK_SIZE, (i4 + 1) * BLOCK_SIZE);
|
|
10888
10891
|
xorBlock(x, m_i);
|
|
10889
10892
|
encryptBlock(this.xk, x);
|
|
10890
10893
|
}
|
|
@@ -13848,211 +13851,1886 @@ function renderSignerStatus(state, signerPubkey) {
|
|
|
13848
13851
|
controls.replaceChildren(devButton, nip07Button, bunkerInput, bunkerButton);
|
|
13849
13852
|
}
|
|
13850
13853
|
|
|
13851
|
-
//
|
|
13852
|
-
var
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
if (!
|
|
13856
|
-
|
|
13854
|
+
// ../../node_modules/.pnpm/nostr-tools@2.23.3_typescript@5.9.3/node_modules/nostr-tools/lib/esm/pool.js
|
|
13855
|
+
var verifiedSymbol3 = /* @__PURE__ */ Symbol("verified");
|
|
13856
|
+
var isRecord3 = (obj) => obj instanceof Object;
|
|
13857
|
+
function validateEvent3(event) {
|
|
13858
|
+
if (!isRecord3(event))
|
|
13859
|
+
return false;
|
|
13860
|
+
if (typeof event.kind !== "number")
|
|
13861
|
+
return false;
|
|
13862
|
+
if (typeof event.content !== "string")
|
|
13863
|
+
return false;
|
|
13864
|
+
if (typeof event.created_at !== "number")
|
|
13865
|
+
return false;
|
|
13866
|
+
if (typeof event.pubkey !== "string")
|
|
13867
|
+
return false;
|
|
13868
|
+
if (!event.pubkey.match(/^[a-f0-9]{64}$/))
|
|
13869
|
+
return false;
|
|
13870
|
+
if (!Array.isArray(event.tags))
|
|
13871
|
+
return false;
|
|
13872
|
+
for (let i22 = 0; i22 < event.tags.length; i22++) {
|
|
13873
|
+
let tag = event.tags[i22];
|
|
13874
|
+
if (!Array.isArray(tag))
|
|
13875
|
+
return false;
|
|
13876
|
+
for (let j = 0; j < tag.length; j++) {
|
|
13877
|
+
if (typeof tag[j] !== "string")
|
|
13878
|
+
return false;
|
|
13879
|
+
}
|
|
13857
13880
|
}
|
|
13858
|
-
return
|
|
13881
|
+
return true;
|
|
13859
13882
|
}
|
|
13860
|
-
|
|
13883
|
+
var utf8Decoder4 = new TextDecoder("utf-8");
|
|
13884
|
+
var utf8Encoder4 = new TextEncoder();
|
|
13885
|
+
function normalizeURL2(url) {
|
|
13861
13886
|
try {
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13887
|
+
if (url.indexOf("://") === -1)
|
|
13888
|
+
url = "wss://" + url;
|
|
13889
|
+
let p = new URL(url);
|
|
13890
|
+
if (p.protocol === "http:")
|
|
13891
|
+
p.protocol = "ws:";
|
|
13892
|
+
else if (p.protocol === "https:")
|
|
13893
|
+
p.protocol = "wss:";
|
|
13894
|
+
p.pathname = p.pathname.replace(/\/+/g, "/");
|
|
13895
|
+
if (p.pathname.endsWith("/"))
|
|
13896
|
+
p.pathname = p.pathname.slice(0, -1);
|
|
13897
|
+
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
|
13898
|
+
p.port = "";
|
|
13899
|
+
p.searchParams.sort();
|
|
13900
|
+
p.hash = "";
|
|
13901
|
+
return p.toString();
|
|
13902
|
+
} catch (e) {
|
|
13903
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
13868
13904
|
}
|
|
13869
13905
|
}
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13906
|
+
var JS3 = class {
|
|
13907
|
+
generateSecretKey() {
|
|
13908
|
+
return schnorr.utils.randomSecretKey();
|
|
13909
|
+
}
|
|
13910
|
+
getPublicKey(secretKey) {
|
|
13911
|
+
return bytesToHex2(schnorr.getPublicKey(secretKey));
|
|
13875
13912
|
}
|
|
13876
|
-
|
|
13913
|
+
finalizeEvent(t, secretKey) {
|
|
13914
|
+
const event = t;
|
|
13915
|
+
event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));
|
|
13916
|
+
event.id = getEventHash3(event);
|
|
13917
|
+
event.sig = bytesToHex2(schnorr.sign(hexToBytes2(getEventHash3(event)), secretKey));
|
|
13918
|
+
event[verifiedSymbol3] = true;
|
|
13919
|
+
return event;
|
|
13920
|
+
}
|
|
13921
|
+
verifyEvent(event) {
|
|
13922
|
+
if (typeof event[verifiedSymbol3] === "boolean")
|
|
13923
|
+
return event[verifiedSymbol3];
|
|
13924
|
+
try {
|
|
13925
|
+
const hash = getEventHash3(event);
|
|
13926
|
+
if (hash !== event.id) {
|
|
13927
|
+
event[verifiedSymbol3] = false;
|
|
13928
|
+
return false;
|
|
13929
|
+
}
|
|
13930
|
+
const valid = schnorr.verify(hexToBytes2(event.sig), hexToBytes2(hash), hexToBytes2(event.pubkey));
|
|
13931
|
+
event[verifiedSymbol3] = valid;
|
|
13932
|
+
return valid;
|
|
13933
|
+
} catch (err) {
|
|
13934
|
+
event[verifiedSymbol3] = false;
|
|
13935
|
+
return false;
|
|
13936
|
+
}
|
|
13937
|
+
}
|
|
13938
|
+
};
|
|
13939
|
+
function serializeEvent3(evt) {
|
|
13940
|
+
if (!validateEvent3(evt))
|
|
13941
|
+
throw new Error("can't serialize event with wrong or missing properties");
|
|
13942
|
+
return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);
|
|
13877
13943
|
}
|
|
13878
|
-
function
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
if (statusEl) statusEl.textContent = status;
|
|
13944
|
+
function getEventHash3(event) {
|
|
13945
|
+
let eventHash = sha256(utf8Encoder4.encode(serializeEvent3(event)));
|
|
13946
|
+
return bytesToHex2(eventHash);
|
|
13882
13947
|
}
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13948
|
+
var i3 = new JS3();
|
|
13949
|
+
var generateSecretKey3 = i3.generateSecretKey;
|
|
13950
|
+
var getPublicKey3 = i3.getPublicKey;
|
|
13951
|
+
var finalizeEvent3 = i3.finalizeEvent;
|
|
13952
|
+
var verifyEvent3 = i3.verifyEvent;
|
|
13953
|
+
var ClientAuth2 = 22242;
|
|
13954
|
+
function matchFilter(filter, event) {
|
|
13955
|
+
if (filter.ids && filter.ids.indexOf(event.id) === -1) {
|
|
13956
|
+
return false;
|
|
13957
|
+
}
|
|
13958
|
+
if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {
|
|
13959
|
+
return false;
|
|
13960
|
+
}
|
|
13961
|
+
if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {
|
|
13962
|
+
return false;
|
|
13963
|
+
}
|
|
13964
|
+
for (let f in filter) {
|
|
13965
|
+
if (f[0] === "#") {
|
|
13966
|
+
let tagName = f.slice(1);
|
|
13967
|
+
let values = filter[`#${tagName}`];
|
|
13968
|
+
if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))
|
|
13969
|
+
return false;
|
|
13970
|
+
}
|
|
13971
|
+
}
|
|
13972
|
+
if (filter.since && event.created_at < filter.since)
|
|
13973
|
+
return false;
|
|
13974
|
+
if (filter.until && event.created_at > filter.until)
|
|
13975
|
+
return false;
|
|
13976
|
+
return true;
|
|
13889
13977
|
}
|
|
13890
|
-
function
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13978
|
+
function matchFilters(filters, event) {
|
|
13979
|
+
for (let i22 = 0; i22 < filters.length; i22++) {
|
|
13980
|
+
if (matchFilter(filters[i22], event)) {
|
|
13981
|
+
return true;
|
|
13982
|
+
}
|
|
13894
13983
|
}
|
|
13895
|
-
|
|
13896
|
-
frame.sandbox.remove("allow-same-origin");
|
|
13897
|
-
return frame;
|
|
13984
|
+
return false;
|
|
13898
13985
|
}
|
|
13899
|
-
function
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13986
|
+
function getHex642(json, field) {
|
|
13987
|
+
let len = field.length + 3;
|
|
13988
|
+
let idx = json.indexOf(`"${field}":`) + len;
|
|
13989
|
+
let s = json.slice(idx).indexOf(`"`) + idx + 1;
|
|
13990
|
+
return json.slice(s, s + 64);
|
|
13991
|
+
}
|
|
13992
|
+
function getSubscriptionId2(json) {
|
|
13993
|
+
let idx = json.slice(0, 22).indexOf(`"EVENT"`);
|
|
13994
|
+
if (idx === -1)
|
|
13995
|
+
return null;
|
|
13996
|
+
let pstart = json.slice(idx + 7 + 1).indexOf(`"`);
|
|
13997
|
+
if (pstart === -1)
|
|
13998
|
+
return null;
|
|
13999
|
+
let start = idx + 7 + 1 + pstart;
|
|
14000
|
+
let pend = json.slice(start + 1, 80).indexOf(`"`);
|
|
14001
|
+
if (pend === -1)
|
|
14002
|
+
return null;
|
|
14003
|
+
let end = start + 1 + pend;
|
|
14004
|
+
return json.slice(start + 1, end);
|
|
13912
14005
|
}
|
|
13913
|
-
function
|
|
14006
|
+
function makeAuthEvent2(relayURL, challenge2) {
|
|
13914
14007
|
return {
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
14008
|
+
kind: ClientAuth2,
|
|
14009
|
+
created_at: Math.floor(Date.now() / 1e3),
|
|
14010
|
+
tags: [
|
|
14011
|
+
["relay", relayURL],
|
|
14012
|
+
["challenge", challenge2]
|
|
14013
|
+
],
|
|
14014
|
+
content: ""
|
|
13918
14015
|
};
|
|
13919
14016
|
}
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
}
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
14017
|
+
var SendingOnClosedConnection = class extends Error {
|
|
14018
|
+
constructor(message, relay) {
|
|
14019
|
+
super(`Tried to send message '${message} on a closed connection to ${relay}.`);
|
|
14020
|
+
this.name = "SendingOnClosedConnection";
|
|
14021
|
+
}
|
|
14022
|
+
};
|
|
14023
|
+
var AbstractRelay = class {
|
|
14024
|
+
url;
|
|
14025
|
+
_connected = false;
|
|
14026
|
+
onclose = null;
|
|
14027
|
+
onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);
|
|
14028
|
+
onauth;
|
|
14029
|
+
baseEoseTimeout = 4400;
|
|
14030
|
+
publishTimeout = 4400;
|
|
14031
|
+
pingFrequency = 29e3;
|
|
14032
|
+
pingTimeout = 2e4;
|
|
14033
|
+
resubscribeBackoff = [1e4, 1e4, 1e4, 2e4, 2e4, 3e4, 6e4];
|
|
14034
|
+
openSubs = /* @__PURE__ */ new Map();
|
|
14035
|
+
enablePing;
|
|
14036
|
+
enableReconnect;
|
|
14037
|
+
idleSince = Date.now();
|
|
14038
|
+
ongoingOperations = 0;
|
|
14039
|
+
reconnectTimeoutHandle;
|
|
14040
|
+
pingIntervalHandle;
|
|
14041
|
+
reconnectAttempts = 0;
|
|
14042
|
+
skipReconnection = false;
|
|
14043
|
+
connectionPromise;
|
|
14044
|
+
openCountRequests = /* @__PURE__ */ new Map();
|
|
14045
|
+
openEventPublishes = /* @__PURE__ */ new Map();
|
|
14046
|
+
ws;
|
|
14047
|
+
challenge;
|
|
14048
|
+
authPromise;
|
|
14049
|
+
serial = 0;
|
|
14050
|
+
verifyEvent;
|
|
14051
|
+
_WebSocket;
|
|
14052
|
+
constructor(url, opts) {
|
|
14053
|
+
this.url = normalizeURL2(url);
|
|
14054
|
+
this.verifyEvent = opts.verifyEvent;
|
|
14055
|
+
this._WebSocket = opts.websocketImplementation || WebSocket;
|
|
14056
|
+
this.enablePing = opts.enablePing;
|
|
14057
|
+
this.enableReconnect = opts.enableReconnect || false;
|
|
14058
|
+
}
|
|
14059
|
+
static async connect(url, opts) {
|
|
14060
|
+
const relay = new AbstractRelay(url, opts);
|
|
14061
|
+
await relay.connect(opts);
|
|
14062
|
+
return relay;
|
|
14063
|
+
}
|
|
14064
|
+
closeAllSubscriptions(reason) {
|
|
14065
|
+
for (let [_, sub] of this.openSubs) {
|
|
14066
|
+
sub.close(reason);
|
|
14067
|
+
}
|
|
14068
|
+
this.openSubs.clear();
|
|
14069
|
+
for (let [_, ep] of this.openEventPublishes) {
|
|
14070
|
+
ep.reject(new Error(reason));
|
|
14071
|
+
}
|
|
14072
|
+
this.openEventPublishes.clear();
|
|
14073
|
+
for (let [_, cr] of this.openCountRequests) {
|
|
14074
|
+
cr.reject(new Error(reason));
|
|
14075
|
+
}
|
|
14076
|
+
this.openCountRequests.clear();
|
|
14077
|
+
}
|
|
14078
|
+
get connected() {
|
|
14079
|
+
return this._connected;
|
|
14080
|
+
}
|
|
14081
|
+
async reconnect() {
|
|
14082
|
+
const backoff = this.resubscribeBackoff[Math.min(this.reconnectAttempts, this.resubscribeBackoff.length - 1)];
|
|
14083
|
+
this.reconnectAttempts++;
|
|
14084
|
+
this.reconnectTimeoutHandle = setTimeout(async () => {
|
|
14085
|
+
try {
|
|
14086
|
+
await this.connect();
|
|
14087
|
+
} catch (err) {
|
|
14088
|
+
}
|
|
14089
|
+
}, backoff);
|
|
14090
|
+
}
|
|
14091
|
+
handleHardClose(reason) {
|
|
14092
|
+
if (this.pingIntervalHandle) {
|
|
14093
|
+
clearInterval(this.pingIntervalHandle);
|
|
14094
|
+
this.pingIntervalHandle = void 0;
|
|
13971
14095
|
}
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
if (
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
}
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
let initReceivedGeneration = -1;
|
|
14002
|
-
const state = {
|
|
14003
|
-
config,
|
|
14004
|
-
capabilities,
|
|
14005
|
-
services,
|
|
14006
|
-
simulation: currentSimulation,
|
|
14007
|
-
signer: signerController.getState(),
|
|
14008
|
-
generation: 0,
|
|
14009
|
-
status: "booting",
|
|
14010
|
-
messageFilter: "",
|
|
14011
|
-
messageLog: [],
|
|
14012
|
-
reload() {
|
|
14013
|
-
if (currentWindowId) {
|
|
14014
|
-
bridge.runtime.destroyWindow(currentWindowId);
|
|
14015
|
-
bridge.runtime.sessionRegistry.unregister(currentWindowId);
|
|
14016
|
-
originRegistry.unregister(currentWindowId);
|
|
14096
|
+
this._connected = false;
|
|
14097
|
+
this.connectionPromise = void 0;
|
|
14098
|
+
this.idleSince = void 0;
|
|
14099
|
+
if (this.enableReconnect && !this.skipReconnection) {
|
|
14100
|
+
this.reconnect();
|
|
14101
|
+
} else {
|
|
14102
|
+
this.onclose?.();
|
|
14103
|
+
this.closeAllSubscriptions(reason);
|
|
14104
|
+
}
|
|
14105
|
+
}
|
|
14106
|
+
async connect(opts) {
|
|
14107
|
+
let connectionTimeoutHandle;
|
|
14108
|
+
if (this.connectionPromise)
|
|
14109
|
+
return this.connectionPromise;
|
|
14110
|
+
this.challenge = void 0;
|
|
14111
|
+
this.authPromise = void 0;
|
|
14112
|
+
this.skipReconnection = false;
|
|
14113
|
+
this.connectionPromise = new Promise((resolve, reject) => {
|
|
14114
|
+
if (opts?.timeout) {
|
|
14115
|
+
connectionTimeoutHandle = setTimeout(() => {
|
|
14116
|
+
reject("connection timed out");
|
|
14117
|
+
this.connectionPromise = void 0;
|
|
14118
|
+
this.skipReconnection = true;
|
|
14119
|
+
this.onclose?.();
|
|
14120
|
+
this.handleHardClose("relay connection timed out");
|
|
14121
|
+
}, opts.timeout);
|
|
14122
|
+
}
|
|
14123
|
+
if (opts?.abort) {
|
|
14124
|
+
opts.abort.onabort = reject;
|
|
14017
14125
|
}
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14126
|
+
try {
|
|
14127
|
+
this.ws = new this._WebSocket(this.url);
|
|
14128
|
+
} catch (err) {
|
|
14129
|
+
clearTimeout(connectionTimeoutHandle);
|
|
14130
|
+
reject(err);
|
|
14131
|
+
return;
|
|
14132
|
+
}
|
|
14133
|
+
this.ws.onopen = () => {
|
|
14134
|
+
if (this.reconnectTimeoutHandle) {
|
|
14135
|
+
clearTimeout(this.reconnectTimeoutHandle);
|
|
14136
|
+
this.reconnectTimeoutHandle = void 0;
|
|
14137
|
+
}
|
|
14138
|
+
clearTimeout(connectionTimeoutHandle);
|
|
14139
|
+
this._connected = true;
|
|
14140
|
+
const isReconnection = this.reconnectAttempts > 0;
|
|
14141
|
+
this.reconnectAttempts = 0;
|
|
14142
|
+
for (const sub of this.openSubs.values()) {
|
|
14143
|
+
sub.eosed = false;
|
|
14144
|
+
if (isReconnection) {
|
|
14145
|
+
for (let f = 0; f < sub.filters.length; f++) {
|
|
14146
|
+
if (sub.lastEmitted) {
|
|
14147
|
+
sub.filters[f].since = sub.lastEmitted + 1;
|
|
14148
|
+
}
|
|
14149
|
+
}
|
|
14150
|
+
}
|
|
14151
|
+
sub.fire();
|
|
14152
|
+
}
|
|
14153
|
+
if (this.enablePing) {
|
|
14154
|
+
this.pingIntervalHandle = setInterval(() => this.pingpong(), this.pingFrequency);
|
|
14029
14155
|
}
|
|
14156
|
+
resolve();
|
|
14030
14157
|
};
|
|
14031
|
-
this.
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14158
|
+
this.ws.onerror = () => {
|
|
14159
|
+
clearTimeout(connectionTimeoutHandle);
|
|
14160
|
+
reject("connection failed");
|
|
14161
|
+
this.connectionPromise = void 0;
|
|
14162
|
+
this.skipReconnection = true;
|
|
14163
|
+
this.onclose?.();
|
|
14164
|
+
this.handleHardClose("relay connection failed");
|
|
14165
|
+
};
|
|
14166
|
+
this.ws.onclose = (ev) => {
|
|
14167
|
+
clearTimeout(connectionTimeoutHandle);
|
|
14168
|
+
reject(ev.message || "websocket closed");
|
|
14169
|
+
this.handleHardClose("relay connection closed");
|
|
14170
|
+
};
|
|
14171
|
+
this.ws.onmessage = this._onmessage.bind(this);
|
|
14172
|
+
});
|
|
14173
|
+
return this.connectionPromise;
|
|
14174
|
+
}
|
|
14175
|
+
waitForPingPong() {
|
|
14176
|
+
return new Promise((resolve) => {
|
|
14177
|
+
;
|
|
14178
|
+
this.ws.once("pong", () => resolve(true));
|
|
14179
|
+
this.ws.ping();
|
|
14180
|
+
});
|
|
14181
|
+
}
|
|
14182
|
+
waitForDummyReq() {
|
|
14183
|
+
return new Promise((resolve, reject) => {
|
|
14184
|
+
if (!this.connectionPromise)
|
|
14185
|
+
return reject(new Error(`no connection to ${this.url}, can't ping`));
|
|
14186
|
+
try {
|
|
14187
|
+
const sub = this.subscribe(
|
|
14188
|
+
[{ ids: ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], limit: 0 }],
|
|
14189
|
+
{
|
|
14190
|
+
label: "<forced-ping>",
|
|
14191
|
+
oneose: () => {
|
|
14192
|
+
resolve(true);
|
|
14193
|
+
sub.close();
|
|
14194
|
+
},
|
|
14195
|
+
onclose() {
|
|
14196
|
+
resolve(true);
|
|
14197
|
+
},
|
|
14198
|
+
eoseTimeout: this.pingTimeout + 1e3
|
|
14199
|
+
}
|
|
14200
|
+
);
|
|
14201
|
+
} catch (err) {
|
|
14202
|
+
reject(err);
|
|
14203
|
+
}
|
|
14204
|
+
});
|
|
14205
|
+
}
|
|
14206
|
+
async pingpong() {
|
|
14207
|
+
if (this.ws?.readyState === 1) {
|
|
14208
|
+
const result = await Promise.any([
|
|
14209
|
+
this.ws && this.ws.ping && this.ws.once ? this.waitForPingPong() : this.waitForDummyReq(),
|
|
14210
|
+
new Promise((res) => setTimeout(() => res(false), this.pingTimeout))
|
|
14211
|
+
]);
|
|
14212
|
+
if (!result) {
|
|
14213
|
+
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
14214
|
+
this.ws?.close();
|
|
14215
|
+
}
|
|
14216
|
+
}
|
|
14217
|
+
}
|
|
14218
|
+
}
|
|
14219
|
+
async send(message) {
|
|
14220
|
+
if (!this.connectionPromise)
|
|
14221
|
+
throw new SendingOnClosedConnection(message, this.url);
|
|
14222
|
+
this.connectionPromise.then(() => {
|
|
14223
|
+
this.ws?.send(message);
|
|
14224
|
+
});
|
|
14225
|
+
}
|
|
14226
|
+
async auth(signAuthEvent) {
|
|
14227
|
+
const challenge2 = this.challenge;
|
|
14228
|
+
if (!challenge2)
|
|
14229
|
+
throw new Error("can't perform auth, no challenge was received");
|
|
14230
|
+
if (this.authPromise)
|
|
14231
|
+
return this.authPromise;
|
|
14232
|
+
this.authPromise = new Promise(async (resolve, reject) => {
|
|
14233
|
+
try {
|
|
14234
|
+
let evt = await signAuthEvent(makeAuthEvent2(this.url, challenge2));
|
|
14235
|
+
let timeout = setTimeout(() => {
|
|
14236
|
+
let ep = this.openEventPublishes.get(evt.id);
|
|
14237
|
+
if (ep) {
|
|
14238
|
+
ep.reject(new Error("auth timed out"));
|
|
14239
|
+
this.openEventPublishes.delete(evt.id);
|
|
14240
|
+
}
|
|
14241
|
+
}, this.publishTimeout);
|
|
14242
|
+
this.openEventPublishes.set(evt.id, { resolve, reject, timeout });
|
|
14243
|
+
this.send('["AUTH",' + JSON.stringify(evt) + "]");
|
|
14244
|
+
} catch (err) {
|
|
14245
|
+
console.warn("subscribe auth function failed:", err);
|
|
14246
|
+
}
|
|
14247
|
+
});
|
|
14248
|
+
return this.authPromise;
|
|
14249
|
+
}
|
|
14250
|
+
async publish(event) {
|
|
14251
|
+
this.idleSince = void 0;
|
|
14252
|
+
this.ongoingOperations++;
|
|
14253
|
+
const ret = new Promise((resolve, reject) => {
|
|
14254
|
+
const timeout = setTimeout(() => {
|
|
14255
|
+
const ep = this.openEventPublishes.get(event.id);
|
|
14256
|
+
if (ep) {
|
|
14257
|
+
ep.reject(new Error("publish timed out"));
|
|
14258
|
+
this.openEventPublishes.delete(event.id);
|
|
14259
|
+
}
|
|
14260
|
+
}, this.publishTimeout);
|
|
14261
|
+
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
14262
|
+
});
|
|
14263
|
+
this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
14264
|
+
this.ongoingOperations--;
|
|
14265
|
+
if (this.ongoingOperations === 0)
|
|
14266
|
+
this.idleSince = Date.now();
|
|
14267
|
+
return ret;
|
|
14268
|
+
}
|
|
14269
|
+
async count(filters, params) {
|
|
14270
|
+
this.serial++;
|
|
14271
|
+
const id = params?.id || "count:" + this.serial;
|
|
14272
|
+
const ret = new Promise((resolve, reject) => {
|
|
14273
|
+
this.openCountRequests.set(id, { resolve, reject });
|
|
14274
|
+
});
|
|
14275
|
+
this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
14276
|
+
return ret;
|
|
14277
|
+
}
|
|
14278
|
+
subscribe(filters, params) {
|
|
14279
|
+
if (params.label !== "<forced-ping>") {
|
|
14280
|
+
this.idleSince = void 0;
|
|
14281
|
+
this.ongoingOperations++;
|
|
14282
|
+
}
|
|
14283
|
+
const sub = this.prepareSubscription(filters, params);
|
|
14284
|
+
sub.fire();
|
|
14285
|
+
if (params.abort) {
|
|
14286
|
+
params.abort.onabort = () => sub.close(String(params.abort.reason || "<aborted>"));
|
|
14287
|
+
}
|
|
14288
|
+
return sub;
|
|
14289
|
+
}
|
|
14290
|
+
prepareSubscription(filters, params) {
|
|
14291
|
+
this.serial++;
|
|
14292
|
+
const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial;
|
|
14293
|
+
const sub = new Subscription(this, id, filters, params);
|
|
14294
|
+
this.openSubs.set(id, sub);
|
|
14295
|
+
return sub;
|
|
14296
|
+
}
|
|
14297
|
+
close() {
|
|
14298
|
+
this.skipReconnection = true;
|
|
14299
|
+
if (this.reconnectTimeoutHandle) {
|
|
14300
|
+
clearTimeout(this.reconnectTimeoutHandle);
|
|
14301
|
+
this.reconnectTimeoutHandle = void 0;
|
|
14302
|
+
}
|
|
14303
|
+
if (this.pingIntervalHandle) {
|
|
14304
|
+
clearInterval(this.pingIntervalHandle);
|
|
14305
|
+
this.pingIntervalHandle = void 0;
|
|
14306
|
+
}
|
|
14307
|
+
this.closeAllSubscriptions("relay connection closed by us");
|
|
14308
|
+
this._connected = false;
|
|
14309
|
+
this.idleSince = void 0;
|
|
14310
|
+
this.onclose?.();
|
|
14311
|
+
if (this.ws?.readyState === this._WebSocket.OPEN) {
|
|
14312
|
+
this.ws?.close();
|
|
14313
|
+
}
|
|
14314
|
+
}
|
|
14315
|
+
_onmessage(ev) {
|
|
14316
|
+
const json = ev.data;
|
|
14317
|
+
if (!json) {
|
|
14318
|
+
return;
|
|
14319
|
+
}
|
|
14320
|
+
const subid = getSubscriptionId2(json);
|
|
14321
|
+
if (subid) {
|
|
14322
|
+
const so = this.openSubs.get(subid);
|
|
14323
|
+
if (!so) {
|
|
14324
|
+
return;
|
|
14325
|
+
}
|
|
14326
|
+
const id = getHex642(json, "id");
|
|
14327
|
+
const alreadyHave = so.alreadyHaveEvent?.(id);
|
|
14328
|
+
so.receivedEvent?.(this, id);
|
|
14329
|
+
if (alreadyHave) {
|
|
14330
|
+
return;
|
|
14331
|
+
}
|
|
14332
|
+
}
|
|
14333
|
+
try {
|
|
14334
|
+
let data = JSON.parse(json);
|
|
14335
|
+
switch (data[0]) {
|
|
14336
|
+
case "EVENT": {
|
|
14337
|
+
const so = this.openSubs.get(data[1]);
|
|
14338
|
+
const event = data[2];
|
|
14339
|
+
if (this.verifyEvent(event) && matchFilters(so.filters, event)) {
|
|
14340
|
+
so.onevent(event);
|
|
14341
|
+
} else {
|
|
14342
|
+
so.oninvalidevent?.(event);
|
|
14343
|
+
}
|
|
14344
|
+
if (!so.lastEmitted || so.lastEmitted < event.created_at)
|
|
14345
|
+
so.lastEmitted = event.created_at;
|
|
14346
|
+
return;
|
|
14347
|
+
}
|
|
14348
|
+
case "COUNT": {
|
|
14349
|
+
const id = data[1];
|
|
14350
|
+
const payload = data[2];
|
|
14351
|
+
const cr = this.openCountRequests.get(id);
|
|
14352
|
+
if (cr) {
|
|
14353
|
+
cr.resolve(payload.count);
|
|
14354
|
+
this.openCountRequests.delete(id);
|
|
14355
|
+
}
|
|
14356
|
+
return;
|
|
14357
|
+
}
|
|
14358
|
+
case "EOSE": {
|
|
14359
|
+
const so = this.openSubs.get(data[1]);
|
|
14360
|
+
if (!so)
|
|
14361
|
+
return;
|
|
14362
|
+
so.receivedEose();
|
|
14363
|
+
return;
|
|
14364
|
+
}
|
|
14365
|
+
case "OK": {
|
|
14366
|
+
const id = data[1];
|
|
14367
|
+
const ok = data[2];
|
|
14368
|
+
const reason = data[3];
|
|
14369
|
+
const ep = this.openEventPublishes.get(id);
|
|
14370
|
+
if (ep) {
|
|
14371
|
+
clearTimeout(ep.timeout);
|
|
14372
|
+
if (ok)
|
|
14373
|
+
ep.resolve(reason);
|
|
14374
|
+
else
|
|
14375
|
+
ep.reject(new Error(reason));
|
|
14376
|
+
this.openEventPublishes.delete(id);
|
|
14377
|
+
}
|
|
14378
|
+
return;
|
|
14379
|
+
}
|
|
14380
|
+
case "CLOSED": {
|
|
14381
|
+
const id = data[1];
|
|
14382
|
+
const so = this.openSubs.get(id);
|
|
14383
|
+
if (!so)
|
|
14384
|
+
return;
|
|
14385
|
+
so.closed = true;
|
|
14386
|
+
so.close(data[2]);
|
|
14387
|
+
return;
|
|
14388
|
+
}
|
|
14389
|
+
case "NOTICE": {
|
|
14390
|
+
this.onnotice(data[1]);
|
|
14391
|
+
return;
|
|
14392
|
+
}
|
|
14393
|
+
case "AUTH": {
|
|
14394
|
+
this.challenge = data[1];
|
|
14395
|
+
if (this.onauth) {
|
|
14396
|
+
this.auth(this.onauth);
|
|
14397
|
+
}
|
|
14398
|
+
return;
|
|
14399
|
+
}
|
|
14400
|
+
default: {
|
|
14401
|
+
const so = this.openSubs.get(data[1]);
|
|
14402
|
+
so?.oncustom?.(data);
|
|
14403
|
+
return;
|
|
14404
|
+
}
|
|
14405
|
+
}
|
|
14406
|
+
} catch (err) {
|
|
14407
|
+
try {
|
|
14408
|
+
const [_, __, event] = JSON.parse(json);
|
|
14409
|
+
console.warn(`[nostr] relay ${this.url} error processing message:`, err, event);
|
|
14410
|
+
} catch (_) {
|
|
14411
|
+
console.warn(`[nostr] relay ${this.url} error processing message:`, err);
|
|
14412
|
+
}
|
|
14413
|
+
return;
|
|
14414
|
+
}
|
|
14415
|
+
}
|
|
14416
|
+
};
|
|
14417
|
+
var Subscription = class {
|
|
14418
|
+
relay;
|
|
14419
|
+
id;
|
|
14420
|
+
lastEmitted;
|
|
14421
|
+
closed = false;
|
|
14422
|
+
eosed = false;
|
|
14423
|
+
filters;
|
|
14424
|
+
alreadyHaveEvent;
|
|
14425
|
+
receivedEvent;
|
|
14426
|
+
onevent;
|
|
14427
|
+
oninvalidevent;
|
|
14428
|
+
oneose;
|
|
14429
|
+
onclose;
|
|
14430
|
+
oncustom;
|
|
14431
|
+
eoseTimeout;
|
|
14432
|
+
eoseTimeoutHandle;
|
|
14433
|
+
constructor(relay, id, filters, params) {
|
|
14434
|
+
if (filters.length === 0)
|
|
14435
|
+
throw new Error("subscription can't be created with zero filters");
|
|
14436
|
+
this.relay = relay;
|
|
14437
|
+
this.filters = filters;
|
|
14438
|
+
this.id = id;
|
|
14439
|
+
this.alreadyHaveEvent = params.alreadyHaveEvent;
|
|
14440
|
+
this.receivedEvent = params.receivedEvent;
|
|
14441
|
+
this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;
|
|
14442
|
+
this.oneose = params.oneose;
|
|
14443
|
+
this.onclose = params.onclose;
|
|
14444
|
+
this.oninvalidevent = params.oninvalidevent;
|
|
14445
|
+
this.onevent = params.onevent || ((event) => {
|
|
14446
|
+
console.warn(
|
|
14447
|
+
`onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,
|
|
14448
|
+
event
|
|
14449
|
+
);
|
|
14450
|
+
});
|
|
14451
|
+
}
|
|
14452
|
+
fire() {
|
|
14453
|
+
this.relay.send('["REQ","' + this.id + '",' + JSON.stringify(this.filters).substring(1));
|
|
14454
|
+
this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);
|
|
14455
|
+
}
|
|
14456
|
+
receivedEose() {
|
|
14457
|
+
if (this.eosed)
|
|
14458
|
+
return;
|
|
14459
|
+
clearTimeout(this.eoseTimeoutHandle);
|
|
14460
|
+
this.eosed = true;
|
|
14461
|
+
this.oneose?.();
|
|
14462
|
+
}
|
|
14463
|
+
close(reason = "closed by caller") {
|
|
14464
|
+
if (!this.closed && this.relay.connected) {
|
|
14465
|
+
try {
|
|
14466
|
+
this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]");
|
|
14467
|
+
} catch (err) {
|
|
14468
|
+
if (err instanceof SendingOnClosedConnection) {
|
|
14469
|
+
} else {
|
|
14470
|
+
throw err;
|
|
14471
|
+
}
|
|
14472
|
+
}
|
|
14473
|
+
this.closed = true;
|
|
14474
|
+
}
|
|
14475
|
+
this.relay.openSubs.delete(this.id);
|
|
14476
|
+
this.relay.ongoingOperations--;
|
|
14477
|
+
if (this.relay.ongoingOperations === 0)
|
|
14478
|
+
this.relay.idleSince = Date.now();
|
|
14479
|
+
this.onclose?.(reason);
|
|
14480
|
+
}
|
|
14481
|
+
};
|
|
14482
|
+
var alwaysTrue = (t) => {
|
|
14483
|
+
t[verifiedSymbol3] = true;
|
|
14484
|
+
return true;
|
|
14485
|
+
};
|
|
14486
|
+
var AbstractSimplePool = class {
|
|
14487
|
+
relays = /* @__PURE__ */ new Map();
|
|
14488
|
+
seenOn = /* @__PURE__ */ new Map();
|
|
14489
|
+
trackRelays = false;
|
|
14490
|
+
verifyEvent;
|
|
14491
|
+
enablePing;
|
|
14492
|
+
enableReconnect;
|
|
14493
|
+
automaticallyAuth;
|
|
14494
|
+
trustedRelayURLs = /* @__PURE__ */ new Set();
|
|
14495
|
+
onRelayConnectionFailure;
|
|
14496
|
+
onRelayConnectionSuccess;
|
|
14497
|
+
allowConnectingToRelay;
|
|
14498
|
+
maxWaitForConnection;
|
|
14499
|
+
_WebSocket;
|
|
14500
|
+
constructor(opts) {
|
|
14501
|
+
this.verifyEvent = opts.verifyEvent;
|
|
14502
|
+
this._WebSocket = opts.websocketImplementation;
|
|
14503
|
+
this.enablePing = opts.enablePing;
|
|
14504
|
+
this.enableReconnect = opts.enableReconnect || false;
|
|
14505
|
+
this.automaticallyAuth = opts.automaticallyAuth;
|
|
14506
|
+
this.onRelayConnectionFailure = opts.onRelayConnectionFailure;
|
|
14507
|
+
this.onRelayConnectionSuccess = opts.onRelayConnectionSuccess;
|
|
14508
|
+
this.allowConnectingToRelay = opts.allowConnectingToRelay;
|
|
14509
|
+
this.maxWaitForConnection = opts.maxWaitForConnection || 3e3;
|
|
14510
|
+
}
|
|
14511
|
+
async ensureRelay(url, params) {
|
|
14512
|
+
url = normalizeURL2(url);
|
|
14513
|
+
let relay = this.relays.get(url);
|
|
14514
|
+
if (!relay) {
|
|
14515
|
+
relay = new AbstractRelay(url, {
|
|
14516
|
+
verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,
|
|
14517
|
+
websocketImplementation: this._WebSocket,
|
|
14518
|
+
enablePing: this.enablePing,
|
|
14519
|
+
enableReconnect: this.enableReconnect
|
|
14520
|
+
});
|
|
14521
|
+
relay.onclose = () => {
|
|
14522
|
+
this.relays.delete(url);
|
|
14523
|
+
};
|
|
14524
|
+
this.relays.set(url, relay);
|
|
14525
|
+
}
|
|
14526
|
+
if (this.automaticallyAuth) {
|
|
14527
|
+
const authSignerFn = this.automaticallyAuth(url);
|
|
14528
|
+
if (authSignerFn) {
|
|
14529
|
+
relay.onauth = authSignerFn;
|
|
14530
|
+
}
|
|
14531
|
+
}
|
|
14532
|
+
try {
|
|
14533
|
+
await relay.connect({
|
|
14534
|
+
timeout: params?.connectionTimeout,
|
|
14535
|
+
abort: params?.abort
|
|
14536
|
+
});
|
|
14537
|
+
} catch (err) {
|
|
14538
|
+
this.relays.delete(url);
|
|
14539
|
+
throw err;
|
|
14540
|
+
}
|
|
14541
|
+
return relay;
|
|
14542
|
+
}
|
|
14543
|
+
close(relays) {
|
|
14544
|
+
relays.map(normalizeURL2).forEach((url) => {
|
|
14545
|
+
this.relays.get(url)?.close();
|
|
14546
|
+
this.relays.delete(url);
|
|
14547
|
+
});
|
|
14548
|
+
}
|
|
14549
|
+
subscribe(relays, filter, params) {
|
|
14550
|
+
const request = [];
|
|
14551
|
+
const uniqUrls = [];
|
|
14552
|
+
for (let i22 = 0; i22 < relays.length; i22++) {
|
|
14553
|
+
const url = normalizeURL2(relays[i22]);
|
|
14554
|
+
if (!request.find((r) => r.url === url)) {
|
|
14555
|
+
if (uniqUrls.indexOf(url) === -1) {
|
|
14556
|
+
uniqUrls.push(url);
|
|
14557
|
+
request.push({ url, filter });
|
|
14558
|
+
}
|
|
14559
|
+
}
|
|
14560
|
+
}
|
|
14561
|
+
return this.subscribeMap(request, params);
|
|
14562
|
+
}
|
|
14563
|
+
subscribeMany(relays, filter, params) {
|
|
14564
|
+
return this.subscribe(relays, filter, params);
|
|
14565
|
+
}
|
|
14566
|
+
subscribeMap(requests, params) {
|
|
14567
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
14568
|
+
for (const req of requests) {
|
|
14569
|
+
const { url, filter } = req;
|
|
14570
|
+
if (!grouped.has(url))
|
|
14571
|
+
grouped.set(url, []);
|
|
14572
|
+
grouped.get(url).push(filter);
|
|
14573
|
+
}
|
|
14574
|
+
const groupedRequests = Array.from(grouped.entries()).map(([url, filters]) => ({ url, filters }));
|
|
14575
|
+
if (this.trackRelays) {
|
|
14576
|
+
params.receivedEvent = (relay, id) => {
|
|
14577
|
+
let set = this.seenOn.get(id);
|
|
14578
|
+
if (!set) {
|
|
14579
|
+
set = /* @__PURE__ */ new Set();
|
|
14580
|
+
this.seenOn.set(id, set);
|
|
14581
|
+
}
|
|
14582
|
+
set.add(relay);
|
|
14583
|
+
};
|
|
14584
|
+
}
|
|
14585
|
+
const _knownIds = /* @__PURE__ */ new Set();
|
|
14586
|
+
const subs = [];
|
|
14587
|
+
const eosesReceived = [];
|
|
14588
|
+
let handleEose = (i22) => {
|
|
14589
|
+
if (eosesReceived[i22])
|
|
14590
|
+
return;
|
|
14591
|
+
eosesReceived[i22] = true;
|
|
14592
|
+
if (eosesReceived.filter((a) => a).length === groupedRequests.length) {
|
|
14593
|
+
params.oneose?.();
|
|
14594
|
+
handleEose = () => {
|
|
14595
|
+
};
|
|
14596
|
+
}
|
|
14597
|
+
};
|
|
14598
|
+
const closesReceived = [];
|
|
14599
|
+
let handleClose = (i22, reason) => {
|
|
14600
|
+
if (closesReceived[i22])
|
|
14601
|
+
return;
|
|
14602
|
+
handleEose(i22);
|
|
14603
|
+
closesReceived[i22] = reason;
|
|
14604
|
+
if (closesReceived.filter((a) => a).length === groupedRequests.length) {
|
|
14605
|
+
params.onclose?.(closesReceived);
|
|
14606
|
+
handleClose = () => {
|
|
14607
|
+
};
|
|
14608
|
+
}
|
|
14609
|
+
};
|
|
14610
|
+
const localAlreadyHaveEventHandler = (id) => {
|
|
14611
|
+
if (params.alreadyHaveEvent?.(id)) {
|
|
14612
|
+
return true;
|
|
14613
|
+
}
|
|
14614
|
+
const have = _knownIds.has(id);
|
|
14615
|
+
_knownIds.add(id);
|
|
14616
|
+
return have;
|
|
14617
|
+
};
|
|
14618
|
+
const allOpened = Promise.all(
|
|
14619
|
+
groupedRequests.map(async ({ url, filters }, i22) => {
|
|
14620
|
+
if (this.allowConnectingToRelay?.(url, ["read", filters]) === false) {
|
|
14621
|
+
handleClose(i22, "connection skipped by allowConnectingToRelay");
|
|
14622
|
+
return;
|
|
14623
|
+
}
|
|
14624
|
+
let relay;
|
|
14625
|
+
try {
|
|
14626
|
+
relay = await this.ensureRelay(url, {
|
|
14627
|
+
connectionTimeout: this.maxWaitForConnection < (params.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
14628
|
+
abort: params.abort
|
|
14629
|
+
});
|
|
14630
|
+
} catch (err) {
|
|
14631
|
+
this.onRelayConnectionFailure?.(url);
|
|
14632
|
+
handleClose(i22, err?.message || String(err));
|
|
14633
|
+
return;
|
|
14634
|
+
}
|
|
14635
|
+
this.onRelayConnectionSuccess?.(url);
|
|
14636
|
+
let subscription = relay.subscribe(filters, {
|
|
14637
|
+
...params,
|
|
14638
|
+
oneose: () => handleEose(i22),
|
|
14639
|
+
onclose: (reason) => {
|
|
14640
|
+
if (reason.startsWith("auth-required: ") && params.onauth) {
|
|
14641
|
+
relay.auth(params.onauth).then(() => {
|
|
14642
|
+
relay.subscribe(filters, {
|
|
14643
|
+
...params,
|
|
14644
|
+
oneose: () => handleEose(i22),
|
|
14645
|
+
onclose: (reason2) => {
|
|
14646
|
+
handleClose(i22, reason2);
|
|
14647
|
+
},
|
|
14648
|
+
alreadyHaveEvent: localAlreadyHaveEventHandler,
|
|
14649
|
+
eoseTimeout: params.maxWait,
|
|
14650
|
+
abort: params.abort
|
|
14651
|
+
});
|
|
14652
|
+
}).catch((err) => {
|
|
14653
|
+
handleClose(i22, `auth was required and attempted, but failed with: ${err}`);
|
|
14654
|
+
});
|
|
14655
|
+
} else {
|
|
14656
|
+
handleClose(i22, reason);
|
|
14657
|
+
}
|
|
14658
|
+
},
|
|
14659
|
+
alreadyHaveEvent: localAlreadyHaveEventHandler,
|
|
14660
|
+
eoseTimeout: params.maxWait,
|
|
14661
|
+
abort: params.abort
|
|
14662
|
+
});
|
|
14663
|
+
subs.push(subscription);
|
|
14664
|
+
})
|
|
14665
|
+
);
|
|
14666
|
+
return {
|
|
14667
|
+
async close(reason) {
|
|
14668
|
+
await allOpened;
|
|
14669
|
+
subs.forEach((sub) => {
|
|
14670
|
+
sub.close(reason);
|
|
14671
|
+
});
|
|
14672
|
+
}
|
|
14673
|
+
};
|
|
14674
|
+
}
|
|
14675
|
+
subscribeEose(relays, filter, params) {
|
|
14676
|
+
let subcloser;
|
|
14677
|
+
subcloser = this.subscribe(relays, filter, {
|
|
14678
|
+
...params,
|
|
14679
|
+
oneose() {
|
|
14680
|
+
const reason = "closed automatically on eose";
|
|
14681
|
+
if (subcloser)
|
|
14682
|
+
subcloser.close(reason);
|
|
14683
|
+
else
|
|
14684
|
+
params.onclose?.(relays.map((_) => reason));
|
|
14685
|
+
}
|
|
14686
|
+
});
|
|
14687
|
+
return subcloser;
|
|
14688
|
+
}
|
|
14689
|
+
subscribeManyEose(relays, filter, params) {
|
|
14690
|
+
return this.subscribeEose(relays, filter, params);
|
|
14691
|
+
}
|
|
14692
|
+
async querySync(relays, filter, params) {
|
|
14693
|
+
return new Promise(async (resolve) => {
|
|
14694
|
+
const events = [];
|
|
14695
|
+
this.subscribeEose(relays, filter, {
|
|
14696
|
+
...params,
|
|
14697
|
+
onevent(event) {
|
|
14698
|
+
events.push(event);
|
|
14699
|
+
},
|
|
14700
|
+
onclose(_) {
|
|
14701
|
+
resolve(events);
|
|
14702
|
+
}
|
|
14703
|
+
});
|
|
14704
|
+
});
|
|
14705
|
+
}
|
|
14706
|
+
async get(relays, filter, params) {
|
|
14707
|
+
filter.limit = 1;
|
|
14708
|
+
const events = await this.querySync(relays, filter, params);
|
|
14709
|
+
events.sort((a, b) => b.created_at - a.created_at);
|
|
14710
|
+
return events[0] || null;
|
|
14711
|
+
}
|
|
14712
|
+
publish(relays, event, params) {
|
|
14713
|
+
return relays.map(normalizeURL2).map(async (url, i22, arr) => {
|
|
14714
|
+
if (arr.indexOf(url) !== i22) {
|
|
14715
|
+
return Promise.reject("duplicate url");
|
|
14716
|
+
}
|
|
14717
|
+
if (this.allowConnectingToRelay?.(url, ["write", event]) === false) {
|
|
14718
|
+
return Promise.reject("connection skipped by allowConnectingToRelay");
|
|
14719
|
+
}
|
|
14720
|
+
let r;
|
|
14721
|
+
try {
|
|
14722
|
+
r = await this.ensureRelay(url, {
|
|
14723
|
+
connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
14724
|
+
abort: params?.abort
|
|
14725
|
+
});
|
|
14726
|
+
} catch (err) {
|
|
14727
|
+
this.onRelayConnectionFailure?.(url);
|
|
14728
|
+
return String("connection failure: " + String(err));
|
|
14729
|
+
}
|
|
14730
|
+
return r.publish(event).catch(async (err) => {
|
|
14731
|
+
if (err instanceof Error && err.message.startsWith("auth-required: ") && params?.onauth) {
|
|
14732
|
+
await r.auth(params.onauth);
|
|
14733
|
+
return r.publish(event);
|
|
14734
|
+
}
|
|
14735
|
+
throw err;
|
|
14736
|
+
}).then((reason) => {
|
|
14737
|
+
if (this.trackRelays) {
|
|
14738
|
+
let set = this.seenOn.get(event.id);
|
|
14739
|
+
if (!set) {
|
|
14740
|
+
set = /* @__PURE__ */ new Set();
|
|
14741
|
+
this.seenOn.set(event.id, set);
|
|
14742
|
+
}
|
|
14743
|
+
set.add(r);
|
|
14744
|
+
}
|
|
14745
|
+
return reason;
|
|
14746
|
+
});
|
|
14747
|
+
});
|
|
14748
|
+
}
|
|
14749
|
+
listConnectionStatus() {
|
|
14750
|
+
const map = /* @__PURE__ */ new Map();
|
|
14751
|
+
this.relays.forEach((relay, url) => map.set(url, relay.connected));
|
|
14752
|
+
return map;
|
|
14753
|
+
}
|
|
14754
|
+
destroy() {
|
|
14755
|
+
this.relays.forEach((conn) => conn.close());
|
|
14756
|
+
this.relays = /* @__PURE__ */ new Map();
|
|
14757
|
+
}
|
|
14758
|
+
pruneIdleRelays(idleThresholdMs = 1e4) {
|
|
14759
|
+
const prunedUrls = [];
|
|
14760
|
+
for (const [url, relay] of this.relays) {
|
|
14761
|
+
if (relay.idleSince && Date.now() - relay.idleSince >= idleThresholdMs) {
|
|
14762
|
+
this.relays.delete(url);
|
|
14763
|
+
prunedUrls.push(url);
|
|
14764
|
+
relay.close();
|
|
14765
|
+
}
|
|
14766
|
+
}
|
|
14767
|
+
return prunedUrls;
|
|
14768
|
+
}
|
|
14769
|
+
};
|
|
14770
|
+
var _WebSocket3;
|
|
14771
|
+
try {
|
|
14772
|
+
_WebSocket3 = WebSocket;
|
|
14773
|
+
} catch {
|
|
14774
|
+
}
|
|
14775
|
+
var SimplePool = class extends AbstractSimplePool {
|
|
14776
|
+
constructor(options) {
|
|
14777
|
+
super({ verifyEvent: verifyEvent3, websocketImplementation: _WebSocket3, maxWaitForConnection: 3e3, ...options });
|
|
14778
|
+
}
|
|
14779
|
+
};
|
|
14780
|
+
|
|
14781
|
+
// ../nip/dist/chunk-2J3CSGKL.js
|
|
14782
|
+
function computeAggregateHash(entries) {
|
|
14783
|
+
const lines = entries.map((entry) => `${entry.sha256} ${entry.path}
|
|
14784
|
+
`);
|
|
14785
|
+
lines.sort();
|
|
14786
|
+
return bytesToHex2(sha256(new TextEncoder().encode(lines.join(""))));
|
|
14787
|
+
}
|
|
14788
|
+
function pathEntriesFromTags(tags) {
|
|
14789
|
+
const entries = [];
|
|
14790
|
+
for (const tag of tags) {
|
|
14791
|
+
if (tag[0] === "path" && typeof tag[1] === "string" && typeof tag[2] === "string" && tag[1].length > 0 && tag[2].length > 0) {
|
|
14792
|
+
entries.push({ path: tag[1], sha256: tag[2] });
|
|
14793
|
+
}
|
|
14794
|
+
}
|
|
14795
|
+
return entries;
|
|
14796
|
+
}
|
|
14797
|
+
function aggregateTagValue(tags) {
|
|
14798
|
+
for (const tag of tags) {
|
|
14799
|
+
if (tag[0] === "x" && tag[2] === "aggregate" && typeof tag[1] === "string" && tag[1].length > 0) {
|
|
14800
|
+
return tag[1];
|
|
14801
|
+
}
|
|
14802
|
+
}
|
|
14803
|
+
return void 0;
|
|
14804
|
+
}
|
|
14805
|
+
|
|
14806
|
+
// ../nip/dist/chunk-CDBUCFLP.js
|
|
14807
|
+
var MIB = 1024 * 1024;
|
|
14808
|
+
var NAPPLET_ARTIFACT_CACHE_NAME = "kehto:napplet-artifacts:v1";
|
|
14809
|
+
var SCHEMA_VERSION = 1;
|
|
14810
|
+
var DEFAULT_BASE_URL = "https://kehto.invalid";
|
|
14811
|
+
var DEFAULT_UNKNOWN_BUDGET_BYTES = 32 * MIB;
|
|
14812
|
+
var DEFAULT_SOFT_CEILING_BYTES = 128 * MIB;
|
|
14813
|
+
var DEFAULT_HARD_CEILING_BYTES = 256 * MIB;
|
|
14814
|
+
var DEFAULT_FOREGROUND_TTL_MS = 15 * 60 * 1e3;
|
|
14815
|
+
var DEFAULT_BACKGROUND_TTL_MS = 60 * 60 * 1e3;
|
|
14816
|
+
function emptyIndex(now2) {
|
|
14817
|
+
return {
|
|
14818
|
+
schemaVersion: SCHEMA_VERSION,
|
|
14819
|
+
updatedAt: now2,
|
|
14820
|
+
blobs: {},
|
|
14821
|
+
aggregates: {},
|
|
14822
|
+
coordinates: {}
|
|
14823
|
+
};
|
|
14824
|
+
}
|
|
14825
|
+
function aggregateKey(dTag, aggregateHash) {
|
|
14826
|
+
return `${encodeURIComponent(dTag)}:${aggregateHash}`;
|
|
14827
|
+
}
|
|
14828
|
+
function coordinateKey(kind, pubkey, dTag) {
|
|
14829
|
+
return `${kind}:${pubkey}:${encodeURIComponent(dTag)}`;
|
|
14830
|
+
}
|
|
14831
|
+
function isCoordinateFresh(coordinate, options = {}) {
|
|
14832
|
+
const now2 = options.now ?? Date.now();
|
|
14833
|
+
const ttl = options.background ? coordinate.backgroundTtlMs : coordinate.foregroundTtlMs;
|
|
14834
|
+
return ttl === Number.POSITIVE_INFINITY || now2 - coordinate.lastResolvedAt <= ttl;
|
|
14835
|
+
}
|
|
14836
|
+
function byteLength2(bytes) {
|
|
14837
|
+
return bytes.byteLength;
|
|
14838
|
+
}
|
|
14839
|
+
function encodeKeyPart(value) {
|
|
14840
|
+
return encodeURIComponent(value).replaceAll("%2F", "%252F");
|
|
14841
|
+
}
|
|
14842
|
+
function cloneBytes(bytes) {
|
|
14843
|
+
return new Uint8Array(bytes);
|
|
14844
|
+
}
|
|
14845
|
+
function responseBody(bytes) {
|
|
14846
|
+
return cloneBytes(bytes).buffer;
|
|
14847
|
+
}
|
|
14848
|
+
function normalizeBaseUrl(baseUrl) {
|
|
14849
|
+
return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
14850
|
+
}
|
|
14851
|
+
function resolveBaseUrl(baseUrl) {
|
|
14852
|
+
if (baseUrl) return normalizeBaseUrl(baseUrl);
|
|
14853
|
+
const maybeLocation = globalThis;
|
|
14854
|
+
if (maybeLocation.location?.origin) return normalizeBaseUrl(maybeLocation.location.origin);
|
|
14855
|
+
return normalizeBaseUrl(DEFAULT_BASE_URL);
|
|
14856
|
+
}
|
|
14857
|
+
async function responseBytes(response) {
|
|
14858
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
14859
|
+
}
|
|
14860
|
+
async function responseJson(response) {
|
|
14861
|
+
return response.json();
|
|
14862
|
+
}
|
|
14863
|
+
function refCounts(index) {
|
|
14864
|
+
const counts = {};
|
|
14865
|
+
for (const aggregate of Object.values(index.aggregates)) {
|
|
14866
|
+
for (const hash of aggregate.blobHashes) counts[hash] = (counts[hash] ?? 0) + 1;
|
|
14867
|
+
}
|
|
14868
|
+
return counts;
|
|
14869
|
+
}
|
|
14870
|
+
function cachedSize(index) {
|
|
14871
|
+
const blobBytes = Object.values(index.blobs).reduce((sum, entry) => sum + entry.size, 0);
|
|
14872
|
+
const aggregateBytes = Object.values(index.aggregates).reduce((sum, entry) => sum + entry.size, 0);
|
|
14873
|
+
return blobBytes + aggregateBytes;
|
|
14874
|
+
}
|
|
14875
|
+
var CacheStorageNappletArtifactCache = class {
|
|
14876
|
+
cacheStorage;
|
|
14877
|
+
storage;
|
|
14878
|
+
cacheName;
|
|
14879
|
+
baseUrl;
|
|
14880
|
+
now;
|
|
14881
|
+
activeAggregates = /* @__PURE__ */ new Set();
|
|
14882
|
+
onDiagnostic;
|
|
14883
|
+
unknownBudgetBytes;
|
|
14884
|
+
softCeilingBytes;
|
|
14885
|
+
hardCeilingBytes;
|
|
14886
|
+
cachePromise;
|
|
14887
|
+
constructor(options = {}) {
|
|
14888
|
+
const maybeCacheStorage = options.cacheStorage ?? globalThis.caches;
|
|
14889
|
+
if (!maybeCacheStorage) {
|
|
14890
|
+
throw new Error("Cache Storage is unavailable");
|
|
14891
|
+
}
|
|
14892
|
+
this.cacheStorage = maybeCacheStorage;
|
|
14893
|
+
this.storage = options.storage ?? globalThis.navigator?.storage;
|
|
14894
|
+
this.cacheName = options.cacheName ?? NAPPLET_ARTIFACT_CACHE_NAME;
|
|
14895
|
+
this.baseUrl = resolveBaseUrl(options.baseUrl);
|
|
14896
|
+
this.now = options.now ?? Date.now;
|
|
14897
|
+
this.onDiagnostic = options.onDiagnostic;
|
|
14898
|
+
this.unknownBudgetBytes = options.unknownBudgetBytes ?? DEFAULT_UNKNOWN_BUDGET_BYTES;
|
|
14899
|
+
this.softCeilingBytes = options.softCeilingBytes ?? DEFAULT_SOFT_CEILING_BYTES;
|
|
14900
|
+
this.hardCeilingBytes = options.hardCeilingBytes ?? DEFAULT_HARD_CEILING_BYTES;
|
|
14901
|
+
}
|
|
14902
|
+
async readBlob(sha256Hex) {
|
|
14903
|
+
try {
|
|
14904
|
+
const cache2 = await this.open();
|
|
14905
|
+
const response = await cache2.match(this.blobUrl(sha256Hex));
|
|
14906
|
+
if (!response) return void 0;
|
|
14907
|
+
const bytes = await responseBytes(response);
|
|
14908
|
+
const index = await this.readIndex(cache2);
|
|
14909
|
+
const entry = index.blobs[sha256Hex];
|
|
14910
|
+
if (entry) {
|
|
14911
|
+
entry.lastAccessed = this.now();
|
|
14912
|
+
index.updatedAt = entry.lastAccessed;
|
|
14913
|
+
await this.writeIndex(cache2, index);
|
|
14914
|
+
}
|
|
14915
|
+
return bytes;
|
|
14916
|
+
} catch (cause) {
|
|
14917
|
+
this.diagnostic({ type: "cache-read-failed", message: `failed to read blob ${sha256Hex}`, cause });
|
|
14918
|
+
return void 0;
|
|
14919
|
+
}
|
|
14920
|
+
}
|
|
14921
|
+
async deleteBlob(sha256Hex) {
|
|
14922
|
+
try {
|
|
14923
|
+
const cache2 = await this.open();
|
|
14924
|
+
await cache2.delete(this.blobUrl(sha256Hex));
|
|
14925
|
+
const index = await this.readIndex(cache2);
|
|
14926
|
+
delete index.blobs[sha256Hex];
|
|
14927
|
+
index.updatedAt = this.now();
|
|
14928
|
+
await this.writeIndex(cache2, index);
|
|
14929
|
+
} catch (cause) {
|
|
14930
|
+
this.diagnostic({ type: "cache-delete-failed", message: `failed to delete blob ${sha256Hex}`, cause });
|
|
14931
|
+
}
|
|
14932
|
+
}
|
|
14933
|
+
async writeVerifiedResolution(input) {
|
|
14934
|
+
try {
|
|
14935
|
+
await this.writeVerifiedResolutionOnce(input);
|
|
14936
|
+
} catch (firstCause) {
|
|
14937
|
+
try {
|
|
14938
|
+
await this.prune(input.now ?? this.now());
|
|
14939
|
+
await this.writeVerifiedResolutionOnce(input);
|
|
14940
|
+
} catch (cause) {
|
|
14941
|
+
this.diagnostic({
|
|
14942
|
+
type: "cache-write-failed",
|
|
14943
|
+
message: "failed to write verified napplet artifacts after prune retry",
|
|
14944
|
+
cause: cause ?? firstCause
|
|
14945
|
+
});
|
|
14946
|
+
}
|
|
14947
|
+
}
|
|
14948
|
+
}
|
|
14949
|
+
async writeCoordinate(input) {
|
|
14950
|
+
const cache2 = await this.open();
|
|
14951
|
+
const now2 = this.now();
|
|
14952
|
+
const index = await this.readIndex(cache2);
|
|
14953
|
+
const key = coordinateKey(input.kind, input.pubkey, input.dTag);
|
|
14954
|
+
index.coordinates[key] = {
|
|
14955
|
+
key,
|
|
14956
|
+
kind: input.kind,
|
|
14957
|
+
pubkey: input.pubkey,
|
|
14958
|
+
dTag: input.dTag,
|
|
14959
|
+
aggregateHash: input.aggregateHash,
|
|
14960
|
+
lastResolvedAt: input.lastResolvedAt ?? now2,
|
|
14961
|
+
foregroundTtlMs: input.foregroundTtlMs ?? DEFAULT_FOREGROUND_TTL_MS,
|
|
14962
|
+
backgroundTtlMs: input.backgroundTtlMs ?? DEFAULT_BACKGROUND_TTL_MS
|
|
14963
|
+
};
|
|
14964
|
+
index.updatedAt = now2;
|
|
14965
|
+
await this.writeIndex(cache2, index);
|
|
14966
|
+
}
|
|
14967
|
+
async getCoordinate(input, options = {}) {
|
|
14968
|
+
const cache2 = await this.open();
|
|
14969
|
+
const index = await this.readIndex(cache2);
|
|
14970
|
+
const coordinate = index.coordinates[coordinateKey(input.kind, input.pubkey, input.dTag)];
|
|
14971
|
+
if (!coordinate) return void 0;
|
|
14972
|
+
return { ...coordinate, fresh: isCoordinateFresh(coordinate, options) };
|
|
14973
|
+
}
|
|
14974
|
+
async touchAggregate(dTag, aggregateHash, now2 = this.now()) {
|
|
14975
|
+
const cache2 = await this.open();
|
|
14976
|
+
const index = await this.readIndex(cache2);
|
|
14977
|
+
const key = aggregateKey(dTag, aggregateHash);
|
|
14978
|
+
const aggregate = index.aggregates[key];
|
|
14979
|
+
if (!aggregate) return;
|
|
14980
|
+
aggregate.lastAccessed = now2;
|
|
14981
|
+
for (const hash of aggregate.blobHashes) {
|
|
14982
|
+
if (index.blobs[hash]) index.blobs[hash].lastAccessed = now2;
|
|
14983
|
+
}
|
|
14984
|
+
index.updatedAt = now2;
|
|
14985
|
+
await this.writeIndex(cache2, index);
|
|
14986
|
+
}
|
|
14987
|
+
markAggregateActive(dTag, aggregateHash) {
|
|
14988
|
+
this.activeAggregates.add(aggregateKey(dTag, aggregateHash));
|
|
14989
|
+
}
|
|
14990
|
+
releaseAggregateActive(dTag, aggregateHash) {
|
|
14991
|
+
this.activeAggregates.delete(aggregateKey(dTag, aggregateHash));
|
|
14992
|
+
}
|
|
14993
|
+
async prune(now2 = this.now()) {
|
|
14994
|
+
try {
|
|
14995
|
+
const cache2 = await this.open();
|
|
14996
|
+
const index = await this.readIndex(cache2);
|
|
14997
|
+
let size = cachedSize(index);
|
|
14998
|
+
const budget = await this.budgetBytes();
|
|
14999
|
+
const hardBudget = await this.hardBudgetBytes();
|
|
15000
|
+
const shouldPrune = size > budget || await this.originPressureHigh();
|
|
15001
|
+
if (!shouldPrune) return;
|
|
15002
|
+
this.rewriteRefCounts(index);
|
|
15003
|
+
for (const [hash, blob] of Object.entries(index.blobs)) {
|
|
15004
|
+
if (size <= budget) break;
|
|
15005
|
+
if (blob.refCount > 0) continue;
|
|
15006
|
+
await cache2.delete(this.blobUrl(hash));
|
|
15007
|
+
delete index.blobs[hash];
|
|
15008
|
+
size -= blob.size;
|
|
15009
|
+
}
|
|
15010
|
+
const currentAggregateHashes = new Set(
|
|
15011
|
+
Object.values(index.coordinates).map((coordinate) => coordinate.aggregateHash)
|
|
15012
|
+
);
|
|
15013
|
+
const aggregates = Object.values(index.aggregates).filter((entry) => !this.activeAggregates.has(entry.key)).sort((a, b) => {
|
|
15014
|
+
const currentA = currentAggregateHashes.has(a.aggregateHash) ? 1 : 0;
|
|
15015
|
+
const currentB = currentAggregateHashes.has(b.aggregateHash) ? 1 : 0;
|
|
15016
|
+
if (currentA !== currentB) return currentA - currentB;
|
|
15017
|
+
return a.lastAccessed - b.lastAccessed;
|
|
15018
|
+
});
|
|
15019
|
+
for (const aggregate of aggregates) {
|
|
15020
|
+
if (size <= budget) break;
|
|
15021
|
+
await cache2.delete(this.aggregateUrl(aggregate.key));
|
|
15022
|
+
delete index.aggregates[aggregate.key];
|
|
15023
|
+
size -= aggregate.size;
|
|
15024
|
+
this.rewriteRefCounts(index);
|
|
15025
|
+
}
|
|
15026
|
+
if (size > hardBudget) {
|
|
15027
|
+
const active = Object.values(index.aggregates).filter((entry) => this.activeAggregates.has(entry.key)).sort((a, b) => a.lastAccessed - b.lastAccessed);
|
|
15028
|
+
for (const aggregate of active) {
|
|
15029
|
+
if (size <= hardBudget) break;
|
|
15030
|
+
await cache2.delete(this.aggregateUrl(aggregate.key));
|
|
15031
|
+
delete index.aggregates[aggregate.key];
|
|
15032
|
+
size -= aggregate.size;
|
|
15033
|
+
}
|
|
15034
|
+
}
|
|
15035
|
+
this.rewriteRefCounts(index);
|
|
15036
|
+
for (const [hash, blob] of Object.entries(index.blobs)) {
|
|
15037
|
+
if (blob.refCount === 0) {
|
|
15038
|
+
await cache2.delete(this.blobUrl(hash));
|
|
15039
|
+
delete index.blobs[hash];
|
|
15040
|
+
}
|
|
15041
|
+
}
|
|
15042
|
+
index.updatedAt = now2;
|
|
15043
|
+
await this.writeIndex(cache2, index);
|
|
15044
|
+
} catch (cause) {
|
|
15045
|
+
this.diagnostic({ type: "cache-prune-failed", message: "failed to prune napplet artifact cache", cause });
|
|
15046
|
+
}
|
|
15047
|
+
}
|
|
15048
|
+
async snapshotIndex() {
|
|
15049
|
+
return this.readIndex(await this.open());
|
|
15050
|
+
}
|
|
15051
|
+
async writeVerifiedResolutionOnce(input) {
|
|
15052
|
+
const cache2 = await this.open();
|
|
15053
|
+
const now2 = input.now ?? this.now();
|
|
15054
|
+
const index = await this.readIndex(cache2);
|
|
15055
|
+
const blobHashes = [];
|
|
15056
|
+
for (const pathEntry of input.manifest.paths) {
|
|
15057
|
+
const bytes = input.files.get(pathEntry.path);
|
|
15058
|
+
if (!bytes) continue;
|
|
15059
|
+
blobHashes.push(pathEntry.sha256);
|
|
15060
|
+
await cache2.put(this.blobUrl(pathEntry.sha256), new Response(responseBody(bytes)));
|
|
15061
|
+
index.blobs[pathEntry.sha256] = {
|
|
15062
|
+
size: byteLength2(bytes),
|
|
15063
|
+
lastAccessed: now2,
|
|
15064
|
+
refCount: index.blobs[pathEntry.sha256]?.refCount ?? 0
|
|
15065
|
+
};
|
|
15066
|
+
}
|
|
15067
|
+
const key = aggregateKey(input.manifest.dTag, input.manifest.aggregateHash);
|
|
15068
|
+
const record = {
|
|
15069
|
+
schemaVersion: SCHEMA_VERSION,
|
|
15070
|
+
dTag: input.manifest.dTag,
|
|
15071
|
+
aggregateHash: input.manifest.aggregateHash,
|
|
15072
|
+
manifest: {
|
|
15073
|
+
kind: input.manifest.kind,
|
|
15074
|
+
pubkey: input.manifest.pubkey,
|
|
15075
|
+
dTag: input.manifest.dTag,
|
|
15076
|
+
paths: input.manifest.paths.map((entry) => ({ path: entry.path, sha256: entry.sha256 })),
|
|
15077
|
+
requires: [...input.manifest.requires],
|
|
15078
|
+
...input.manifest.title === void 0 ? {} : { title: input.manifest.title },
|
|
15079
|
+
...input.manifest.description === void 0 ? {} : { description: input.manifest.description }
|
|
15080
|
+
},
|
|
15081
|
+
indexHtml: input.indexHtml,
|
|
15082
|
+
blobHashes,
|
|
15083
|
+
writtenAt: now2
|
|
15084
|
+
};
|
|
15085
|
+
const aggregateBytes = new TextEncoder().encode(JSON.stringify(record));
|
|
15086
|
+
await cache2.put(this.aggregateUrl(key), new Response(responseBody(aggregateBytes), {
|
|
15087
|
+
headers: { "content-type": "application/json" }
|
|
15088
|
+
}));
|
|
15089
|
+
const coordKey = coordinateKey(input.manifest.kind, input.manifest.pubkey, input.manifest.dTag);
|
|
15090
|
+
index.aggregates[key] = {
|
|
15091
|
+
dTag: input.manifest.dTag,
|
|
15092
|
+
aggregateHash: input.manifest.aggregateHash,
|
|
15093
|
+
key,
|
|
15094
|
+
blobHashes,
|
|
15095
|
+
size: byteLength2(aggregateBytes),
|
|
15096
|
+
lastAccessed: now2,
|
|
15097
|
+
coordinateKey: coordKey
|
|
15098
|
+
};
|
|
15099
|
+
index.coordinates[coordKey] = {
|
|
15100
|
+
key: coordKey,
|
|
15101
|
+
kind: input.manifest.kind,
|
|
15102
|
+
pubkey: input.manifest.pubkey,
|
|
15103
|
+
dTag: input.manifest.dTag,
|
|
15104
|
+
aggregateHash: input.manifest.aggregateHash,
|
|
15105
|
+
lastResolvedAt: now2,
|
|
15106
|
+
foregroundTtlMs: DEFAULT_FOREGROUND_TTL_MS,
|
|
15107
|
+
backgroundTtlMs: DEFAULT_BACKGROUND_TTL_MS
|
|
15108
|
+
};
|
|
15109
|
+
this.rewriteRefCounts(index);
|
|
15110
|
+
index.updatedAt = now2;
|
|
15111
|
+
await this.writeIndex(cache2, index);
|
|
15112
|
+
await this.prune(now2);
|
|
15113
|
+
}
|
|
15114
|
+
async open() {
|
|
15115
|
+
this.cachePromise ??= this.cacheStorage.open(this.cacheName);
|
|
15116
|
+
return this.cachePromise;
|
|
15117
|
+
}
|
|
15118
|
+
indexUrl() {
|
|
15119
|
+
return new URL("__kehto_napplet_cache/index.json", this.baseUrl).toString();
|
|
15120
|
+
}
|
|
15121
|
+
blobUrl(hash) {
|
|
15122
|
+
return new URL(`__kehto_napplet_cache/blob/${encodeKeyPart(hash)}`, this.baseUrl).toString();
|
|
15123
|
+
}
|
|
15124
|
+
aggregateUrl(key) {
|
|
15125
|
+
return new URL(`__kehto_napplet_cache/aggregate/${encodeKeyPart(key)}.json`, this.baseUrl).toString();
|
|
15126
|
+
}
|
|
15127
|
+
async readIndex(cache2) {
|
|
15128
|
+
const response = await cache2.match(this.indexUrl());
|
|
15129
|
+
if (!response) return emptyIndex(this.now());
|
|
15130
|
+
try {
|
|
15131
|
+
const index = await responseJson(response);
|
|
15132
|
+
if (index.schemaVersion !== SCHEMA_VERSION) return emptyIndex(this.now());
|
|
15133
|
+
return index;
|
|
15134
|
+
} catch {
|
|
15135
|
+
return emptyIndex(this.now());
|
|
15136
|
+
}
|
|
15137
|
+
}
|
|
15138
|
+
async writeIndex(cache2, index) {
|
|
15139
|
+
await cache2.put(this.indexUrl(), new Response(JSON.stringify(index), {
|
|
15140
|
+
headers: { "content-type": "application/json" }
|
|
15141
|
+
}));
|
|
15142
|
+
}
|
|
15143
|
+
rewriteRefCounts(index) {
|
|
15144
|
+
const counts = refCounts(index);
|
|
15145
|
+
for (const [hash, blob] of Object.entries(index.blobs)) {
|
|
15146
|
+
blob.refCount = counts[hash] ?? 0;
|
|
15147
|
+
}
|
|
15148
|
+
}
|
|
15149
|
+
async budgetBytes() {
|
|
15150
|
+
const estimate = await this.estimateStorage();
|
|
15151
|
+
if (!estimate?.quota) return this.unknownBudgetBytes;
|
|
15152
|
+
return Math.min(this.softCeilingBytes, Math.floor(estimate.quota * 0.1));
|
|
15153
|
+
}
|
|
15154
|
+
async hardBudgetBytes() {
|
|
15155
|
+
const estimate = await this.estimateStorage();
|
|
15156
|
+
if (!estimate?.quota) return this.unknownBudgetBytes;
|
|
15157
|
+
return Math.min(this.hardCeilingBytes, Math.floor(estimate.quota * 0.2));
|
|
15158
|
+
}
|
|
15159
|
+
async originPressureHigh() {
|
|
15160
|
+
const estimate = await this.estimateStorage();
|
|
15161
|
+
if (!estimate?.quota || estimate.usage === void 0) return false;
|
|
15162
|
+
return estimate.usage / estimate.quota >= 0.8;
|
|
15163
|
+
}
|
|
15164
|
+
async estimateStorage() {
|
|
15165
|
+
if (!this.storage?.estimate) return void 0;
|
|
15166
|
+
try {
|
|
15167
|
+
return this.storage.estimate();
|
|
15168
|
+
} catch (cause) {
|
|
15169
|
+
this.diagnostic({
|
|
15170
|
+
type: "storage-estimate-unavailable",
|
|
15171
|
+
message: "storage estimate failed; using unknown quota cache budget",
|
|
15172
|
+
cause
|
|
15173
|
+
});
|
|
15174
|
+
return void 0;
|
|
15175
|
+
}
|
|
15176
|
+
}
|
|
15177
|
+
diagnostic(diagnostic) {
|
|
15178
|
+
this.onDiagnostic?.(diagnostic);
|
|
15179
|
+
}
|
|
15180
|
+
};
|
|
15181
|
+
async function openNappletArtifactCache(options = {}) {
|
|
15182
|
+
const cacheStorage = options.cacheStorage ?? globalThis.caches;
|
|
15183
|
+
if (!cacheStorage) return void 0;
|
|
15184
|
+
const storage = options.storage ?? globalThis.navigator?.storage;
|
|
15185
|
+
if (options.requireStorageEstimate && !storage?.estimate) {
|
|
15186
|
+
options.onDiagnostic?.({
|
|
15187
|
+
type: "storage-estimate-unavailable",
|
|
15188
|
+
message: "storage estimates are unavailable; using network-only loading"
|
|
15189
|
+
});
|
|
15190
|
+
return void 0;
|
|
15191
|
+
}
|
|
15192
|
+
try {
|
|
15193
|
+
const cache2 = new CacheStorageNappletArtifactCache({ ...options, cacheStorage, storage });
|
|
15194
|
+
await cache2.snapshotIndex();
|
|
15195
|
+
return cache2;
|
|
15196
|
+
} catch (cause) {
|
|
15197
|
+
options.onDiagnostic?.({
|
|
15198
|
+
type: "cache-open-failed",
|
|
15199
|
+
message: "Cache Storage napplet artifact cache could not be opened",
|
|
15200
|
+
cause
|
|
15201
|
+
});
|
|
15202
|
+
return void 0;
|
|
15203
|
+
}
|
|
15204
|
+
}
|
|
15205
|
+
var NAPPLET_KIND_SNAPSHOT = 5129;
|
|
15206
|
+
var NAPPLET_KIND_ROOT = 15129;
|
|
15207
|
+
var NAPPLET_KIND_NAMED = 35129;
|
|
15208
|
+
var NAPPLET_KINDS = [
|
|
15209
|
+
NAPPLET_KIND_SNAPSHOT,
|
|
15210
|
+
NAPPLET_KIND_ROOT,
|
|
15211
|
+
NAPPLET_KIND_NAMED
|
|
15212
|
+
];
|
|
15213
|
+
function isNappletManifestKind(kind) {
|
|
15214
|
+
return NAPPLET_KINDS.includes(kind);
|
|
15215
|
+
}
|
|
15216
|
+
var NappletResolutionError = class extends Error {
|
|
15217
|
+
code;
|
|
15218
|
+
constructor(code, message) {
|
|
15219
|
+
super(message);
|
|
15220
|
+
this.name = "NappletResolutionError";
|
|
15221
|
+
this.code = code;
|
|
15222
|
+
}
|
|
15223
|
+
};
|
|
15224
|
+
function firstTagValue(tags, name) {
|
|
15225
|
+
for (const tag of tags) {
|
|
15226
|
+
if (tag[0] === name && typeof tag[1] === "string" && tag[1].length > 0) return tag[1];
|
|
15227
|
+
}
|
|
15228
|
+
return void 0;
|
|
15229
|
+
}
|
|
15230
|
+
function allTagValues(tags, name) {
|
|
15231
|
+
const out = [];
|
|
15232
|
+
for (const tag of tags) {
|
|
15233
|
+
if (tag[0] === name && typeof tag[1] === "string" && tag[1].length > 0) out.push(tag[1]);
|
|
15234
|
+
}
|
|
15235
|
+
return out;
|
|
15236
|
+
}
|
|
15237
|
+
function archetypesFromTags(tags) {
|
|
15238
|
+
const out = [];
|
|
15239
|
+
for (const tag of tags) {
|
|
15240
|
+
if (tag[0] !== "archetype") continue;
|
|
15241
|
+
if (typeof tag[1] !== "string" || tag[1].length === 0) continue;
|
|
15242
|
+
out.push(
|
|
15243
|
+
typeof tag[2] === "string" && tag[2].length > 0 ? { slug: tag[1], nap: tag[2] } : { slug: tag[1] }
|
|
15244
|
+
);
|
|
15245
|
+
}
|
|
15246
|
+
return out;
|
|
15247
|
+
}
|
|
15248
|
+
function parseNappletManifest(event) {
|
|
15249
|
+
if (!isNappletManifestKind(event.kind)) {
|
|
15250
|
+
throw new NappletResolutionError("invalid-manifest", `not a NIP-5D napplet kind: ${event.kind}`);
|
|
15251
|
+
}
|
|
15252
|
+
const paths = pathEntriesFromTags(event.tags);
|
|
15253
|
+
if (paths.length === 0) {
|
|
15254
|
+
throw new NappletResolutionError("invalid-manifest", "manifest has no path tags");
|
|
15255
|
+
}
|
|
15256
|
+
const aggregateHash = aggregateTagValue(event.tags);
|
|
15257
|
+
if (!aggregateHash) {
|
|
15258
|
+
throw new NappletResolutionError("invalid-manifest", "manifest has no aggregate x tag");
|
|
15259
|
+
}
|
|
15260
|
+
return {
|
|
15261
|
+
kind: event.kind,
|
|
15262
|
+
pubkey: event.pubkey,
|
|
15263
|
+
dTag: firstTagValue(event.tags, "d") ?? "",
|
|
15264
|
+
paths,
|
|
15265
|
+
aggregateHash,
|
|
15266
|
+
servers: allTagValues(event.tags, "server"),
|
|
15267
|
+
requires: allTagValues(event.tags, "requires"),
|
|
15268
|
+
archetypes: archetypesFromTags(event.tags),
|
|
15269
|
+
title: firstTagValue(event.tags, "title"),
|
|
15270
|
+
description: firstTagValue(event.tags, "description"),
|
|
15271
|
+
source: firstTagValue(event.tags, "source")
|
|
15272
|
+
};
|
|
15273
|
+
}
|
|
15274
|
+
function verifyManifestSignature(event) {
|
|
15275
|
+
try {
|
|
15276
|
+
return verifyEvent(event);
|
|
15277
|
+
} catch {
|
|
15278
|
+
return false;
|
|
15279
|
+
}
|
|
15280
|
+
}
|
|
15281
|
+
function verifyBlobHash(bytes, sha256Hex) {
|
|
15282
|
+
return bytesToHex2(sha256(bytes)) === sha256Hex;
|
|
15283
|
+
}
|
|
15284
|
+
function stripTrailingSlash(url) {
|
|
15285
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
15286
|
+
}
|
|
15287
|
+
async function fetchBlob(servers, sha256Hex, fetchBytes) {
|
|
15288
|
+
for (const server of servers) {
|
|
15289
|
+
const url = `${stripTrailingSlash(server)}/${sha256Hex}`;
|
|
15290
|
+
try {
|
|
15291
|
+
const bytes = await fetchBytes(url);
|
|
15292
|
+
if (verifyBlobHash(bytes, sha256Hex)) return bytes;
|
|
15293
|
+
} catch {
|
|
15294
|
+
}
|
|
15295
|
+
}
|
|
15296
|
+
throw new NappletResolutionError("blob-unavailable", `no server served blob ${sha256Hex}`);
|
|
15297
|
+
}
|
|
15298
|
+
var INDEX_PATHS = ["/index.html", "index.html", "/"];
|
|
15299
|
+
function defaultDecode(bytes) {
|
|
15300
|
+
return new TextDecoder().decode(bytes);
|
|
15301
|
+
}
|
|
15302
|
+
async function resolveNapplet(options) {
|
|
15303
|
+
const { event, fetchBlob: fetchBlobBytes, textDecode = defaultDecode, cache: cache2 } = options;
|
|
15304
|
+
if (!verifyManifestSignature(event)) {
|
|
15305
|
+
throw new NappletResolutionError("invalid-signature", "manifest signature is invalid");
|
|
15306
|
+
}
|
|
15307
|
+
const manifest = parseNappletManifest(event);
|
|
15308
|
+
const recomputed = computeAggregateHash(manifest.paths);
|
|
15309
|
+
if (recomputed !== manifest.aggregateHash) {
|
|
15310
|
+
throw new NappletResolutionError(
|
|
15311
|
+
"aggregate-mismatch",
|
|
15312
|
+
`recomputed aggregate ${recomputed} != manifest ${manifest.aggregateHash}`
|
|
15313
|
+
);
|
|
15314
|
+
}
|
|
15315
|
+
const files = /* @__PURE__ */ new Map();
|
|
15316
|
+
for (const entry of manifest.paths) {
|
|
15317
|
+
let bytes = await cache2?.readBlob(entry.sha256);
|
|
15318
|
+
if (bytes && !verifyBlobHash(bytes, entry.sha256)) {
|
|
15319
|
+
await cache2?.deleteBlob(entry.sha256);
|
|
15320
|
+
bytes = void 0;
|
|
15321
|
+
}
|
|
15322
|
+
bytes ??= await fetchBlobBytes(entry.sha256, manifest.servers);
|
|
15323
|
+
if (!verifyBlobHash(bytes, entry.sha256)) {
|
|
15324
|
+
throw new NappletResolutionError(
|
|
15325
|
+
"blob-hash-mismatch",
|
|
15326
|
+
`blob for ${entry.path} does not match hash ${entry.sha256}`
|
|
15327
|
+
);
|
|
15328
|
+
}
|
|
15329
|
+
files.set(entry.path, bytes);
|
|
15330
|
+
}
|
|
15331
|
+
const indexEntry = manifest.paths.find((e) => INDEX_PATHS.includes(e.path));
|
|
15332
|
+
if (!indexEntry) {
|
|
15333
|
+
throw new NappletResolutionError("missing-index", "manifest has no /index.html entry");
|
|
15334
|
+
}
|
|
15335
|
+
const indexHtml = textDecode(files.get(indexEntry.path));
|
|
15336
|
+
await cache2?.writeVerifiedResolution({ event, manifest, files, indexHtml });
|
|
15337
|
+
return {
|
|
15338
|
+
dTag: manifest.dTag,
|
|
15339
|
+
aggregateHash: manifest.aggregateHash,
|
|
15340
|
+
files,
|
|
15341
|
+
indexHtml,
|
|
15342
|
+
manifest
|
|
15343
|
+
};
|
|
15344
|
+
}
|
|
15345
|
+
|
|
15346
|
+
// src/runtime-resolver.ts
|
|
15347
|
+
var PAJA_NAPPLET_MANIFEST_KIND = 35129;
|
|
15348
|
+
function decodePajaPointer(value) {
|
|
15349
|
+
const trimmed = value.trim();
|
|
15350
|
+
const decoded = decode(trimmed);
|
|
15351
|
+
if (decoded.type === "naddr") {
|
|
15352
|
+
return {
|
|
15353
|
+
type: "naddr",
|
|
15354
|
+
value: trimmed,
|
|
15355
|
+
identifier: decoded.data.identifier,
|
|
15356
|
+
pubkey: decoded.data.pubkey,
|
|
15357
|
+
kind: decoded.data.kind,
|
|
15358
|
+
relays: [...decoded.data.relays ?? []]
|
|
15359
|
+
};
|
|
15360
|
+
}
|
|
15361
|
+
if (decoded.type === "nevent") {
|
|
15362
|
+
return {
|
|
15363
|
+
type: "nevent",
|
|
15364
|
+
value: trimmed,
|
|
15365
|
+
id: decoded.data.id,
|
|
15366
|
+
...decoded.data.author ? { author: decoded.data.author } : {},
|
|
15367
|
+
...decoded.data.kind ? { kind: decoded.data.kind } : {},
|
|
15368
|
+
relays: [...decoded.data.relays ?? []]
|
|
15369
|
+
};
|
|
15370
|
+
}
|
|
15371
|
+
throw new Error(`Expected naddr or nevent pointer, got ${decoded.type}.`);
|
|
15372
|
+
}
|
|
15373
|
+
async function resolvePajaPointer(value, options = {}) {
|
|
15374
|
+
const pointer = decodePajaPointer(value);
|
|
15375
|
+
const relays = uniqueRelayUrls([...pointer.relays, ...options.relays ?? []]);
|
|
15376
|
+
if (relays.length === 0) {
|
|
15377
|
+
throw new Error("Pointer does not include relay hints; add a relay-bearing naddr or nevent.");
|
|
15378
|
+
}
|
|
15379
|
+
const pool = options.pool ?? new SimplePool();
|
|
15380
|
+
const ownsPool = options.pool === void 0;
|
|
15381
|
+
try {
|
|
15382
|
+
const event = await resolvePointerEvent(pointer, pool, relays, options.maxWaitMs ?? 5e3);
|
|
15383
|
+
const blossomServers = [...options.blossomServers ?? []];
|
|
15384
|
+
const resolved = await resolveNapplet({
|
|
15385
|
+
event,
|
|
15386
|
+
cache: await openNappletArtifactCache({ requireStorageEstimate: false }),
|
|
15387
|
+
fetchBlob: (sha256Hex, servers) => fetchBlob([...servers, ...blossomServers], sha256Hex, async (url) => {
|
|
15388
|
+
const response = await (options.fetcher ?? fetch)(url);
|
|
15389
|
+
if (!response.ok) throw new Error(`[paja-runtime] blob ${url}: ${response.status}`);
|
|
15390
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
15391
|
+
})
|
|
15392
|
+
});
|
|
15393
|
+
return {
|
|
15394
|
+
pointer,
|
|
15395
|
+
event,
|
|
15396
|
+
relays,
|
|
15397
|
+
blossomServers,
|
|
15398
|
+
dTag: resolved.dTag,
|
|
15399
|
+
aggregateHash: resolved.aggregateHash,
|
|
15400
|
+
indexHtml: resolved.indexHtml,
|
|
15401
|
+
manifest: resolved.manifest
|
|
15402
|
+
};
|
|
15403
|
+
} finally {
|
|
15404
|
+
if (ownsPool) {
|
|
15405
|
+
pool.close?.(relays);
|
|
15406
|
+
pool.destroy?.();
|
|
15407
|
+
}
|
|
15408
|
+
}
|
|
15409
|
+
}
|
|
15410
|
+
function injectPajaRuntimeCsp(html, origins) {
|
|
15411
|
+
const value = origins.length > 0 ? `connect-src ${[...new Set(origins)].sort().join(" ")}` : "connect-src 'none'";
|
|
15412
|
+
const meta = `<meta http-equiv="Content-Security-Policy" content="${escapeAttribute(value)}">`;
|
|
15413
|
+
if (/<head[^>]*>/i.test(html)) {
|
|
15414
|
+
return html.replace(/<head[^>]*>/i, (open) => `${open}${meta}`);
|
|
15415
|
+
}
|
|
15416
|
+
if (/<html[^>]*>/i.test(html)) {
|
|
15417
|
+
return html.replace(/<html[^>]*>/i, (open) => `${open}<head>${meta}</head>`);
|
|
15418
|
+
}
|
|
15419
|
+
return `${meta}${html}`;
|
|
15420
|
+
}
|
|
15421
|
+
async function resolvePointerEvent(pointer, pool, relays, maxWaitMs) {
|
|
15422
|
+
const filter = pointer.type === "naddr" ? addressableFilter(pointer) : eventFilter(pointer);
|
|
15423
|
+
const events = await pool.querySync([...relays], filter, {
|
|
15424
|
+
maxWait: maxWaitMs,
|
|
15425
|
+
label: "kehto-paja-runtime"
|
|
15426
|
+
});
|
|
15427
|
+
const event = events.filter((candidate) => matchesPointer(pointer, candidate)).sort((a, b) => b.created_at - a.created_at)[0];
|
|
15428
|
+
if (!event) {
|
|
15429
|
+
throw new Error(`No napplet manifest event found for ${pointer.type} pointer.`);
|
|
15430
|
+
}
|
|
15431
|
+
if (event.kind !== PAJA_NAPPLET_MANIFEST_KIND) {
|
|
15432
|
+
throw new Error(`Pointer resolved kind ${event.kind}; expected ${PAJA_NAPPLET_MANIFEST_KIND}.`);
|
|
15433
|
+
}
|
|
15434
|
+
return event;
|
|
15435
|
+
}
|
|
15436
|
+
function addressableFilter(pointer) {
|
|
15437
|
+
if (pointer.kind !== PAJA_NAPPLET_MANIFEST_KIND) {
|
|
15438
|
+
throw new Error(`naddr kind ${pointer.kind} is not a napplet manifest kind.`);
|
|
15439
|
+
}
|
|
15440
|
+
return {
|
|
15441
|
+
kinds: [PAJA_NAPPLET_MANIFEST_KIND],
|
|
15442
|
+
authors: [pointer.pubkey],
|
|
15443
|
+
"#d": [pointer.identifier],
|
|
15444
|
+
limit: 1
|
|
15445
|
+
};
|
|
15446
|
+
}
|
|
15447
|
+
function eventFilter(pointer) {
|
|
15448
|
+
return {
|
|
15449
|
+
ids: [pointer.id],
|
|
15450
|
+
...pointer.kind ? { kinds: [pointer.kind] } : {},
|
|
15451
|
+
...pointer.author ? { authors: [pointer.author] } : {},
|
|
15452
|
+
limit: 1
|
|
15453
|
+
};
|
|
15454
|
+
}
|
|
15455
|
+
function matchesPointer(pointer, event) {
|
|
15456
|
+
if (pointer.type === "nevent") {
|
|
15457
|
+
if (event.id !== pointer.id) return false;
|
|
15458
|
+
if (pointer.author && event.pubkey !== pointer.author) return false;
|
|
15459
|
+
if (pointer.kind && event.kind !== pointer.kind) return false;
|
|
15460
|
+
return true;
|
|
15461
|
+
}
|
|
15462
|
+
return event.kind === pointer.kind && event.pubkey === pointer.pubkey && event.tags.some((tag) => tag[0] === "d" && tag[1] === pointer.identifier);
|
|
15463
|
+
}
|
|
15464
|
+
function uniqueRelayUrls(values) {
|
|
15465
|
+
const out = [];
|
|
15466
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15467
|
+
for (const value of values) {
|
|
15468
|
+
const url = normalizeRelayUrl(value);
|
|
15469
|
+
if (!url || seen.has(url)) continue;
|
|
15470
|
+
seen.add(url);
|
|
15471
|
+
out.push(url);
|
|
15472
|
+
}
|
|
15473
|
+
return out;
|
|
15474
|
+
}
|
|
15475
|
+
function normalizeRelayUrl(value) {
|
|
15476
|
+
const raw = value.trim();
|
|
15477
|
+
if (!raw) return void 0;
|
|
15478
|
+
try {
|
|
15479
|
+
const url = new URL(raw);
|
|
15480
|
+
if (url.protocol !== "wss:" && url.protocol !== "ws:") return void 0;
|
|
15481
|
+
url.hash = "";
|
|
15482
|
+
url.search = "";
|
|
15483
|
+
return url.href.replace(/\/$/, "");
|
|
15484
|
+
} catch {
|
|
15485
|
+
return void 0;
|
|
15486
|
+
}
|
|
15487
|
+
}
|
|
15488
|
+
function escapeAttribute(value) {
|
|
15489
|
+
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
15490
|
+
}
|
|
15491
|
+
|
|
15492
|
+
// src/browser-host.ts
|
|
15493
|
+
var bridgeRef = null;
|
|
15494
|
+
function readConfig() {
|
|
15495
|
+
const script = document.getElementById("kehto-paja-config");
|
|
15496
|
+
if (!script?.textContent) {
|
|
15497
|
+
throw new Error("Missing Kehto Paja config.");
|
|
15498
|
+
}
|
|
15499
|
+
return JSON.parse(script.textContent);
|
|
15500
|
+
}
|
|
15501
|
+
async function readLatestConfig(fallback) {
|
|
15502
|
+
try {
|
|
15503
|
+
const response = await fetch(new URL("./__kehto/config.json", window.location.href), { cache: "no-store" });
|
|
15504
|
+
if (!response.ok) return fallback;
|
|
15505
|
+
return await response.json();
|
|
15506
|
+
} catch (error) {
|
|
15507
|
+
console.warn("[paja] config refresh failed; using embedded config", error);
|
|
15508
|
+
return fallback;
|
|
15509
|
+
}
|
|
15510
|
+
}
|
|
15511
|
+
function setTargetUrlDisplay(config, frame) {
|
|
15512
|
+
const label = getTargetLabel(config);
|
|
15513
|
+
const targetEl = document.querySelector(".target");
|
|
15514
|
+
if (targetEl) {
|
|
15515
|
+
targetEl.textContent = label;
|
|
15516
|
+
targetEl.setAttribute("title", label);
|
|
15517
|
+
}
|
|
15518
|
+
frame.dataset.targetUrl = label;
|
|
15519
|
+
}
|
|
15520
|
+
function getTargetLabel(config) {
|
|
15521
|
+
if (config.target.mode === "runtime-pointer") return config.target.pointer?.value ?? "runtime pointer";
|
|
15522
|
+
return config.target.url;
|
|
15523
|
+
}
|
|
15524
|
+
function readInitialPointerValue(config) {
|
|
15525
|
+
if (config.target.mode !== "runtime-pointer") return "";
|
|
15526
|
+
const params = new URLSearchParams(window.location.search);
|
|
15527
|
+
return params.get("naddr") ?? params.get("nevent") ?? params.get("pointer") ?? config.target.pointer?.value ?? "";
|
|
15528
|
+
}
|
|
15529
|
+
function connectOrigins(urls) {
|
|
15530
|
+
const out = /* @__PURE__ */ new Set();
|
|
15531
|
+
for (const value of urls) {
|
|
15532
|
+
try {
|
|
15533
|
+
const url = new URL(value);
|
|
15534
|
+
if (url.protocol === "wss:" || url.protocol === "ws:") {
|
|
15535
|
+
out.add(value.replace(/\/$/, ""));
|
|
15536
|
+
} else {
|
|
15537
|
+
out.add(url.origin);
|
|
15538
|
+
}
|
|
15539
|
+
} catch {
|
|
15540
|
+
}
|
|
15541
|
+
}
|
|
15542
|
+
return [...out];
|
|
15543
|
+
}
|
|
15544
|
+
function setStatus(state, status) {
|
|
15545
|
+
state.status = status;
|
|
15546
|
+
const statusEl = document.getElementById("lifecycle-status");
|
|
15547
|
+
if (statusEl) statusEl.textContent = status;
|
|
15548
|
+
}
|
|
15549
|
+
function setSimulationStatus(state) {
|
|
15550
|
+
const statusEl = document.getElementById("simulation-status");
|
|
15551
|
+
if (statusEl) statusEl.textContent = summarizePajaSimulation(state.simulation);
|
|
15552
|
+
const themeSelect = document.getElementById("simulation-theme");
|
|
15553
|
+
if (themeSelect instanceof HTMLSelectElement) themeSelect.value = state.simulation.theme.mode;
|
|
15554
|
+
renderPajaDevtools(state, { bridge: bridgeRef, devSignerPubkey: PAJA_DEV_SIGNER_PUBKEY });
|
|
15555
|
+
}
|
|
15556
|
+
function setPointerStatus(state, message) {
|
|
15557
|
+
state.pointerStatus = message;
|
|
15558
|
+
const statusEl = document.getElementById("runtime-pointer-status");
|
|
15559
|
+
if (statusEl) statusEl.textContent = message;
|
|
15560
|
+
}
|
|
15561
|
+
function getFrame() {
|
|
15562
|
+
const frame = document.getElementById("napplet-frame");
|
|
15563
|
+
if (!(frame instanceof HTMLIFrameElement)) {
|
|
15564
|
+
throw new Error("Missing Kehto Paja iframe.");
|
|
15565
|
+
}
|
|
15566
|
+
frame.sandbox.add("allow-scripts");
|
|
15567
|
+
frame.sandbox.remove("allow-same-origin");
|
|
15568
|
+
return frame;
|
|
15569
|
+
}
|
|
15570
|
+
function confirmPajaRequest(state, request) {
|
|
15571
|
+
const event = request.event;
|
|
15572
|
+
const kind = typeof event.kind === "number" ? event.kind : "unknown";
|
|
15573
|
+
const content = typeof event.content === "string" && event.content.length > 0 ? `
|
|
15574
|
+
|
|
15575
|
+
${event.content.slice(0, 240)}` : "";
|
|
15576
|
+
const allowed = window.confirm(`Paja ${request.action} request
|
|
15577
|
+
kind: ${kind}${content}`);
|
|
15578
|
+
appendPajaMessageLog(state, "paja", {
|
|
15579
|
+
type: `paja.${request.action}.${allowed ? "confirmed" : "denied"}`,
|
|
15580
|
+
kind
|
|
15581
|
+
});
|
|
15582
|
+
return allowed;
|
|
15583
|
+
}
|
|
15584
|
+
function getTargetIdentity2(config, resolvedTarget) {
|
|
15585
|
+
return {
|
|
15586
|
+
pubkey: "",
|
|
15587
|
+
dTag: resolvedTarget?.dTag ?? config.window.dTag,
|
|
15588
|
+
aggregateHash: resolvedTarget?.aggregateHash ?? config.window.aggregateHash
|
|
15589
|
+
};
|
|
15590
|
+
}
|
|
15591
|
+
function registerFrameForGeneration(bridge, frame, config, generation, resolvedTarget) {
|
|
15592
|
+
const win = frame.contentWindow;
|
|
15593
|
+
if (!win) return null;
|
|
15594
|
+
const windowId = `${config.window.id}:${generation}`;
|
|
15595
|
+
const identity = getTargetIdentity2(config, resolvedTarget);
|
|
15596
|
+
originRegistry.register(win, windowId, {
|
|
15597
|
+
dTag: identity.dTag,
|
|
15598
|
+
aggregateHash: identity.aggregateHash
|
|
15599
|
+
});
|
|
15600
|
+
bridge.runtime.sessionRegistry.register(windowId, {
|
|
15601
|
+
...identity,
|
|
15602
|
+
windowId,
|
|
15603
|
+
origin: "null",
|
|
15604
|
+
type: "napplet",
|
|
15605
|
+
registeredAt: Date.now(),
|
|
15606
|
+
instanceId: `${windowId}:${Date.now()}`,
|
|
15607
|
+
provenance: "nip-5d"
|
|
15608
|
+
});
|
|
15609
|
+
return windowId;
|
|
15610
|
+
}
|
|
15611
|
+
function navigateFrame(bridge, frame, config, generation, resolvedTarget) {
|
|
15612
|
+
if (config.target.mode === "runtime-pointer") {
|
|
15613
|
+
if (!resolvedTarget) {
|
|
15614
|
+
frame.removeAttribute("src");
|
|
15615
|
+
frame.srcdoc = "<!doctype html><html><body></body></html>";
|
|
15616
|
+
return null;
|
|
15617
|
+
}
|
|
15618
|
+
const windowId2 = registerFrameForGeneration(bridge, frame, config, generation, resolvedTarget);
|
|
15619
|
+
frame.removeAttribute("src");
|
|
15620
|
+
frame.srcdoc = injectPajaRuntimeCsp(
|
|
15621
|
+
resolvedTarget.indexHtml,
|
|
15622
|
+
connectOrigins([...resolvedTarget.relays, ...resolvedTarget.blossomServers])
|
|
15623
|
+
);
|
|
15624
|
+
return windowId2;
|
|
15625
|
+
}
|
|
15626
|
+
const windowId = registerFrameForGeneration(bridge, frame, config, generation, resolvedTarget);
|
|
15627
|
+
frame.src = config.target.url;
|
|
15628
|
+
return windowId;
|
|
15629
|
+
}
|
|
15630
|
+
function createHostSignerController(getState) {
|
|
15631
|
+
return createPajaSignerController({
|
|
15632
|
+
confirmRequest: (request) => confirmPajaRequest(getState(), request),
|
|
15633
|
+
onChange(signer) {
|
|
15634
|
+
const state = getState();
|
|
15635
|
+
if (!state) return;
|
|
15636
|
+
state.signer = signer;
|
|
15637
|
+
appendPajaMessageLog(state, "paja", {
|
|
15638
|
+
type: `paja.signer.${signer.method}.${signer.status}`,
|
|
15639
|
+
pubkey: signer.pubkey,
|
|
15640
|
+
relay: signer.relay,
|
|
15641
|
+
error: signer.error
|
|
15642
|
+
});
|
|
15643
|
+
setSimulationStatus(state);
|
|
15644
|
+
if (signer.status === "connected") state.reload();
|
|
15645
|
+
}
|
|
15646
|
+
});
|
|
15647
|
+
}
|
|
15648
|
+
function installPajaControlListeners(state) {
|
|
15649
|
+
document.getElementById("reload-target")?.addEventListener("click", () => {
|
|
15650
|
+
state.reload();
|
|
15651
|
+
});
|
|
15652
|
+
document.getElementById("simulation-theme")?.addEventListener("change", (event) => {
|
|
15653
|
+
const target = event.target;
|
|
15654
|
+
if (!(target instanceof HTMLSelectElement)) return;
|
|
15655
|
+
if (target.value === "dark" || target.value === "light") {
|
|
15656
|
+
state.setThemeMode(target.value);
|
|
15657
|
+
}
|
|
15658
|
+
});
|
|
15659
|
+
document.getElementById("message-filter")?.addEventListener("input", (event) => {
|
|
15660
|
+
const target = event.target;
|
|
15661
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
15662
|
+
state.messageFilter = target.value;
|
|
15663
|
+
renderPajaMessageLog(state);
|
|
15664
|
+
});
|
|
15665
|
+
document.getElementById("clear-log")?.addEventListener("click", () => {
|
|
15666
|
+
state.clearLog();
|
|
15667
|
+
});
|
|
15668
|
+
document.getElementById("runtime-pointer-form")?.addEventListener("submit", (event) => {
|
|
15669
|
+
event.preventDefault();
|
|
15670
|
+
const input = document.getElementById("runtime-pointer-input");
|
|
15671
|
+
if (!(input instanceof HTMLInputElement)) return;
|
|
15672
|
+
void state.loadPointer(input.value);
|
|
15673
|
+
});
|
|
15674
|
+
}
|
|
15675
|
+
function createPajaBrowserState(context) {
|
|
15676
|
+
const { config, frame, bridge, adapter, signerController, capabilities, runtime } = context;
|
|
15677
|
+
return {
|
|
15678
|
+
config,
|
|
15679
|
+
capabilities,
|
|
15680
|
+
services: Object.keys(adapter.services ?? {}).sort(),
|
|
15681
|
+
simulation: runtime.currentSimulation,
|
|
15682
|
+
signer: signerController.getState(),
|
|
15683
|
+
resolvedTarget: null,
|
|
15684
|
+
pointerValue: readInitialPointerValue(config),
|
|
15685
|
+
pointerStatus: config.target.mode === "runtime-pointer" ? "idle" : "",
|
|
15686
|
+
generation: 0,
|
|
15687
|
+
status: "booting",
|
|
15688
|
+
messageFilter: "",
|
|
15689
|
+
messageLog: [],
|
|
15690
|
+
reload() {
|
|
15691
|
+
if (runtime.currentWindowId) {
|
|
15692
|
+
bridge.runtime.destroyWindow(runtime.currentWindowId);
|
|
15693
|
+
bridge.runtime.sessionRegistry.unregister(runtime.currentWindowId);
|
|
15694
|
+
originRegistry.unregister(runtime.currentWindowId);
|
|
15695
|
+
}
|
|
15696
|
+
this.generation += 1;
|
|
15697
|
+
runtime.initReceivedGeneration = -1;
|
|
15698
|
+
setStatus(this, "reloading");
|
|
15699
|
+
runtime.currentWindowId = navigateFrame(bridge, frame, config, this.generation, this.resolvedTarget);
|
|
15700
|
+
},
|
|
15701
|
+
setThemeMode(mode) {
|
|
15702
|
+
runtime.currentSimulation = {
|
|
15703
|
+
...runtime.currentSimulation,
|
|
15704
|
+
theme: {
|
|
15705
|
+
...runtime.currentSimulation.theme,
|
|
15706
|
+
mode
|
|
15707
|
+
}
|
|
15708
|
+
};
|
|
15709
|
+
this.simulation = runtime.currentSimulation;
|
|
15710
|
+
runtime.themeService?.publishTheme(createDevTheme(runtime.currentSimulation.theme.mode, runtime.currentSimulation.theme.values));
|
|
15711
|
+
setSimulationStatus(this);
|
|
15712
|
+
},
|
|
14035
15713
|
setDomainEnabled(domain, enabled) {
|
|
14036
|
-
currentSimulation = {
|
|
14037
|
-
...currentSimulation,
|
|
15714
|
+
runtime.currentSimulation = {
|
|
15715
|
+
...runtime.currentSimulation,
|
|
14038
15716
|
capabilities: {
|
|
14039
15717
|
domains: {
|
|
14040
|
-
...currentSimulation.capabilities.domains,
|
|
15718
|
+
...runtime.currentSimulation.capabilities.domains,
|
|
14041
15719
|
[domain]: enabled
|
|
14042
15720
|
},
|
|
14043
15721
|
disabledDomains: PAJA_SIMULATION_DOMAINS.filter(
|
|
14044
|
-
(entry) => entry === domain ? !enabled : !currentSimulation.capabilities.domains[entry]
|
|
15722
|
+
(entry) => entry === domain ? !enabled : !runtime.currentSimulation.capabilities.domains[entry]
|
|
14045
15723
|
)
|
|
14046
15724
|
}
|
|
14047
15725
|
};
|
|
14048
|
-
this.simulation = currentSimulation;
|
|
14049
|
-
this.services = Object.keys(adapter.services ?? {}).filter((name) => currentSimulation.capabilities.domains[name] !== false).sort();
|
|
15726
|
+
this.simulation = runtime.currentSimulation;
|
|
15727
|
+
this.services = Object.keys(adapter.services ?? {}).filter((name) => runtime.currentSimulation.capabilities.domains[name] !== false).sort();
|
|
14050
15728
|
setSimulationStatus(this);
|
|
14051
15729
|
appendPajaMessageLog(this, "paja", { type: `paja.interface.${enabled ? "enabled" : "disabled"}`, domain });
|
|
14052
15730
|
this.reload();
|
|
14053
15731
|
},
|
|
14054
15732
|
setAclCapability(capability, enabled) {
|
|
14055
|
-
const identity = getTargetIdentity2(config);
|
|
15733
|
+
const identity = getTargetIdentity2(config, this.resolvedTarget);
|
|
14056
15734
|
if (enabled) bridge.runtime.aclState.grant(identity.pubkey, identity.dTag, identity.aggregateHash, capability);
|
|
14057
15735
|
else bridge.runtime.aclState.revoke(identity.pubkey, identity.dTag, identity.aggregateHash, capability);
|
|
14058
15736
|
bridge.runtime.aclState.persist();
|
|
@@ -14068,6 +15746,40 @@ async function installPajaHost() {
|
|
|
14068
15746
|
connectBunker(uri) {
|
|
14069
15747
|
return signerController.connectBunker(uri);
|
|
14070
15748
|
},
|
|
15749
|
+
async loadPointer(value) {
|
|
15750
|
+
if (config.target.mode !== "runtime-pointer") return;
|
|
15751
|
+
const pointer = value.trim();
|
|
15752
|
+
const input = document.getElementById("runtime-pointer-input");
|
|
15753
|
+
if (input instanceof HTMLInputElement) input.value = pointer;
|
|
15754
|
+
this.pointerValue = pointer;
|
|
15755
|
+
if (!pointer) {
|
|
15756
|
+
setPointerStatus(this, "idle");
|
|
15757
|
+
return;
|
|
15758
|
+
}
|
|
15759
|
+
setPointerStatus(this, "resolving");
|
|
15760
|
+
setStatus(this, "booting");
|
|
15761
|
+
appendPajaMessageLog(this, "paja", { type: "paja.pointer.resolve", pointer });
|
|
15762
|
+
try {
|
|
15763
|
+
this.resolvedTarget = await resolvePajaPointer(pointer, {
|
|
15764
|
+
relays: config.target.pointer?.relays ?? [],
|
|
15765
|
+
blossomServers: config.target.pointer?.blossomServers ?? [],
|
|
15766
|
+
maxWaitMs: config.target.pointer?.maxWaitMs
|
|
15767
|
+
});
|
|
15768
|
+
setPointerStatus(this, `${this.resolvedTarget.dTag}:${this.resolvedTarget.aggregateHash.slice(0, 12)}`);
|
|
15769
|
+
appendPajaMessageLog(this, "paja", {
|
|
15770
|
+
type: "paja.pointer.resolved",
|
|
15771
|
+
dTag: this.resolvedTarget.dTag,
|
|
15772
|
+
aggregateHash: this.resolvedTarget.aggregateHash
|
|
15773
|
+
});
|
|
15774
|
+
this.reload();
|
|
15775
|
+
} catch (error) {
|
|
15776
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15777
|
+
this.resolvedTarget = null;
|
|
15778
|
+
setPointerStatus(this, message);
|
|
15779
|
+
setStatus(this, "error");
|
|
15780
|
+
appendPajaMessageLog(this, "paja", { type: "paja.pointer.error", error: message });
|
|
15781
|
+
}
|
|
15782
|
+
},
|
|
14071
15783
|
clearLog() {
|
|
14072
15784
|
this.messageLog.length = 0;
|
|
14073
15785
|
renderPajaMessageLog(this);
|
|
@@ -14077,20 +15789,52 @@ async function installPajaHost() {
|
|
|
14077
15789
|
generation: this.generation,
|
|
14078
15790
|
status: this.status,
|
|
14079
15791
|
iframeCount: document.querySelectorAll("iframe").length,
|
|
14080
|
-
initSent: initReceivedGeneration === this.generation,
|
|
15792
|
+
initSent: runtime.initReceivedGeneration === this.generation,
|
|
14081
15793
|
services: this.services,
|
|
14082
|
-
simulation: currentSimulation,
|
|
15794
|
+
simulation: runtime.currentSimulation,
|
|
14083
15795
|
signer: this.signer,
|
|
15796
|
+
resolvedTarget: this.resolvedTarget,
|
|
15797
|
+
pointerStatus: this.pointerStatus,
|
|
14084
15798
|
messageLog: [...this.messageLog]
|
|
14085
15799
|
};
|
|
14086
15800
|
}
|
|
14087
15801
|
};
|
|
15802
|
+
}
|
|
15803
|
+
async function installPajaHost() {
|
|
15804
|
+
const config = await readLatestConfig(readConfig());
|
|
15805
|
+
const frame = getFrame();
|
|
15806
|
+
setTargetUrlDisplay(config, frame);
|
|
15807
|
+
const runtime = {
|
|
15808
|
+
currentSimulation: config.simulation,
|
|
15809
|
+
themeService: null,
|
|
15810
|
+
currentWindowId: null,
|
|
15811
|
+
initReceivedGeneration: -1
|
|
15812
|
+
};
|
|
15813
|
+
const getSimulation = () => runtime.currentSimulation;
|
|
15814
|
+
let stateRef = null;
|
|
15815
|
+
const signerController = createHostSignerController(() => stateRef);
|
|
15816
|
+
const adapter = createPajaAdapter(config, getSimulation, (theme) => {
|
|
15817
|
+
runtime.themeService = theme;
|
|
15818
|
+
}, (request) => confirmPajaRequest(stateRef, request), signerController, () => getTargetIdentity2(config, stateRef?.resolvedTarget));
|
|
15819
|
+
const bridge = createShellBridge(adapter);
|
|
15820
|
+
bridgeRef = bridge;
|
|
15821
|
+
installPajaOriginRegistryProxy(originRegistry, () => stateRef);
|
|
15822
|
+
const capabilities = buildShellCapabilities(adapter);
|
|
15823
|
+
const state = createPajaBrowserState({
|
|
15824
|
+
config,
|
|
15825
|
+
frame,
|
|
15826
|
+
bridge,
|
|
15827
|
+
adapter,
|
|
15828
|
+
signerController,
|
|
15829
|
+
capabilities,
|
|
15830
|
+
runtime
|
|
15831
|
+
});
|
|
14088
15832
|
stateRef = state;
|
|
14089
15833
|
window.__KEHTO_PAJA__ = state;
|
|
14090
15834
|
window.addEventListener("message", (event) => {
|
|
14091
15835
|
if (event.source !== frame.contentWindow) return;
|
|
14092
|
-
appendPajaMessageLog(state, "napplet->shell", event.data, currentWindowId ?? void 0);
|
|
14093
|
-
const proxiedSource = createPajaPostMessageProxy(event.source, state, currentWindowId ?? void 0);
|
|
15836
|
+
appendPajaMessageLog(state, "napplet->shell", event.data, runtime.currentWindowId ?? void 0);
|
|
15837
|
+
const proxiedSource = createPajaPostMessageProxy(event.source, state, runtime.currentWindowId ?? void 0);
|
|
14094
15838
|
const syntheticEvent = new Proxy(event, {
|
|
14095
15839
|
get(target, prop) {
|
|
14096
15840
|
if (prop === "source") return proxiedSource;
|
|
@@ -14101,13 +15845,13 @@ async function installPajaHost() {
|
|
|
14101
15845
|
bridge.handleMessage(syntheticEvent);
|
|
14102
15846
|
const data = event.data;
|
|
14103
15847
|
if (data && typeof data === "object" && data.type === "shell.ready") {
|
|
14104
|
-
initReceivedGeneration = state.generation;
|
|
15848
|
+
runtime.initReceivedGeneration = state.generation;
|
|
14105
15849
|
setStatus(state, "ready");
|
|
14106
15850
|
}
|
|
14107
15851
|
});
|
|
14108
15852
|
frame.addEventListener("load", () => {
|
|
14109
15853
|
if (state.status === "booting" || state.status === "reloading") {
|
|
14110
|
-
registerFrameForGeneration(bridge, frame, config, state.generation);
|
|
15854
|
+
runtime.currentWindowId = registerFrameForGeneration(bridge, frame, config, state.generation, state.resolvedTarget);
|
|
14111
15855
|
}
|
|
14112
15856
|
});
|
|
14113
15857
|
frame.addEventListener("error", () => {
|
|
@@ -14116,7 +15860,15 @@ async function installPajaHost() {
|
|
|
14116
15860
|
installPajaControlListeners(state);
|
|
14117
15861
|
setStatus(state, "booting");
|
|
14118
15862
|
setSimulationStatus(state);
|
|
14119
|
-
|
|
15863
|
+
setPointerStatus(state, state.pointerStatus);
|
|
15864
|
+
if (config.target.mode === "runtime-pointer") {
|
|
15865
|
+
const input = document.getElementById("runtime-pointer-input");
|
|
15866
|
+
if (input instanceof HTMLInputElement) input.value = state.pointerValue;
|
|
15867
|
+
if (state.pointerValue) void state.loadPointer(state.pointerValue);
|
|
15868
|
+
else runtime.currentWindowId = navigateFrame(bridge, frame, config, state.generation, state.resolvedTarget);
|
|
15869
|
+
} else {
|
|
15870
|
+
runtime.currentWindowId = navigateFrame(bridge, frame, config, state.generation, state.resolvedTarget);
|
|
15871
|
+
}
|
|
14120
15872
|
}
|
|
14121
15873
|
try {
|
|
14122
15874
|
void installPajaHost().catch((error) => {
|