11535 lines
321 KiB
JavaScript
11535 lines
321 KiB
JavaScript
"use strict";
|
|
var NostrTools = (() => {
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod3) => __copyProps(__defProp({}, "__esModule", { value: true }), mod3);
|
|
|
|
// index.ts
|
|
var nostr_tools_exports = {};
|
|
__export(nostr_tools_exports, {
|
|
Relay: () => Relay,
|
|
SimplePool: () => SimplePool,
|
|
finalizeEvent: () => finalizeEvent,
|
|
fj: () => fakejson_exports,
|
|
generateSecretKey: () => generateSecretKey,
|
|
getEventHash: () => getEventHash,
|
|
getFilterLimit: () => getFilterLimit,
|
|
getPublicKey: () => getPublicKey,
|
|
kinds: () => kinds_exports,
|
|
matchFilter: () => matchFilter,
|
|
matchFilters: () => matchFilters,
|
|
mergeFilters: () => mergeFilters,
|
|
nip04: () => nip04_exports,
|
|
nip05: () => nip05_exports,
|
|
nip06: () => nip06_exports,
|
|
nip10: () => nip10_exports,
|
|
nip11: () => nip11_exports,
|
|
nip13: () => nip13_exports,
|
|
nip17: () => nip17_exports,
|
|
nip18: () => nip18_exports,
|
|
nip19: () => nip19_exports,
|
|
nip21: () => nip21_exports,
|
|
nip25: () => nip25_exports,
|
|
nip27: () => nip27_exports,
|
|
nip28: () => nip28_exports,
|
|
nip30: () => nip30_exports,
|
|
nip39: () => nip39_exports,
|
|
nip42: () => nip42_exports,
|
|
nip44: () => nip44_exports,
|
|
nip46: () => nip46_exports,
|
|
nip47: () => nip47_exports,
|
|
nip54: () => nip54_exports,
|
|
nip57: () => nip57_exports,
|
|
nip59: () => nip59_exports,
|
|
nip98: () => nip98_exports,
|
|
parseReferences: () => parseReferences,
|
|
serializeEvent: () => serializeEvent,
|
|
sortEvents: () => sortEvents,
|
|
utils: () => utils_exports2,
|
|
validateEvent: () => validateEvent,
|
|
verifiedSymbol: () => verifiedSymbol,
|
|
verifyEvent: () => verifyEvent
|
|
});
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/_assert.js
|
|
function number(n) {
|
|
if (!Number.isSafeInteger(n) || n < 0)
|
|
throw new Error(`Wrong positive integer: ${n}`);
|
|
}
|
|
function bytes(b, ...lengths) {
|
|
if (!(b instanceof Uint8Array))
|
|
throw new Error("Expected Uint8Array");
|
|
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
|
|
}
|
|
function hash(hash3) {
|
|
if (typeof hash3 !== "function" || typeof hash3.create !== "function")
|
|
throw new Error("Hash should be wrapped by utils.wrapConstructor");
|
|
number(hash3.outputLen);
|
|
number(hash3.blockLen);
|
|
}
|
|
function exists(instance, checkFinished = true) {
|
|
if (instance.destroyed)
|
|
throw new Error("Hash instance has been destroyed");
|
|
if (checkFinished && instance.finished)
|
|
throw new Error("Hash#digest() has already been called");
|
|
}
|
|
function output(out, instance) {
|
|
bytes(out);
|
|
const min = instance.outputLen;
|
|
if (out.length < min) {
|
|
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
|
}
|
|
}
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/crypto.js
|
|
var crypto = typeof globalThis === "object" && "crypto" in globalThis ? globalThis.crypto : void 0;
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/utils.js
|
|
var u8a = (a) => a instanceof Uint8Array;
|
|
var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
var rotr = (word, shift) => word << 32 - shift | word >>> shift;
|
|
var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
|
|
if (!isLE)
|
|
throw new Error("Non little-endian hardware is not supported");
|
|
function utf8ToBytes(str) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
}
|
|
function toBytes(data) {
|
|
if (typeof data === "string")
|
|
data = utf8ToBytes(data);
|
|
if (!u8a(data))
|
|
throw new Error(`expected Uint8Array, got ${typeof data}`);
|
|
return data;
|
|
}
|
|
function concatBytes(...arrays) {
|
|
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
|
|
let pad2 = 0;
|
|
arrays.forEach((a) => {
|
|
if (!u8a(a))
|
|
throw new Error("Uint8Array expected");
|
|
r.set(a, pad2);
|
|
pad2 += a.length;
|
|
});
|
|
return r;
|
|
}
|
|
var Hash = class {
|
|
clone() {
|
|
return this._cloneInto();
|
|
}
|
|
};
|
|
var toStr = {}.toString;
|
|
function wrapConstructor(hashCons) {
|
|
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
|
|
const tmp = hashCons();
|
|
hashC.outputLen = tmp.outputLen;
|
|
hashC.blockLen = tmp.blockLen;
|
|
hashC.create = () => hashCons();
|
|
return hashC;
|
|
}
|
|
function randomBytes(bytesLength = 32) {
|
|
if (crypto && typeof crypto.getRandomValues === "function") {
|
|
return crypto.getRandomValues(new Uint8Array(bytesLength));
|
|
}
|
|
throw new Error("crypto.getRandomValues must be defined");
|
|
}
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/_sha2.js
|
|
function setBigUint64(view, byteOffset, value, isLE4) {
|
|
if (typeof view.setBigUint64 === "function")
|
|
return view.setBigUint64(byteOffset, value, isLE4);
|
|
const _32n2 = BigInt(32);
|
|
const _u32_max = BigInt(4294967295);
|
|
const wh = Number(value >> _32n2 & _u32_max);
|
|
const wl = Number(value & _u32_max);
|
|
const h = isLE4 ? 4 : 0;
|
|
const l = isLE4 ? 0 : 4;
|
|
view.setUint32(byteOffset + h, wh, isLE4);
|
|
view.setUint32(byteOffset + l, wl, isLE4);
|
|
}
|
|
var SHA2 = class extends Hash {
|
|
constructor(blockLen, outputLen, padOffset, isLE4) {
|
|
super();
|
|
this.blockLen = blockLen;
|
|
this.outputLen = outputLen;
|
|
this.padOffset = padOffset;
|
|
this.isLE = isLE4;
|
|
this.finished = false;
|
|
this.length = 0;
|
|
this.pos = 0;
|
|
this.destroyed = false;
|
|
this.buffer = new Uint8Array(blockLen);
|
|
this.view = createView(this.buffer);
|
|
}
|
|
update(data) {
|
|
exists(this);
|
|
const { view, buffer, blockLen } = this;
|
|
data = toBytes(data);
|
|
const len = data.length;
|
|
for (let pos = 0; pos < len; ) {
|
|
const take = Math.min(blockLen - this.pos, len - pos);
|
|
if (take === blockLen) {
|
|
const dataView = createView(data);
|
|
for (; blockLen <= len - pos; pos += blockLen)
|
|
this.process(dataView, pos);
|
|
continue;
|
|
}
|
|
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
this.pos += take;
|
|
pos += take;
|
|
if (this.pos === blockLen) {
|
|
this.process(view, 0);
|
|
this.pos = 0;
|
|
}
|
|
}
|
|
this.length += data.length;
|
|
this.roundClean();
|
|
return this;
|
|
}
|
|
digestInto(out) {
|
|
exists(this);
|
|
output(out, this);
|
|
this.finished = true;
|
|
const { buffer, view, blockLen, isLE: isLE4 } = this;
|
|
let { pos } = this;
|
|
buffer[pos++] = 128;
|
|
this.buffer.subarray(pos).fill(0);
|
|
if (this.padOffset > blockLen - pos) {
|
|
this.process(view, 0);
|
|
pos = 0;
|
|
}
|
|
for (let i2 = pos; i2 < blockLen; i2++)
|
|
buffer[i2] = 0;
|
|
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE4);
|
|
this.process(view, 0);
|
|
const oview = createView(out);
|
|
const len = this.outputLen;
|
|
if (len % 4)
|
|
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
const outLen = len / 4;
|
|
const state = this.get();
|
|
if (outLen > state.length)
|
|
throw new Error("_sha2: outputLen bigger than state");
|
|
for (let i2 = 0; i2 < outLen; i2++)
|
|
oview.setUint32(4 * i2, state[i2], isLE4);
|
|
}
|
|
digest() {
|
|
const { buffer, outputLen } = this;
|
|
this.digestInto(buffer);
|
|
const res = buffer.slice(0, outputLen);
|
|
this.destroy();
|
|
return res;
|
|
}
|
|
_cloneInto(to) {
|
|
to || (to = new this.constructor());
|
|
to.set(...this.get());
|
|
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
to.length = length;
|
|
to.pos = pos;
|
|
to.finished = finished;
|
|
to.destroyed = destroyed;
|
|
if (length % blockLen)
|
|
to.buffer.set(buffer);
|
|
return to;
|
|
}
|
|
};
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha256.js
|
|
var Chi = (a, b, c) => a & b ^ ~a & c;
|
|
var Maj = (a, b, c) => a & b ^ a & c ^ b & c;
|
|
var SHA256_K = /* @__PURE__ */ new Uint32Array([
|
|
1116352408,
|
|
1899447441,
|
|
3049323471,
|
|
3921009573,
|
|
961987163,
|
|
1508970993,
|
|
2453635748,
|
|
2870763221,
|
|
3624381080,
|
|
310598401,
|
|
607225278,
|
|
1426881987,
|
|
1925078388,
|
|
2162078206,
|
|
2614888103,
|
|
3248222580,
|
|
3835390401,
|
|
4022224774,
|
|
264347078,
|
|
604807628,
|
|
770255983,
|
|
1249150122,
|
|
1555081692,
|
|
1996064986,
|
|
2554220882,
|
|
2821834349,
|
|
2952996808,
|
|
3210313671,
|
|
3336571891,
|
|
3584528711,
|
|
113926993,
|
|
338241895,
|
|
666307205,
|
|
773529912,
|
|
1294757372,
|
|
1396182291,
|
|
1695183700,
|
|
1986661051,
|
|
2177026350,
|
|
2456956037,
|
|
2730485921,
|
|
2820302411,
|
|
3259730800,
|
|
3345764771,
|
|
3516065817,
|
|
3600352804,
|
|
4094571909,
|
|
275423344,
|
|
430227734,
|
|
506948616,
|
|
659060556,
|
|
883997877,
|
|
958139571,
|
|
1322822218,
|
|
1537002063,
|
|
1747873779,
|
|
1955562222,
|
|
2024104815,
|
|
2227730452,
|
|
2361852424,
|
|
2428436474,
|
|
2756734187,
|
|
3204031479,
|
|
3329325298
|
|
]);
|
|
var IV = /* @__PURE__ */ new Uint32Array([
|
|
1779033703,
|
|
3144134277,
|
|
1013904242,
|
|
2773480762,
|
|
1359893119,
|
|
2600822924,
|
|
528734635,
|
|
1541459225
|
|
]);
|
|
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
var SHA256 = class extends SHA2 {
|
|
constructor() {
|
|
super(64, 32, 8, false);
|
|
this.A = IV[0] | 0;
|
|
this.B = IV[1] | 0;
|
|
this.C = IV[2] | 0;
|
|
this.D = IV[3] | 0;
|
|
this.E = IV[4] | 0;
|
|
this.F = IV[5] | 0;
|
|
this.G = IV[6] | 0;
|
|
this.H = IV[7] | 0;
|
|
}
|
|
get() {
|
|
const { A, B, C, D, E, F, G, H } = this;
|
|
return [A, B, C, D, E, F, G, H];
|
|
}
|
|
set(A, B, C, D, E, F, G, H) {
|
|
this.A = A | 0;
|
|
this.B = B | 0;
|
|
this.C = C | 0;
|
|
this.D = D | 0;
|
|
this.E = E | 0;
|
|
this.F = F | 0;
|
|
this.G = G | 0;
|
|
this.H = H | 0;
|
|
}
|
|
process(view, offset) {
|
|
for (let i2 = 0; i2 < 16; i2++, offset += 4)
|
|
SHA256_W[i2] = view.getUint32(offset, false);
|
|
for (let i2 = 16; i2 < 64; i2++) {
|
|
const W15 = SHA256_W[i2 - 15];
|
|
const W2 = SHA256_W[i2 - 2];
|
|
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
SHA256_W[i2] = s1 + SHA256_W[i2 - 7] + s0 + SHA256_W[i2 - 16] | 0;
|
|
}
|
|
let { A, B, C, D, E, F, G, H } = this;
|
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i2] + SHA256_W[i2] | 0;
|
|
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
H = G;
|
|
G = F;
|
|
F = E;
|
|
E = D + T1 | 0;
|
|
D = C;
|
|
C = B;
|
|
B = A;
|
|
A = T1 + T2 | 0;
|
|
}
|
|
A = A + this.A | 0;
|
|
B = B + this.B | 0;
|
|
C = C + this.C | 0;
|
|
D = D + this.D | 0;
|
|
E = E + this.E | 0;
|
|
F = F + this.F | 0;
|
|
G = G + this.G | 0;
|
|
H = H + this.H | 0;
|
|
this.set(A, B, C, D, E, F, G, H);
|
|
}
|
|
roundClean() {
|
|
SHA256_W.fill(0);
|
|
}
|
|
destroy() {
|
|
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
this.buffer.fill(0);
|
|
}
|
|
};
|
|
var sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
|
|
|
|
// node_modules/@noble/curves/esm/abstract/utils.js
|
|
var utils_exports = {};
|
|
__export(utils_exports, {
|
|
bitGet: () => bitGet,
|
|
bitLen: () => bitLen,
|
|
bitMask: () => bitMask,
|
|
bitSet: () => bitSet,
|
|
bytesToHex: () => bytesToHex,
|
|
bytesToNumberBE: () => bytesToNumberBE,
|
|
bytesToNumberLE: () => bytesToNumberLE,
|
|
concatBytes: () => concatBytes2,
|
|
createHmacDrbg: () => createHmacDrbg,
|
|
ensureBytes: () => ensureBytes,
|
|
equalBytes: () => equalBytes,
|
|
hexToBytes: () => hexToBytes,
|
|
hexToNumber: () => hexToNumber,
|
|
numberToBytesBE: () => numberToBytesBE,
|
|
numberToBytesLE: () => numberToBytesLE,
|
|
numberToHexUnpadded: () => numberToHexUnpadded,
|
|
numberToVarBytesBE: () => numberToVarBytesBE,
|
|
utf8ToBytes: () => utf8ToBytes2,
|
|
validateObject: () => validateObject
|
|
});
|
|
var _0n = BigInt(0);
|
|
var _1n = BigInt(1);
|
|
var _2n = BigInt(2);
|
|
var u8a2 = (a) => a instanceof Uint8Array;
|
|
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i2) => i2.toString(16).padStart(2, "0"));
|
|
function bytesToHex(bytes4) {
|
|
if (!u8a2(bytes4))
|
|
throw new Error("Uint8Array expected");
|
|
let hex2 = "";
|
|
for (let i2 = 0; i2 < bytes4.length; i2++) {
|
|
hex2 += hexes[bytes4[i2]];
|
|
}
|
|
return hex2;
|
|
}
|
|
function numberToHexUnpadded(num) {
|
|
const hex2 = num.toString(16);
|
|
return hex2.length & 1 ? `0${hex2}` : hex2;
|
|
}
|
|
function hexToNumber(hex2) {
|
|
if (typeof hex2 !== "string")
|
|
throw new Error("hex string expected, got " + typeof hex2);
|
|
return BigInt(hex2 === "" ? "0" : `0x${hex2}`);
|
|
}
|
|
function hexToBytes(hex2) {
|
|
if (typeof hex2 !== "string")
|
|
throw new Error("hex string expected, got " + typeof hex2);
|
|
const len = hex2.length;
|
|
if (len % 2)
|
|
throw new Error("padded hex string expected, got unpadded hex of length " + len);
|
|
const array = new Uint8Array(len / 2);
|
|
for (let i2 = 0; i2 < array.length; i2++) {
|
|
const j = i2 * 2;
|
|
const hexByte = hex2.slice(j, j + 2);
|
|
const byte = Number.parseInt(hexByte, 16);
|
|
if (Number.isNaN(byte) || byte < 0)
|
|
throw new Error("Invalid byte sequence");
|
|
array[i2] = byte;
|
|
}
|
|
return array;
|
|
}
|
|
function bytesToNumberBE(bytes4) {
|
|
return hexToNumber(bytesToHex(bytes4));
|
|
}
|
|
function bytesToNumberLE(bytes4) {
|
|
if (!u8a2(bytes4))
|
|
throw new Error("Uint8Array expected");
|
|
return hexToNumber(bytesToHex(Uint8Array.from(bytes4).reverse()));
|
|
}
|
|
function numberToBytesBE(n, len) {
|
|
return hexToBytes(n.toString(16).padStart(len * 2, "0"));
|
|
}
|
|
function numberToBytesLE(n, len) {
|
|
return numberToBytesBE(n, len).reverse();
|
|
}
|
|
function numberToVarBytesBE(n) {
|
|
return hexToBytes(numberToHexUnpadded(n));
|
|
}
|
|
function ensureBytes(title, hex2, expectedLength) {
|
|
let res;
|
|
if (typeof hex2 === "string") {
|
|
try {
|
|
res = hexToBytes(hex2);
|
|
} catch (e) {
|
|
throw new Error(`${title} must be valid hex string, got "${hex2}". Cause: ${e}`);
|
|
}
|
|
} else if (u8a2(hex2)) {
|
|
res = Uint8Array.from(hex2);
|
|
} else {
|
|
throw new Error(`${title} must be hex string or Uint8Array`);
|
|
}
|
|
const len = res.length;
|
|
if (typeof expectedLength === "number" && len !== expectedLength)
|
|
throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
|
|
return res;
|
|
}
|
|
function concatBytes2(...arrays) {
|
|
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
|
|
let pad2 = 0;
|
|
arrays.forEach((a) => {
|
|
if (!u8a2(a))
|
|
throw new Error("Uint8Array expected");
|
|
r.set(a, pad2);
|
|
pad2 += a.length;
|
|
});
|
|
return r;
|
|
}
|
|
function equalBytes(b1, b2) {
|
|
if (b1.length !== b2.length)
|
|
return false;
|
|
for (let i2 = 0; i2 < b1.length; i2++)
|
|
if (b1[i2] !== b2[i2])
|
|
return false;
|
|
return true;
|
|
}
|
|
function utf8ToBytes2(str) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
}
|
|
function bitLen(n) {
|
|
let len;
|
|
for (len = 0; n > _0n; n >>= _1n, len += 1)
|
|
;
|
|
return len;
|
|
}
|
|
function bitGet(n, pos) {
|
|
return n >> BigInt(pos) & _1n;
|
|
}
|
|
var bitSet = (n, pos, value) => {
|
|
return n | (value ? _1n : _0n) << BigInt(pos);
|
|
};
|
|
var bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
|
|
var u8n = (data) => new Uint8Array(data);
|
|
var u8fr = (arr) => Uint8Array.from(arr);
|
|
function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
if (typeof hashLen !== "number" || hashLen < 2)
|
|
throw new Error("hashLen must be a number");
|
|
if (typeof qByteLen !== "number" || qByteLen < 2)
|
|
throw new Error("qByteLen must be a number");
|
|
if (typeof hmacFn !== "function")
|
|
throw new Error("hmacFn must be a function");
|
|
let v = u8n(hashLen);
|
|
let k = u8n(hashLen);
|
|
let i2 = 0;
|
|
const reset = () => {
|
|
v.fill(1);
|
|
k.fill(0);
|
|
i2 = 0;
|
|
};
|
|
const h = (...b) => hmacFn(k, v, ...b);
|
|
const reseed = (seed = u8n()) => {
|
|
k = h(u8fr([0]), seed);
|
|
v = h();
|
|
if (seed.length === 0)
|
|
return;
|
|
k = h(u8fr([1]), seed);
|
|
v = h();
|
|
};
|
|
const gen = () => {
|
|
if (i2++ >= 1e3)
|
|
throw new Error("drbg: tried 1000 values");
|
|
let len = 0;
|
|
const out = [];
|
|
while (len < qByteLen) {
|
|
v = h();
|
|
const sl = v.slice();
|
|
out.push(sl);
|
|
len += v.length;
|
|
}
|
|
return concatBytes2(...out);
|
|
};
|
|
const genUntil = (seed, pred) => {
|
|
reset();
|
|
reseed(seed);
|
|
let res = void 0;
|
|
while (!(res = pred(gen())))
|
|
reseed();
|
|
reset();
|
|
return res;
|
|
};
|
|
return genUntil;
|
|
}
|
|
var validatorFns = {
|
|
bigint: (val) => typeof val === "bigint",
|
|
function: (val) => typeof val === "function",
|
|
boolean: (val) => typeof val === "boolean",
|
|
string: (val) => typeof val === "string",
|
|
stringOrUint8Array: (val) => typeof val === "string" || val instanceof Uint8Array,
|
|
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
array: (val) => Array.isArray(val),
|
|
field: (val, object) => object.Fp.isValid(val),
|
|
hash: (val) => typeof val === "function" && Number.isSafeInteger(val.outputLen)
|
|
};
|
|
function validateObject(object, validators, optValidators = {}) {
|
|
const checkField = (fieldName, type, isOptional) => {
|
|
const checkVal = validatorFns[type];
|
|
if (typeof checkVal !== "function")
|
|
throw new Error(`Invalid validator "${type}", expected function`);
|
|
const val = object[fieldName];
|
|
if (isOptional && val === void 0)
|
|
return;
|
|
if (!checkVal(val, object)) {
|
|
throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
|
|
}
|
|
};
|
|
for (const [fieldName, type] of Object.entries(validators))
|
|
checkField(fieldName, type, false);
|
|
for (const [fieldName, type] of Object.entries(optValidators))
|
|
checkField(fieldName, type, true);
|
|
return object;
|
|
}
|
|
|
|
// node_modules/@noble/curves/esm/abstract/modular.js
|
|
var _0n2 = BigInt(0);
|
|
var _1n2 = BigInt(1);
|
|
var _2n2 = BigInt(2);
|
|
var _3n = BigInt(3);
|
|
var _4n = BigInt(4);
|
|
var _5n = BigInt(5);
|
|
var _8n = BigInt(8);
|
|
var _9n = BigInt(9);
|
|
var _16n = BigInt(16);
|
|
function mod(a, b) {
|
|
const result = a % b;
|
|
return result >= _0n2 ? result : b + result;
|
|
}
|
|
function pow(num, power, modulo) {
|
|
if (modulo <= _0n2 || power < _0n2)
|
|
throw new Error("Expected power/modulo > 0");
|
|
if (modulo === _1n2)
|
|
return _0n2;
|
|
let res = _1n2;
|
|
while (power > _0n2) {
|
|
if (power & _1n2)
|
|
res = res * num % modulo;
|
|
num = num * num % modulo;
|
|
power >>= _1n2;
|
|
}
|
|
return res;
|
|
}
|
|
function pow2(x, power, modulo) {
|
|
let res = x;
|
|
while (power-- > _0n2) {
|
|
res *= res;
|
|
res %= modulo;
|
|
}
|
|
return res;
|
|
}
|
|
function invert(number4, modulo) {
|
|
if (number4 === _0n2 || modulo <= _0n2) {
|
|
throw new Error(`invert: expected positive integers, got n=${number4} mod=${modulo}`);
|
|
}
|
|
let a = mod(number4, modulo);
|
|
let b = modulo;
|
|
let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
|
|
while (a !== _0n2) {
|
|
const q = b / a;
|
|
const r = b % a;
|
|
const m = x - u * q;
|
|
const n = y - v * q;
|
|
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
}
|
|
const gcd2 = b;
|
|
if (gcd2 !== _1n2)
|
|
throw new Error("invert: does not exist");
|
|
return mod(x, modulo);
|
|
}
|
|
function tonelliShanks(P) {
|
|
const legendreC = (P - _1n2) / _2n2;
|
|
let Q, S, Z;
|
|
for (Q = P - _1n2, S = 0; Q % _2n2 === _0n2; Q /= _2n2, S++)
|
|
;
|
|
for (Z = _2n2; Z < P && pow(Z, legendreC, P) !== P - _1n2; Z++)
|
|
;
|
|
if (S === 1) {
|
|
const p1div4 = (P + _1n2) / _4n;
|
|
return function tonelliFast(Fp3, n) {
|
|
const root = Fp3.pow(n, p1div4);
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
const Q1div2 = (Q + _1n2) / _2n2;
|
|
return function tonelliSlow(Fp3, n) {
|
|
if (Fp3.pow(n, legendreC) === Fp3.neg(Fp3.ONE))
|
|
throw new Error("Cannot find square root");
|
|
let r = S;
|
|
let g = Fp3.pow(Fp3.mul(Fp3.ONE, Z), Q);
|
|
let x = Fp3.pow(n, Q1div2);
|
|
let b = Fp3.pow(n, Q);
|
|
while (!Fp3.eql(b, Fp3.ONE)) {
|
|
if (Fp3.eql(b, Fp3.ZERO))
|
|
return Fp3.ZERO;
|
|
let m = 1;
|
|
for (let t2 = Fp3.sqr(b); m < r; m++) {
|
|
if (Fp3.eql(t2, Fp3.ONE))
|
|
break;
|
|
t2 = Fp3.sqr(t2);
|
|
}
|
|
const ge2 = Fp3.pow(g, _1n2 << BigInt(r - m - 1));
|
|
g = Fp3.sqr(ge2);
|
|
x = Fp3.mul(x, ge2);
|
|
b = Fp3.mul(b, g);
|
|
r = m;
|
|
}
|
|
return x;
|
|
};
|
|
}
|
|
function FpSqrt(P) {
|
|
if (P % _4n === _3n) {
|
|
const p1div4 = (P + _1n2) / _4n;
|
|
return function sqrt3mod4(Fp3, n) {
|
|
const root = Fp3.pow(n, p1div4);
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
if (P % _8n === _5n) {
|
|
const c1 = (P - _5n) / _8n;
|
|
return function sqrt5mod8(Fp3, n) {
|
|
const n2 = Fp3.mul(n, _2n2);
|
|
const v = Fp3.pow(n2, c1);
|
|
const nv = Fp3.mul(n, v);
|
|
const i2 = Fp3.mul(Fp3.mul(nv, _2n2), v);
|
|
const root = Fp3.mul(nv, Fp3.sub(i2, Fp3.ONE));
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
if (P % _16n === _9n) {
|
|
}
|
|
return tonelliShanks(P);
|
|
}
|
|
var FIELD_FIELDS = [
|
|
"create",
|
|
"isValid",
|
|
"is0",
|
|
"neg",
|
|
"inv",
|
|
"sqrt",
|
|
"sqr",
|
|
"eql",
|
|
"add",
|
|
"sub",
|
|
"mul",
|
|
"pow",
|
|
"div",
|
|
"addN",
|
|
"subN",
|
|
"mulN",
|
|
"sqrN"
|
|
];
|
|
function validateField(field) {
|
|
const initial = {
|
|
ORDER: "bigint",
|
|
MASK: "bigint",
|
|
BYTES: "isSafeInteger",
|
|
BITS: "isSafeInteger"
|
|
};
|
|
const opts = FIELD_FIELDS.reduce((map, val) => {
|
|
map[val] = "function";
|
|
return map;
|
|
}, initial);
|
|
return validateObject(field, opts);
|
|
}
|
|
function FpPow(f2, num, power) {
|
|
if (power < _0n2)
|
|
throw new Error("Expected power > 0");
|
|
if (power === _0n2)
|
|
return f2.ONE;
|
|
if (power === _1n2)
|
|
return num;
|
|
let p = f2.ONE;
|
|
let d = num;
|
|
while (power > _0n2) {
|
|
if (power & _1n2)
|
|
p = f2.mul(p, d);
|
|
d = f2.sqr(d);
|
|
power >>= _1n2;
|
|
}
|
|
return p;
|
|
}
|
|
function FpInvertBatch(f2, nums) {
|
|
const tmp = new Array(nums.length);
|
|
const lastMultiplied = nums.reduce((acc, num, i2) => {
|
|
if (f2.is0(num))
|
|
return acc;
|
|
tmp[i2] = acc;
|
|
return f2.mul(acc, num);
|
|
}, f2.ONE);
|
|
const inverted = f2.inv(lastMultiplied);
|
|
nums.reduceRight((acc, num, i2) => {
|
|
if (f2.is0(num))
|
|
return acc;
|
|
tmp[i2] = f2.mul(acc, tmp[i2]);
|
|
return f2.mul(acc, num);
|
|
}, inverted);
|
|
return tmp;
|
|
}
|
|
function nLength(n, nBitLength) {
|
|
const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length;
|
|
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
return { nBitLength: _nBitLength, nByteLength };
|
|
}
|
|
function Field(ORDER, bitLen3, isLE4 = false, redef = {}) {
|
|
if (ORDER <= _0n2)
|
|
throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
|
|
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen3);
|
|
if (BYTES > 2048)
|
|
throw new Error("Field lengths over 2048 bytes are not supported");
|
|
const sqrtP = FpSqrt(ORDER);
|
|
const f2 = Object.freeze({
|
|
ORDER,
|
|
BITS,
|
|
BYTES,
|
|
MASK: bitMask(BITS),
|
|
ZERO: _0n2,
|
|
ONE: _1n2,
|
|
create: (num) => mod(num, ORDER),
|
|
isValid: (num) => {
|
|
if (typeof num !== "bigint")
|
|
throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
|
|
return _0n2 <= num && num < ORDER;
|
|
},
|
|
is0: (num) => num === _0n2,
|
|
isOdd: (num) => (num & _1n2) === _1n2,
|
|
neg: (num) => mod(-num, ORDER),
|
|
eql: (lhs, rhs) => lhs === rhs,
|
|
sqr: (num) => mod(num * num, ORDER),
|
|
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
|
|
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
|
|
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
|
|
pow: (num, power) => FpPow(f2, num, power),
|
|
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
|
|
sqrN: (num) => num * num,
|
|
addN: (lhs, rhs) => lhs + rhs,
|
|
subN: (lhs, rhs) => lhs - rhs,
|
|
mulN: (lhs, rhs) => lhs * rhs,
|
|
inv: (num) => invert(num, ORDER),
|
|
sqrt: redef.sqrt || ((n) => sqrtP(f2, n)),
|
|
invertBatch: (lst) => FpInvertBatch(f2, lst),
|
|
cmov: (a, b, c) => c ? b : a,
|
|
toBytes: (num) => isLE4 ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES),
|
|
fromBytes: (bytes4) => {
|
|
if (bytes4.length !== BYTES)
|
|
throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes4.length}`);
|
|
return isLE4 ? bytesToNumberLE(bytes4) : bytesToNumberBE(bytes4);
|
|
}
|
|
});
|
|
return Object.freeze(f2);
|
|
}
|
|
function getFieldBytesLength(fieldOrder) {
|
|
if (typeof fieldOrder !== "bigint")
|
|
throw new Error("field order must be bigint");
|
|
const bitLength = fieldOrder.toString(2).length;
|
|
return Math.ceil(bitLength / 8);
|
|
}
|
|
function getMinHashLength(fieldOrder) {
|
|
const length = getFieldBytesLength(fieldOrder);
|
|
return length + Math.ceil(length / 2);
|
|
}
|
|
function mapHashToField(key, fieldOrder, isLE4 = false) {
|
|
const len = key.length;
|
|
const fieldLen = getFieldBytesLength(fieldOrder);
|
|
const minLen = getMinHashLength(fieldOrder);
|
|
if (len < 16 || len < minLen || len > 1024)
|
|
throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
|
|
const num = isLE4 ? bytesToNumberBE(key) : bytesToNumberLE(key);
|
|
const reduced = mod(num, fieldOrder - _1n2) + _1n2;
|
|
return isLE4 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
|
|
}
|
|
|
|
// node_modules/@noble/curves/esm/abstract/curve.js
|
|
var _0n3 = BigInt(0);
|
|
var _1n3 = BigInt(1);
|
|
function wNAF(c, bits) {
|
|
const constTimeNegate = (condition, item) => {
|
|
const neg = item.negate();
|
|
return condition ? neg : item;
|
|
};
|
|
const opts = (W) => {
|
|
const windows = Math.ceil(bits / W) + 1;
|
|
const windowSize = 2 ** (W - 1);
|
|
return { windows, windowSize };
|
|
};
|
|
return {
|
|
constTimeNegate,
|
|
unsafeLadder(elm, n) {
|
|
let p = c.ZERO;
|
|
let d = elm;
|
|
while (n > _0n3) {
|
|
if (n & _1n3)
|
|
p = p.add(d);
|
|
d = d.double();
|
|
n >>= _1n3;
|
|
}
|
|
return p;
|
|
},
|
|
precomputeWindow(elm, W) {
|
|
const { windows, windowSize } = opts(W);
|
|
const points = [];
|
|
let p = elm;
|
|
let base = p;
|
|
for (let window = 0; window < windows; window++) {
|
|
base = p;
|
|
points.push(base);
|
|
for (let i2 = 1; i2 < windowSize; i2++) {
|
|
base = base.add(p);
|
|
points.push(base);
|
|
}
|
|
p = base.double();
|
|
}
|
|
return points;
|
|
},
|
|
wNAF(W, precomputes, n) {
|
|
const { windows, windowSize } = opts(W);
|
|
let p = c.ZERO;
|
|
let f2 = c.BASE;
|
|
const mask = BigInt(2 ** W - 1);
|
|
const maxNumber = 2 ** W;
|
|
const shiftBy = BigInt(W);
|
|
for (let window = 0; window < windows; window++) {
|
|
const offset = window * windowSize;
|
|
let wbits = Number(n & mask);
|
|
n >>= shiftBy;
|
|
if (wbits > windowSize) {
|
|
wbits -= maxNumber;
|
|
n += _1n3;
|
|
}
|
|
const offset1 = offset;
|
|
const offset2 = offset + Math.abs(wbits) - 1;
|
|
const cond1 = window % 2 !== 0;
|
|
const cond2 = wbits < 0;
|
|
if (wbits === 0) {
|
|
f2 = f2.add(constTimeNegate(cond1, precomputes[offset1]));
|
|
} else {
|
|
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
|
|
}
|
|
}
|
|
return { p, f: f2 };
|
|
},
|
|
wNAFCached(P, precomputesMap, n, transform) {
|
|
const W = P._WINDOW_SIZE || 1;
|
|
let comp = precomputesMap.get(P);
|
|
if (!comp) {
|
|
comp = this.precomputeWindow(P, W);
|
|
if (W !== 1) {
|
|
precomputesMap.set(P, transform(comp));
|
|
}
|
|
}
|
|
return this.wNAF(W, comp, n);
|
|
}
|
|
};
|
|
}
|
|
function validateBasic(curve) {
|
|
validateField(curve.Fp);
|
|
validateObject(curve, {
|
|
n: "bigint",
|
|
h: "bigint",
|
|
Gx: "field",
|
|
Gy: "field"
|
|
}, {
|
|
nBitLength: "isSafeInteger",
|
|
nByteLength: "isSafeInteger"
|
|
});
|
|
return Object.freeze({
|
|
...nLength(curve.n, curve.nBitLength),
|
|
...curve,
|
|
...{ p: curve.Fp.ORDER }
|
|
});
|
|
}
|
|
|
|
// node_modules/@noble/curves/esm/abstract/weierstrass.js
|
|
function validatePointOpts(curve) {
|
|
const opts = validateBasic(curve);
|
|
validateObject(opts, {
|
|
a: "field",
|
|
b: "field"
|
|
}, {
|
|
allowedPrivateKeyLengths: "array",
|
|
wrapPrivateKey: "boolean",
|
|
isTorsionFree: "function",
|
|
clearCofactor: "function",
|
|
allowInfinityPoint: "boolean",
|
|
fromBytes: "function",
|
|
toBytes: "function"
|
|
});
|
|
const { endo, Fp: Fp3, a } = opts;
|
|
if (endo) {
|
|
if (!Fp3.eql(a, Fp3.ZERO)) {
|
|
throw new Error("Endomorphism can only be defined for Koblitz curves that have a=0");
|
|
}
|
|
if (typeof endo !== "object" || typeof endo.beta !== "bigint" || typeof endo.splitScalar !== "function") {
|
|
throw new Error("Expected endomorphism with beta: bigint and splitScalar: function");
|
|
}
|
|
}
|
|
return Object.freeze({ ...opts });
|
|
}
|
|
var { bytesToNumberBE: b2n, hexToBytes: h2b } = utils_exports;
|
|
var DER = {
|
|
Err: class DERErr extends Error {
|
|
constructor(m = "") {
|
|
super(m);
|
|
}
|
|
},
|
|
_parseInt(data) {
|
|
const { Err: E } = DER;
|
|
if (data.length < 2 || data[0] !== 2)
|
|
throw new E("Invalid signature integer tag");
|
|
const len = data[1];
|
|
const res = data.subarray(2, len + 2);
|
|
if (!len || res.length !== len)
|
|
throw new E("Invalid signature integer: wrong length");
|
|
if (res[0] & 128)
|
|
throw new E("Invalid signature integer: negative");
|
|
if (res[0] === 0 && !(res[1] & 128))
|
|
throw new E("Invalid signature integer: unnecessary leading zero");
|
|
return { d: b2n(res), l: data.subarray(len + 2) };
|
|
},
|
|
toSig(hex2) {
|
|
const { Err: E } = DER;
|
|
const data = typeof hex2 === "string" ? h2b(hex2) : hex2;
|
|
if (!(data instanceof Uint8Array))
|
|
throw new Error("ui8a expected");
|
|
let l = data.length;
|
|
if (l < 2 || data[0] != 48)
|
|
throw new E("Invalid signature tag");
|
|
if (data[1] !== l - 2)
|
|
throw new E("Invalid signature: incorrect length");
|
|
const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));
|
|
const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);
|
|
if (rBytesLeft.length)
|
|
throw new E("Invalid signature: left bytes after parsing");
|
|
return { r, s };
|
|
},
|
|
hexFromSig(sig) {
|
|
const slice = (s2) => Number.parseInt(s2[0], 16) & 8 ? "00" + s2 : s2;
|
|
const h = (num) => {
|
|
const hex2 = num.toString(16);
|
|
return hex2.length & 1 ? `0${hex2}` : hex2;
|
|
};
|
|
const s = slice(h(sig.s));
|
|
const r = slice(h(sig.r));
|
|
const shl = s.length / 2;
|
|
const rhl = r.length / 2;
|
|
const sl = h(shl);
|
|
const rl = h(rhl);
|
|
return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
|
|
}
|
|
};
|
|
var _0n4 = BigInt(0);
|
|
var _1n4 = BigInt(1);
|
|
var _2n3 = BigInt(2);
|
|
var _3n2 = BigInt(3);
|
|
var _4n2 = BigInt(4);
|
|
function weierstrassPoints(opts) {
|
|
const CURVE = validatePointOpts(opts);
|
|
const { Fp: Fp3 } = CURVE;
|
|
const toBytes4 = CURVE.toBytes || ((_c, point, _isCompressed) => {
|
|
const a = point.toAffine();
|
|
return concatBytes2(Uint8Array.from([4]), Fp3.toBytes(a.x), Fp3.toBytes(a.y));
|
|
});
|
|
const fromBytes = CURVE.fromBytes || ((bytes4) => {
|
|
const tail = bytes4.subarray(1);
|
|
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
|
|
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
|
|
return { x, y };
|
|
});
|
|
function weierstrassEquation(x) {
|
|
const { a, b } = CURVE;
|
|
const x2 = Fp3.sqr(x);
|
|
const x3 = Fp3.mul(x2, x);
|
|
return Fp3.add(Fp3.add(x3, Fp3.mul(x, a)), b);
|
|
}
|
|
if (!Fp3.eql(Fp3.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
|
|
throw new Error("bad generator point: equation left != right");
|
|
function isWithinCurveOrder(num) {
|
|
return typeof num === "bigint" && _0n4 < num && num < CURVE.n;
|
|
}
|
|
function assertGE(num) {
|
|
if (!isWithinCurveOrder(num))
|
|
throw new Error("Expected valid bigint: 0 < bigint < curve.n");
|
|
}
|
|
function normPrivateKeyToScalar(key) {
|
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
|
if (lengths && typeof key !== "bigint") {
|
|
if (key instanceof Uint8Array)
|
|
key = bytesToHex(key);
|
|
if (typeof key !== "string" || !lengths.includes(key.length))
|
|
throw new Error("Invalid key");
|
|
key = key.padStart(nByteLength * 2, "0");
|
|
}
|
|
let num;
|
|
try {
|
|
num = typeof key === "bigint" ? key : bytesToNumberBE(ensureBytes("private key", key, nByteLength));
|
|
} catch (error) {
|
|
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
|
}
|
|
if (wrapPrivateKey)
|
|
num = mod(num, n);
|
|
assertGE(num);
|
|
return num;
|
|
}
|
|
const pointPrecomputes = /* @__PURE__ */ new Map();
|
|
function assertPrjPoint(other) {
|
|
if (!(other instanceof Point4))
|
|
throw new Error("ProjectivePoint expected");
|
|
}
|
|
class Point4 {
|
|
constructor(px, py, pz) {
|
|
this.px = px;
|
|
this.py = py;
|
|
this.pz = pz;
|
|
if (px == null || !Fp3.isValid(px))
|
|
throw new Error("x required");
|
|
if (py == null || !Fp3.isValid(py))
|
|
throw new Error("y required");
|
|
if (pz == null || !Fp3.isValid(pz))
|
|
throw new Error("z required");
|
|
}
|
|
static fromAffine(p) {
|
|
const { x, y } = p || {};
|
|
if (!p || !Fp3.isValid(x) || !Fp3.isValid(y))
|
|
throw new Error("invalid affine point");
|
|
if (p instanceof Point4)
|
|
throw new Error("projective point not allowed");
|
|
const is0 = (i2) => Fp3.eql(i2, Fp3.ZERO);
|
|
if (is0(x) && is0(y))
|
|
return Point4.ZERO;
|
|
return new Point4(x, y, Fp3.ONE);
|
|
}
|
|
get x() {
|
|
return this.toAffine().x;
|
|
}
|
|
get y() {
|
|
return this.toAffine().y;
|
|
}
|
|
static normalizeZ(points) {
|
|
const toInv = Fp3.invertBatch(points.map((p) => p.pz));
|
|
return points.map((p, i2) => p.toAffine(toInv[i2])).map(Point4.fromAffine);
|
|
}
|
|
static fromHex(hex2) {
|
|
const P = Point4.fromAffine(fromBytes(ensureBytes("pointHex", hex2)));
|
|
P.assertValidity();
|
|
return P;
|
|
}
|
|
static fromPrivateKey(privateKey) {
|
|
return Point4.BASE.multiply(normPrivateKeyToScalar(privateKey));
|
|
}
|
|
_setWindowSize(windowSize) {
|
|
this._WINDOW_SIZE = windowSize;
|
|
pointPrecomputes.delete(this);
|
|
}
|
|
assertValidity() {
|
|
if (this.is0()) {
|
|
if (CURVE.allowInfinityPoint && !Fp3.is0(this.py))
|
|
return;
|
|
throw new Error("bad point: ZERO");
|
|
}
|
|
const { x, y } = this.toAffine();
|
|
if (!Fp3.isValid(x) || !Fp3.isValid(y))
|
|
throw new Error("bad point: x or y not FE");
|
|
const left = Fp3.sqr(y);
|
|
const right = weierstrassEquation(x);
|
|
if (!Fp3.eql(left, right))
|
|
throw new Error("bad point: equation left != right");
|
|
if (!this.isTorsionFree())
|
|
throw new Error("bad point: not in prime-order subgroup");
|
|
}
|
|
hasEvenY() {
|
|
const { y } = this.toAffine();
|
|
if (Fp3.isOdd)
|
|
return !Fp3.isOdd(y);
|
|
throw new Error("Field doesn't support isOdd");
|
|
}
|
|
equals(other) {
|
|
assertPrjPoint(other);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
const U1 = Fp3.eql(Fp3.mul(X1, Z2), Fp3.mul(X2, Z1));
|
|
const U2 = Fp3.eql(Fp3.mul(Y1, Z2), Fp3.mul(Y2, Z1));
|
|
return U1 && U2;
|
|
}
|
|
negate() {
|
|
return new Point4(this.px, Fp3.neg(this.py), this.pz);
|
|
}
|
|
double() {
|
|
const { a, b } = CURVE;
|
|
const b3 = Fp3.mul(b, _3n2);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
let t0 = Fp3.mul(X1, X1);
|
|
let t1 = Fp3.mul(Y1, Y1);
|
|
let t2 = Fp3.mul(Z1, Z1);
|
|
let t3 = Fp3.mul(X1, Y1);
|
|
t3 = Fp3.add(t3, t3);
|
|
Z3 = Fp3.mul(X1, Z1);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
X3 = Fp3.mul(a, Z3);
|
|
Y3 = Fp3.mul(b3, t2);
|
|
Y3 = Fp3.add(X3, Y3);
|
|
X3 = Fp3.sub(t1, Y3);
|
|
Y3 = Fp3.add(t1, Y3);
|
|
Y3 = Fp3.mul(X3, Y3);
|
|
X3 = Fp3.mul(t3, X3);
|
|
Z3 = Fp3.mul(b3, Z3);
|
|
t2 = Fp3.mul(a, t2);
|
|
t3 = Fp3.sub(t0, t2);
|
|
t3 = Fp3.mul(a, t3);
|
|
t3 = Fp3.add(t3, Z3);
|
|
Z3 = Fp3.add(t0, t0);
|
|
t0 = Fp3.add(Z3, t0);
|
|
t0 = Fp3.add(t0, t2);
|
|
t0 = Fp3.mul(t0, t3);
|
|
Y3 = Fp3.add(Y3, t0);
|
|
t2 = Fp3.mul(Y1, Z1);
|
|
t2 = Fp3.add(t2, t2);
|
|
t0 = Fp3.mul(t2, t3);
|
|
X3 = Fp3.sub(X3, t0);
|
|
Z3 = Fp3.mul(t2, t1);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
return new Point4(X3, Y3, Z3);
|
|
}
|
|
add(other) {
|
|
assertPrjPoint(other);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
const a = CURVE.a;
|
|
const b3 = Fp3.mul(CURVE.b, _3n2);
|
|
let t0 = Fp3.mul(X1, X2);
|
|
let t1 = Fp3.mul(Y1, Y2);
|
|
let t2 = Fp3.mul(Z1, Z2);
|
|
let t3 = Fp3.add(X1, Y1);
|
|
let t4 = Fp3.add(X2, Y2);
|
|
t3 = Fp3.mul(t3, t4);
|
|
t4 = Fp3.add(t0, t1);
|
|
t3 = Fp3.sub(t3, t4);
|
|
t4 = Fp3.add(X1, Z1);
|
|
let t5 = Fp3.add(X2, Z2);
|
|
t4 = Fp3.mul(t4, t5);
|
|
t5 = Fp3.add(t0, t2);
|
|
t4 = Fp3.sub(t4, t5);
|
|
t5 = Fp3.add(Y1, Z1);
|
|
X3 = Fp3.add(Y2, Z2);
|
|
t5 = Fp3.mul(t5, X3);
|
|
X3 = Fp3.add(t1, t2);
|
|
t5 = Fp3.sub(t5, X3);
|
|
Z3 = Fp3.mul(a, t4);
|
|
X3 = Fp3.mul(b3, t2);
|
|
Z3 = Fp3.add(X3, Z3);
|
|
X3 = Fp3.sub(t1, Z3);
|
|
Z3 = Fp3.add(t1, Z3);
|
|
Y3 = Fp3.mul(X3, Z3);
|
|
t1 = Fp3.add(t0, t0);
|
|
t1 = Fp3.add(t1, t0);
|
|
t2 = Fp3.mul(a, t2);
|
|
t4 = Fp3.mul(b3, t4);
|
|
t1 = Fp3.add(t1, t2);
|
|
t2 = Fp3.sub(t0, t2);
|
|
t2 = Fp3.mul(a, t2);
|
|
t4 = Fp3.add(t4, t2);
|
|
t0 = Fp3.mul(t1, t4);
|
|
Y3 = Fp3.add(Y3, t0);
|
|
t0 = Fp3.mul(t5, t4);
|
|
X3 = Fp3.mul(t3, X3);
|
|
X3 = Fp3.sub(X3, t0);
|
|
t0 = Fp3.mul(t3, t1);
|
|
Z3 = Fp3.mul(t5, Z3);
|
|
Z3 = Fp3.add(Z3, t0);
|
|
return new Point4(X3, Y3, Z3);
|
|
}
|
|
subtract(other) {
|
|
return this.add(other.negate());
|
|
}
|
|
is0() {
|
|
return this.equals(Point4.ZERO);
|
|
}
|
|
wNAF(n) {
|
|
return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
|
|
const toInv = Fp3.invertBatch(comp.map((p) => p.pz));
|
|
return comp.map((p, i2) => p.toAffine(toInv[i2])).map(Point4.fromAffine);
|
|
});
|
|
}
|
|
multiplyUnsafe(n) {
|
|
const I = Point4.ZERO;
|
|
if (n === _0n4)
|
|
return I;
|
|
assertGE(n);
|
|
if (n === _1n4)
|
|
return this;
|
|
const { endo } = CURVE;
|
|
if (!endo)
|
|
return wnaf.unsafeLadder(this, n);
|
|
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
|
|
let k1p = I;
|
|
let k2p = I;
|
|
let d = this;
|
|
while (k1 > _0n4 || k2 > _0n4) {
|
|
if (k1 & _1n4)
|
|
k1p = k1p.add(d);
|
|
if (k2 & _1n4)
|
|
k2p = k2p.add(d);
|
|
d = d.double();
|
|
k1 >>= _1n4;
|
|
k2 >>= _1n4;
|
|
}
|
|
if (k1neg)
|
|
k1p = k1p.negate();
|
|
if (k2neg)
|
|
k2p = k2p.negate();
|
|
k2p = new Point4(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
return k1p.add(k2p);
|
|
}
|
|
multiply(scalar) {
|
|
assertGE(scalar);
|
|
let n = scalar;
|
|
let point, fake;
|
|
const { endo } = CURVE;
|
|
if (endo) {
|
|
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
|
|
let { p: k1p, f: f1p } = this.wNAF(k1);
|
|
let { p: k2p, f: f2p } = this.wNAF(k2);
|
|
k1p = wnaf.constTimeNegate(k1neg, k1p);
|
|
k2p = wnaf.constTimeNegate(k2neg, k2p);
|
|
k2p = new Point4(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
point = k1p.add(k2p);
|
|
fake = f1p.add(f2p);
|
|
} else {
|
|
const { p, f: f2 } = this.wNAF(n);
|
|
point = p;
|
|
fake = f2;
|
|
}
|
|
return Point4.normalizeZ([point, fake])[0];
|
|
}
|
|
multiplyAndAddUnsafe(Q, a, b) {
|
|
const G = Point4.BASE;
|
|
const mul3 = (P, a2) => a2 === _0n4 || a2 === _1n4 || !P.equals(G) ? P.multiplyUnsafe(a2) : P.multiply(a2);
|
|
const sum = mul3(this, a).add(mul3(Q, b));
|
|
return sum.is0() ? void 0 : sum;
|
|
}
|
|
toAffine(iz) {
|
|
const { px: x, py: y, pz: z } = this;
|
|
const is0 = this.is0();
|
|
if (iz == null)
|
|
iz = is0 ? Fp3.ONE : Fp3.inv(z);
|
|
const ax = Fp3.mul(x, iz);
|
|
const ay = Fp3.mul(y, iz);
|
|
const zz = Fp3.mul(z, iz);
|
|
if (is0)
|
|
return { x: Fp3.ZERO, y: Fp3.ZERO };
|
|
if (!Fp3.eql(zz, Fp3.ONE))
|
|
throw new Error("invZ was invalid");
|
|
return { x: ax, y: ay };
|
|
}
|
|
isTorsionFree() {
|
|
const { h: cofactor, isTorsionFree } = CURVE;
|
|
if (cofactor === _1n4)
|
|
return true;
|
|
if (isTorsionFree)
|
|
return isTorsionFree(Point4, this);
|
|
throw new Error("isTorsionFree() has not been declared for the elliptic curve");
|
|
}
|
|
clearCofactor() {
|
|
const { h: cofactor, clearCofactor } = CURVE;
|
|
if (cofactor === _1n4)
|
|
return this;
|
|
if (clearCofactor)
|
|
return clearCofactor(Point4, this);
|
|
return this.multiplyUnsafe(CURVE.h);
|
|
}
|
|
toRawBytes(isCompressed = true) {
|
|
this.assertValidity();
|
|
return toBytes4(Point4, this, isCompressed);
|
|
}
|
|
toHex(isCompressed = true) {
|
|
return bytesToHex(this.toRawBytes(isCompressed));
|
|
}
|
|
}
|
|
Point4.BASE = new Point4(CURVE.Gx, CURVE.Gy, Fp3.ONE);
|
|
Point4.ZERO = new Point4(Fp3.ZERO, Fp3.ONE, Fp3.ZERO);
|
|
const _bits = CURVE.nBitLength;
|
|
const wnaf = wNAF(Point4, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
|
|
return {
|
|
CURVE,
|
|
ProjectivePoint: Point4,
|
|
normPrivateKeyToScalar,
|
|
weierstrassEquation,
|
|
isWithinCurveOrder
|
|
};
|
|
}
|
|
function validateOpts(curve) {
|
|
const opts = validateBasic(curve);
|
|
validateObject(opts, {
|
|
hash: "hash",
|
|
hmac: "function",
|
|
randomBytes: "function"
|
|
}, {
|
|
bits2int: "function",
|
|
bits2int_modN: "function",
|
|
lowS: "boolean"
|
|
});
|
|
return Object.freeze({ lowS: true, ...opts });
|
|
}
|
|
function weierstrass(curveDef) {
|
|
const CURVE = validateOpts(curveDef);
|
|
const { Fp: Fp3, n: CURVE_ORDER } = CURVE;
|
|
const compressedLen = Fp3.BYTES + 1;
|
|
const uncompressedLen = 2 * Fp3.BYTES + 1;
|
|
function isValidFieldElement(num) {
|
|
return _0n4 < num && num < Fp3.ORDER;
|
|
}
|
|
function modN2(a) {
|
|
return mod(a, CURVE_ORDER);
|
|
}
|
|
function invN(a) {
|
|
return invert(a, CURVE_ORDER);
|
|
}
|
|
const { ProjectivePoint: Point4, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints({
|
|
...CURVE,
|
|
toBytes(_c, point, isCompressed) {
|
|
const a = point.toAffine();
|
|
const x = Fp3.toBytes(a.x);
|
|
const cat = concatBytes2;
|
|
if (isCompressed) {
|
|
return cat(Uint8Array.from([point.hasEvenY() ? 2 : 3]), x);
|
|
} else {
|
|
return cat(Uint8Array.from([4]), x, Fp3.toBytes(a.y));
|
|
}
|
|
},
|
|
fromBytes(bytes4) {
|
|
const len = bytes4.length;
|
|
const head = bytes4[0];
|
|
const tail = bytes4.subarray(1);
|
|
if (len === compressedLen && (head === 2 || head === 3)) {
|
|
const x = bytesToNumberBE(tail);
|
|
if (!isValidFieldElement(x))
|
|
throw new Error("Point is not on curve");
|
|
const y2 = weierstrassEquation(x);
|
|
let y = Fp3.sqrt(y2);
|
|
const isYOdd = (y & _1n4) === _1n4;
|
|
const isHeadOdd = (head & 1) === 1;
|
|
if (isHeadOdd !== isYOdd)
|
|
y = Fp3.neg(y);
|
|
return { x, y };
|
|
} else if (len === uncompressedLen && head === 4) {
|
|
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
|
|
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
|
|
return { x, y };
|
|
} else {
|
|
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
|
|
}
|
|
}
|
|
});
|
|
const numToNByteStr = (num) => bytesToHex(numberToBytesBE(num, CURVE.nByteLength));
|
|
function isBiggerThanHalfOrder(number4) {
|
|
const HALF = CURVE_ORDER >> _1n4;
|
|
return number4 > HALF;
|
|
}
|
|
function normalizeS(s) {
|
|
return isBiggerThanHalfOrder(s) ? modN2(-s) : s;
|
|
}
|
|
const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to));
|
|
class Signature {
|
|
constructor(r, s, recovery) {
|
|
this.r = r;
|
|
this.s = s;
|
|
this.recovery = recovery;
|
|
this.assertValidity();
|
|
}
|
|
static fromCompact(hex2) {
|
|
const l = CURVE.nByteLength;
|
|
hex2 = ensureBytes("compactSignature", hex2, l * 2);
|
|
return new Signature(slcNum(hex2, 0, l), slcNum(hex2, l, 2 * l));
|
|
}
|
|
static fromDER(hex2) {
|
|
const { r, s } = DER.toSig(ensureBytes("DER", hex2));
|
|
return new Signature(r, s);
|
|
}
|
|
assertValidity() {
|
|
if (!isWithinCurveOrder(this.r))
|
|
throw new Error("r must be 0 < r < CURVE.n");
|
|
if (!isWithinCurveOrder(this.s))
|
|
throw new Error("s must be 0 < s < CURVE.n");
|
|
}
|
|
addRecoveryBit(recovery) {
|
|
return new Signature(this.r, this.s, recovery);
|
|
}
|
|
recoverPublicKey(msgHash) {
|
|
const { r, s, recovery: rec } = this;
|
|
const h = bits2int_modN(ensureBytes("msgHash", msgHash));
|
|
if (rec == null || ![0, 1, 2, 3].includes(rec))
|
|
throw new Error("recovery id invalid");
|
|
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
|
|
if (radj >= Fp3.ORDER)
|
|
throw new Error("recovery id 2 or 3 invalid");
|
|
const prefix = (rec & 1) === 0 ? "02" : "03";
|
|
const R = Point4.fromHex(prefix + numToNByteStr(radj));
|
|
const ir = invN(radj);
|
|
const u1 = modN2(-h * ir);
|
|
const u2 = modN2(s * ir);
|
|
const Q = Point4.BASE.multiplyAndAddUnsafe(R, u1, u2);
|
|
if (!Q)
|
|
throw new Error("point at infinify");
|
|
Q.assertValidity();
|
|
return Q;
|
|
}
|
|
hasHighS() {
|
|
return isBiggerThanHalfOrder(this.s);
|
|
}
|
|
normalizeS() {
|
|
return this.hasHighS() ? new Signature(this.r, modN2(-this.s), this.recovery) : this;
|
|
}
|
|
toDERRawBytes() {
|
|
return hexToBytes(this.toDERHex());
|
|
}
|
|
toDERHex() {
|
|
return DER.hexFromSig({ r: this.r, s: this.s });
|
|
}
|
|
toCompactRawBytes() {
|
|
return hexToBytes(this.toCompactHex());
|
|
}
|
|
toCompactHex() {
|
|
return numToNByteStr(this.r) + numToNByteStr(this.s);
|
|
}
|
|
}
|
|
const utils2 = {
|
|
isValidPrivateKey(privateKey) {
|
|
try {
|
|
normPrivateKeyToScalar(privateKey);
|
|
return true;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
normPrivateKeyToScalar,
|
|
randomPrivateKey: () => {
|
|
const length = getMinHashLength(CURVE.n);
|
|
return mapHashToField(CURVE.randomBytes(length), CURVE.n);
|
|
},
|
|
precompute(windowSize = 8, point = Point4.BASE) {
|
|
point._setWindowSize(windowSize);
|
|
point.multiply(BigInt(3));
|
|
return point;
|
|
}
|
|
};
|
|
function getPublicKey2(privateKey, isCompressed = true) {
|
|
return Point4.fromPrivateKey(privateKey).toRawBytes(isCompressed);
|
|
}
|
|
function isProbPub(item) {
|
|
const arr = item instanceof Uint8Array;
|
|
const str = typeof item === "string";
|
|
const len = (arr || str) && item.length;
|
|
if (arr)
|
|
return len === compressedLen || len === uncompressedLen;
|
|
if (str)
|
|
return len === 2 * compressedLen || len === 2 * uncompressedLen;
|
|
if (item instanceof Point4)
|
|
return true;
|
|
return false;
|
|
}
|
|
function getSharedSecret(privateA, publicB, isCompressed = true) {
|
|
if (isProbPub(privateA))
|
|
throw new Error("first arg must be private key");
|
|
if (!isProbPub(publicB))
|
|
throw new Error("second arg must be public key");
|
|
const b = Point4.fromHex(publicB);
|
|
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
|
|
}
|
|
const bits2int = CURVE.bits2int || function(bytes4) {
|
|
const num = bytesToNumberBE(bytes4);
|
|
const delta = bytes4.length * 8 - CURVE.nBitLength;
|
|
return delta > 0 ? num >> BigInt(delta) : num;
|
|
};
|
|
const bits2int_modN = CURVE.bits2int_modN || function(bytes4) {
|
|
return modN2(bits2int(bytes4));
|
|
};
|
|
const ORDER_MASK = bitMask(CURVE.nBitLength);
|
|
function int2octets(num) {
|
|
if (typeof num !== "bigint")
|
|
throw new Error("bigint expected");
|
|
if (!(_0n4 <= num && num < ORDER_MASK))
|
|
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
|
return numberToBytesBE(num, CURVE.nByteLength);
|
|
}
|
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
|
if (["recovered", "canonical"].some((k) => k in opts))
|
|
throw new Error("sign() legacy options not supported");
|
|
const { hash: hash3, randomBytes: randomBytes3 } = CURVE;
|
|
let { lowS, prehash, extraEntropy: ent } = opts;
|
|
if (lowS == null)
|
|
lowS = true;
|
|
msgHash = ensureBytes("msgHash", msgHash);
|
|
if (prehash)
|
|
msgHash = ensureBytes("prehashed msgHash", hash3(msgHash));
|
|
const h1int = bits2int_modN(msgHash);
|
|
const d = normPrivateKeyToScalar(privateKey);
|
|
const seedArgs = [int2octets(d), int2octets(h1int)];
|
|
if (ent != null) {
|
|
const e = ent === true ? randomBytes3(Fp3.BYTES) : ent;
|
|
seedArgs.push(ensureBytes("extraEntropy", e));
|
|
}
|
|
const seed = concatBytes2(...seedArgs);
|
|
const m = h1int;
|
|
function k2sig(kBytes) {
|
|
const k = bits2int(kBytes);
|
|
if (!isWithinCurveOrder(k))
|
|
return;
|
|
const ik = invN(k);
|
|
const q = Point4.BASE.multiply(k).toAffine();
|
|
const r = modN2(q.x);
|
|
if (r === _0n4)
|
|
return;
|
|
const s = modN2(ik * modN2(m + r * d));
|
|
if (s === _0n4)
|
|
return;
|
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n4);
|
|
let normS = s;
|
|
if (lowS && isBiggerThanHalfOrder(s)) {
|
|
normS = normalizeS(s);
|
|
recovery ^= 1;
|
|
}
|
|
return new Signature(r, normS, recovery);
|
|
}
|
|
return { seed, k2sig };
|
|
}
|
|
const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
|
|
const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
|
|
function sign(msgHash, privKey, opts = defaultSigOpts) {
|
|
const { seed, k2sig } = prepSig(msgHash, privKey, opts);
|
|
const C = CURVE;
|
|
const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
|
|
return drbg(seed, k2sig);
|
|
}
|
|
Point4.BASE._setWindowSize(8);
|
|
function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
|
|
const sg = signature;
|
|
msgHash = ensureBytes("msgHash", msgHash);
|
|
publicKey = ensureBytes("publicKey", publicKey);
|
|
if ("strict" in opts)
|
|
throw new Error("options.strict was renamed to lowS");
|
|
const { lowS, prehash } = opts;
|
|
let _sig = void 0;
|
|
let P;
|
|
try {
|
|
if (typeof sg === "string" || sg instanceof Uint8Array) {
|
|
try {
|
|
_sig = Signature.fromDER(sg);
|
|
} catch (derError) {
|
|
if (!(derError instanceof DER.Err))
|
|
throw derError;
|
|
_sig = Signature.fromCompact(sg);
|
|
}
|
|
} else if (typeof sg === "object" && typeof sg.r === "bigint" && typeof sg.s === "bigint") {
|
|
const { r: r2, s: s2 } = sg;
|
|
_sig = new Signature(r2, s2);
|
|
} else {
|
|
throw new Error("PARSE");
|
|
}
|
|
P = Point4.fromHex(publicKey);
|
|
} catch (error) {
|
|
if (error.message === "PARSE")
|
|
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
|
|
return false;
|
|
}
|
|
if (lowS && _sig.hasHighS())
|
|
return false;
|
|
if (prehash)
|
|
msgHash = CURVE.hash(msgHash);
|
|
const { r, s } = _sig;
|
|
const h = bits2int_modN(msgHash);
|
|
const is = invN(s);
|
|
const u1 = modN2(h * is);
|
|
const u2 = modN2(r * is);
|
|
const R = Point4.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine();
|
|
if (!R)
|
|
return false;
|
|
const v = modN2(R.x);
|
|
return v === r;
|
|
}
|
|
return {
|
|
CURVE,
|
|
getPublicKey: getPublicKey2,
|
|
getSharedSecret,
|
|
sign,
|
|
verify,
|
|
ProjectivePoint: Point4,
|
|
Signature,
|
|
utils: utils2
|
|
};
|
|
}
|
|
|
|
// node_modules/@noble/curves/node_modules/@noble/hashes/esm/hmac.js
|
|
var HMAC = class extends Hash {
|
|
constructor(hash3, _key) {
|
|
super();
|
|
this.finished = false;
|
|
this.destroyed = false;
|
|
hash(hash3);
|
|
const key = toBytes(_key);
|
|
this.iHash = hash3.create();
|
|
if (typeof this.iHash.update !== "function")
|
|
throw new Error("Expected instance of class which extends utils.Hash");
|
|
this.blockLen = this.iHash.blockLen;
|
|
this.outputLen = this.iHash.outputLen;
|
|
const blockLen = this.blockLen;
|
|
const pad2 = new Uint8Array(blockLen);
|
|
pad2.set(key.length > blockLen ? hash3.create().update(key).digest() : key);
|
|
for (let i2 = 0; i2 < pad2.length; i2++)
|
|
pad2[i2] ^= 54;
|
|
this.iHash.update(pad2);
|
|
this.oHash = hash3.create();
|
|
for (let i2 = 0; i2 < pad2.length; i2++)
|
|
pad2[i2] ^= 54 ^ 92;
|
|
this.oHash.update(pad2);
|
|
pad2.fill(0);
|
|
}
|
|
update(buf) {
|
|
exists(this);
|
|
this.iHash.update(buf);
|
|
return this;
|
|
}
|
|
digestInto(out) {
|
|
exists(this);
|
|
bytes(out, this.outputLen);
|
|
this.finished = true;
|
|
this.iHash.digestInto(out);
|
|
this.oHash.update(out);
|
|
this.oHash.digestInto(out);
|
|
this.destroy();
|
|
}
|
|
digest() {
|
|
const out = new Uint8Array(this.oHash.outputLen);
|
|
this.digestInto(out);
|
|
return out;
|
|
}
|
|
_cloneInto(to) {
|
|
to || (to = Object.create(Object.getPrototypeOf(this), {}));
|
|
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
|
|
to = to;
|
|
to.finished = finished;
|
|
to.destroyed = destroyed;
|
|
to.blockLen = blockLen;
|
|
to.outputLen = outputLen;
|
|
to.oHash = oHash._cloneInto(to.oHash);
|
|
to.iHash = iHash._cloneInto(to.iHash);
|
|
return to;
|
|
}
|
|
destroy() {
|
|
this.destroyed = true;
|
|
this.oHash.destroy();
|
|
this.iHash.destroy();
|
|
}
|
|
};
|
|
var hmac = (hash3, key, message) => new HMAC(hash3, key).update(message).digest();
|
|
hmac.create = (hash3, key) => new HMAC(hash3, key);
|
|
|
|
// node_modules/@noble/curves/esm/_shortw_utils.js
|
|
function getHash(hash3) {
|
|
return {
|
|
hash: hash3,
|
|
hmac: (key, ...msgs) => hmac(hash3, key, concatBytes(...msgs)),
|
|
randomBytes
|
|
};
|
|
}
|
|
function createCurve(curveDef, defHash) {
|
|
const create = (hash3) => weierstrass({ ...curveDef, ...getHash(hash3) });
|
|
return Object.freeze({ ...create(defHash), create });
|
|
}
|
|
|
|
// node_modules/@noble/curves/esm/secp256k1.js
|
|
var secp256k1P = BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f");
|
|
var secp256k1N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
|
var _1n5 = BigInt(1);
|
|
var _2n4 = BigInt(2);
|
|
var divNearest = (a, b) => (a + b / _2n4) / b;
|
|
function sqrtMod(y) {
|
|
const P = secp256k1P;
|
|
const _3n5 = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
|
|
const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
|
|
const b2 = y * y * y % P;
|
|
const b3 = b2 * b2 * y % P;
|
|
const b6 = pow2(b3, _3n5, P) * b3 % P;
|
|
const b9 = pow2(b6, _3n5, P) * b3 % P;
|
|
const b11 = pow2(b9, _2n4, P) * b2 % P;
|
|
const b22 = pow2(b11, _11n, P) * b11 % P;
|
|
const b44 = pow2(b22, _22n, P) * b22 % P;
|
|
const b88 = pow2(b44, _44n, P) * b44 % P;
|
|
const b176 = pow2(b88, _88n, P) * b88 % P;
|
|
const b220 = pow2(b176, _44n, P) * b44 % P;
|
|
const b223 = pow2(b220, _3n5, P) * b3 % P;
|
|
const t1 = pow2(b223, _23n, P) * b22 % P;
|
|
const t2 = pow2(t1, _6n, P) * b2 % P;
|
|
const root = pow2(t2, _2n4, P);
|
|
if (!Fp.eql(Fp.sqr(root), y))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
}
|
|
var Fp = Field(secp256k1P, void 0, void 0, { sqrt: sqrtMod });
|
|
var secp256k1 = createCurve({
|
|
a: BigInt(0),
|
|
b: BigInt(7),
|
|
Fp,
|
|
n: secp256k1N,
|
|
Gx: BigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240"),
|
|
Gy: BigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424"),
|
|
h: BigInt(1),
|
|
lowS: true,
|
|
endo: {
|
|
beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),
|
|
splitScalar: (k) => {
|
|
const n = secp256k1N;
|
|
const a1 = BigInt("0x3086d221a7d46bcde86c90e49284eb15");
|
|
const b1 = -_1n5 * BigInt("0xe4437ed6010e88286f547fa90abfe4c3");
|
|
const a2 = BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8");
|
|
const b2 = a1;
|
|
const POW_2_128 = BigInt("0x100000000000000000000000000000000");
|
|
const c1 = divNearest(b2 * k, n);
|
|
const c2 = divNearest(-b1 * k, n);
|
|
let k1 = mod(k - c1 * a1 - c2 * a2, n);
|
|
let k2 = mod(-c1 * b1 - c2 * b2, n);
|
|
const k1neg = k1 > POW_2_128;
|
|
const k2neg = k2 > POW_2_128;
|
|
if (k1neg)
|
|
k1 = n - k1;
|
|
if (k2neg)
|
|
k2 = n - k2;
|
|
if (k1 > POW_2_128 || k2 > POW_2_128) {
|
|
throw new Error("splitScalar: Endomorphism failed, k=" + k);
|
|
}
|
|
return { k1neg, k1, k2neg, k2 };
|
|
}
|
|
}
|
|
}, sha256);
|
|
var _0n5 = BigInt(0);
|
|
var fe = (x) => typeof x === "bigint" && _0n5 < x && x < secp256k1P;
|
|
var ge = (x) => typeof x === "bigint" && _0n5 < x && x < secp256k1N;
|
|
var TAGGED_HASH_PREFIXES = {};
|
|
function taggedHash(tag, ...messages) {
|
|
let tagP = TAGGED_HASH_PREFIXES[tag];
|
|
if (tagP === void 0) {
|
|
const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0)));
|
|
tagP = concatBytes2(tagH, tagH);
|
|
TAGGED_HASH_PREFIXES[tag] = tagP;
|
|
}
|
|
return sha256(concatBytes2(tagP, ...messages));
|
|
}
|
|
var pointToBytes = (point) => point.toRawBytes(true).slice(1);
|
|
var numTo32b = (n) => numberToBytesBE(n, 32);
|
|
var modP = (x) => mod(x, secp256k1P);
|
|
var modN = (x) => mod(x, secp256k1N);
|
|
var Point = secp256k1.ProjectivePoint;
|
|
var GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b);
|
|
function schnorrGetExtPubKey(priv) {
|
|
let d_ = secp256k1.utils.normPrivateKeyToScalar(priv);
|
|
let p = Point.fromPrivateKey(d_);
|
|
const scalar = p.hasEvenY() ? d_ : modN(-d_);
|
|
return { scalar, bytes: pointToBytes(p) };
|
|
}
|
|
function lift_x(x) {
|
|
if (!fe(x))
|
|
throw new Error("bad x: need 0 < x < p");
|
|
const xx = modP(x * x);
|
|
const c = modP(xx * x + BigInt(7));
|
|
let y = sqrtMod(c);
|
|
if (y % _2n4 !== _0n5)
|
|
y = modP(-y);
|
|
const p = new Point(x, y, _1n5);
|
|
p.assertValidity();
|
|
return p;
|
|
}
|
|
function challenge(...args) {
|
|
return modN(bytesToNumberBE(taggedHash("BIP0340/challenge", ...args)));
|
|
}
|
|
function schnorrGetPublicKey(privateKey) {
|
|
return schnorrGetExtPubKey(privateKey).bytes;
|
|
}
|
|
function schnorrSign(message, privateKey, auxRand = randomBytes(32)) {
|
|
const m = ensureBytes("message", message);
|
|
const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey);
|
|
const a = ensureBytes("auxRand", auxRand, 32);
|
|
const t = numTo32b(d ^ bytesToNumberBE(taggedHash("BIP0340/aux", a)));
|
|
const rand = taggedHash("BIP0340/nonce", t, px, m);
|
|
const k_ = modN(bytesToNumberBE(rand));
|
|
if (k_ === _0n5)
|
|
throw new Error("sign failed: k is zero");
|
|
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_);
|
|
const e = challenge(rx, px, m);
|
|
const sig = new Uint8Array(64);
|
|
sig.set(rx, 0);
|
|
sig.set(numTo32b(modN(k + e * d)), 32);
|
|
if (!schnorrVerify(sig, m, px))
|
|
throw new Error("sign: Invalid signature produced");
|
|
return sig;
|
|
}
|
|
function schnorrVerify(signature, message, publicKey) {
|
|
const sig = ensureBytes("signature", signature, 64);
|
|
const m = ensureBytes("message", message);
|
|
const pub = ensureBytes("publicKey", publicKey, 32);
|
|
try {
|
|
const P = lift_x(bytesToNumberBE(pub));
|
|
const r = bytesToNumberBE(sig.subarray(0, 32));
|
|
if (!fe(r))
|
|
return false;
|
|
const s = bytesToNumberBE(sig.subarray(32, 64));
|
|
if (!ge(s))
|
|
return false;
|
|
const e = challenge(numTo32b(r), pointToBytes(P), m);
|
|
const R = GmulAdd(P, s, modN(-e));
|
|
if (!R || !R.hasEvenY() || R.toAffine().x !== r)
|
|
return false;
|
|
return true;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
var schnorr = /* @__PURE__ */ (() => ({
|
|
getPublicKey: schnorrGetPublicKey,
|
|
sign: schnorrSign,
|
|
verify: schnorrVerify,
|
|
utils: {
|
|
randomPrivateKey: secp256k1.utils.randomPrivateKey,
|
|
lift_x,
|
|
pointToBytes,
|
|
numberToBytesBE,
|
|
bytesToNumberBE,
|
|
taggedHash,
|
|
mod
|
|
}
|
|
}))();
|
|
|
|
// node_modules/@noble/hashes/esm/crypto.js
|
|
var crypto2 = typeof globalThis === "object" && "crypto" in globalThis ? globalThis.crypto : void 0;
|
|
|
|
// node_modules/@noble/hashes/esm/utils.js
|
|
var u8a3 = (a) => a instanceof Uint8Array;
|
|
var createView2 = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
var rotr2 = (word, shift) => word << 32 - shift | word >>> shift;
|
|
var isLE2 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
|
|
if (!isLE2)
|
|
throw new Error("Non little-endian hardware is not supported");
|
|
var hexes2 = Array.from({ length: 256 }, (v, i2) => i2.toString(16).padStart(2, "0"));
|
|
function bytesToHex2(bytes4) {
|
|
if (!u8a3(bytes4))
|
|
throw new Error("Uint8Array expected");
|
|
let hex2 = "";
|
|
for (let i2 = 0; i2 < bytes4.length; i2++) {
|
|
hex2 += hexes2[bytes4[i2]];
|
|
}
|
|
return hex2;
|
|
}
|
|
function hexToBytes2(hex2) {
|
|
if (typeof hex2 !== "string")
|
|
throw new Error("hex string expected, got " + typeof hex2);
|
|
const len = hex2.length;
|
|
if (len % 2)
|
|
throw new Error("padded hex string expected, got unpadded hex of length " + len);
|
|
const array = new Uint8Array(len / 2);
|
|
for (let i2 = 0; i2 < array.length; i2++) {
|
|
const j = i2 * 2;
|
|
const hexByte = hex2.slice(j, j + 2);
|
|
const byte = Number.parseInt(hexByte, 16);
|
|
if (Number.isNaN(byte) || byte < 0)
|
|
throw new Error("Invalid byte sequence");
|
|
array[i2] = byte;
|
|
}
|
|
return array;
|
|
}
|
|
function utf8ToBytes3(str) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
}
|
|
function toBytes2(data) {
|
|
if (typeof data === "string")
|
|
data = utf8ToBytes3(data);
|
|
if (!u8a3(data))
|
|
throw new Error(`expected Uint8Array, got ${typeof data}`);
|
|
return data;
|
|
}
|
|
function concatBytes3(...arrays) {
|
|
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
|
|
let pad2 = 0;
|
|
arrays.forEach((a) => {
|
|
if (!u8a3(a))
|
|
throw new Error("Uint8Array expected");
|
|
r.set(a, pad2);
|
|
pad2 += a.length;
|
|
});
|
|
return r;
|
|
}
|
|
var Hash2 = class {
|
|
clone() {
|
|
return this._cloneInto();
|
|
}
|
|
};
|
|
var isPlainObject = (obj) => Object.prototype.toString.call(obj) === "[object Object]" && obj.constructor === Object;
|
|
function checkOpts(defaults, opts) {
|
|
if (opts !== void 0 && (typeof opts !== "object" || !isPlainObject(opts)))
|
|
throw new Error("Options should be object or undefined");
|
|
const merged = Object.assign(defaults, opts);
|
|
return merged;
|
|
}
|
|
function wrapConstructor2(hashCons) {
|
|
const hashC = (msg) => hashCons().update(toBytes2(msg)).digest();
|
|
const tmp = hashCons();
|
|
hashC.outputLen = tmp.outputLen;
|
|
hashC.blockLen = tmp.blockLen;
|
|
hashC.create = () => hashCons();
|
|
return hashC;
|
|
}
|
|
function randomBytes2(bytesLength = 32) {
|
|
if (crypto2 && typeof crypto2.getRandomValues === "function") {
|
|
return crypto2.getRandomValues(new Uint8Array(bytesLength));
|
|
}
|
|
throw new Error("crypto.getRandomValues must be defined");
|
|
}
|
|
|
|
// core.ts
|
|
var verifiedSymbol = Symbol("verified");
|
|
var isRecord = (obj) => obj instanceof Object;
|
|
function validateEvent(event) {
|
|
if (!isRecord(event))
|
|
return false;
|
|
if (typeof event.kind !== "number")
|
|
return false;
|
|
if (typeof event.content !== "string")
|
|
return false;
|
|
if (typeof event.created_at !== "number")
|
|
return false;
|
|
if (typeof event.pubkey !== "string")
|
|
return false;
|
|
if (!event.pubkey.match(/^[a-f0-9]{64}$/))
|
|
return false;
|
|
if (!Array.isArray(event.tags))
|
|
return false;
|
|
for (let i2 = 0; i2 < event.tags.length; i2++) {
|
|
let tag = event.tags[i2];
|
|
if (!Array.isArray(tag))
|
|
return false;
|
|
for (let j = 0; j < tag.length; j++) {
|
|
if (typeof tag[j] !== "string")
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function sortEvents(events) {
|
|
return events.sort((a, b) => {
|
|
if (a.created_at !== b.created_at) {
|
|
return b.created_at - a.created_at;
|
|
}
|
|
return a.id.localeCompare(b.id);
|
|
});
|
|
}
|
|
|
|
// node_modules/@noble/hashes/esm/_assert.js
|
|
function number2(n) {
|
|
if (!Number.isSafeInteger(n) || n < 0)
|
|
throw new Error(`Wrong positive integer: ${n}`);
|
|
}
|
|
function bool(b) {
|
|
if (typeof b !== "boolean")
|
|
throw new Error(`Expected boolean, not ${b}`);
|
|
}
|
|
function bytes2(b, ...lengths) {
|
|
if (!(b instanceof Uint8Array))
|
|
throw new Error("Expected Uint8Array");
|
|
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
|
|
}
|
|
function hash2(hash3) {
|
|
if (typeof hash3 !== "function" || typeof hash3.create !== "function")
|
|
throw new Error("Hash should be wrapped by utils.wrapConstructor");
|
|
number2(hash3.outputLen);
|
|
number2(hash3.blockLen);
|
|
}
|
|
function exists2(instance, checkFinished = true) {
|
|
if (instance.destroyed)
|
|
throw new Error("Hash instance has been destroyed");
|
|
if (checkFinished && instance.finished)
|
|
throw new Error("Hash#digest() has already been called");
|
|
}
|
|
function output2(out, instance) {
|
|
bytes2(out);
|
|
const min = instance.outputLen;
|
|
if (out.length < min) {
|
|
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
|
}
|
|
}
|
|
var assert = {
|
|
number: number2,
|
|
bool,
|
|
bytes: bytes2,
|
|
hash: hash2,
|
|
exists: exists2,
|
|
output: output2
|
|
};
|
|
var assert_default = assert;
|
|
|
|
// node_modules/@noble/hashes/esm/_sha2.js
|
|
function setBigUint642(view, byteOffset, value, isLE4) {
|
|
if (typeof view.setBigUint64 === "function")
|
|
return view.setBigUint64(byteOffset, value, isLE4);
|
|
const _32n2 = BigInt(32);
|
|
const _u32_max = BigInt(4294967295);
|
|
const wh = Number(value >> _32n2 & _u32_max);
|
|
const wl = Number(value & _u32_max);
|
|
const h = isLE4 ? 4 : 0;
|
|
const l = isLE4 ? 0 : 4;
|
|
view.setUint32(byteOffset + h, wh, isLE4);
|
|
view.setUint32(byteOffset + l, wl, isLE4);
|
|
}
|
|
var SHA22 = class extends Hash2 {
|
|
constructor(blockLen, outputLen, padOffset, isLE4) {
|
|
super();
|
|
this.blockLen = blockLen;
|
|
this.outputLen = outputLen;
|
|
this.padOffset = padOffset;
|
|
this.isLE = isLE4;
|
|
this.finished = false;
|
|
this.length = 0;
|
|
this.pos = 0;
|
|
this.destroyed = false;
|
|
this.buffer = new Uint8Array(blockLen);
|
|
this.view = createView2(this.buffer);
|
|
}
|
|
update(data) {
|
|
assert_default.exists(this);
|
|
const { view, buffer, blockLen } = this;
|
|
data = toBytes2(data);
|
|
const len = data.length;
|
|
for (let pos = 0; pos < len; ) {
|
|
const take = Math.min(blockLen - this.pos, len - pos);
|
|
if (take === blockLen) {
|
|
const dataView = createView2(data);
|
|
for (; blockLen <= len - pos; pos += blockLen)
|
|
this.process(dataView, pos);
|
|
continue;
|
|
}
|
|
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
this.pos += take;
|
|
pos += take;
|
|
if (this.pos === blockLen) {
|
|
this.process(view, 0);
|
|
this.pos = 0;
|
|
}
|
|
}
|
|
this.length += data.length;
|
|
this.roundClean();
|
|
return this;
|
|
}
|
|
digestInto(out) {
|
|
assert_default.exists(this);
|
|
assert_default.output(out, this);
|
|
this.finished = true;
|
|
const { buffer, view, blockLen, isLE: isLE4 } = this;
|
|
let { pos } = this;
|
|
buffer[pos++] = 128;
|
|
this.buffer.subarray(pos).fill(0);
|
|
if (this.padOffset > blockLen - pos) {
|
|
this.process(view, 0);
|
|
pos = 0;
|
|
}
|
|
for (let i2 = pos; i2 < blockLen; i2++)
|
|
buffer[i2] = 0;
|
|
setBigUint642(view, blockLen - 8, BigInt(this.length * 8), isLE4);
|
|
this.process(view, 0);
|
|
const oview = createView2(out);
|
|
const len = this.outputLen;
|
|
if (len % 4)
|
|
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
const outLen = len / 4;
|
|
const state = this.get();
|
|
if (outLen > state.length)
|
|
throw new Error("_sha2: outputLen bigger than state");
|
|
for (let i2 = 0; i2 < outLen; i2++)
|
|
oview.setUint32(4 * i2, state[i2], isLE4);
|
|
}
|
|
digest() {
|
|
const { buffer, outputLen } = this;
|
|
this.digestInto(buffer);
|
|
const res = buffer.slice(0, outputLen);
|
|
this.destroy();
|
|
return res;
|
|
}
|
|
_cloneInto(to) {
|
|
to || (to = new this.constructor());
|
|
to.set(...this.get());
|
|
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
to.length = length;
|
|
to.pos = pos;
|
|
to.finished = finished;
|
|
to.destroyed = destroyed;
|
|
if (length % blockLen)
|
|
to.buffer.set(buffer);
|
|
return to;
|
|
}
|
|
};
|
|
|
|
// node_modules/@noble/hashes/esm/sha256.js
|
|
var Chi2 = (a, b, c) => a & b ^ ~a & c;
|
|
var Maj2 = (a, b, c) => a & b ^ a & c ^ b & c;
|
|
var SHA256_K2 = new Uint32Array([
|
|
1116352408,
|
|
1899447441,
|
|
3049323471,
|
|
3921009573,
|
|
961987163,
|
|
1508970993,
|
|
2453635748,
|
|
2870763221,
|
|
3624381080,
|
|
310598401,
|
|
607225278,
|
|
1426881987,
|
|
1925078388,
|
|
2162078206,
|
|
2614888103,
|
|
3248222580,
|
|
3835390401,
|
|
4022224774,
|
|
264347078,
|
|
604807628,
|
|
770255983,
|
|
1249150122,
|
|
1555081692,
|
|
1996064986,
|
|
2554220882,
|
|
2821834349,
|
|
2952996808,
|
|
3210313671,
|
|
3336571891,
|
|
3584528711,
|
|
113926993,
|
|
338241895,
|
|
666307205,
|
|
773529912,
|
|
1294757372,
|
|
1396182291,
|
|
1695183700,
|
|
1986661051,
|
|
2177026350,
|
|
2456956037,
|
|
2730485921,
|
|
2820302411,
|
|
3259730800,
|
|
3345764771,
|
|
3516065817,
|
|
3600352804,
|
|
4094571909,
|
|
275423344,
|
|
430227734,
|
|
506948616,
|
|
659060556,
|
|
883997877,
|
|
958139571,
|
|
1322822218,
|
|
1537002063,
|
|
1747873779,
|
|
1955562222,
|
|
2024104815,
|
|
2227730452,
|
|
2361852424,
|
|
2428436474,
|
|
2756734187,
|
|
3204031479,
|
|
3329325298
|
|
]);
|
|
var IV2 = new Uint32Array([
|
|
1779033703,
|
|
3144134277,
|
|
1013904242,
|
|
2773480762,
|
|
1359893119,
|
|
2600822924,
|
|
528734635,
|
|
1541459225
|
|
]);
|
|
var SHA256_W2 = new Uint32Array(64);
|
|
var SHA2562 = class extends SHA22 {
|
|
constructor() {
|
|
super(64, 32, 8, false);
|
|
this.A = IV2[0] | 0;
|
|
this.B = IV2[1] | 0;
|
|
this.C = IV2[2] | 0;
|
|
this.D = IV2[3] | 0;
|
|
this.E = IV2[4] | 0;
|
|
this.F = IV2[5] | 0;
|
|
this.G = IV2[6] | 0;
|
|
this.H = IV2[7] | 0;
|
|
}
|
|
get() {
|
|
const { A, B, C, D, E, F, G, H } = this;
|
|
return [A, B, C, D, E, F, G, H];
|
|
}
|
|
set(A, B, C, D, E, F, G, H) {
|
|
this.A = A | 0;
|
|
this.B = B | 0;
|
|
this.C = C | 0;
|
|
this.D = D | 0;
|
|
this.E = E | 0;
|
|
this.F = F | 0;
|
|
this.G = G | 0;
|
|
this.H = H | 0;
|
|
}
|
|
process(view, offset) {
|
|
for (let i2 = 0; i2 < 16; i2++, offset += 4)
|
|
SHA256_W2[i2] = view.getUint32(offset, false);
|
|
for (let i2 = 16; i2 < 64; i2++) {
|
|
const W15 = SHA256_W2[i2 - 15];
|
|
const W2 = SHA256_W2[i2 - 2];
|
|
const s0 = rotr2(W15, 7) ^ rotr2(W15, 18) ^ W15 >>> 3;
|
|
const s1 = rotr2(W2, 17) ^ rotr2(W2, 19) ^ W2 >>> 10;
|
|
SHA256_W2[i2] = s1 + SHA256_W2[i2 - 7] + s0 + SHA256_W2[i2 - 16] | 0;
|
|
}
|
|
let { A, B, C, D, E, F, G, H } = this;
|
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
const sigma1 = rotr2(E, 6) ^ rotr2(E, 11) ^ rotr2(E, 25);
|
|
const T1 = H + sigma1 + Chi2(E, F, G) + SHA256_K2[i2] + SHA256_W2[i2] | 0;
|
|
const sigma0 = rotr2(A, 2) ^ rotr2(A, 13) ^ rotr2(A, 22);
|
|
const T2 = sigma0 + Maj2(A, B, C) | 0;
|
|
H = G;
|
|
G = F;
|
|
F = E;
|
|
E = D + T1 | 0;
|
|
D = C;
|
|
C = B;
|
|
B = A;
|
|
A = T1 + T2 | 0;
|
|
}
|
|
A = A + this.A | 0;
|
|
B = B + this.B | 0;
|
|
C = C + this.C | 0;
|
|
D = D + this.D | 0;
|
|
E = E + this.E | 0;
|
|
F = F + this.F | 0;
|
|
G = G + this.G | 0;
|
|
H = H + this.H | 0;
|
|
this.set(A, B, C, D, E, F, G, H);
|
|
}
|
|
roundClean() {
|
|
SHA256_W2.fill(0);
|
|
}
|
|
destroy() {
|
|
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
this.buffer.fill(0);
|
|
}
|
|
};
|
|
var SHA224 = class extends SHA2562 {
|
|
constructor() {
|
|
super();
|
|
this.A = 3238371032 | 0;
|
|
this.B = 914150663 | 0;
|
|
this.C = 812702999 | 0;
|
|
this.D = 4144912697 | 0;
|
|
this.E = 4290775857 | 0;
|
|
this.F = 1750603025 | 0;
|
|
this.G = 1694076839 | 0;
|
|
this.H = 3204075428 | 0;
|
|
this.outputLen = 28;
|
|
}
|
|
};
|
|
var sha2562 = wrapConstructor2(() => new SHA2562());
|
|
var sha224 = wrapConstructor2(() => new SHA224());
|
|
|
|
// utils.ts
|
|
var utils_exports2 = {};
|
|
__export(utils_exports2, {
|
|
Queue: () => Queue,
|
|
QueueNode: () => QueueNode,
|
|
binarySearch: () => binarySearch,
|
|
bytesToHex: () => bytesToHex2,
|
|
hexToBytes: () => hexToBytes2,
|
|
insertEventIntoAscendingList: () => insertEventIntoAscendingList,
|
|
insertEventIntoDescendingList: () => insertEventIntoDescendingList,
|
|
normalizeURL: () => normalizeURL,
|
|
utf8Decoder: () => utf8Decoder,
|
|
utf8Encoder: () => utf8Encoder
|
|
});
|
|
var utf8Decoder = new TextDecoder("utf-8");
|
|
var utf8Encoder = new TextEncoder();
|
|
function normalizeURL(url) {
|
|
try {
|
|
if (url.indexOf("://") === -1)
|
|
url = "wss://" + url;
|
|
let p = new URL(url);
|
|
p.pathname = p.pathname.replace(/\/+/g, "/");
|
|
if (p.pathname.endsWith("/"))
|
|
p.pathname = p.pathname.slice(0, -1);
|
|
if (p.port === "80" && p.protocol === "ws:" || p.port === "443" && p.protocol === "wss:")
|
|
p.port = "";
|
|
p.searchParams.sort();
|
|
p.hash = "";
|
|
return p.toString();
|
|
} catch (e) {
|
|
throw new Error(`Invalid URL: ${url}`);
|
|
}
|
|
}
|
|
function insertEventIntoDescendingList(sortedArray, event) {
|
|
const [idx, found] = binarySearch(sortedArray, (b) => {
|
|
if (event.id === b.id)
|
|
return 0;
|
|
if (event.created_at === b.created_at)
|
|
return -1;
|
|
return b.created_at - event.created_at;
|
|
});
|
|
if (!found) {
|
|
sortedArray.splice(idx, 0, event);
|
|
}
|
|
return sortedArray;
|
|
}
|
|
function insertEventIntoAscendingList(sortedArray, event) {
|
|
const [idx, found] = binarySearch(sortedArray, (b) => {
|
|
if (event.id === b.id)
|
|
return 0;
|
|
if (event.created_at === b.created_at)
|
|
return -1;
|
|
return event.created_at - b.created_at;
|
|
});
|
|
if (!found) {
|
|
sortedArray.splice(idx, 0, event);
|
|
}
|
|
return sortedArray;
|
|
}
|
|
function binarySearch(arr, compare) {
|
|
let start = 0;
|
|
let end = arr.length - 1;
|
|
while (start <= end) {
|
|
const mid = Math.floor((start + end) / 2);
|
|
const cmp = compare(arr[mid]);
|
|
if (cmp === 0) {
|
|
return [mid, true];
|
|
}
|
|
if (cmp < 0) {
|
|
end = mid - 1;
|
|
} else {
|
|
start = mid + 1;
|
|
}
|
|
}
|
|
return [start, false];
|
|
}
|
|
var QueueNode = class {
|
|
value;
|
|
next = null;
|
|
prev = null;
|
|
constructor(message) {
|
|
this.value = message;
|
|
}
|
|
};
|
|
var Queue = class {
|
|
first;
|
|
last;
|
|
constructor() {
|
|
this.first = null;
|
|
this.last = null;
|
|
}
|
|
enqueue(value) {
|
|
const newNode = new QueueNode(value);
|
|
if (!this.last) {
|
|
this.first = newNode;
|
|
this.last = newNode;
|
|
} else if (this.last === this.first) {
|
|
this.last = newNode;
|
|
this.last.prev = this.first;
|
|
this.first.next = newNode;
|
|
} else {
|
|
newNode.prev = this.last;
|
|
this.last.next = newNode;
|
|
this.last = newNode;
|
|
}
|
|
return true;
|
|
}
|
|
dequeue() {
|
|
if (!this.first)
|
|
return null;
|
|
if (this.first === this.last) {
|
|
const target2 = this.first;
|
|
this.first = null;
|
|
this.last = null;
|
|
return target2.value;
|
|
}
|
|
const target = this.first;
|
|
this.first = target.next;
|
|
if (this.first) {
|
|
this.first.prev = null;
|
|
}
|
|
return target.value;
|
|
}
|
|
};
|
|
|
|
// pure.ts
|
|
var JS = class {
|
|
generateSecretKey() {
|
|
return schnorr.utils.randomPrivateKey();
|
|
}
|
|
getPublicKey(secretKey) {
|
|
return bytesToHex2(schnorr.getPublicKey(secretKey));
|
|
}
|
|
finalizeEvent(t, secretKey) {
|
|
const event = t;
|
|
event.pubkey = bytesToHex2(schnorr.getPublicKey(secretKey));
|
|
event.id = getEventHash(event);
|
|
event.sig = bytesToHex2(schnorr.sign(getEventHash(event), secretKey));
|
|
event[verifiedSymbol] = true;
|
|
return event;
|
|
}
|
|
verifyEvent(event) {
|
|
if (typeof event[verifiedSymbol] === "boolean")
|
|
return event[verifiedSymbol];
|
|
const hash3 = getEventHash(event);
|
|
if (hash3 !== event.id) {
|
|
event[verifiedSymbol] = false;
|
|
return false;
|
|
}
|
|
try {
|
|
const valid = schnorr.verify(event.sig, hash3, event.pubkey);
|
|
event[verifiedSymbol] = valid;
|
|
return valid;
|
|
} catch (err) {
|
|
event[verifiedSymbol] = false;
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
function serializeEvent(evt) {
|
|
if (!validateEvent(evt))
|
|
throw new Error("can't serialize event with wrong or missing properties");
|
|
return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);
|
|
}
|
|
function getEventHash(event) {
|
|
let eventHash = sha2562(utf8Encoder.encode(serializeEvent(event)));
|
|
return bytesToHex2(eventHash);
|
|
}
|
|
var i = new JS();
|
|
var generateSecretKey = i.generateSecretKey;
|
|
var getPublicKey = i.getPublicKey;
|
|
var finalizeEvent = i.finalizeEvent;
|
|
var verifyEvent = i.verifyEvent;
|
|
|
|
// kinds.ts
|
|
var kinds_exports = {};
|
|
__export(kinds_exports, {
|
|
Application: () => Application,
|
|
BadgeAward: () => BadgeAward,
|
|
BadgeDefinition: () => BadgeDefinition,
|
|
BlockedRelaysList: () => BlockedRelaysList,
|
|
BookmarkList: () => BookmarkList,
|
|
Bookmarksets: () => Bookmarksets,
|
|
Calendar: () => Calendar,
|
|
CalendarEventRSVP: () => CalendarEventRSVP,
|
|
ChannelCreation: () => ChannelCreation,
|
|
ChannelHideMessage: () => ChannelHideMessage,
|
|
ChannelMessage: () => ChannelMessage,
|
|
ChannelMetadata: () => ChannelMetadata,
|
|
ChannelMuteUser: () => ChannelMuteUser,
|
|
ClassifiedListing: () => ClassifiedListing,
|
|
ClientAuth: () => ClientAuth,
|
|
CommunitiesList: () => CommunitiesList,
|
|
CommunityDefinition: () => CommunityDefinition,
|
|
CommunityPostApproval: () => CommunityPostApproval,
|
|
Contacts: () => Contacts,
|
|
CreateOrUpdateProduct: () => CreateOrUpdateProduct,
|
|
CreateOrUpdateStall: () => CreateOrUpdateStall,
|
|
Curationsets: () => Curationsets,
|
|
Date: () => Date2,
|
|
DirectMessageRelaysList: () => DirectMessageRelaysList,
|
|
DraftClassifiedListing: () => DraftClassifiedListing,
|
|
DraftLong: () => DraftLong,
|
|
Emojisets: () => Emojisets,
|
|
EncryptedDirectMessage: () => EncryptedDirectMessage,
|
|
EventDeletion: () => EventDeletion,
|
|
FileMetadata: () => FileMetadata,
|
|
FileServerPreference: () => FileServerPreference,
|
|
Followsets: () => Followsets,
|
|
GenericRepost: () => GenericRepost,
|
|
Genericlists: () => Genericlists,
|
|
GiftWrap: () => GiftWrap,
|
|
HTTPAuth: () => HTTPAuth,
|
|
Handlerinformation: () => Handlerinformation,
|
|
Handlerrecommendation: () => Handlerrecommendation,
|
|
Highlights: () => Highlights,
|
|
InterestsList: () => InterestsList,
|
|
Interestsets: () => Interestsets,
|
|
JobFeedback: () => JobFeedback,
|
|
JobRequest: () => JobRequest,
|
|
JobResult: () => JobResult,
|
|
Label: () => Label,
|
|
LightningPubRPC: () => LightningPubRPC,
|
|
LiveChatMessage: () => LiveChatMessage,
|
|
LiveEvent: () => LiveEvent,
|
|
LongFormArticle: () => LongFormArticle,
|
|
Metadata: () => Metadata,
|
|
Mutelist: () => Mutelist,
|
|
NWCWalletInfo: () => NWCWalletInfo,
|
|
NWCWalletRequest: () => NWCWalletRequest,
|
|
NWCWalletResponse: () => NWCWalletResponse,
|
|
NostrConnect: () => NostrConnect,
|
|
OpenTimestamps: () => OpenTimestamps,
|
|
Pinlist: () => Pinlist,
|
|
PrivateDirectMessage: () => PrivateDirectMessage,
|
|
ProblemTracker: () => ProblemTracker,
|
|
ProfileBadges: () => ProfileBadges,
|
|
PublicChatsList: () => PublicChatsList,
|
|
Reaction: () => Reaction,
|
|
RecommendRelay: () => RecommendRelay,
|
|
RelayList: () => RelayList,
|
|
Relaysets: () => Relaysets,
|
|
Report: () => Report,
|
|
Reporting: () => Reporting,
|
|
Repost: () => Repost,
|
|
Seal: () => Seal,
|
|
SearchRelaysList: () => SearchRelaysList,
|
|
ShortTextNote: () => ShortTextNote,
|
|
Time: () => Time,
|
|
UserEmojiList: () => UserEmojiList,
|
|
UserStatuses: () => UserStatuses,
|
|
Zap: () => Zap,
|
|
ZapGoal: () => ZapGoal,
|
|
ZapRequest: () => ZapRequest,
|
|
classifyKind: () => classifyKind,
|
|
isAddressableKind: () => isAddressableKind,
|
|
isEphemeralKind: () => isEphemeralKind,
|
|
isKind: () => isKind,
|
|
isRegularKind: () => isRegularKind,
|
|
isReplaceableKind: () => isReplaceableKind
|
|
});
|
|
function isRegularKind(kind) {
|
|
return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);
|
|
}
|
|
function isReplaceableKind(kind) {
|
|
return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;
|
|
}
|
|
function isEphemeralKind(kind) {
|
|
return 2e4 <= kind && kind < 3e4;
|
|
}
|
|
function isAddressableKind(kind) {
|
|
return 3e4 <= kind && kind < 4e4;
|
|
}
|
|
function classifyKind(kind) {
|
|
if (isRegularKind(kind))
|
|
return "regular";
|
|
if (isReplaceableKind(kind))
|
|
return "replaceable";
|
|
if (isEphemeralKind(kind))
|
|
return "ephemeral";
|
|
if (isAddressableKind(kind))
|
|
return "parameterized";
|
|
return "unknown";
|
|
}
|
|
function isKind(event, kind) {
|
|
const kindAsArray = kind instanceof Array ? kind : [kind];
|
|
return validateEvent(event) && kindAsArray.includes(event.kind) || false;
|
|
}
|
|
var Metadata = 0;
|
|
var ShortTextNote = 1;
|
|
var RecommendRelay = 2;
|
|
var Contacts = 3;
|
|
var EncryptedDirectMessage = 4;
|
|
var EventDeletion = 5;
|
|
var Repost = 6;
|
|
var Reaction = 7;
|
|
var BadgeAward = 8;
|
|
var Seal = 13;
|
|
var PrivateDirectMessage = 14;
|
|
var GenericRepost = 16;
|
|
var ChannelCreation = 40;
|
|
var ChannelMetadata = 41;
|
|
var ChannelMessage = 42;
|
|
var ChannelHideMessage = 43;
|
|
var ChannelMuteUser = 44;
|
|
var OpenTimestamps = 1040;
|
|
var GiftWrap = 1059;
|
|
var FileMetadata = 1063;
|
|
var LiveChatMessage = 1311;
|
|
var ProblemTracker = 1971;
|
|
var Report = 1984;
|
|
var Reporting = 1984;
|
|
var Label = 1985;
|
|
var CommunityPostApproval = 4550;
|
|
var JobRequest = 5999;
|
|
var JobResult = 6999;
|
|
var JobFeedback = 7e3;
|
|
var ZapGoal = 9041;
|
|
var ZapRequest = 9734;
|
|
var Zap = 9735;
|
|
var Highlights = 9802;
|
|
var Mutelist = 1e4;
|
|
var Pinlist = 10001;
|
|
var RelayList = 10002;
|
|
var BookmarkList = 10003;
|
|
var CommunitiesList = 10004;
|
|
var PublicChatsList = 10005;
|
|
var BlockedRelaysList = 10006;
|
|
var SearchRelaysList = 10007;
|
|
var InterestsList = 10015;
|
|
var UserEmojiList = 10030;
|
|
var DirectMessageRelaysList = 10050;
|
|
var FileServerPreference = 10096;
|
|
var NWCWalletInfo = 13194;
|
|
var LightningPubRPC = 21e3;
|
|
var ClientAuth = 22242;
|
|
var NWCWalletRequest = 23194;
|
|
var NWCWalletResponse = 23195;
|
|
var NostrConnect = 24133;
|
|
var HTTPAuth = 27235;
|
|
var Followsets = 3e4;
|
|
var Genericlists = 30001;
|
|
var Relaysets = 30002;
|
|
var Bookmarksets = 30003;
|
|
var Curationsets = 30004;
|
|
var ProfileBadges = 30008;
|
|
var BadgeDefinition = 30009;
|
|
var Interestsets = 30015;
|
|
var CreateOrUpdateStall = 30017;
|
|
var CreateOrUpdateProduct = 30018;
|
|
var LongFormArticle = 30023;
|
|
var DraftLong = 30024;
|
|
var Emojisets = 30030;
|
|
var Application = 30078;
|
|
var LiveEvent = 30311;
|
|
var UserStatuses = 30315;
|
|
var ClassifiedListing = 30402;
|
|
var DraftClassifiedListing = 30403;
|
|
var Date2 = 31922;
|
|
var Time = 31923;
|
|
var Calendar = 31924;
|
|
var CalendarEventRSVP = 31925;
|
|
var Handlerrecommendation = 31989;
|
|
var Handlerinformation = 31990;
|
|
var CommunityDefinition = 34550;
|
|
|
|
// filter.ts
|
|
function matchFilter(filter, event) {
|
|
if (filter.ids && filter.ids.indexOf(event.id) === -1) {
|
|
return false;
|
|
}
|
|
if (filter.kinds && filter.kinds.indexOf(event.kind) === -1) {
|
|
return false;
|
|
}
|
|
if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {
|
|
return false;
|
|
}
|
|
for (let f2 in filter) {
|
|
if (f2[0] === "#") {
|
|
let tagName = f2.slice(1);
|
|
let values = filter[`#${tagName}`];
|
|
if (values && !event.tags.find(([t, v]) => t === f2.slice(1) && values.indexOf(v) !== -1))
|
|
return false;
|
|
}
|
|
}
|
|
if (filter.since && event.created_at < filter.since)
|
|
return false;
|
|
if (filter.until && event.created_at > filter.until)
|
|
return false;
|
|
return true;
|
|
}
|
|
function matchFilters(filters, event) {
|
|
for (let i2 = 0; i2 < filters.length; i2++) {
|
|
if (matchFilter(filters[i2], event)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function mergeFilters(...filters) {
|
|
let result = {};
|
|
for (let i2 = 0; i2 < filters.length; i2++) {
|
|
let filter = filters[i2];
|
|
Object.entries(filter).forEach(([property, values]) => {
|
|
if (property === "kinds" || property === "ids" || property === "authors" || property[0] === "#") {
|
|
result[property] = result[property] || [];
|
|
for (let v = 0; v < values.length; v++) {
|
|
let value = values[v];
|
|
if (!result[property].includes(value))
|
|
result[property].push(value);
|
|
}
|
|
}
|
|
});
|
|
if (filter.limit && (!result.limit || filter.limit > result.limit))
|
|
result.limit = filter.limit;
|
|
if (filter.until && (!result.until || filter.until > result.until))
|
|
result.until = filter.until;
|
|
if (filter.since && (!result.since || filter.since < result.since))
|
|
result.since = filter.since;
|
|
}
|
|
return result;
|
|
}
|
|
function getFilterLimit(filter) {
|
|
if (filter.ids && !filter.ids.length)
|
|
return 0;
|
|
if (filter.kinds && !filter.kinds.length)
|
|
return 0;
|
|
if (filter.authors && !filter.authors.length)
|
|
return 0;
|
|
for (const [key, value] of Object.entries(filter)) {
|
|
if (key[0] === "#" && Array.isArray(value) && !value.length)
|
|
return 0;
|
|
}
|
|
return Math.min(
|
|
Math.max(0, filter.limit ?? Infinity),
|
|
filter.ids?.length ?? Infinity,
|
|
filter.authors?.length && filter.kinds?.every((kind) => isReplaceableKind(kind)) ? filter.authors.length * filter.kinds.length : Infinity,
|
|
filter.authors?.length && filter.kinds?.every((kind) => isAddressableKind(kind)) && filter["#d"]?.length ? filter.authors.length * filter.kinds.length * filter["#d"].length : Infinity
|
|
);
|
|
}
|
|
|
|
// fakejson.ts
|
|
var fakejson_exports = {};
|
|
__export(fakejson_exports, {
|
|
getHex64: () => getHex64,
|
|
getInt: () => getInt,
|
|
getSubscriptionId: () => getSubscriptionId,
|
|
matchEventId: () => matchEventId,
|
|
matchEventKind: () => matchEventKind,
|
|
matchEventPubkey: () => matchEventPubkey
|
|
});
|
|
function getHex64(json, field) {
|
|
let len = field.length + 3;
|
|
let idx = json.indexOf(`"${field}":`) + len;
|
|
let s = json.slice(idx).indexOf(`"`) + idx + 1;
|
|
return json.slice(s, s + 64);
|
|
}
|
|
function getInt(json, field) {
|
|
let len = field.length;
|
|
let idx = json.indexOf(`"${field}":`) + len + 3;
|
|
let sliced = json.slice(idx);
|
|
let end = Math.min(sliced.indexOf(","), sliced.indexOf("}"));
|
|
return parseInt(sliced.slice(0, end), 10);
|
|
}
|
|
function getSubscriptionId(json) {
|
|
let idx = json.slice(0, 22).indexOf(`"EVENT"`);
|
|
if (idx === -1)
|
|
return null;
|
|
let pstart = json.slice(idx + 7 + 1).indexOf(`"`);
|
|
if (pstart === -1)
|
|
return null;
|
|
let start = idx + 7 + 1 + pstart;
|
|
let pend = json.slice(start + 1, 80).indexOf(`"`);
|
|
if (pend === -1)
|
|
return null;
|
|
let end = start + 1 + pend;
|
|
return json.slice(start + 1, end);
|
|
}
|
|
function matchEventId(json, id) {
|
|
return id === getHex64(json, "id");
|
|
}
|
|
function matchEventPubkey(json, pubkey) {
|
|
return pubkey === getHex64(json, "pubkey");
|
|
}
|
|
function matchEventKind(json, kind) {
|
|
return kind === getInt(json, "kind");
|
|
}
|
|
|
|
// nip42.ts
|
|
var nip42_exports = {};
|
|
__export(nip42_exports, {
|
|
makeAuthEvent: () => makeAuthEvent
|
|
});
|
|
function makeAuthEvent(relayURL, challenge2) {
|
|
return {
|
|
kind: ClientAuth,
|
|
created_at: Math.floor(Date.now() / 1e3),
|
|
tags: [
|
|
["relay", relayURL],
|
|
["challenge", challenge2]
|
|
],
|
|
content: ""
|
|
};
|
|
}
|
|
|
|
// helpers.ts
|
|
async function yieldThread() {
|
|
return new Promise((resolve) => {
|
|
const ch = new MessageChannel();
|
|
const handler = () => {
|
|
ch.port1.removeEventListener("message", handler);
|
|
resolve();
|
|
};
|
|
ch.port1.addEventListener("message", handler);
|
|
ch.port2.postMessage(0);
|
|
ch.port1.start();
|
|
});
|
|
}
|
|
var alwaysTrue = (t) => {
|
|
t[verifiedSymbol] = true;
|
|
return true;
|
|
};
|
|
|
|
// abstract-relay.ts
|
|
var SendingOnClosedConnection = class extends Error {
|
|
constructor(message, relay) {
|
|
super(`Tried to send message '${message} on a closed connection to ${relay}.`);
|
|
this.name = "SendingOnClosedConnection";
|
|
}
|
|
};
|
|
var AbstractRelay = class {
|
|
url;
|
|
_connected = false;
|
|
onclose = null;
|
|
onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);
|
|
baseEoseTimeout = 4400;
|
|
connectionTimeout = 4400;
|
|
publishTimeout = 4400;
|
|
pingFrequency = 2e4;
|
|
pingTimeout = 2e4;
|
|
openSubs = /* @__PURE__ */ new Map();
|
|
enablePing;
|
|
connectionTimeoutHandle;
|
|
connectionPromise;
|
|
openCountRequests = /* @__PURE__ */ new Map();
|
|
openEventPublishes = /* @__PURE__ */ new Map();
|
|
ws;
|
|
incomingMessageQueue = new Queue();
|
|
queueRunning = false;
|
|
challenge;
|
|
authPromise;
|
|
serial = 0;
|
|
verifyEvent;
|
|
_WebSocket;
|
|
constructor(url, opts) {
|
|
this.url = normalizeURL(url);
|
|
this.verifyEvent = opts.verifyEvent;
|
|
this._WebSocket = opts.websocketImplementation || WebSocket;
|
|
this.enablePing = opts.enablePing;
|
|
}
|
|
static async connect(url, opts) {
|
|
const relay = new AbstractRelay(url, opts);
|
|
await relay.connect();
|
|
return relay;
|
|
}
|
|
closeAllSubscriptions(reason) {
|
|
for (let [_, sub] of this.openSubs) {
|
|
sub.close(reason);
|
|
}
|
|
this.openSubs.clear();
|
|
for (let [_, ep] of this.openEventPublishes) {
|
|
ep.reject(new Error(reason));
|
|
}
|
|
this.openEventPublishes.clear();
|
|
for (let [_, cr] of this.openCountRequests) {
|
|
cr.reject(new Error(reason));
|
|
}
|
|
this.openCountRequests.clear();
|
|
}
|
|
get connected() {
|
|
return this._connected;
|
|
}
|
|
async connect() {
|
|
if (this.connectionPromise)
|
|
return this.connectionPromise;
|
|
this.challenge = void 0;
|
|
this.authPromise = void 0;
|
|
this.connectionPromise = new Promise((resolve, reject) => {
|
|
this.connectionTimeoutHandle = setTimeout(() => {
|
|
reject("connection timed out");
|
|
this.connectionPromise = void 0;
|
|
this.onclose?.();
|
|
this.closeAllSubscriptions("relay connection timed out");
|
|
}, this.connectionTimeout);
|
|
try {
|
|
this.ws = new this._WebSocket(this.url);
|
|
} catch (err) {
|
|
clearTimeout(this.connectionTimeoutHandle);
|
|
reject(err);
|
|
return;
|
|
}
|
|
this.ws.onopen = () => {
|
|
clearTimeout(this.connectionTimeoutHandle);
|
|
this._connected = true;
|
|
if (this.enablePing) {
|
|
this.pingpong();
|
|
}
|
|
resolve();
|
|
};
|
|
this.ws.onerror = (ev) => {
|
|
clearTimeout(this.connectionTimeoutHandle);
|
|
reject(ev.message || "websocket error");
|
|
this._connected = false;
|
|
this.connectionPromise = void 0;
|
|
this.onclose?.();
|
|
this.closeAllSubscriptions("relay connection errored");
|
|
};
|
|
this.ws.onclose = (ev) => {
|
|
clearTimeout(this.connectionTimeoutHandle);
|
|
reject(ev.message || "websocket closed");
|
|
this._connected = false;
|
|
this.connectionPromise = void 0;
|
|
this.onclose?.();
|
|
this.closeAllSubscriptions("relay connection closed");
|
|
};
|
|
this.ws.onmessage = this._onmessage.bind(this);
|
|
});
|
|
return this.connectionPromise;
|
|
}
|
|
async waitForPingPong() {
|
|
return new Promise((res, err) => {
|
|
;
|
|
this.ws && this.ws.on && this.ws.on("pong", () => res(true)) || err("ws can't listen for pong");
|
|
this.ws && this.ws.ping && this.ws.ping();
|
|
});
|
|
}
|
|
async waitForDummyReq() {
|
|
return new Promise((resolve, _) => {
|
|
const sub = this.subscribe([{ ids: ["a".repeat(64)] }], {
|
|
oneose: () => {
|
|
sub.close();
|
|
resolve(true);
|
|
},
|
|
eoseTimeout: this.pingTimeout + 1e3
|
|
});
|
|
});
|
|
}
|
|
async pingpong() {
|
|
if (this.ws?.readyState === 1) {
|
|
const result = await Promise.any([
|
|
this.ws && this.ws.ping && this.ws.on ? this.waitForPingPong() : this.waitForDummyReq(),
|
|
new Promise((res) => setTimeout(() => res(false), this.pingTimeout))
|
|
]);
|
|
if (result) {
|
|
setTimeout(() => this.pingpong(), this.pingFrequency);
|
|
} else {
|
|
this.closeAllSubscriptions("pingpong timed out");
|
|
this._connected = false;
|
|
this.onclose?.();
|
|
this.ws?.close();
|
|
}
|
|
}
|
|
}
|
|
async runQueue() {
|
|
this.queueRunning = true;
|
|
while (true) {
|
|
if (false === this.handleNext()) {
|
|
break;
|
|
}
|
|
await yieldThread();
|
|
}
|
|
this.queueRunning = false;
|
|
}
|
|
handleNext() {
|
|
const json = this.incomingMessageQueue.dequeue();
|
|
if (!json) {
|
|
return false;
|
|
}
|
|
const subid = getSubscriptionId(json);
|
|
if (subid) {
|
|
const so = this.openSubs.get(subid);
|
|
if (!so) {
|
|
return;
|
|
}
|
|
const id = getHex64(json, "id");
|
|
const alreadyHave = so.alreadyHaveEvent?.(id);
|
|
so.receivedEvent?.(this, id);
|
|
if (alreadyHave) {
|
|
return;
|
|
}
|
|
}
|
|
try {
|
|
let data = JSON.parse(json);
|
|
switch (data[0]) {
|
|
case "EVENT": {
|
|
const so = this.openSubs.get(data[1]);
|
|
const event = data[2];
|
|
if (this.verifyEvent(event) && matchFilters(so.filters, event)) {
|
|
so.onevent(event);
|
|
}
|
|
return;
|
|
}
|
|
case "COUNT": {
|
|
const id = data[1];
|
|
const payload = data[2];
|
|
const cr = this.openCountRequests.get(id);
|
|
if (cr) {
|
|
cr.resolve(payload.count);
|
|
this.openCountRequests.delete(id);
|
|
}
|
|
return;
|
|
}
|
|
case "EOSE": {
|
|
const so = this.openSubs.get(data[1]);
|
|
if (!so)
|
|
return;
|
|
so.receivedEose();
|
|
return;
|
|
}
|
|
case "OK": {
|
|
const id = data[1];
|
|
const ok = data[2];
|
|
const reason = data[3];
|
|
const ep = this.openEventPublishes.get(id);
|
|
if (ep) {
|
|
clearTimeout(ep.timeout);
|
|
if (ok)
|
|
ep.resolve(reason);
|
|
else
|
|
ep.reject(new Error(reason));
|
|
this.openEventPublishes.delete(id);
|
|
}
|
|
return;
|
|
}
|
|
case "CLOSED": {
|
|
const id = data[1];
|
|
const so = this.openSubs.get(id);
|
|
if (!so)
|
|
return;
|
|
so.closed = true;
|
|
so.close(data[2]);
|
|
return;
|
|
}
|
|
case "NOTICE":
|
|
this.onnotice(data[1]);
|
|
return;
|
|
case "AUTH": {
|
|
this.challenge = data[1];
|
|
return;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
return;
|
|
}
|
|
}
|
|
async send(message) {
|
|
if (!this.connectionPromise)
|
|
throw new SendingOnClosedConnection(message, this.url);
|
|
this.connectionPromise.then(() => {
|
|
this.ws?.send(message);
|
|
});
|
|
}
|
|
async auth(signAuthEvent) {
|
|
const challenge2 = this.challenge;
|
|
if (!challenge2)
|
|
throw new Error("can't perform auth, no challenge was received");
|
|
if (this.authPromise)
|
|
return this.authPromise;
|
|
this.authPromise = new Promise(async (resolve, reject) => {
|
|
try {
|
|
let evt = await signAuthEvent(makeAuthEvent(this.url, challenge2));
|
|
let timeout = setTimeout(() => {
|
|
let ep = this.openEventPublishes.get(evt.id);
|
|
if (ep) {
|
|
ep.reject(new Error("auth timed out"));
|
|
this.openEventPublishes.delete(evt.id);
|
|
}
|
|
}, this.publishTimeout);
|
|
this.openEventPublishes.set(evt.id, { resolve, reject, timeout });
|
|
this.send('["AUTH",' + JSON.stringify(evt) + "]");
|
|
} catch (err) {
|
|
console.warn("subscribe auth function failed:", err);
|
|
}
|
|
});
|
|
return this.authPromise;
|
|
}
|
|
async publish(event) {
|
|
const ret = new Promise((resolve, reject) => {
|
|
const timeout = setTimeout(() => {
|
|
const ep = this.openEventPublishes.get(event.id);
|
|
if (ep) {
|
|
ep.reject(new Error("publish timed out"));
|
|
this.openEventPublishes.delete(event.id);
|
|
}
|
|
}, this.publishTimeout);
|
|
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
});
|
|
this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
return ret;
|
|
}
|
|
async count(filters, params) {
|
|
this.serial++;
|
|
const id = params?.id || "count:" + this.serial;
|
|
const ret = new Promise((resolve, reject) => {
|
|
this.openCountRequests.set(id, { resolve, reject });
|
|
});
|
|
this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
return ret;
|
|
}
|
|
subscribe(filters, params) {
|
|
const subscription = this.prepareSubscription(filters, params);
|
|
subscription.fire();
|
|
return subscription;
|
|
}
|
|
prepareSubscription(filters, params) {
|
|
this.serial++;
|
|
const id = params.id || (params.label ? params.label + ":" : "sub:") + this.serial;
|
|
const subscription = new Subscription(this, id, filters, params);
|
|
this.openSubs.set(id, subscription);
|
|
return subscription;
|
|
}
|
|
close() {
|
|
this.closeAllSubscriptions("relay connection closed by us");
|
|
this._connected = false;
|
|
this.onclose?.();
|
|
this.ws?.close();
|
|
}
|
|
_onmessage(ev) {
|
|
this.incomingMessageQueue.enqueue(ev.data);
|
|
if (!this.queueRunning) {
|
|
this.runQueue();
|
|
}
|
|
}
|
|
};
|
|
var Subscription = class {
|
|
relay;
|
|
id;
|
|
closed = false;
|
|
eosed = false;
|
|
filters;
|
|
alreadyHaveEvent;
|
|
receivedEvent;
|
|
onevent;
|
|
oneose;
|
|
onclose;
|
|
eoseTimeout;
|
|
eoseTimeoutHandle;
|
|
constructor(relay, id, filters, params) {
|
|
this.relay = relay;
|
|
this.filters = filters;
|
|
this.id = id;
|
|
this.alreadyHaveEvent = params.alreadyHaveEvent;
|
|
this.receivedEvent = params.receivedEvent;
|
|
this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;
|
|
this.oneose = params.oneose;
|
|
this.onclose = params.onclose;
|
|
this.onevent = params.onevent || ((event) => {
|
|
console.warn(
|
|
`onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,
|
|
event
|
|
);
|
|
});
|
|
}
|
|
fire() {
|
|
this.relay.send('["REQ","' + this.id + '",' + JSON.stringify(this.filters).substring(1));
|
|
this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);
|
|
}
|
|
receivedEose() {
|
|
if (this.eosed)
|
|
return;
|
|
clearTimeout(this.eoseTimeoutHandle);
|
|
this.eosed = true;
|
|
this.oneose?.();
|
|
}
|
|
close(reason = "closed by caller") {
|
|
if (!this.closed && this.relay.connected) {
|
|
try {
|
|
this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]");
|
|
} catch (err) {
|
|
if (err instanceof SendingOnClosedConnection) {
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
this.closed = true;
|
|
}
|
|
this.relay.openSubs.delete(this.id);
|
|
this.onclose?.(reason);
|
|
}
|
|
};
|
|
|
|
// relay.ts
|
|
var _WebSocket;
|
|
try {
|
|
_WebSocket = WebSocket;
|
|
} catch {
|
|
}
|
|
var Relay = class extends AbstractRelay {
|
|
constructor(url) {
|
|
super(url, { verifyEvent, websocketImplementation: _WebSocket });
|
|
}
|
|
static async connect(url) {
|
|
const relay = new Relay(url);
|
|
await relay.connect();
|
|
return relay;
|
|
}
|
|
};
|
|
|
|
// abstract-pool.ts
|
|
var AbstractSimplePool = class {
|
|
relays = /* @__PURE__ */ new Map();
|
|
seenOn = /* @__PURE__ */ new Map();
|
|
trackRelays = false;
|
|
verifyEvent;
|
|
enablePing;
|
|
trustedRelayURLs = /* @__PURE__ */ new Set();
|
|
_WebSocket;
|
|
constructor(opts) {
|
|
this.verifyEvent = opts.verifyEvent;
|
|
this._WebSocket = opts.websocketImplementation;
|
|
this.enablePing = opts.enablePing;
|
|
}
|
|
async ensureRelay(url, params) {
|
|
url = normalizeURL(url);
|
|
let relay = this.relays.get(url);
|
|
if (!relay) {
|
|
relay = new AbstractRelay(url, {
|
|
verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent,
|
|
websocketImplementation: this._WebSocket,
|
|
enablePing: this.enablePing
|
|
});
|
|
relay.onclose = () => {
|
|
this.relays.delete(url);
|
|
};
|
|
if (params?.connectionTimeout)
|
|
relay.connectionTimeout = params.connectionTimeout;
|
|
this.relays.set(url, relay);
|
|
}
|
|
await relay.connect();
|
|
return relay;
|
|
}
|
|
close(relays) {
|
|
relays.map(normalizeURL).forEach((url) => {
|
|
this.relays.get(url)?.close();
|
|
this.relays.delete(url);
|
|
});
|
|
}
|
|
subscribe(relays, filter, params) {
|
|
params.onauth = params.onauth || params.doauth;
|
|
const request = [];
|
|
for (let i2 = 0; i2 < relays.length; i2++) {
|
|
const url = normalizeURL(relays[i2]);
|
|
if (!request.find((r) => r.url === url)) {
|
|
request.push({ url, filter });
|
|
}
|
|
}
|
|
return this.subscribeMap(request, params);
|
|
}
|
|
subscribeMany(relays, filters, params) {
|
|
params.onauth = params.onauth || params.doauth;
|
|
const request = [];
|
|
const uniqUrls = [];
|
|
for (let i2 = 0; i2 < relays.length; i2++) {
|
|
const url = normalizeURL(relays[i2]);
|
|
if (uniqUrls.indexOf(url) === -1) {
|
|
for (let f2 = 0; f2 < filters.length; f2++) {
|
|
request.push({ url, filter: filters[f2] });
|
|
}
|
|
}
|
|
}
|
|
return this.subscribeMap(request, params);
|
|
}
|
|
subscribeMap(requests, params) {
|
|
params.onauth = params.onauth || params.doauth;
|
|
if (this.trackRelays) {
|
|
params.receivedEvent = (relay, id) => {
|
|
let set = this.seenOn.get(id);
|
|
if (!set) {
|
|
set = /* @__PURE__ */ new Set();
|
|
this.seenOn.set(id, set);
|
|
}
|
|
set.add(relay);
|
|
};
|
|
}
|
|
const _knownIds = /* @__PURE__ */ new Set();
|
|
const subs = [];
|
|
const eosesReceived = [];
|
|
let handleEose = (i2) => {
|
|
if (eosesReceived[i2])
|
|
return;
|
|
eosesReceived[i2] = true;
|
|
if (eosesReceived.filter((a) => a).length === requests.length) {
|
|
params.oneose?.();
|
|
handleEose = () => {
|
|
};
|
|
}
|
|
};
|
|
const closesReceived = [];
|
|
let handleClose = (i2, reason) => {
|
|
if (closesReceived[i2])
|
|
return;
|
|
handleEose(i2);
|
|
closesReceived[i2] = reason;
|
|
if (closesReceived.filter((a) => a).length === requests.length) {
|
|
params.onclose?.(closesReceived);
|
|
handleClose = () => {
|
|
};
|
|
}
|
|
};
|
|
const localAlreadyHaveEventHandler = (id) => {
|
|
if (params.alreadyHaveEvent?.(id)) {
|
|
return true;
|
|
}
|
|
const have = _knownIds.has(id);
|
|
_knownIds.add(id);
|
|
return have;
|
|
};
|
|
const allOpened = Promise.all(
|
|
requests.map(async ({ url, filter }, i2) => {
|
|
let relay;
|
|
try {
|
|
relay = await this.ensureRelay(url, {
|
|
connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0
|
|
});
|
|
} catch (err) {
|
|
handleClose(i2, err?.message || String(err));
|
|
return;
|
|
}
|
|
let subscription = relay.subscribe([filter], {
|
|
...params,
|
|
oneose: () => handleEose(i2),
|
|
onclose: (reason) => {
|
|
if (reason.startsWith("auth-required: ") && params.onauth) {
|
|
relay.auth(params.onauth).then(() => {
|
|
relay.subscribe([filter], {
|
|
...params,
|
|
oneose: () => handleEose(i2),
|
|
onclose: (reason2) => {
|
|
handleClose(i2, reason2);
|
|
},
|
|
alreadyHaveEvent: localAlreadyHaveEventHandler,
|
|
eoseTimeout: params.maxWait
|
|
});
|
|
}).catch((err) => {
|
|
handleClose(i2, `auth was required and attempted, but failed with: ${err}`);
|
|
});
|
|
} else {
|
|
handleClose(i2, reason);
|
|
}
|
|
},
|
|
alreadyHaveEvent: localAlreadyHaveEventHandler,
|
|
eoseTimeout: params.maxWait
|
|
});
|
|
subs.push(subscription);
|
|
})
|
|
);
|
|
return {
|
|
async close(reason) {
|
|
await allOpened;
|
|
subs.forEach((sub) => {
|
|
sub.close(reason);
|
|
});
|
|
}
|
|
};
|
|
}
|
|
subscribeEose(relays, filter, params) {
|
|
params.onauth = params.onauth || params.doauth;
|
|
const subcloser = this.subscribe(relays, filter, {
|
|
...params,
|
|
oneose() {
|
|
subcloser.close("closed automatically on eose");
|
|
}
|
|
});
|
|
return subcloser;
|
|
}
|
|
subscribeManyEose(relays, filters, params) {
|
|
params.onauth = params.onauth || params.doauth;
|
|
const subcloser = this.subscribeMany(relays, filters, {
|
|
...params,
|
|
oneose() {
|
|
subcloser.close("closed automatically on eose");
|
|
}
|
|
});
|
|
return subcloser;
|
|
}
|
|
async querySync(relays, filter, params) {
|
|
return new Promise(async (resolve) => {
|
|
const events = [];
|
|
this.subscribeEose(relays, filter, {
|
|
...params,
|
|
onevent(event) {
|
|
events.push(event);
|
|
},
|
|
onclose(_) {
|
|
resolve(events);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
async get(relays, filter, params) {
|
|
filter.limit = 1;
|
|
const events = await this.querySync(relays, filter, params);
|
|
events.sort((a, b) => b.created_at - a.created_at);
|
|
return events[0] || null;
|
|
}
|
|
publish(relays, event, options) {
|
|
return relays.map(normalizeURL).map(async (url, i2, arr) => {
|
|
if (arr.indexOf(url) !== i2) {
|
|
return Promise.reject("duplicate url");
|
|
}
|
|
let r = await this.ensureRelay(url);
|
|
return r.publish(event).catch(async (err) => {
|
|
if (err instanceof Error && err.message.startsWith("auth-required: ") && options?.onauth) {
|
|
await r.auth(options.onauth);
|
|
return r.publish(event);
|
|
}
|
|
throw err;
|
|
}).then((reason) => {
|
|
if (this.trackRelays) {
|
|
let set = this.seenOn.get(event.id);
|
|
if (!set) {
|
|
set = /* @__PURE__ */ new Set();
|
|
this.seenOn.set(event.id, set);
|
|
}
|
|
set.add(r);
|
|
}
|
|
return reason;
|
|
});
|
|
});
|
|
}
|
|
listConnectionStatus() {
|
|
const map = /* @__PURE__ */ new Map();
|
|
this.relays.forEach((relay, url) => map.set(url, relay.connected));
|
|
return map;
|
|
}
|
|
destroy() {
|
|
this.relays.forEach((conn) => conn.close());
|
|
this.relays = /* @__PURE__ */ new Map();
|
|
}
|
|
};
|
|
|
|
// pool.ts
|
|
var _WebSocket2;
|
|
try {
|
|
_WebSocket2 = WebSocket;
|
|
} catch {
|
|
}
|
|
var SimplePool = class extends AbstractSimplePool {
|
|
constructor(options) {
|
|
super({ verifyEvent, websocketImplementation: _WebSocket2, ...options });
|
|
}
|
|
};
|
|
|
|
// nip19.ts
|
|
var nip19_exports = {};
|
|
__export(nip19_exports, {
|
|
BECH32_REGEX: () => BECH32_REGEX,
|
|
Bech32MaxSize: () => Bech32MaxSize,
|
|
NostrTypeGuard: () => NostrTypeGuard,
|
|
decode: () => decode,
|
|
decodeNostrURI: () => decodeNostrURI,
|
|
encodeBytes: () => encodeBytes,
|
|
naddrEncode: () => naddrEncode,
|
|
neventEncode: () => neventEncode,
|
|
noteEncode: () => noteEncode,
|
|
nprofileEncode: () => nprofileEncode,
|
|
npubEncode: () => npubEncode,
|
|
nsecEncode: () => nsecEncode
|
|
});
|
|
|
|
// node_modules/@scure/base/lib/esm/index.js
|
|
function assertNumber(n) {
|
|
if (!Number.isSafeInteger(n))
|
|
throw new Error(`Wrong integer: ${n}`);
|
|
}
|
|
function chain(...args) {
|
|
const wrap = (a, b) => (c) => a(b(c));
|
|
const encode = Array.from(args).reverse().reduce((acc, i2) => acc ? wrap(acc, i2.encode) : i2.encode, void 0);
|
|
const decode2 = args.reduce((acc, i2) => acc ? wrap(acc, i2.decode) : i2.decode, void 0);
|
|
return { encode, decode: decode2 };
|
|
}
|
|
function alphabet(alphabet2) {
|
|
return {
|
|
encode: (digits) => {
|
|
if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
|
|
throw new Error("alphabet.encode input should be an array of numbers");
|
|
return digits.map((i2) => {
|
|
assertNumber(i2);
|
|
if (i2 < 0 || i2 >= alphabet2.length)
|
|
throw new Error(`Digit index outside alphabet: ${i2} (alphabet: ${alphabet2.length})`);
|
|
return alphabet2[i2];
|
|
});
|
|
},
|
|
decode: (input) => {
|
|
if (!Array.isArray(input) || input.length && typeof input[0] !== "string")
|
|
throw new Error("alphabet.decode input should be array of strings");
|
|
return input.map((letter) => {
|
|
if (typeof letter !== "string")
|
|
throw new Error(`alphabet.decode: not string element=${letter}`);
|
|
const index = alphabet2.indexOf(letter);
|
|
if (index === -1)
|
|
throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet2}`);
|
|
return index;
|
|
});
|
|
}
|
|
};
|
|
}
|
|
function join(separator = "") {
|
|
if (typeof separator !== "string")
|
|
throw new Error("join separator should be string");
|
|
return {
|
|
encode: (from) => {
|
|
if (!Array.isArray(from) || from.length && typeof from[0] !== "string")
|
|
throw new Error("join.encode input should be array of strings");
|
|
for (let i2 of from)
|
|
if (typeof i2 !== "string")
|
|
throw new Error(`join.encode: non-string input=${i2}`);
|
|
return from.join(separator);
|
|
},
|
|
decode: (to) => {
|
|
if (typeof to !== "string")
|
|
throw new Error("join.decode input should be string");
|
|
return to.split(separator);
|
|
}
|
|
};
|
|
}
|
|
function padding(bits, chr = "=") {
|
|
assertNumber(bits);
|
|
if (typeof chr !== "string")
|
|
throw new Error("padding chr should be string");
|
|
return {
|
|
encode(data) {
|
|
if (!Array.isArray(data) || data.length && typeof data[0] !== "string")
|
|
throw new Error("padding.encode input should be array of strings");
|
|
for (let i2 of data)
|
|
if (typeof i2 !== "string")
|
|
throw new Error(`padding.encode: non-string input=${i2}`);
|
|
while (data.length * bits % 8)
|
|
data.push(chr);
|
|
return data;
|
|
},
|
|
decode(input) {
|
|
if (!Array.isArray(input) || input.length && typeof input[0] !== "string")
|
|
throw new Error("padding.encode input should be array of strings");
|
|
for (let i2 of input)
|
|
if (typeof i2 !== "string")
|
|
throw new Error(`padding.decode: non-string input=${i2}`);
|
|
let end = input.length;
|
|
if (end * bits % 8)
|
|
throw new Error("Invalid padding: string should have whole number of bytes");
|
|
for (; end > 0 && input[end - 1] === chr; end--) {
|
|
if (!((end - 1) * bits % 8))
|
|
throw new Error("Invalid padding: string has too much padding");
|
|
}
|
|
return input.slice(0, end);
|
|
}
|
|
};
|
|
}
|
|
function normalize(fn) {
|
|
if (typeof fn !== "function")
|
|
throw new Error("normalize fn should be function");
|
|
return { encode: (from) => from, decode: (to) => fn(to) };
|
|
}
|
|
function convertRadix(data, from, to) {
|
|
if (from < 2)
|
|
throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
|
|
if (to < 2)
|
|
throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
|
|
if (!Array.isArray(data))
|
|
throw new Error("convertRadix: data should be array");
|
|
if (!data.length)
|
|
return [];
|
|
let pos = 0;
|
|
const res = [];
|
|
const digits = Array.from(data);
|
|
digits.forEach((d) => {
|
|
assertNumber(d);
|
|
if (d < 0 || d >= from)
|
|
throw new Error(`Wrong integer: ${d}`);
|
|
});
|
|
while (true) {
|
|
let carry = 0;
|
|
let done = true;
|
|
for (let i2 = pos; i2 < digits.length; i2++) {
|
|
const digit = digits[i2];
|
|
const digitBase = from * carry + digit;
|
|
if (!Number.isSafeInteger(digitBase) || from * carry / from !== carry || digitBase - digit !== from * carry) {
|
|
throw new Error("convertRadix: carry overflow");
|
|
}
|
|
carry = digitBase % to;
|
|
digits[i2] = Math.floor(digitBase / to);
|
|
if (!Number.isSafeInteger(digits[i2]) || digits[i2] * to + carry !== digitBase)
|
|
throw new Error("convertRadix: carry overflow");
|
|
if (!done)
|
|
continue;
|
|
else if (!digits[i2])
|
|
pos = i2;
|
|
else
|
|
done = false;
|
|
}
|
|
res.push(carry);
|
|
if (done)
|
|
break;
|
|
}
|
|
for (let i2 = 0; i2 < data.length - 1 && data[i2] === 0; i2++)
|
|
res.push(0);
|
|
return res.reverse();
|
|
}
|
|
var gcd = (a, b) => !b ? a : gcd(b, a % b);
|
|
var radix2carry = (from, to) => from + (to - gcd(from, to));
|
|
function convertRadix2(data, from, to, padding2) {
|
|
if (!Array.isArray(data))
|
|
throw new Error("convertRadix2: data should be array");
|
|
if (from <= 0 || from > 32)
|
|
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
if (to <= 0 || to > 32)
|
|
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
if (radix2carry(from, to) > 32) {
|
|
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
|
|
}
|
|
let carry = 0;
|
|
let pos = 0;
|
|
const mask = 2 ** to - 1;
|
|
const res = [];
|
|
for (const n of data) {
|
|
assertNumber(n);
|
|
if (n >= 2 ** from)
|
|
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
carry = carry << from | n;
|
|
if (pos + from > 32)
|
|
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
pos += from;
|
|
for (; pos >= to; pos -= to)
|
|
res.push((carry >> pos - to & mask) >>> 0);
|
|
carry &= 2 ** pos - 1;
|
|
}
|
|
carry = carry << to - pos & mask;
|
|
if (!padding2 && pos >= from)
|
|
throw new Error("Excess padding");
|
|
if (!padding2 && carry)
|
|
throw new Error(`Non-zero padding: ${carry}`);
|
|
if (padding2 && pos > 0)
|
|
res.push(carry >>> 0);
|
|
return res;
|
|
}
|
|
function radix(num) {
|
|
assertNumber(num);
|
|
return {
|
|
encode: (bytes4) => {
|
|
if (!(bytes4 instanceof Uint8Array))
|
|
throw new Error("radix.encode input should be Uint8Array");
|
|
return convertRadix(Array.from(bytes4), 2 ** 8, num);
|
|
},
|
|
decode: (digits) => {
|
|
if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
|
|
throw new Error("radix.decode input should be array of strings");
|
|
return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
|
|
}
|
|
};
|
|
}
|
|
function radix2(bits, revPadding = false) {
|
|
assertNumber(bits);
|
|
if (bits <= 0 || bits > 32)
|
|
throw new Error("radix2: bits should be in (0..32]");
|
|
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
|
|
throw new Error("radix2: carry overflow");
|
|
return {
|
|
encode: (bytes4) => {
|
|
if (!(bytes4 instanceof Uint8Array))
|
|
throw new Error("radix2.encode input should be Uint8Array");
|
|
return convertRadix2(Array.from(bytes4), 8, bits, !revPadding);
|
|
},
|
|
decode: (digits) => {
|
|
if (!Array.isArray(digits) || digits.length && typeof digits[0] !== "number")
|
|
throw new Error("radix2.decode input should be array of strings");
|
|
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
}
|
|
};
|
|
}
|
|
function unsafeWrapper(fn) {
|
|
if (typeof fn !== "function")
|
|
throw new Error("unsafeWrapper fn should be function");
|
|
return function(...args) {
|
|
try {
|
|
return fn.apply(null, args);
|
|
} catch (e) {
|
|
}
|
|
};
|
|
}
|
|
function checksum(len, fn) {
|
|
assertNumber(len);
|
|
if (typeof fn !== "function")
|
|
throw new Error("checksum fn should be function");
|
|
return {
|
|
encode(data) {
|
|
if (!(data instanceof Uint8Array))
|
|
throw new Error("checksum.encode: input should be Uint8Array");
|
|
const checksum2 = fn(data).slice(0, len);
|
|
const res = new Uint8Array(data.length + len);
|
|
res.set(data);
|
|
res.set(checksum2, data.length);
|
|
return res;
|
|
},
|
|
decode(data) {
|
|
if (!(data instanceof Uint8Array))
|
|
throw new Error("checksum.decode: input should be Uint8Array");
|
|
const payload = data.slice(0, -len);
|
|
const newChecksum = fn(payload).slice(0, len);
|
|
const oldChecksum = data.slice(-len);
|
|
for (let i2 = 0; i2 < len; i2++)
|
|
if (newChecksum[i2] !== oldChecksum[i2])
|
|
throw new Error("Invalid checksum");
|
|
return payload;
|
|
}
|
|
};
|
|
}
|
|
var utils = { alphabet, chain, checksum, radix, radix2, join, padding };
|
|
var base16 = chain(radix2(4), alphabet("0123456789ABCDEF"), join(""));
|
|
var base32 = chain(radix2(5), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), padding(5), join(""));
|
|
var base32hex = chain(radix2(5), alphabet("0123456789ABCDEFGHIJKLMNOPQRSTUV"), padding(5), join(""));
|
|
var base32crockford = chain(radix2(5), alphabet("0123456789ABCDEFGHJKMNPQRSTVWXYZ"), join(""), normalize((s) => s.toUpperCase().replace(/O/g, "0").replace(/[IL]/g, "1")));
|
|
var base64 = chain(radix2(6), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), padding(6), join(""));
|
|
var base64url = chain(radix2(6), alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), padding(6), join(""));
|
|
var genBase58 = (abc) => chain(radix(58), alphabet(abc), join(""));
|
|
var base58 = genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
var base58flickr = genBase58("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ");
|
|
var base58xrp = genBase58("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");
|
|
var XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
|
|
var base58xmr = {
|
|
encode(data) {
|
|
let res = "";
|
|
for (let i2 = 0; i2 < data.length; i2 += 8) {
|
|
const block = data.subarray(i2, i2 + 8);
|
|
res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], "1");
|
|
}
|
|
return res;
|
|
},
|
|
decode(str) {
|
|
let res = [];
|
|
for (let i2 = 0; i2 < str.length; i2 += 11) {
|
|
const slice = str.slice(i2, i2 + 11);
|
|
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
|
|
const block = base58.decode(slice);
|
|
for (let j = 0; j < block.length - blockLen; j++) {
|
|
if (block[j] !== 0)
|
|
throw new Error("base58xmr: wrong padding");
|
|
}
|
|
res = res.concat(Array.from(block.slice(block.length - blockLen)));
|
|
}
|
|
return Uint8Array.from(res);
|
|
}
|
|
};
|
|
var base58check = (sha2563) => chain(checksum(4, (data) => sha2563(sha2563(data))), base58);
|
|
var BECH_ALPHABET = chain(alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), join(""));
|
|
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
function bech32Polymod(pre) {
|
|
const b = pre >> 25;
|
|
let chk = (pre & 33554431) << 5;
|
|
for (let i2 = 0; i2 < POLYMOD_GENERATORS.length; i2++) {
|
|
if ((b >> i2 & 1) === 1)
|
|
chk ^= POLYMOD_GENERATORS[i2];
|
|
}
|
|
return chk;
|
|
}
|
|
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
const len = prefix.length;
|
|
let chk = 1;
|
|
for (let i2 = 0; i2 < len; i2++) {
|
|
const c = prefix.charCodeAt(i2);
|
|
if (c < 33 || c > 126)
|
|
throw new Error(`Invalid prefix (${prefix})`);
|
|
chk = bech32Polymod(chk) ^ c >> 5;
|
|
}
|
|
chk = bech32Polymod(chk);
|
|
for (let i2 = 0; i2 < len; i2++)
|
|
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i2) & 31;
|
|
for (let v of words)
|
|
chk = bech32Polymod(chk) ^ v;
|
|
for (let i2 = 0; i2 < 6; i2++)
|
|
chk = bech32Polymod(chk);
|
|
chk ^= encodingConst;
|
|
return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
|
|
}
|
|
function genBech32(encoding) {
|
|
const ENCODING_CONST = encoding === "bech32" ? 1 : 734539939;
|
|
const _words = radix2(5);
|
|
const fromWords = _words.decode;
|
|
const toWords = _words.encode;
|
|
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
function encode(prefix, words, limit2 = 90) {
|
|
if (typeof prefix !== "string")
|
|
throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
|
|
if (!Array.isArray(words) || words.length && typeof words[0] !== "number")
|
|
throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
|
|
const actualLength = prefix.length + 7 + words.length;
|
|
if (limit2 !== false && actualLength > limit2)
|
|
throw new TypeError(`Length ${actualLength} exceeds limit ${limit2}`);
|
|
prefix = prefix.toLowerCase();
|
|
return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
|
|
}
|
|
function decode2(str, limit2 = 90) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`bech32.decode input should be string, not ${typeof str}`);
|
|
if (str.length < 8 || limit2 !== false && str.length > limit2)
|
|
throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit2})`);
|
|
const lowered = str.toLowerCase();
|
|
if (str !== lowered && str !== str.toUpperCase())
|
|
throw new Error(`String must be lowercase or uppercase`);
|
|
str = lowered;
|
|
const sepIndex = str.lastIndexOf("1");
|
|
if (sepIndex === 0 || sepIndex === -1)
|
|
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
const prefix = str.slice(0, sepIndex);
|
|
const _words2 = str.slice(sepIndex + 1);
|
|
if (_words2.length < 6)
|
|
throw new Error("Data must be at least 6 characters long");
|
|
const words = BECH_ALPHABET.decode(_words2).slice(0, -6);
|
|
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
if (!_words2.endsWith(sum))
|
|
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
return { prefix, words };
|
|
}
|
|
const decodeUnsafe = unsafeWrapper(decode2);
|
|
function decodeToBytes(str) {
|
|
const { prefix, words } = decode2(str, false);
|
|
return { prefix, words, bytes: fromWords(words) };
|
|
}
|
|
return { encode, decode: decode2, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
|
|
}
|
|
var bech32 = genBech32("bech32");
|
|
var bech32m = genBech32("bech32m");
|
|
var utf8 = {
|
|
encode: (data) => new TextDecoder().decode(data),
|
|
decode: (str) => new TextEncoder().encode(str)
|
|
};
|
|
var hex = chain(radix2(4), alphabet("0123456789abcdef"), join(""), normalize((s) => {
|
|
if (typeof s !== "string" || s.length % 2)
|
|
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
|
|
return s.toLowerCase();
|
|
}));
|
|
var CODERS = {
|
|
utf8,
|
|
hex,
|
|
base16,
|
|
base32,
|
|
base64,
|
|
base64url,
|
|
base58,
|
|
base58xmr
|
|
};
|
|
var coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(", ")}`;
|
|
|
|
// nip19.ts
|
|
var NostrTypeGuard = {
|
|
isNProfile: (value) => /^nprofile1[a-z\d]+$/.test(value || ""),
|
|
isNEvent: (value) => /^nevent1[a-z\d]+$/.test(value || ""),
|
|
isNAddr: (value) => /^naddr1[a-z\d]+$/.test(value || ""),
|
|
isNSec: (value) => /^nsec1[a-z\d]{58}$/.test(value || ""),
|
|
isNPub: (value) => /^npub1[a-z\d]{58}$/.test(value || ""),
|
|
isNote: (value) => /^note1[a-z\d]+$/.test(value || ""),
|
|
isNcryptsec: (value) => /^ncryptsec1[a-z\d]+$/.test(value || "")
|
|
};
|
|
var Bech32MaxSize = 5e3;
|
|
var BECH32_REGEX = /[\x21-\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/;
|
|
function integerToUint8Array(number4) {
|
|
const uint8Array = new Uint8Array(4);
|
|
uint8Array[0] = number4 >> 24 & 255;
|
|
uint8Array[1] = number4 >> 16 & 255;
|
|
uint8Array[2] = number4 >> 8 & 255;
|
|
uint8Array[3] = number4 & 255;
|
|
return uint8Array;
|
|
}
|
|
function decodeNostrURI(nip19code) {
|
|
try {
|
|
if (nip19code.startsWith("nostr:"))
|
|
nip19code = nip19code.substring(6);
|
|
return decode(nip19code);
|
|
} catch (_err) {
|
|
return { type: "invalid", data: null };
|
|
}
|
|
}
|
|
function decode(code) {
|
|
let { prefix, words } = bech32.decode(code, Bech32MaxSize);
|
|
let data = new Uint8Array(bech32.fromWords(words));
|
|
switch (prefix) {
|
|
case "nprofile": {
|
|
let tlv = parseTLV(data);
|
|
if (!tlv[0]?.[0])
|
|
throw new Error("missing TLV 0 for nprofile");
|
|
if (tlv[0][0].length !== 32)
|
|
throw new Error("TLV 0 should be 32 bytes");
|
|
return {
|
|
type: "nprofile",
|
|
data: {
|
|
pubkey: bytesToHex2(tlv[0][0]),
|
|
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
}
|
|
};
|
|
}
|
|
case "nevent": {
|
|
let tlv = parseTLV(data);
|
|
if (!tlv[0]?.[0])
|
|
throw new Error("missing TLV 0 for nevent");
|
|
if (tlv[0][0].length !== 32)
|
|
throw new Error("TLV 0 should be 32 bytes");
|
|
if (tlv[2] && tlv[2][0].length !== 32)
|
|
throw new Error("TLV 2 should be 32 bytes");
|
|
if (tlv[3] && tlv[3][0].length !== 4)
|
|
throw new Error("TLV 3 should be 4 bytes");
|
|
return {
|
|
type: "nevent",
|
|
data: {
|
|
id: bytesToHex2(tlv[0][0]),
|
|
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],
|
|
author: tlv[2]?.[0] ? bytesToHex2(tlv[2][0]) : void 0,
|
|
kind: tlv[3]?.[0] ? parseInt(bytesToHex2(tlv[3][0]), 16) : void 0
|
|
}
|
|
};
|
|
}
|
|
case "naddr": {
|
|
let tlv = parseTLV(data);
|
|
if (!tlv[0]?.[0])
|
|
throw new Error("missing TLV 0 for naddr");
|
|
if (!tlv[2]?.[0])
|
|
throw new Error("missing TLV 2 for naddr");
|
|
if (tlv[2][0].length !== 32)
|
|
throw new Error("TLV 2 should be 32 bytes");
|
|
if (!tlv[3]?.[0])
|
|
throw new Error("missing TLV 3 for naddr");
|
|
if (tlv[3][0].length !== 4)
|
|
throw new Error("TLV 3 should be 4 bytes");
|
|
return {
|
|
type: "naddr",
|
|
data: {
|
|
identifier: utf8Decoder.decode(tlv[0][0]),
|
|
pubkey: bytesToHex2(tlv[2][0]),
|
|
kind: parseInt(bytesToHex2(tlv[3][0]), 16),
|
|
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
}
|
|
};
|
|
}
|
|
case "nsec":
|
|
return { type: prefix, data };
|
|
case "npub":
|
|
case "note":
|
|
return { type: prefix, data: bytesToHex2(data) };
|
|
default:
|
|
throw new Error(`unknown prefix ${prefix}`);
|
|
}
|
|
}
|
|
function parseTLV(data) {
|
|
let result = {};
|
|
let rest = data;
|
|
while (rest.length > 0) {
|
|
let t = rest[0];
|
|
let l = rest[1];
|
|
let v = rest.slice(2, 2 + l);
|
|
rest = rest.slice(2 + l);
|
|
if (v.length < l)
|
|
throw new Error(`not enough data to read on TLV ${t}`);
|
|
result[t] = result[t] || [];
|
|
result[t].push(v);
|
|
}
|
|
return result;
|
|
}
|
|
function nsecEncode(key) {
|
|
return encodeBytes("nsec", key);
|
|
}
|
|
function npubEncode(hex2) {
|
|
return encodeBytes("npub", hexToBytes2(hex2));
|
|
}
|
|
function noteEncode(hex2) {
|
|
return encodeBytes("note", hexToBytes2(hex2));
|
|
}
|
|
function encodeBech32(prefix, data) {
|
|
let words = bech32.toWords(data);
|
|
return bech32.encode(prefix, words, Bech32MaxSize);
|
|
}
|
|
function encodeBytes(prefix, bytes4) {
|
|
return encodeBech32(prefix, bytes4);
|
|
}
|
|
function nprofileEncode(profile) {
|
|
let data = encodeTLV({
|
|
0: [hexToBytes2(profile.pubkey)],
|
|
1: (profile.relays || []).map((url) => utf8Encoder.encode(url))
|
|
});
|
|
return encodeBech32("nprofile", data);
|
|
}
|
|
function neventEncode(event) {
|
|
let kindArray;
|
|
if (event.kind !== void 0) {
|
|
kindArray = integerToUint8Array(event.kind);
|
|
}
|
|
let data = encodeTLV({
|
|
0: [hexToBytes2(event.id)],
|
|
1: (event.relays || []).map((url) => utf8Encoder.encode(url)),
|
|
2: event.author ? [hexToBytes2(event.author)] : [],
|
|
3: kindArray ? [new Uint8Array(kindArray)] : []
|
|
});
|
|
return encodeBech32("nevent", data);
|
|
}
|
|
function naddrEncode(addr) {
|
|
let kind = new ArrayBuffer(4);
|
|
new DataView(kind).setUint32(0, addr.kind, false);
|
|
let data = encodeTLV({
|
|
0: [utf8Encoder.encode(addr.identifier)],
|
|
1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),
|
|
2: [hexToBytes2(addr.pubkey)],
|
|
3: [new Uint8Array(kind)]
|
|
});
|
|
return encodeBech32("naddr", data);
|
|
}
|
|
function encodeTLV(tlv) {
|
|
let entries = [];
|
|
Object.entries(tlv).reverse().forEach(([t, vs]) => {
|
|
vs.forEach((v) => {
|
|
let entry = new Uint8Array(v.length + 2);
|
|
entry.set([parseInt(t)], 0);
|
|
entry.set([v.length], 1);
|
|
entry.set(v, 2);
|
|
entries.push(entry);
|
|
});
|
|
});
|
|
return concatBytes3(...entries);
|
|
}
|
|
|
|
// references.ts
|
|
var mentionRegex = /\bnostr:((note|npub|naddr|nevent|nprofile)1\w+)\b|#\[(\d+)\]/g;
|
|
function parseReferences(evt) {
|
|
let references = [];
|
|
for (let ref of evt.content.matchAll(mentionRegex)) {
|
|
if (ref[2]) {
|
|
try {
|
|
let { type, data } = decode(ref[1]);
|
|
switch (type) {
|
|
case "npub": {
|
|
references.push({
|
|
text: ref[0],
|
|
profile: { pubkey: data, relays: [] }
|
|
});
|
|
break;
|
|
}
|
|
case "nprofile": {
|
|
references.push({
|
|
text: ref[0],
|
|
profile: data
|
|
});
|
|
break;
|
|
}
|
|
case "note": {
|
|
references.push({
|
|
text: ref[0],
|
|
event: { id: data, relays: [] }
|
|
});
|
|
break;
|
|
}
|
|
case "nevent": {
|
|
references.push({
|
|
text: ref[0],
|
|
event: data
|
|
});
|
|
break;
|
|
}
|
|
case "naddr": {
|
|
references.push({
|
|
text: ref[0],
|
|
address: data
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
}
|
|
} else if (ref[3]) {
|
|
let idx = parseInt(ref[3], 10);
|
|
let tag = evt.tags[idx];
|
|
if (!tag)
|
|
continue;
|
|
switch (tag[0]) {
|
|
case "p": {
|
|
references.push({
|
|
text: ref[0],
|
|
profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] }
|
|
});
|
|
break;
|
|
}
|
|
case "e": {
|
|
references.push({
|
|
text: ref[0],
|
|
event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] }
|
|
});
|
|
break;
|
|
}
|
|
case "a": {
|
|
try {
|
|
let [kind, pubkey, identifier] = tag[1].split(":");
|
|
references.push({
|
|
text: ref[0],
|
|
address: {
|
|
identifier,
|
|
pubkey,
|
|
kind: parseInt(kind, 10),
|
|
relays: tag[2] ? [tag[2]] : []
|
|
}
|
|
});
|
|
} catch (err) {
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return references;
|
|
}
|
|
|
|
// nip04.ts
|
|
var nip04_exports = {};
|
|
__export(nip04_exports, {
|
|
decrypt: () => decrypt2,
|
|
encrypt: () => encrypt2
|
|
});
|
|
|
|
// node_modules/@noble/ciphers/esm/_assert.js
|
|
function number3(n) {
|
|
if (!Number.isSafeInteger(n) || n < 0)
|
|
throw new Error(`positive integer expected, not ${n}`);
|
|
}
|
|
function bool2(b) {
|
|
if (typeof b !== "boolean")
|
|
throw new Error(`boolean expected, not ${b}`);
|
|
}
|
|
function isBytes(a) {
|
|
return a instanceof Uint8Array || a != null && typeof a === "object" && a.constructor.name === "Uint8Array";
|
|
}
|
|
function bytes3(b, ...lengths) {
|
|
if (!isBytes(b))
|
|
throw new Error("Uint8Array expected");
|
|
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);
|
|
}
|
|
function exists3(instance, checkFinished = true) {
|
|
if (instance.destroyed)
|
|
throw new Error("Hash instance has been destroyed");
|
|
if (checkFinished && instance.finished)
|
|
throw new Error("Hash#digest() has already been called");
|
|
}
|
|
function output3(out, instance) {
|
|
bytes3(out);
|
|
const min = instance.outputLen;
|
|
if (out.length < min) {
|
|
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
|
}
|
|
}
|
|
|
|
// node_modules/@noble/ciphers/esm/utils.js
|
|
var u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
var u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
|
var createView3 = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
var isLE3 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
|
|
if (!isLE3)
|
|
throw new Error("Non little-endian hardware is not supported");
|
|
function utf8ToBytes4(str) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`string expected, got ${typeof str}`);
|
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
}
|
|
function toBytes3(data) {
|
|
if (typeof data === "string")
|
|
data = utf8ToBytes4(data);
|
|
else if (isBytes(data))
|
|
data = data.slice();
|
|
else
|
|
throw new Error(`Uint8Array expected, got ${typeof data}`);
|
|
return data;
|
|
}
|
|
function checkOpts2(defaults, opts) {
|
|
if (opts == null || typeof opts !== "object")
|
|
throw new Error("options must be defined");
|
|
const merged = Object.assign(defaults, opts);
|
|
return merged;
|
|
}
|
|
function equalBytes2(a, b) {
|
|
if (a.length !== b.length)
|
|
return false;
|
|
let diff = 0;
|
|
for (let i2 = 0; i2 < a.length; i2++)
|
|
diff |= a[i2] ^ b[i2];
|
|
return diff === 0;
|
|
}
|
|
var wrapCipher = (params, c) => {
|
|
Object.assign(c, params);
|
|
return c;
|
|
};
|
|
function setBigUint643(view, byteOffset, value, isLE4) {
|
|
if (typeof view.setBigUint64 === "function")
|
|
return view.setBigUint64(byteOffset, value, isLE4);
|
|
const _32n2 = BigInt(32);
|
|
const _u32_max = BigInt(4294967295);
|
|
const wh = Number(value >> _32n2 & _u32_max);
|
|
const wl = Number(value & _u32_max);
|
|
const h = isLE4 ? 4 : 0;
|
|
const l = isLE4 ? 0 : 4;
|
|
view.setUint32(byteOffset + h, wh, isLE4);
|
|
view.setUint32(byteOffset + l, wl, isLE4);
|
|
}
|
|
|
|
// node_modules/@noble/ciphers/esm/_polyval.js
|
|
var BLOCK_SIZE = 16;
|
|
var ZEROS16 = /* @__PURE__ */ new Uint8Array(16);
|
|
var ZEROS32 = u32(ZEROS16);
|
|
var POLY = 225;
|
|
var mul2 = (s0, s1, s2, s3) => {
|
|
const hiBit = s3 & 1;
|
|
return {
|
|
s3: s2 << 31 | s3 >>> 1,
|
|
s2: s1 << 31 | s2 >>> 1,
|
|
s1: s0 << 31 | s1 >>> 1,
|
|
s0: s0 >>> 1 ^ POLY << 24 & -(hiBit & 1)
|
|
};
|
|
};
|
|
var swapLE = (n) => (n >>> 0 & 255) << 24 | (n >>> 8 & 255) << 16 | (n >>> 16 & 255) << 8 | n >>> 24 & 255 | 0;
|
|
function _toGHASHKey(k) {
|
|
k.reverse();
|
|
const hiBit = k[15] & 1;
|
|
let carry = 0;
|
|
for (let i2 = 0; i2 < k.length; i2++) {
|
|
const t = k[i2];
|
|
k[i2] = t >>> 1 | carry;
|
|
carry = (t & 1) << 7;
|
|
}
|
|
k[0] ^= -hiBit & 225;
|
|
return k;
|
|
}
|
|
var estimateWindow = (bytes4) => {
|
|
if (bytes4 > 64 * 1024)
|
|
return 8;
|
|
if (bytes4 > 1024)
|
|
return 4;
|
|
return 2;
|
|
};
|
|
var GHASH = class {
|
|
constructor(key, expectedLength) {
|
|
this.blockLen = BLOCK_SIZE;
|
|
this.outputLen = BLOCK_SIZE;
|
|
this.s0 = 0;
|
|
this.s1 = 0;
|
|
this.s2 = 0;
|
|
this.s3 = 0;
|
|
this.finished = false;
|
|
key = toBytes3(key);
|
|
bytes3(key, 16);
|
|
const kView = createView3(key);
|
|
let k0 = kView.getUint32(0, false);
|
|
let k1 = kView.getUint32(4, false);
|
|
let k2 = kView.getUint32(8, false);
|
|
let k3 = kView.getUint32(12, false);
|
|
const doubles = [];
|
|
for (let i2 = 0; i2 < 128; i2++) {
|
|
doubles.push({ s0: swapLE(k0), s1: swapLE(k1), s2: swapLE(k2), s3: swapLE(k3) });
|
|
({ s0: k0, s1: k1, s2: k2, s3: k3 } = mul2(k0, k1, k2, k3));
|
|
}
|
|
const W = estimateWindow(expectedLength || 1024);
|
|
if (![1, 2, 4, 8].includes(W))
|
|
throw new Error(`ghash: wrong window size=${W}, should be 2, 4 or 8`);
|
|
this.W = W;
|
|
const bits = 128;
|
|
const windows = bits / W;
|
|
const windowSize = this.windowSize = 2 ** W;
|
|
const items = [];
|
|
for (let w = 0; w < windows; w++) {
|
|
for (let byte = 0; byte < windowSize; byte++) {
|
|
let s0 = 0, s1 = 0, s2 = 0, s3 = 0;
|
|
for (let j = 0; j < W; j++) {
|
|
const bit = byte >>> W - j - 1 & 1;
|
|
if (!bit)
|
|
continue;
|
|
const { s0: d0, s1: d1, s2: d2, s3: d3 } = doubles[W * w + j];
|
|
s0 ^= d0, s1 ^= d1, s2 ^= d2, s3 ^= d3;
|
|
}
|
|
items.push({ s0, s1, s2, s3 });
|
|
}
|
|
}
|
|
this.t = items;
|
|
}
|
|
_updateBlock(s0, s1, s2, s3) {
|
|
s0 ^= this.s0, s1 ^= this.s1, s2 ^= this.s2, s3 ^= this.s3;
|
|
const { W, t, windowSize } = this;
|
|
let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
|
|
const mask = (1 << W) - 1;
|
|
let w = 0;
|
|
for (const num of [s0, s1, s2, s3]) {
|
|
for (let bytePos = 0; bytePos < 4; bytePos++) {
|
|
const byte = num >>> 8 * bytePos & 255;
|
|
for (let bitPos = 8 / W - 1; bitPos >= 0; bitPos--) {
|
|
const bit = byte >>> W * bitPos & mask;
|
|
const { s0: e0, s1: e1, s2: e2, s3: e3 } = t[w * windowSize + bit];
|
|
o0 ^= e0, o1 ^= e1, o2 ^= e2, o3 ^= e3;
|
|
w += 1;
|
|
}
|
|
}
|
|
}
|
|
this.s0 = o0;
|
|
this.s1 = o1;
|
|
this.s2 = o2;
|
|
this.s3 = o3;
|
|
}
|
|
update(data) {
|
|
data = toBytes3(data);
|
|
exists3(this);
|
|
const b32 = u32(data);
|
|
const blocks = Math.floor(data.length / BLOCK_SIZE);
|
|
const left = data.length % BLOCK_SIZE;
|
|
for (let i2 = 0; i2 < blocks; i2++) {
|
|
this._updateBlock(b32[i2 * 4 + 0], b32[i2 * 4 + 1], b32[i2 * 4 + 2], b32[i2 * 4 + 3]);
|
|
}
|
|
if (left) {
|
|
ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
|
|
this._updateBlock(ZEROS32[0], ZEROS32[1], ZEROS32[2], ZEROS32[3]);
|
|
ZEROS32.fill(0);
|
|
}
|
|
return this;
|
|
}
|
|
destroy() {
|
|
const { t } = this;
|
|
for (const elm of t) {
|
|
elm.s0 = 0, elm.s1 = 0, elm.s2 = 0, elm.s3 = 0;
|
|
}
|
|
}
|
|
digestInto(out) {
|
|
exists3(this);
|
|
output3(out, this);
|
|
this.finished = true;
|
|
const { s0, s1, s2, s3 } = this;
|
|
const o32 = u32(out);
|
|
o32[0] = s0;
|
|
o32[1] = s1;
|
|
o32[2] = s2;
|
|
o32[3] = s3;
|
|
return out;
|
|
}
|
|
digest() {
|
|
const res = new Uint8Array(BLOCK_SIZE);
|
|
this.digestInto(res);
|
|
this.destroy();
|
|
return res;
|
|
}
|
|
};
|
|
var Polyval = class extends GHASH {
|
|
constructor(key, expectedLength) {
|
|
key = toBytes3(key);
|
|
const ghKey = _toGHASHKey(key.slice());
|
|
super(ghKey, expectedLength);
|
|
ghKey.fill(0);
|
|
}
|
|
update(data) {
|
|
data = toBytes3(data);
|
|
exists3(this);
|
|
const b32 = u32(data);
|
|
const left = data.length % BLOCK_SIZE;
|
|
const blocks = Math.floor(data.length / BLOCK_SIZE);
|
|
for (let i2 = 0; i2 < blocks; i2++) {
|
|
this._updateBlock(swapLE(b32[i2 * 4 + 3]), swapLE(b32[i2 * 4 + 2]), swapLE(b32[i2 * 4 + 1]), swapLE(b32[i2 * 4 + 0]));
|
|
}
|
|
if (left) {
|
|
ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
|
|
this._updateBlock(swapLE(ZEROS32[3]), swapLE(ZEROS32[2]), swapLE(ZEROS32[1]), swapLE(ZEROS32[0]));
|
|
ZEROS32.fill(0);
|
|
}
|
|
return this;
|
|
}
|
|
digestInto(out) {
|
|
exists3(this);
|
|
output3(out, this);
|
|
this.finished = true;
|
|
const { s0, s1, s2, s3 } = this;
|
|
const o32 = u32(out);
|
|
o32[0] = s0;
|
|
o32[1] = s1;
|
|
o32[2] = s2;
|
|
o32[3] = s3;
|
|
return out.reverse();
|
|
}
|
|
};
|
|
function wrapConstructorWithKey(hashCons) {
|
|
const hashC = (msg, key) => hashCons(key, msg.length).update(toBytes3(msg)).digest();
|
|
const tmp = hashCons(new Uint8Array(16), 0);
|
|
hashC.outputLen = tmp.outputLen;
|
|
hashC.blockLen = tmp.blockLen;
|
|
hashC.create = (key, expectedLength) => hashCons(key, expectedLength);
|
|
return hashC;
|
|
}
|
|
var ghash = wrapConstructorWithKey((key, expectedLength) => new GHASH(key, expectedLength));
|
|
var polyval = wrapConstructorWithKey((key, expectedLength) => new Polyval(key, expectedLength));
|
|
|
|
// node_modules/@noble/ciphers/esm/aes.js
|
|
var BLOCK_SIZE2 = 16;
|
|
var BLOCK_SIZE32 = 4;
|
|
var EMPTY_BLOCK = new Uint8Array(BLOCK_SIZE2);
|
|
var POLY2 = 283;
|
|
function mul22(n) {
|
|
return n << 1 ^ POLY2 & -(n >> 7);
|
|
}
|
|
function mul(a, b) {
|
|
let res = 0;
|
|
for (; b > 0; b >>= 1) {
|
|
res ^= a & -(b & 1);
|
|
a = mul22(a);
|
|
}
|
|
return res;
|
|
}
|
|
var sbox = /* @__PURE__ */ (() => {
|
|
let t = new Uint8Array(256);
|
|
for (let i2 = 0, x = 1; i2 < 256; i2++, x ^= mul22(x))
|
|
t[i2] = x;
|
|
const box = new Uint8Array(256);
|
|
box[0] = 99;
|
|
for (let i2 = 0; i2 < 255; i2++) {
|
|
let x = t[255 - i2];
|
|
x |= x << 8;
|
|
box[t[i2]] = (x ^ x >> 4 ^ x >> 5 ^ x >> 6 ^ x >> 7 ^ 99) & 255;
|
|
}
|
|
return box;
|
|
})();
|
|
var invSbox = /* @__PURE__ */ sbox.map((_, j) => sbox.indexOf(j));
|
|
var rotr32_8 = (n) => n << 24 | n >>> 8;
|
|
var rotl32_8 = (n) => n << 8 | n >>> 24;
|
|
function genTtable(sbox2, fn) {
|
|
if (sbox2.length !== 256)
|
|
throw new Error("Wrong sbox length");
|
|
const T0 = new Uint32Array(256).map((_, j) => fn(sbox2[j]));
|
|
const T1 = T0.map(rotl32_8);
|
|
const T2 = T1.map(rotl32_8);
|
|
const T3 = T2.map(rotl32_8);
|
|
const T01 = new Uint32Array(256 * 256);
|
|
const T23 = new Uint32Array(256 * 256);
|
|
const sbox22 = new Uint16Array(256 * 256);
|
|
for (let i2 = 0; i2 < 256; i2++) {
|
|
for (let j = 0; j < 256; j++) {
|
|
const idx = i2 * 256 + j;
|
|
T01[idx] = T0[i2] ^ T1[j];
|
|
T23[idx] = T2[i2] ^ T3[j];
|
|
sbox22[idx] = sbox2[i2] << 8 | sbox2[j];
|
|
}
|
|
}
|
|
return { sbox: sbox2, sbox2: sbox22, T0, T1, T2, T3, T01, T23 };
|
|
}
|
|
var tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => mul(s, 3) << 24 | s << 16 | s << 8 | mul(s, 2));
|
|
var tableDecoding = /* @__PURE__ */ genTtable(invSbox, (s) => mul(s, 11) << 24 | mul(s, 13) << 16 | mul(s, 9) << 8 | mul(s, 14));
|
|
var xPowers = /* @__PURE__ */ (() => {
|
|
const p = new Uint8Array(16);
|
|
for (let i2 = 0, x = 1; i2 < 16; i2++, x = mul22(x))
|
|
p[i2] = x;
|
|
return p;
|
|
})();
|
|
function expandKeyLE(key) {
|
|
bytes3(key);
|
|
const len = key.length;
|
|
if (![16, 24, 32].includes(len))
|
|
throw new Error(`aes: wrong key size: should be 16, 24 or 32, got: ${len}`);
|
|
const { sbox2 } = tableEncoding;
|
|
const k32 = u32(key);
|
|
const Nk = k32.length;
|
|
const subByte = (n) => applySbox(sbox2, n, n, n, n);
|
|
const xk = new Uint32Array(len + 28);
|
|
xk.set(k32);
|
|
for (let i2 = Nk; i2 < xk.length; i2++) {
|
|
let t = xk[i2 - 1];
|
|
if (i2 % Nk === 0)
|
|
t = subByte(rotr32_8(t)) ^ xPowers[i2 / Nk - 1];
|
|
else if (Nk > 6 && i2 % Nk === 4)
|
|
t = subByte(t);
|
|
xk[i2] = xk[i2 - Nk] ^ t;
|
|
}
|
|
return xk;
|
|
}
|
|
function expandKeyDecLE(key) {
|
|
const encKey = expandKeyLE(key);
|
|
const xk = encKey.slice();
|
|
const Nk = encKey.length;
|
|
const { sbox2 } = tableEncoding;
|
|
const { T0, T1, T2, T3 } = tableDecoding;
|
|
for (let i2 = 0; i2 < Nk; i2 += 4) {
|
|
for (let j = 0; j < 4; j++)
|
|
xk[i2 + j] = encKey[Nk - i2 - 4 + j];
|
|
}
|
|
encKey.fill(0);
|
|
for (let i2 = 4; i2 < Nk - 4; i2++) {
|
|
const x = xk[i2];
|
|
const w = applySbox(sbox2, x, x, x, x);
|
|
xk[i2] = T0[w & 255] ^ T1[w >>> 8 & 255] ^ T2[w >>> 16 & 255] ^ T3[w >>> 24];
|
|
}
|
|
return xk;
|
|
}
|
|
function apply0123(T01, T23, s0, s1, s2, s3) {
|
|
return T01[s0 << 8 & 65280 | s1 >>> 8 & 255] ^ T23[s2 >>> 8 & 65280 | s3 >>> 24 & 255];
|
|
}
|
|
function applySbox(sbox2, s0, s1, s2, s3) {
|
|
return sbox2[s0 & 255 | s1 & 65280] | sbox2[s2 >>> 16 & 255 | s3 >>> 16 & 65280] << 16;
|
|
}
|
|
function encrypt(xk, s0, s1, s2, s3) {
|
|
const { sbox2, T01, T23 } = tableEncoding;
|
|
let k = 0;
|
|
s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
|
|
const rounds = xk.length / 4 - 2;
|
|
for (let i2 = 0; i2 < rounds; i2++) {
|
|
const t02 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);
|
|
const t12 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);
|
|
const t22 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);
|
|
const t32 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);
|
|
s0 = t02, s1 = t12, s2 = t22, s3 = t32;
|
|
}
|
|
const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);
|
|
const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);
|
|
const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);
|
|
const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);
|
|
return { s0: t0, s1: t1, s2: t2, s3: t3 };
|
|
}
|
|
function decrypt(xk, s0, s1, s2, s3) {
|
|
const { sbox2, T01, T23 } = tableDecoding;
|
|
let k = 0;
|
|
s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
|
|
const rounds = xk.length / 4 - 2;
|
|
for (let i2 = 0; i2 < rounds; i2++) {
|
|
const t02 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);
|
|
const t12 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);
|
|
const t22 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);
|
|
const t32 = xk[k++] ^ apply0123(T01, T23, s3, s2, s1, s0);
|
|
s0 = t02, s1 = t12, s2 = t22, s3 = t32;
|
|
}
|
|
const t0 = xk[k++] ^ applySbox(sbox2, s0, s3, s2, s1);
|
|
const t1 = xk[k++] ^ applySbox(sbox2, s1, s0, s3, s2);
|
|
const t2 = xk[k++] ^ applySbox(sbox2, s2, s1, s0, s3);
|
|
const t3 = xk[k++] ^ applySbox(sbox2, s3, s2, s1, s0);
|
|
return { s0: t0, s1: t1, s2: t2, s3: t3 };
|
|
}
|
|
function getDst(len, dst) {
|
|
if (!dst)
|
|
return new Uint8Array(len);
|
|
bytes3(dst);
|
|
if (dst.length < len)
|
|
throw new Error(`aes: wrong destination length, expected at least ${len}, got: ${dst.length}`);
|
|
return dst;
|
|
}
|
|
function ctrCounter(xk, nonce, src, dst) {
|
|
bytes3(nonce, BLOCK_SIZE2);
|
|
bytes3(src);
|
|
const srcLen = src.length;
|
|
dst = getDst(srcLen, dst);
|
|
const ctr3 = nonce;
|
|
const c32 = u32(ctr3);
|
|
let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
|
|
const src32 = u32(src);
|
|
const dst32 = u32(dst);
|
|
for (let i2 = 0; i2 + 4 <= src32.length; i2 += 4) {
|
|
dst32[i2 + 0] = src32[i2 + 0] ^ s0;
|
|
dst32[i2 + 1] = src32[i2 + 1] ^ s1;
|
|
dst32[i2 + 2] = src32[i2 + 2] ^ s2;
|
|
dst32[i2 + 3] = src32[i2 + 3] ^ s3;
|
|
let carry = 1;
|
|
for (let i3 = ctr3.length - 1; i3 >= 0; i3--) {
|
|
carry = carry + (ctr3[i3] & 255) | 0;
|
|
ctr3[i3] = carry & 255;
|
|
carry >>>= 8;
|
|
}
|
|
({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
|
|
}
|
|
const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
|
|
if (start < srcLen) {
|
|
const b32 = new Uint32Array([s0, s1, s2, s3]);
|
|
const buf = u8(b32);
|
|
for (let i2 = start, pos = 0; i2 < srcLen; i2++, pos++)
|
|
dst[i2] = src[i2] ^ buf[pos];
|
|
}
|
|
return dst;
|
|
}
|
|
function ctr32(xk, isLE4, nonce, src, dst) {
|
|
bytes3(nonce, BLOCK_SIZE2);
|
|
bytes3(src);
|
|
dst = getDst(src.length, dst);
|
|
const ctr3 = nonce;
|
|
const c32 = u32(ctr3);
|
|
const view = createView3(ctr3);
|
|
const src32 = u32(src);
|
|
const dst32 = u32(dst);
|
|
const ctrPos = isLE4 ? 0 : 12;
|
|
const srcLen = src.length;
|
|
let ctrNum = view.getUint32(ctrPos, isLE4);
|
|
let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
|
|
for (let i2 = 0; i2 + 4 <= src32.length; i2 += 4) {
|
|
dst32[i2 + 0] = src32[i2 + 0] ^ s0;
|
|
dst32[i2 + 1] = src32[i2 + 1] ^ s1;
|
|
dst32[i2 + 2] = src32[i2 + 2] ^ s2;
|
|
dst32[i2 + 3] = src32[i2 + 3] ^ s3;
|
|
ctrNum = ctrNum + 1 >>> 0;
|
|
view.setUint32(ctrPos, ctrNum, isLE4);
|
|
({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
|
|
}
|
|
const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
|
|
if (start < srcLen) {
|
|
const b32 = new Uint32Array([s0, s1, s2, s3]);
|
|
const buf = u8(b32);
|
|
for (let i2 = start, pos = 0; i2 < srcLen; i2++, pos++)
|
|
dst[i2] = src[i2] ^ buf[pos];
|
|
}
|
|
return dst;
|
|
}
|
|
var ctr = wrapCipher({ blockSize: 16, nonceLength: 16 }, function ctr2(key, nonce) {
|
|
bytes3(key);
|
|
bytes3(nonce, BLOCK_SIZE2);
|
|
function processCtr(buf, dst) {
|
|
const xk = expandKeyLE(key);
|
|
const n = nonce.slice();
|
|
const out = ctrCounter(xk, n, buf, dst);
|
|
xk.fill(0);
|
|
n.fill(0);
|
|
return out;
|
|
}
|
|
return {
|
|
encrypt: (plaintext, dst) => processCtr(plaintext, dst),
|
|
decrypt: (ciphertext, dst) => processCtr(ciphertext, dst)
|
|
};
|
|
});
|
|
function validateBlockDecrypt(data) {
|
|
bytes3(data);
|
|
if (data.length % BLOCK_SIZE2 !== 0) {
|
|
throw new Error(`aes/(cbc-ecb).decrypt ciphertext should consist of blocks with size ${BLOCK_SIZE2}`);
|
|
}
|
|
}
|
|
function validateBlockEncrypt(plaintext, pcks5, dst) {
|
|
let outLen = plaintext.length;
|
|
const remaining = outLen % BLOCK_SIZE2;
|
|
if (!pcks5 && remaining !== 0)
|
|
throw new Error("aec/(cbc-ecb): unpadded plaintext with disabled padding");
|
|
const b = u32(plaintext);
|
|
if (pcks5) {
|
|
let left = BLOCK_SIZE2 - remaining;
|
|
if (!left)
|
|
left = BLOCK_SIZE2;
|
|
outLen = outLen + left;
|
|
}
|
|
const out = getDst(outLen, dst);
|
|
const o = u32(out);
|
|
return { b, o, out };
|
|
}
|
|
function validatePCKS(data, pcks5) {
|
|
if (!pcks5)
|
|
return data;
|
|
const len = data.length;
|
|
if (!len)
|
|
throw new Error(`aes/pcks5: empty ciphertext not allowed`);
|
|
const lastByte = data[len - 1];
|
|
if (lastByte <= 0 || lastByte > 16)
|
|
throw new Error(`aes/pcks5: wrong padding byte: ${lastByte}`);
|
|
const out = data.subarray(0, -lastByte);
|
|
for (let i2 = 0; i2 < lastByte; i2++)
|
|
if (data[len - i2 - 1] !== lastByte)
|
|
throw new Error(`aes/pcks5: wrong padding`);
|
|
return out;
|
|
}
|
|
function padPCKS(left) {
|
|
const tmp = new Uint8Array(16);
|
|
const tmp32 = u32(tmp);
|
|
tmp.set(left);
|
|
const paddingByte = BLOCK_SIZE2 - left.length;
|
|
for (let i2 = BLOCK_SIZE2 - paddingByte; i2 < BLOCK_SIZE2; i2++)
|
|
tmp[i2] = paddingByte;
|
|
return tmp32;
|
|
}
|
|
var ecb = wrapCipher({ blockSize: 16 }, function ecb2(key, opts = {}) {
|
|
bytes3(key);
|
|
const pcks5 = !opts.disablePadding;
|
|
return {
|
|
encrypt: (plaintext, dst) => {
|
|
bytes3(plaintext);
|
|
const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
|
|
const xk = expandKeyLE(key);
|
|
let i2 = 0;
|
|
for (; i2 + 4 <= b.length; ) {
|
|
const { s0, s1, s2, s3 } = encrypt(xk, b[i2 + 0], b[i2 + 1], b[i2 + 2], b[i2 + 3]);
|
|
o[i2++] = s0, o[i2++] = s1, o[i2++] = s2, o[i2++] = s3;
|
|
}
|
|
if (pcks5) {
|
|
const tmp32 = padPCKS(plaintext.subarray(i2 * 4));
|
|
const { s0, s1, s2, s3 } = encrypt(xk, tmp32[0], tmp32[1], tmp32[2], tmp32[3]);
|
|
o[i2++] = s0, o[i2++] = s1, o[i2++] = s2, o[i2++] = s3;
|
|
}
|
|
xk.fill(0);
|
|
return _out;
|
|
},
|
|
decrypt: (ciphertext, dst) => {
|
|
validateBlockDecrypt(ciphertext);
|
|
const xk = expandKeyDecLE(key);
|
|
const out = getDst(ciphertext.length, dst);
|
|
const b = u32(ciphertext);
|
|
const o = u32(out);
|
|
for (let i2 = 0; i2 + 4 <= b.length; ) {
|
|
const { s0, s1, s2, s3 } = decrypt(xk, b[i2 + 0], b[i2 + 1], b[i2 + 2], b[i2 + 3]);
|
|
o[i2++] = s0, o[i2++] = s1, o[i2++] = s2, o[i2++] = s3;
|
|
}
|
|
xk.fill(0);
|
|
return validatePCKS(out, pcks5);
|
|
}
|
|
};
|
|
});
|
|
var cbc = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cbc2(key, iv, opts = {}) {
|
|
bytes3(key);
|
|
bytes3(iv, 16);
|
|
const pcks5 = !opts.disablePadding;
|
|
return {
|
|
encrypt: (plaintext, dst) => {
|
|
const xk = expandKeyLE(key);
|
|
const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
|
|
const n32 = u32(iv);
|
|
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
|
let i2 = 0;
|
|
for (; i2 + 4 <= b.length; ) {
|
|
s0 ^= b[i2 + 0], s1 ^= b[i2 + 1], s2 ^= b[i2 + 2], s3 ^= b[i2 + 3];
|
|
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
|
o[i2++] = s0, o[i2++] = s1, o[i2++] = s2, o[i2++] = s3;
|
|
}
|
|
if (pcks5) {
|
|
const tmp32 = padPCKS(plaintext.subarray(i2 * 4));
|
|
s0 ^= tmp32[0], s1 ^= tmp32[1], s2 ^= tmp32[2], s3 ^= tmp32[3];
|
|
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
|
o[i2++] = s0, o[i2++] = s1, o[i2++] = s2, o[i2++] = s3;
|
|
}
|
|
xk.fill(0);
|
|
return _out;
|
|
},
|
|
decrypt: (ciphertext, dst) => {
|
|
validateBlockDecrypt(ciphertext);
|
|
const xk = expandKeyDecLE(key);
|
|
const n32 = u32(iv);
|
|
const out = getDst(ciphertext.length, dst);
|
|
const b = u32(ciphertext);
|
|
const o = u32(out);
|
|
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
|
for (let i2 = 0; i2 + 4 <= b.length; ) {
|
|
const ps0 = s0, ps1 = s1, ps2 = s2, ps3 = s3;
|
|
s0 = b[i2 + 0], s1 = b[i2 + 1], s2 = b[i2 + 2], s3 = b[i2 + 3];
|
|
const { s0: o0, s1: o1, s2: o2, s3: o3 } = decrypt(xk, s0, s1, s2, s3);
|
|
o[i2++] = o0 ^ ps0, o[i2++] = o1 ^ ps1, o[i2++] = o2 ^ ps2, o[i2++] = o3 ^ ps3;
|
|
}
|
|
xk.fill(0);
|
|
return validatePCKS(out, pcks5);
|
|
}
|
|
};
|
|
});
|
|
var cfb = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cfb2(key, iv) {
|
|
bytes3(key);
|
|
bytes3(iv, 16);
|
|
function processCfb(src, isEncrypt, dst) {
|
|
const xk = expandKeyLE(key);
|
|
const srcLen = src.length;
|
|
dst = getDst(srcLen, dst);
|
|
const src32 = u32(src);
|
|
const dst32 = u32(dst);
|
|
const next32 = isEncrypt ? dst32 : src32;
|
|
const n32 = u32(iv);
|
|
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
|
for (let i2 = 0; i2 + 4 <= src32.length; ) {
|
|
const { s0: e0, s1: e1, s2: e2, s3: e3 } = encrypt(xk, s0, s1, s2, s3);
|
|
dst32[i2 + 0] = src32[i2 + 0] ^ e0;
|
|
dst32[i2 + 1] = src32[i2 + 1] ^ e1;
|
|
dst32[i2 + 2] = src32[i2 + 2] ^ e2;
|
|
dst32[i2 + 3] = src32[i2 + 3] ^ e3;
|
|
s0 = next32[i2++], s1 = next32[i2++], s2 = next32[i2++], s3 = next32[i2++];
|
|
}
|
|
const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
|
|
if (start < srcLen) {
|
|
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
|
const buf = u8(new Uint32Array([s0, s1, s2, s3]));
|
|
for (let i2 = start, pos = 0; i2 < srcLen; i2++, pos++)
|
|
dst[i2] = src[i2] ^ buf[pos];
|
|
buf.fill(0);
|
|
}
|
|
xk.fill(0);
|
|
return dst;
|
|
}
|
|
return {
|
|
encrypt: (plaintext, dst) => processCfb(plaintext, true, dst),
|
|
decrypt: (ciphertext, dst) => processCfb(ciphertext, false, dst)
|
|
};
|
|
});
|
|
function computeTag(fn, isLE4, key, data, AAD) {
|
|
const h = fn.create(key, data.length + (AAD?.length || 0));
|
|
if (AAD)
|
|
h.update(AAD);
|
|
h.update(data);
|
|
const num = new Uint8Array(16);
|
|
const view = createView3(num);
|
|
if (AAD)
|
|
setBigUint643(view, 0, BigInt(AAD.length * 8), isLE4);
|
|
setBigUint643(view, 8, BigInt(data.length * 8), isLE4);
|
|
h.update(num);
|
|
return h.digest();
|
|
}
|
|
var gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function gcm2(key, nonce, AAD) {
|
|
bytes3(nonce);
|
|
if (nonce.length === 0)
|
|
throw new Error("aes/gcm: empty nonce");
|
|
const tagLength = 16;
|
|
function _computeTag(authKey, tagMask, data) {
|
|
const tag = computeTag(ghash, false, authKey, data, AAD);
|
|
for (let i2 = 0; i2 < tagMask.length; i2++)
|
|
tag[i2] ^= tagMask[i2];
|
|
return tag;
|
|
}
|
|
function deriveKeys() {
|
|
const xk = expandKeyLE(key);
|
|
const authKey = EMPTY_BLOCK.slice();
|
|
const counter = EMPTY_BLOCK.slice();
|
|
ctr32(xk, false, counter, counter, authKey);
|
|
if (nonce.length === 12) {
|
|
counter.set(nonce);
|
|
} else {
|
|
const nonceLen = EMPTY_BLOCK.slice();
|
|
const view = createView3(nonceLen);
|
|
setBigUint643(view, 8, BigInt(nonce.length * 8), false);
|
|
ghash.create(authKey).update(nonce).update(nonceLen).digestInto(counter);
|
|
}
|
|
const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);
|
|
return { xk, authKey, counter, tagMask };
|
|
}
|
|
return {
|
|
encrypt: (plaintext) => {
|
|
bytes3(plaintext);
|
|
const { xk, authKey, counter, tagMask } = deriveKeys();
|
|
const out = new Uint8Array(plaintext.length + tagLength);
|
|
ctr32(xk, false, counter, plaintext, out);
|
|
const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));
|
|
out.set(tag, plaintext.length);
|
|
xk.fill(0);
|
|
return out;
|
|
},
|
|
decrypt: (ciphertext) => {
|
|
bytes3(ciphertext);
|
|
if (ciphertext.length < tagLength)
|
|
throw new Error(`aes/gcm: ciphertext less than tagLen (${tagLength})`);
|
|
const { xk, authKey, counter, tagMask } = deriveKeys();
|
|
const data = ciphertext.subarray(0, -tagLength);
|
|
const passedTag = ciphertext.subarray(-tagLength);
|
|
const tag = _computeTag(authKey, tagMask, data);
|
|
if (!equalBytes2(tag, passedTag))
|
|
throw new Error("aes/gcm: invalid ghash tag");
|
|
const out = ctr32(xk, false, counter, data);
|
|
authKey.fill(0);
|
|
tagMask.fill(0);
|
|
xk.fill(0);
|
|
return out;
|
|
}
|
|
};
|
|
});
|
|
var limit = (name, min, max) => (value) => {
|
|
if (!Number.isSafeInteger(value) || min > value || value > max)
|
|
throw new Error(`${name}: invalid value=${value}, must be [${min}..${max}]`);
|
|
};
|
|
var siv = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function siv2(key, nonce, AAD) {
|
|
const tagLength = 16;
|
|
const AAD_LIMIT = limit("AAD", 0, 2 ** 36);
|
|
const PLAIN_LIMIT = limit("plaintext", 0, 2 ** 36);
|
|
const NONCE_LIMIT = limit("nonce", 12, 12);
|
|
const CIPHER_LIMIT = limit("ciphertext", 16, 2 ** 36 + 16);
|
|
bytes3(nonce);
|
|
NONCE_LIMIT(nonce.length);
|
|
if (AAD) {
|
|
bytes3(AAD);
|
|
AAD_LIMIT(AAD.length);
|
|
}
|
|
function deriveKeys() {
|
|
const len = key.length;
|
|
if (len !== 16 && len !== 24 && len !== 32)
|
|
throw new Error(`key length must be 16, 24 or 32 bytes, got: ${len} bytes`);
|
|
const xk = expandKeyLE(key);
|
|
const encKey = new Uint8Array(len);
|
|
const authKey = new Uint8Array(16);
|
|
const n32 = u32(nonce);
|
|
let s0 = 0, s1 = n32[0], s2 = n32[1], s3 = n32[2];
|
|
let counter = 0;
|
|
for (const derivedKey of [authKey, encKey].map(u32)) {
|
|
const d32 = u32(derivedKey);
|
|
for (let i2 = 0; i2 < d32.length; i2 += 2) {
|
|
const { s0: o0, s1: o1 } = encrypt(xk, s0, s1, s2, s3);
|
|
d32[i2 + 0] = o0;
|
|
d32[i2 + 1] = o1;
|
|
s0 = ++counter;
|
|
}
|
|
}
|
|
xk.fill(0);
|
|
return { authKey, encKey: expandKeyLE(encKey) };
|
|
}
|
|
function _computeTag(encKey, authKey, data) {
|
|
const tag = computeTag(polyval, true, authKey, data, AAD);
|
|
for (let i2 = 0; i2 < 12; i2++)
|
|
tag[i2] ^= nonce[i2];
|
|
tag[15] &= 127;
|
|
const t32 = u32(tag);
|
|
let s0 = t32[0], s1 = t32[1], s2 = t32[2], s3 = t32[3];
|
|
({ s0, s1, s2, s3 } = encrypt(encKey, s0, s1, s2, s3));
|
|
t32[0] = s0, t32[1] = s1, t32[2] = s2, t32[3] = s3;
|
|
return tag;
|
|
}
|
|
function processSiv(encKey, tag, input) {
|
|
let block = tag.slice();
|
|
block[15] |= 128;
|
|
return ctr32(encKey, true, block, input);
|
|
}
|
|
return {
|
|
encrypt: (plaintext) => {
|
|
bytes3(plaintext);
|
|
PLAIN_LIMIT(plaintext.length);
|
|
const { encKey, authKey } = deriveKeys();
|
|
const tag = _computeTag(encKey, authKey, plaintext);
|
|
const out = new Uint8Array(plaintext.length + tagLength);
|
|
out.set(tag, plaintext.length);
|
|
out.set(processSiv(encKey, tag, plaintext));
|
|
encKey.fill(0);
|
|
authKey.fill(0);
|
|
return out;
|
|
},
|
|
decrypt: (ciphertext) => {
|
|
bytes3(ciphertext);
|
|
CIPHER_LIMIT(ciphertext.length);
|
|
const tag = ciphertext.subarray(-tagLength);
|
|
const { encKey, authKey } = deriveKeys();
|
|
const plaintext = processSiv(encKey, tag, ciphertext.subarray(0, -tagLength));
|
|
const expectedTag = _computeTag(encKey, authKey, plaintext);
|
|
encKey.fill(0);
|
|
authKey.fill(0);
|
|
if (!equalBytes2(tag, expectedTag))
|
|
throw new Error("invalid polyval tag");
|
|
return plaintext;
|
|
}
|
|
};
|
|
});
|
|
|
|
// nip04.ts
|
|
function encrypt2(secretKey, pubkey, text) {
|
|
const privkey = secretKey instanceof Uint8Array ? bytesToHex2(secretKey) : secretKey;
|
|
const key = secp256k1.getSharedSecret(privkey, "02" + pubkey);
|
|
const normalizedKey = getNormalizedX(key);
|
|
let iv = Uint8Array.from(randomBytes2(16));
|
|
let plaintext = utf8Encoder.encode(text);
|
|
let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext);
|
|
let ctb64 = base64.encode(new Uint8Array(ciphertext));
|
|
let ivb64 = base64.encode(new Uint8Array(iv.buffer));
|
|
return `${ctb64}?iv=${ivb64}`;
|
|
}
|
|
function decrypt2(secretKey, pubkey, data) {
|
|
const privkey = secretKey instanceof Uint8Array ? bytesToHex2(secretKey) : secretKey;
|
|
let [ctb64, ivb64] = data.split("?iv=");
|
|
let key = secp256k1.getSharedSecret(privkey, "02" + pubkey);
|
|
let normalizedKey = getNormalizedX(key);
|
|
let iv = base64.decode(ivb64);
|
|
let ciphertext = base64.decode(ctb64);
|
|
let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext);
|
|
return utf8Decoder.decode(plaintext);
|
|
}
|
|
function getNormalizedX(key) {
|
|
return key.slice(1, 33);
|
|
}
|
|
|
|
// nip05.ts
|
|
var nip05_exports = {};
|
|
__export(nip05_exports, {
|
|
NIP05_REGEX: () => NIP05_REGEX,
|
|
isNip05: () => isNip05,
|
|
isValid: () => isValid,
|
|
queryProfile: () => queryProfile,
|
|
searchDomain: () => searchDomain,
|
|
useFetchImplementation: () => useFetchImplementation
|
|
});
|
|
var NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/;
|
|
var isNip05 = (value) => NIP05_REGEX.test(value || "");
|
|
var _fetch;
|
|
try {
|
|
_fetch = fetch;
|
|
} catch (_) {
|
|
null;
|
|
}
|
|
function useFetchImplementation(fetchImplementation) {
|
|
_fetch = fetchImplementation;
|
|
}
|
|
async function searchDomain(domain, query = "") {
|
|
try {
|
|
const url = `https://${domain}/.well-known/nostr.json?name=${query}`;
|
|
const res = await _fetch(url, { redirect: "manual" });
|
|
if (res.status !== 200) {
|
|
throw Error("Wrong response code");
|
|
}
|
|
const json = await res.json();
|
|
return json.names;
|
|
} catch (_) {
|
|
return {};
|
|
}
|
|
}
|
|
async function queryProfile(fullname) {
|
|
const match = fullname.match(NIP05_REGEX);
|
|
if (!match)
|
|
return null;
|
|
const [, name = "_", domain] = match;
|
|
try {
|
|
const url = `https://${domain}/.well-known/nostr.json?name=${name}`;
|
|
const res = await _fetch(url, { redirect: "manual" });
|
|
if (res.status !== 200) {
|
|
throw Error("Wrong response code");
|
|
}
|
|
const json = await res.json();
|
|
const pubkey = json.names[name];
|
|
return pubkey ? { pubkey, relays: json.relays?.[pubkey] } : null;
|
|
} catch (_e) {
|
|
return null;
|
|
}
|
|
}
|
|
async function isValid(pubkey, nip05) {
|
|
const res = await queryProfile(nip05);
|
|
return res ? res.pubkey === pubkey : false;
|
|
}
|
|
|
|
// nip06.ts
|
|
var nip06_exports = {};
|
|
__export(nip06_exports, {
|
|
accountFromExtendedKey: () => accountFromExtendedKey,
|
|
accountFromSeedWords: () => accountFromSeedWords,
|
|
extendedKeysFromSeedWords: () => extendedKeysFromSeedWords,
|
|
generateSeedWords: () => generateSeedWords,
|
|
privateKeyFromSeedWords: () => privateKeyFromSeedWords,
|
|
validateWords: () => validateWords
|
|
});
|
|
|
|
// node_modules/@scure/bip39/esm/wordlists/english.js
|
|
var wordlist = `abandon
|
|
ability
|
|
able
|
|
about
|
|
above
|
|
absent
|
|
absorb
|
|
abstract
|
|
absurd
|
|
abuse
|
|
access
|
|
accident
|
|
account
|
|
accuse
|
|
achieve
|
|
acid
|
|
acoustic
|
|
acquire
|
|
across
|
|
act
|
|
action
|
|
actor
|
|
actress
|
|
actual
|
|
adapt
|
|
add
|
|
addict
|
|
address
|
|
adjust
|
|
admit
|
|
adult
|
|
advance
|
|
advice
|
|
aerobic
|
|
affair
|
|
afford
|
|
afraid
|
|
again
|
|
age
|
|
agent
|
|
agree
|
|
ahead
|
|
aim
|
|
air
|
|
airport
|
|
aisle
|
|
alarm
|
|
album
|
|
alcohol
|
|
alert
|
|
alien
|
|
all
|
|
alley
|
|
allow
|
|
almost
|
|
alone
|
|
alpha
|
|
already
|
|
also
|
|
alter
|
|
always
|
|
amateur
|
|
amazing
|
|
among
|
|
amount
|
|
amused
|
|
analyst
|
|
anchor
|
|
ancient
|
|
anger
|
|
angle
|
|
angry
|
|
animal
|
|
ankle
|
|
announce
|
|
annual
|
|
another
|
|
answer
|
|
antenna
|
|
antique
|
|
anxiety
|
|
any
|
|
apart
|
|
apology
|
|
appear
|
|
apple
|
|
approve
|
|
april
|
|
arch
|
|
arctic
|
|
area
|
|
arena
|
|
argue
|
|
arm
|
|
armed
|
|
armor
|
|
army
|
|
around
|
|
arrange
|
|
arrest
|
|
arrive
|
|
arrow
|
|
art
|
|
artefact
|
|
artist
|
|
artwork
|
|
ask
|
|
aspect
|
|
assault
|
|
asset
|
|
assist
|
|
assume
|
|
asthma
|
|
athlete
|
|
atom
|
|
attack
|
|
attend
|
|
attitude
|
|
attract
|
|
auction
|
|
audit
|
|
august
|
|
aunt
|
|
author
|
|
auto
|
|
autumn
|
|
average
|
|
avocado
|
|
avoid
|
|
awake
|
|
aware
|
|
away
|
|
awesome
|
|
awful
|
|
awkward
|
|
axis
|
|
baby
|
|
bachelor
|
|
bacon
|
|
badge
|
|
bag
|
|
balance
|
|
balcony
|
|
ball
|
|
bamboo
|
|
banana
|
|
banner
|
|
bar
|
|
barely
|
|
bargain
|
|
barrel
|
|
base
|
|
basic
|
|
basket
|
|
battle
|
|
beach
|
|
bean
|
|
beauty
|
|
because
|
|
become
|
|
beef
|
|
before
|
|
begin
|
|
behave
|
|
behind
|
|
believe
|
|
below
|
|
belt
|
|
bench
|
|
benefit
|
|
best
|
|
betray
|
|
better
|
|
between
|
|
beyond
|
|
bicycle
|
|
bid
|
|
bike
|
|
bind
|
|
biology
|
|
bird
|
|
birth
|
|
bitter
|
|
black
|
|
blade
|
|
blame
|
|
blanket
|
|
blast
|
|
bleak
|
|
bless
|
|
blind
|
|
blood
|
|
blossom
|
|
blouse
|
|
blue
|
|
blur
|
|
blush
|
|
board
|
|
boat
|
|
body
|
|
boil
|
|
bomb
|
|
bone
|
|
bonus
|
|
book
|
|
boost
|
|
border
|
|
boring
|
|
borrow
|
|
boss
|
|
bottom
|
|
bounce
|
|
box
|
|
boy
|
|
bracket
|
|
brain
|
|
brand
|
|
brass
|
|
brave
|
|
bread
|
|
breeze
|
|
brick
|
|
bridge
|
|
brief
|
|
bright
|
|
bring
|
|
brisk
|
|
broccoli
|
|
broken
|
|
bronze
|
|
broom
|
|
brother
|
|
brown
|
|
brush
|
|
bubble
|
|
buddy
|
|
budget
|
|
buffalo
|
|
build
|
|
bulb
|
|
bulk
|
|
bullet
|
|
bundle
|
|
bunker
|
|
burden
|
|
burger
|
|
burst
|
|
bus
|
|
business
|
|
busy
|
|
butter
|
|
buyer
|
|
buzz
|
|
cabbage
|
|
cabin
|
|
cable
|
|
cactus
|
|
cage
|
|
cake
|
|
call
|
|
calm
|
|
camera
|
|
camp
|
|
can
|
|
canal
|
|
cancel
|
|
candy
|
|
cannon
|
|
canoe
|
|
canvas
|
|
canyon
|
|
capable
|
|
capital
|
|
captain
|
|
car
|
|
carbon
|
|
card
|
|
cargo
|
|
carpet
|
|
carry
|
|
cart
|
|
case
|
|
cash
|
|
casino
|
|
castle
|
|
casual
|
|
cat
|
|
catalog
|
|
catch
|
|
category
|
|
cattle
|
|
caught
|
|
cause
|
|
caution
|
|
cave
|
|
ceiling
|
|
celery
|
|
cement
|
|
census
|
|
century
|
|
cereal
|
|
certain
|
|
chair
|
|
chalk
|
|
champion
|
|
change
|
|
chaos
|
|
chapter
|
|
charge
|
|
chase
|
|
chat
|
|
cheap
|
|
check
|
|
cheese
|
|
chef
|
|
cherry
|
|
chest
|
|
chicken
|
|
chief
|
|
child
|
|
chimney
|
|
choice
|
|
choose
|
|
chronic
|
|
chuckle
|
|
chunk
|
|
churn
|
|
cigar
|
|
cinnamon
|
|
circle
|
|
citizen
|
|
city
|
|
civil
|
|
claim
|
|
clap
|
|
clarify
|
|
claw
|
|
clay
|
|
clean
|
|
clerk
|
|
clever
|
|
click
|
|
client
|
|
cliff
|
|
climb
|
|
clinic
|
|
clip
|
|
clock
|
|
clog
|
|
close
|
|
cloth
|
|
cloud
|
|
clown
|
|
club
|
|
clump
|
|
cluster
|
|
clutch
|
|
coach
|
|
coast
|
|
coconut
|
|
code
|
|
coffee
|
|
coil
|
|
coin
|
|
collect
|
|
color
|
|
column
|
|
combine
|
|
come
|
|
comfort
|
|
comic
|
|
common
|
|
company
|
|
concert
|
|
conduct
|
|
confirm
|
|
congress
|
|
connect
|
|
consider
|
|
control
|
|
convince
|
|
cook
|
|
cool
|
|
copper
|
|
copy
|
|
coral
|
|
core
|
|
corn
|
|
correct
|
|
cost
|
|
cotton
|
|
couch
|
|
country
|
|
couple
|
|
course
|
|
cousin
|
|
cover
|
|
coyote
|
|
crack
|
|
cradle
|
|
craft
|
|
cram
|
|
crane
|
|
crash
|
|
crater
|
|
crawl
|
|
crazy
|
|
cream
|
|
credit
|
|
creek
|
|
crew
|
|
cricket
|
|
crime
|
|
crisp
|
|
critic
|
|
crop
|
|
cross
|
|
crouch
|
|
crowd
|
|
crucial
|
|
cruel
|
|
cruise
|
|
crumble
|
|
crunch
|
|
crush
|
|
cry
|
|
crystal
|
|
cube
|
|
culture
|
|
cup
|
|
cupboard
|
|
curious
|
|
current
|
|
curtain
|
|
curve
|
|
cushion
|
|
custom
|
|
cute
|
|
cycle
|
|
dad
|
|
damage
|
|
damp
|
|
dance
|
|
danger
|
|
daring
|
|
dash
|
|
daughter
|
|
dawn
|
|
day
|
|
deal
|
|
debate
|
|
debris
|
|
decade
|
|
december
|
|
decide
|
|
decline
|
|
decorate
|
|
decrease
|
|
deer
|
|
defense
|
|
define
|
|
defy
|
|
degree
|
|
delay
|
|
deliver
|
|
demand
|
|
demise
|
|
denial
|
|
dentist
|
|
deny
|
|
depart
|
|
depend
|
|
deposit
|
|
depth
|
|
deputy
|
|
derive
|
|
describe
|
|
desert
|
|
design
|
|
desk
|
|
despair
|
|
destroy
|
|
detail
|
|
detect
|
|
develop
|
|
device
|
|
devote
|
|
diagram
|
|
dial
|
|
diamond
|
|
diary
|
|
dice
|
|
diesel
|
|
diet
|
|
differ
|
|
digital
|
|
dignity
|
|
dilemma
|
|
dinner
|
|
dinosaur
|
|
direct
|
|
dirt
|
|
disagree
|
|
discover
|
|
disease
|
|
dish
|
|
dismiss
|
|
disorder
|
|
display
|
|
distance
|
|
divert
|
|
divide
|
|
divorce
|
|
dizzy
|
|
doctor
|
|
document
|
|
dog
|
|
doll
|
|
dolphin
|
|
domain
|
|
donate
|
|
donkey
|
|
donor
|
|
door
|
|
dose
|
|
double
|
|
dove
|
|
draft
|
|
dragon
|
|
drama
|
|
drastic
|
|
draw
|
|
dream
|
|
dress
|
|
drift
|
|
drill
|
|
drink
|
|
drip
|
|
drive
|
|
drop
|
|
drum
|
|
dry
|
|
duck
|
|
dumb
|
|
dune
|
|
during
|
|
dust
|
|
dutch
|
|
duty
|
|
dwarf
|
|
dynamic
|
|
eager
|
|
eagle
|
|
early
|
|
earn
|
|
earth
|
|
easily
|
|
east
|
|
easy
|
|
echo
|
|
ecology
|
|
economy
|
|
edge
|
|
edit
|
|
educate
|
|
effort
|
|
egg
|
|
eight
|
|
either
|
|
elbow
|
|
elder
|
|
electric
|
|
elegant
|
|
element
|
|
elephant
|
|
elevator
|
|
elite
|
|
else
|
|
embark
|
|
embody
|
|
embrace
|
|
emerge
|
|
emotion
|
|
employ
|
|
empower
|
|
empty
|
|
enable
|
|
enact
|
|
end
|
|
endless
|
|
endorse
|
|
enemy
|
|
energy
|
|
enforce
|
|
engage
|
|
engine
|
|
enhance
|
|
enjoy
|
|
enlist
|
|
enough
|
|
enrich
|
|
enroll
|
|
ensure
|
|
enter
|
|
entire
|
|
entry
|
|
envelope
|
|
episode
|
|
equal
|
|
equip
|
|
era
|
|
erase
|
|
erode
|
|
erosion
|
|
error
|
|
erupt
|
|
escape
|
|
essay
|
|
essence
|
|
estate
|
|
eternal
|
|
ethics
|
|
evidence
|
|
evil
|
|
evoke
|
|
evolve
|
|
exact
|
|
example
|
|
excess
|
|
exchange
|
|
excite
|
|
exclude
|
|
excuse
|
|
execute
|
|
exercise
|
|
exhaust
|
|
exhibit
|
|
exile
|
|
exist
|
|
exit
|
|
exotic
|
|
expand
|
|
expect
|
|
expire
|
|
explain
|
|
expose
|
|
express
|
|
extend
|
|
extra
|
|
eye
|
|
eyebrow
|
|
fabric
|
|
face
|
|
faculty
|
|
fade
|
|
faint
|
|
faith
|
|
fall
|
|
false
|
|
fame
|
|
family
|
|
famous
|
|
fan
|
|
fancy
|
|
fantasy
|
|
farm
|
|
fashion
|
|
fat
|
|
fatal
|
|
father
|
|
fatigue
|
|
fault
|
|
favorite
|
|
feature
|
|
february
|
|
federal
|
|
fee
|
|
feed
|
|
feel
|
|
female
|
|
fence
|
|
festival
|
|
fetch
|
|
fever
|
|
few
|
|
fiber
|
|
fiction
|
|
field
|
|
figure
|
|
file
|
|
film
|
|
filter
|
|
final
|
|
find
|
|
fine
|
|
finger
|
|
finish
|
|
fire
|
|
firm
|
|
first
|
|
fiscal
|
|
fish
|
|
fit
|
|
fitness
|
|
fix
|
|
flag
|
|
flame
|
|
flash
|
|
flat
|
|
flavor
|
|
flee
|
|
flight
|
|
flip
|
|
float
|
|
flock
|
|
floor
|
|
flower
|
|
fluid
|
|
flush
|
|
fly
|
|
foam
|
|
focus
|
|
fog
|
|
foil
|
|
fold
|
|
follow
|
|
food
|
|
foot
|
|
force
|
|
forest
|
|
forget
|
|
fork
|
|
fortune
|
|
forum
|
|
forward
|
|
fossil
|
|
foster
|
|
found
|
|
fox
|
|
fragile
|
|
frame
|
|
frequent
|
|
fresh
|
|
friend
|
|
fringe
|
|
frog
|
|
front
|
|
frost
|
|
frown
|
|
frozen
|
|
fruit
|
|
fuel
|
|
fun
|
|
funny
|
|
furnace
|
|
fury
|
|
future
|
|
gadget
|
|
gain
|
|
galaxy
|
|
gallery
|
|
game
|
|
gap
|
|
garage
|
|
garbage
|
|
garden
|
|
garlic
|
|
garment
|
|
gas
|
|
gasp
|
|
gate
|
|
gather
|
|
gauge
|
|
gaze
|
|
general
|
|
genius
|
|
genre
|
|
gentle
|
|
genuine
|
|
gesture
|
|
ghost
|
|
giant
|
|
gift
|
|
giggle
|
|
ginger
|
|
giraffe
|
|
girl
|
|
give
|
|
glad
|
|
glance
|
|
glare
|
|
glass
|
|
glide
|
|
glimpse
|
|
globe
|
|
gloom
|
|
glory
|
|
glove
|
|
glow
|
|
glue
|
|
goat
|
|
goddess
|
|
gold
|
|
good
|
|
goose
|
|
gorilla
|
|
gospel
|
|
gossip
|
|
govern
|
|
gown
|
|
grab
|
|
grace
|
|
grain
|
|
grant
|
|
grape
|
|
grass
|
|
gravity
|
|
great
|
|
green
|
|
grid
|
|
grief
|
|
grit
|
|
grocery
|
|
group
|
|
grow
|
|
grunt
|
|
guard
|
|
guess
|
|
guide
|
|
guilt
|
|
guitar
|
|
gun
|
|
gym
|
|
habit
|
|
hair
|
|
half
|
|
hammer
|
|
hamster
|
|
hand
|
|
happy
|
|
harbor
|
|
hard
|
|
harsh
|
|
harvest
|
|
hat
|
|
have
|
|
hawk
|
|
hazard
|
|
head
|
|
health
|
|
heart
|
|
heavy
|
|
hedgehog
|
|
height
|
|
hello
|
|
helmet
|
|
help
|
|
hen
|
|
hero
|
|
hidden
|
|
high
|
|
hill
|
|
hint
|
|
hip
|
|
hire
|
|
history
|
|
hobby
|
|
hockey
|
|
hold
|
|
hole
|
|
holiday
|
|
hollow
|
|
home
|
|
honey
|
|
hood
|
|
hope
|
|
horn
|
|
horror
|
|
horse
|
|
hospital
|
|
host
|
|
hotel
|
|
hour
|
|
hover
|
|
hub
|
|
huge
|
|
human
|
|
humble
|
|
humor
|
|
hundred
|
|
hungry
|
|
hunt
|
|
hurdle
|
|
hurry
|
|
hurt
|
|
husband
|
|
hybrid
|
|
ice
|
|
icon
|
|
idea
|
|
identify
|
|
idle
|
|
ignore
|
|
ill
|
|
illegal
|
|
illness
|
|
image
|
|
imitate
|
|
immense
|
|
immune
|
|
impact
|
|
impose
|
|
improve
|
|
impulse
|
|
inch
|
|
include
|
|
income
|
|
increase
|
|
index
|
|
indicate
|
|
indoor
|
|
industry
|
|
infant
|
|
inflict
|
|
inform
|
|
inhale
|
|
inherit
|
|
initial
|
|
inject
|
|
injury
|
|
inmate
|
|
inner
|
|
innocent
|
|
input
|
|
inquiry
|
|
insane
|
|
insect
|
|
inside
|
|
inspire
|
|
install
|
|
intact
|
|
interest
|
|
into
|
|
invest
|
|
invite
|
|
involve
|
|
iron
|
|
island
|
|
isolate
|
|
issue
|
|
item
|
|
ivory
|
|
jacket
|
|
jaguar
|
|
jar
|
|
jazz
|
|
jealous
|
|
jeans
|
|
jelly
|
|
jewel
|
|
job
|
|
join
|
|
joke
|
|
journey
|
|
joy
|
|
judge
|
|
juice
|
|
jump
|
|
jungle
|
|
junior
|
|
junk
|
|
just
|
|
kangaroo
|
|
keen
|
|
keep
|
|
ketchup
|
|
key
|
|
kick
|
|
kid
|
|
kidney
|
|
kind
|
|
kingdom
|
|
kiss
|
|
kit
|
|
kitchen
|
|
kite
|
|
kitten
|
|
kiwi
|
|
knee
|
|
knife
|
|
knock
|
|
know
|
|
lab
|
|
label
|
|
labor
|
|
ladder
|
|
lady
|
|
lake
|
|
lamp
|
|
language
|
|
laptop
|
|
large
|
|
later
|
|
latin
|
|
laugh
|
|
laundry
|
|
lava
|
|
law
|
|
lawn
|
|
lawsuit
|
|
layer
|
|
lazy
|
|
leader
|
|
leaf
|
|
learn
|
|
leave
|
|
lecture
|
|
left
|
|
leg
|
|
legal
|
|
legend
|
|
leisure
|
|
lemon
|
|
lend
|
|
length
|
|
lens
|
|
leopard
|
|
lesson
|
|
letter
|
|
level
|
|
liar
|
|
liberty
|
|
library
|
|
license
|
|
life
|
|
lift
|
|
light
|
|
like
|
|
limb
|
|
limit
|
|
link
|
|
lion
|
|
liquid
|
|
list
|
|
little
|
|
live
|
|
lizard
|
|
load
|
|
loan
|
|
lobster
|
|
local
|
|
lock
|
|
logic
|
|
lonely
|
|
long
|
|
loop
|
|
lottery
|
|
loud
|
|
lounge
|
|
love
|
|
loyal
|
|
lucky
|
|
luggage
|
|
lumber
|
|
lunar
|
|
lunch
|
|
luxury
|
|
lyrics
|
|
machine
|
|
mad
|
|
magic
|
|
magnet
|
|
maid
|
|
mail
|
|
main
|
|
major
|
|
make
|
|
mammal
|
|
man
|
|
manage
|
|
mandate
|
|
mango
|
|
mansion
|
|
manual
|
|
maple
|
|
marble
|
|
march
|
|
margin
|
|
marine
|
|
market
|
|
marriage
|
|
mask
|
|
mass
|
|
master
|
|
match
|
|
material
|
|
math
|
|
matrix
|
|
matter
|
|
maximum
|
|
maze
|
|
meadow
|
|
mean
|
|
measure
|
|
meat
|
|
mechanic
|
|
medal
|
|
media
|
|
melody
|
|
melt
|
|
member
|
|
memory
|
|
mention
|
|
menu
|
|
mercy
|
|
merge
|
|
merit
|
|
merry
|
|
mesh
|
|
message
|
|
metal
|
|
method
|
|
middle
|
|
midnight
|
|
milk
|
|
million
|
|
mimic
|
|
mind
|
|
minimum
|
|
minor
|
|
minute
|
|
miracle
|
|
mirror
|
|
misery
|
|
miss
|
|
mistake
|
|
mix
|
|
mixed
|
|
mixture
|
|
mobile
|
|
model
|
|
modify
|
|
mom
|
|
moment
|
|
monitor
|
|
monkey
|
|
monster
|
|
month
|
|
moon
|
|
moral
|
|
more
|
|
morning
|
|
mosquito
|
|
mother
|
|
motion
|
|
motor
|
|
mountain
|
|
mouse
|
|
move
|
|
movie
|
|
much
|
|
muffin
|
|
mule
|
|
multiply
|
|
muscle
|
|
museum
|
|
mushroom
|
|
music
|
|
must
|
|
mutual
|
|
myself
|
|
mystery
|
|
myth
|
|
naive
|
|
name
|
|
napkin
|
|
narrow
|
|
nasty
|
|
nation
|
|
nature
|
|
near
|
|
neck
|
|
need
|
|
negative
|
|
neglect
|
|
neither
|
|
nephew
|
|
nerve
|
|
nest
|
|
net
|
|
network
|
|
neutral
|
|
never
|
|
news
|
|
next
|
|
nice
|
|
night
|
|
noble
|
|
noise
|
|
nominee
|
|
noodle
|
|
normal
|
|
north
|
|
nose
|
|
notable
|
|
note
|
|
nothing
|
|
notice
|
|
novel
|
|
now
|
|
nuclear
|
|
number
|
|
nurse
|
|
nut
|
|
oak
|
|
obey
|
|
object
|
|
oblige
|
|
obscure
|
|
observe
|
|
obtain
|
|
obvious
|
|
occur
|
|
ocean
|
|
october
|
|
odor
|
|
off
|
|
offer
|
|
office
|
|
often
|
|
oil
|
|
okay
|
|
old
|
|
olive
|
|
olympic
|
|
omit
|
|
once
|
|
one
|
|
onion
|
|
online
|
|
only
|
|
open
|
|
opera
|
|
opinion
|
|
oppose
|
|
option
|
|
orange
|
|
orbit
|
|
orchard
|
|
order
|
|
ordinary
|
|
organ
|
|
orient
|
|
original
|
|
orphan
|
|
ostrich
|
|
other
|
|
outdoor
|
|
outer
|
|
output
|
|
outside
|
|
oval
|
|
oven
|
|
over
|
|
own
|
|
owner
|
|
oxygen
|
|
oyster
|
|
ozone
|
|
pact
|
|
paddle
|
|
page
|
|
pair
|
|
palace
|
|
palm
|
|
panda
|
|
panel
|
|
panic
|
|
panther
|
|
paper
|
|
parade
|
|
parent
|
|
park
|
|
parrot
|
|
party
|
|
pass
|
|
patch
|
|
path
|
|
patient
|
|
patrol
|
|
pattern
|
|
pause
|
|
pave
|
|
payment
|
|
peace
|
|
peanut
|
|
pear
|
|
peasant
|
|
pelican
|
|
pen
|
|
penalty
|
|
pencil
|
|
people
|
|
pepper
|
|
perfect
|
|
permit
|
|
person
|
|
pet
|
|
phone
|
|
photo
|
|
phrase
|
|
physical
|
|
piano
|
|
picnic
|
|
picture
|
|
piece
|
|
pig
|
|
pigeon
|
|
pill
|
|
pilot
|
|
pink
|
|
pioneer
|
|
pipe
|
|
pistol
|
|
pitch
|
|
pizza
|
|
place
|
|
planet
|
|
plastic
|
|
plate
|
|
play
|
|
please
|
|
pledge
|
|
pluck
|
|
plug
|
|
plunge
|
|
poem
|
|
poet
|
|
point
|
|
polar
|
|
pole
|
|
police
|
|
pond
|
|
pony
|
|
pool
|
|
popular
|
|
portion
|
|
position
|
|
possible
|
|
post
|
|
potato
|
|
pottery
|
|
poverty
|
|
powder
|
|
power
|
|
practice
|
|
praise
|
|
predict
|
|
prefer
|
|
prepare
|
|
present
|
|
pretty
|
|
prevent
|
|
price
|
|
pride
|
|
primary
|
|
print
|
|
priority
|
|
prison
|
|
private
|
|
prize
|
|
problem
|
|
process
|
|
produce
|
|
profit
|
|
program
|
|
project
|
|
promote
|
|
proof
|
|
property
|
|
prosper
|
|
protect
|
|
proud
|
|
provide
|
|
public
|
|
pudding
|
|
pull
|
|
pulp
|
|
pulse
|
|
pumpkin
|
|
punch
|
|
pupil
|
|
puppy
|
|
purchase
|
|
purity
|
|
purpose
|
|
purse
|
|
push
|
|
put
|
|
puzzle
|
|
pyramid
|
|
quality
|
|
quantum
|
|
quarter
|
|
question
|
|
quick
|
|
quit
|
|
quiz
|
|
quote
|
|
rabbit
|
|
raccoon
|
|
race
|
|
rack
|
|
radar
|
|
radio
|
|
rail
|
|
rain
|
|
raise
|
|
rally
|
|
ramp
|
|
ranch
|
|
random
|
|
range
|
|
rapid
|
|
rare
|
|
rate
|
|
rather
|
|
raven
|
|
raw
|
|
razor
|
|
ready
|
|
real
|
|
reason
|
|
rebel
|
|
rebuild
|
|
recall
|
|
receive
|
|
recipe
|
|
record
|
|
recycle
|
|
reduce
|
|
reflect
|
|
reform
|
|
refuse
|
|
region
|
|
regret
|
|
regular
|
|
reject
|
|
relax
|
|
release
|
|
relief
|
|
rely
|
|
remain
|
|
remember
|
|
remind
|
|
remove
|
|
render
|
|
renew
|
|
rent
|
|
reopen
|
|
repair
|
|
repeat
|
|
replace
|
|
report
|
|
require
|
|
rescue
|
|
resemble
|
|
resist
|
|
resource
|
|
response
|
|
result
|
|
retire
|
|
retreat
|
|
return
|
|
reunion
|
|
reveal
|
|
review
|
|
reward
|
|
rhythm
|
|
rib
|
|
ribbon
|
|
rice
|
|
rich
|
|
ride
|
|
ridge
|
|
rifle
|
|
right
|
|
rigid
|
|
ring
|
|
riot
|
|
ripple
|
|
risk
|
|
ritual
|
|
rival
|
|
river
|
|
road
|
|
roast
|
|
robot
|
|
robust
|
|
rocket
|
|
romance
|
|
roof
|
|
rookie
|
|
room
|
|
rose
|
|
rotate
|
|
rough
|
|
round
|
|
route
|
|
royal
|
|
rubber
|
|
rude
|
|
rug
|
|
rule
|
|
run
|
|
runway
|
|
rural
|
|
sad
|
|
saddle
|
|
sadness
|
|
safe
|
|
sail
|
|
salad
|
|
salmon
|
|
salon
|
|
salt
|
|
salute
|
|
same
|
|
sample
|
|
sand
|
|
satisfy
|
|
satoshi
|
|
sauce
|
|
sausage
|
|
save
|
|
say
|
|
scale
|
|
scan
|
|
scare
|
|
scatter
|
|
scene
|
|
scheme
|
|
school
|
|
science
|
|
scissors
|
|
scorpion
|
|
scout
|
|
scrap
|
|
screen
|
|
script
|
|
scrub
|
|
sea
|
|
search
|
|
season
|
|
seat
|
|
second
|
|
secret
|
|
section
|
|
security
|
|
seed
|
|
seek
|
|
segment
|
|
select
|
|
sell
|
|
seminar
|
|
senior
|
|
sense
|
|
sentence
|
|
series
|
|
service
|
|
session
|
|
settle
|
|
setup
|
|
seven
|
|
shadow
|
|
shaft
|
|
shallow
|
|
share
|
|
shed
|
|
shell
|
|
sheriff
|
|
shield
|
|
shift
|
|
shine
|
|
ship
|
|
shiver
|
|
shock
|
|
shoe
|
|
shoot
|
|
shop
|
|
short
|
|
shoulder
|
|
shove
|
|
shrimp
|
|
shrug
|
|
shuffle
|
|
shy
|
|
sibling
|
|
sick
|
|
side
|
|
siege
|
|
sight
|
|
sign
|
|
silent
|
|
silk
|
|
silly
|
|
silver
|
|
similar
|
|
simple
|
|
since
|
|
sing
|
|
siren
|
|
sister
|
|
situate
|
|
six
|
|
size
|
|
skate
|
|
sketch
|
|
ski
|
|
skill
|
|
skin
|
|
skirt
|
|
skull
|
|
slab
|
|
slam
|
|
sleep
|
|
slender
|
|
slice
|
|
slide
|
|
slight
|
|
slim
|
|
slogan
|
|
slot
|
|
slow
|
|
slush
|
|
small
|
|
smart
|
|
smile
|
|
smoke
|
|
smooth
|
|
snack
|
|
snake
|
|
snap
|
|
sniff
|
|
snow
|
|
soap
|
|
soccer
|
|
social
|
|
sock
|
|
soda
|
|
soft
|
|
solar
|
|
soldier
|
|
solid
|
|
solution
|
|
solve
|
|
someone
|
|
song
|
|
soon
|
|
sorry
|
|
sort
|
|
soul
|
|
sound
|
|
soup
|
|
source
|
|
south
|
|
space
|
|
spare
|
|
spatial
|
|
spawn
|
|
speak
|
|
special
|
|
speed
|
|
spell
|
|
spend
|
|
sphere
|
|
spice
|
|
spider
|
|
spike
|
|
spin
|
|
spirit
|
|
split
|
|
spoil
|
|
sponsor
|
|
spoon
|
|
sport
|
|
spot
|
|
spray
|
|
spread
|
|
spring
|
|
spy
|
|
square
|
|
squeeze
|
|
squirrel
|
|
stable
|
|
stadium
|
|
staff
|
|
stage
|
|
stairs
|
|
stamp
|
|
stand
|
|
start
|
|
state
|
|
stay
|
|
steak
|
|
steel
|
|
stem
|
|
step
|
|
stereo
|
|
stick
|
|
still
|
|
sting
|
|
stock
|
|
stomach
|
|
stone
|
|
stool
|
|
story
|
|
stove
|
|
strategy
|
|
street
|
|
strike
|
|
strong
|
|
struggle
|
|
student
|
|
stuff
|
|
stumble
|
|
style
|
|
subject
|
|
submit
|
|
subway
|
|
success
|
|
such
|
|
sudden
|
|
suffer
|
|
sugar
|
|
suggest
|
|
suit
|
|
summer
|
|
sun
|
|
sunny
|
|
sunset
|
|
super
|
|
supply
|
|
supreme
|
|
sure
|
|
surface
|
|
surge
|
|
surprise
|
|
surround
|
|
survey
|
|
suspect
|
|
sustain
|
|
swallow
|
|
swamp
|
|
swap
|
|
swarm
|
|
swear
|
|
sweet
|
|
swift
|
|
swim
|
|
swing
|
|
switch
|
|
sword
|
|
symbol
|
|
symptom
|
|
syrup
|
|
system
|
|
table
|
|
tackle
|
|
tag
|
|
tail
|
|
talent
|
|
talk
|
|
tank
|
|
tape
|
|
target
|
|
task
|
|
taste
|
|
tattoo
|
|
taxi
|
|
teach
|
|
team
|
|
tell
|
|
ten
|
|
tenant
|
|
tennis
|
|
tent
|
|
term
|
|
test
|
|
text
|
|
thank
|
|
that
|
|
theme
|
|
then
|
|
theory
|
|
there
|
|
they
|
|
thing
|
|
this
|
|
thought
|
|
three
|
|
thrive
|
|
throw
|
|
thumb
|
|
thunder
|
|
ticket
|
|
tide
|
|
tiger
|
|
tilt
|
|
timber
|
|
time
|
|
tiny
|
|
tip
|
|
tired
|
|
tissue
|
|
title
|
|
toast
|
|
tobacco
|
|
today
|
|
toddler
|
|
toe
|
|
together
|
|
toilet
|
|
token
|
|
tomato
|
|
tomorrow
|
|
tone
|
|
tongue
|
|
tonight
|
|
tool
|
|
tooth
|
|
top
|
|
topic
|
|
topple
|
|
torch
|
|
tornado
|
|
tortoise
|
|
toss
|
|
total
|
|
tourist
|
|
toward
|
|
tower
|
|
town
|
|
toy
|
|
track
|
|
trade
|
|
traffic
|
|
tragic
|
|
train
|
|
transfer
|
|
trap
|
|
trash
|
|
travel
|
|
tray
|
|
treat
|
|
tree
|
|
trend
|
|
trial
|
|
tribe
|
|
trick
|
|
trigger
|
|
trim
|
|
trip
|
|
trophy
|
|
trouble
|
|
truck
|
|
true
|
|
truly
|
|
trumpet
|
|
trust
|
|
truth
|
|
try
|
|
tube
|
|
tuition
|
|
tumble
|
|
tuna
|
|
tunnel
|
|
turkey
|
|
turn
|
|
turtle
|
|
twelve
|
|
twenty
|
|
twice
|
|
twin
|
|
twist
|
|
two
|
|
type
|
|
typical
|
|
ugly
|
|
umbrella
|
|
unable
|
|
unaware
|
|
uncle
|
|
uncover
|
|
under
|
|
undo
|
|
unfair
|
|
unfold
|
|
unhappy
|
|
uniform
|
|
unique
|
|
unit
|
|
universe
|
|
unknown
|
|
unlock
|
|
until
|
|
unusual
|
|
unveil
|
|
update
|
|
upgrade
|
|
uphold
|
|
upon
|
|
upper
|
|
upset
|
|
urban
|
|
urge
|
|
usage
|
|
use
|
|
used
|
|
useful
|
|
useless
|
|
usual
|
|
utility
|
|
vacant
|
|
vacuum
|
|
vague
|
|
valid
|
|
valley
|
|
valve
|
|
van
|
|
vanish
|
|
vapor
|
|
various
|
|
vast
|
|
vault
|
|
vehicle
|
|
velvet
|
|
vendor
|
|
venture
|
|
venue
|
|
verb
|
|
verify
|
|
version
|
|
very
|
|
vessel
|
|
veteran
|
|
viable
|
|
vibrant
|
|
vicious
|
|
victory
|
|
video
|
|
view
|
|
village
|
|
vintage
|
|
violin
|
|
virtual
|
|
virus
|
|
visa
|
|
visit
|
|
visual
|
|
vital
|
|
vivid
|
|
vocal
|
|
voice
|
|
void
|
|
volcano
|
|
volume
|
|
vote
|
|
voyage
|
|
wage
|
|
wagon
|
|
wait
|
|
walk
|
|
wall
|
|
walnut
|
|
want
|
|
warfare
|
|
warm
|
|
warrior
|
|
wash
|
|
wasp
|
|
waste
|
|
water
|
|
wave
|
|
way
|
|
wealth
|
|
weapon
|
|
wear
|
|
weasel
|
|
weather
|
|
web
|
|
wedding
|
|
weekend
|
|
weird
|
|
welcome
|
|
west
|
|
wet
|
|
whale
|
|
what
|
|
wheat
|
|
wheel
|
|
when
|
|
where
|
|
whip
|
|
whisper
|
|
wide
|
|
width
|
|
wife
|
|
wild
|
|
will
|
|
win
|
|
window
|
|
wine
|
|
wing
|
|
wink
|
|
winner
|
|
winter
|
|
wire
|
|
wisdom
|
|
wise
|
|
wish
|
|
witness
|
|
wolf
|
|
woman
|
|
wonder
|
|
wood
|
|
wool
|
|
word
|
|
work
|
|
world
|
|
worry
|
|
worth
|
|
wrap
|
|
wreck
|
|
wrestle
|
|
wrist
|
|
write
|
|
wrong
|
|
yard
|
|
year
|
|
yellow
|
|
you
|
|
young
|
|
youth
|
|
zebra
|
|
zero
|
|
zone
|
|
zoo`.split("\n");
|
|
|
|
// node_modules/@noble/hashes/esm/hmac.js
|
|
var HMAC2 = class extends Hash2 {
|
|
constructor(hash3, _key) {
|
|
super();
|
|
this.finished = false;
|
|
this.destroyed = false;
|
|
assert_default.hash(hash3);
|
|
const key = toBytes2(_key);
|
|
this.iHash = hash3.create();
|
|
if (typeof this.iHash.update !== "function")
|
|
throw new Error("Expected instance of class which extends utils.Hash");
|
|
this.blockLen = this.iHash.blockLen;
|
|
this.outputLen = this.iHash.outputLen;
|
|
const blockLen = this.blockLen;
|
|
const pad2 = new Uint8Array(blockLen);
|
|
pad2.set(key.length > blockLen ? hash3.create().update(key).digest() : key);
|
|
for (let i2 = 0; i2 < pad2.length; i2++)
|
|
pad2[i2] ^= 54;
|
|
this.iHash.update(pad2);
|
|
this.oHash = hash3.create();
|
|
for (let i2 = 0; i2 < pad2.length; i2++)
|
|
pad2[i2] ^= 54 ^ 92;
|
|
this.oHash.update(pad2);
|
|
pad2.fill(0);
|
|
}
|
|
update(buf) {
|
|
assert_default.exists(this);
|
|
this.iHash.update(buf);
|
|
return this;
|
|
}
|
|
digestInto(out) {
|
|
assert_default.exists(this);
|
|
assert_default.bytes(out, this.outputLen);
|
|
this.finished = true;
|
|
this.iHash.digestInto(out);
|
|
this.oHash.update(out);
|
|
this.oHash.digestInto(out);
|
|
this.destroy();
|
|
}
|
|
digest() {
|
|
const out = new Uint8Array(this.oHash.outputLen);
|
|
this.digestInto(out);
|
|
return out;
|
|
}
|
|
_cloneInto(to) {
|
|
to || (to = Object.create(Object.getPrototypeOf(this), {}));
|
|
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
|
|
to = to;
|
|
to.finished = finished;
|
|
to.destroyed = destroyed;
|
|
to.blockLen = blockLen;
|
|
to.outputLen = outputLen;
|
|
to.oHash = oHash._cloneInto(to.oHash);
|
|
to.iHash = iHash._cloneInto(to.iHash);
|
|
return to;
|
|
}
|
|
destroy() {
|
|
this.destroyed = true;
|
|
this.oHash.destroy();
|
|
this.iHash.destroy();
|
|
}
|
|
};
|
|
var hmac2 = (hash3, key, message) => new HMAC2(hash3, key).update(message).digest();
|
|
hmac2.create = (hash3, key) => new HMAC2(hash3, key);
|
|
|
|
// node_modules/@noble/hashes/esm/pbkdf2.js
|
|
function pbkdf2Init(hash3, _password, _salt, _opts) {
|
|
assert_default.hash(hash3);
|
|
const opts = checkOpts({ dkLen: 32, asyncTick: 10 }, _opts);
|
|
const { c, dkLen, asyncTick } = opts;
|
|
assert_default.number(c);
|
|
assert_default.number(dkLen);
|
|
assert_default.number(asyncTick);
|
|
if (c < 1)
|
|
throw new Error("PBKDF2: iterations (c) should be >= 1");
|
|
const password = toBytes2(_password);
|
|
const salt2 = toBytes2(_salt);
|
|
const DK = new Uint8Array(dkLen);
|
|
const PRF = hmac2.create(hash3, password);
|
|
const PRFSalt = PRF._cloneInto().update(salt2);
|
|
return { c, dkLen, asyncTick, DK, PRF, PRFSalt };
|
|
}
|
|
function pbkdf2Output(PRF, PRFSalt, DK, prfW, u) {
|
|
PRF.destroy();
|
|
PRFSalt.destroy();
|
|
if (prfW)
|
|
prfW.destroy();
|
|
u.fill(0);
|
|
return DK;
|
|
}
|
|
function pbkdf2(hash3, password, salt2, opts) {
|
|
const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash3, password, salt2, opts);
|
|
let prfW;
|
|
const arr = new Uint8Array(4);
|
|
const view = createView2(arr);
|
|
const u = new Uint8Array(PRF.outputLen);
|
|
for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
|
|
const Ti = DK.subarray(pos, pos + PRF.outputLen);
|
|
view.setInt32(0, ti, false);
|
|
(prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
|
|
Ti.set(u.subarray(0, Ti.length));
|
|
for (let ui = 1; ui < c; ui++) {
|
|
PRF._cloneInto(prfW).update(u).digestInto(u);
|
|
for (let i2 = 0; i2 < Ti.length; i2++)
|
|
Ti[i2] ^= u[i2];
|
|
}
|
|
}
|
|
return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
|
|
}
|
|
|
|
// node_modules/@noble/hashes/esm/_u64.js
|
|
var U32_MASK64 = BigInt(2 ** 32 - 1);
|
|
var _32n = BigInt(32);
|
|
function fromBig(n, le = false) {
|
|
if (le)
|
|
return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
|
|
return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
|
|
}
|
|
function split(lst, le = false) {
|
|
let Ah = new Uint32Array(lst.length);
|
|
let Al = new Uint32Array(lst.length);
|
|
for (let i2 = 0; i2 < lst.length; i2++) {
|
|
const { h, l } = fromBig(lst[i2], le);
|
|
[Ah[i2], Al[i2]] = [h, l];
|
|
}
|
|
return [Ah, Al];
|
|
}
|
|
var toBig = (h, l) => BigInt(h >>> 0) << _32n | BigInt(l >>> 0);
|
|
var shrSH = (h, l, s) => h >>> s;
|
|
var shrSL = (h, l, s) => h << 32 - s | l >>> s;
|
|
var rotrSH = (h, l, s) => h >>> s | l << 32 - s;
|
|
var rotrSL = (h, l, s) => h << 32 - s | l >>> s;
|
|
var rotrBH = (h, l, s) => h << 64 - s | l >>> s - 32;
|
|
var rotrBL = (h, l, s) => h >>> s - 32 | l << 64 - s;
|
|
var rotr32H = (h, l) => l;
|
|
var rotr32L = (h, l) => h;
|
|
var rotlSH = (h, l, s) => h << s | l >>> 32 - s;
|
|
var rotlSL = (h, l, s) => l << s | h >>> 32 - s;
|
|
var rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
|
|
var rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
|
|
function add(Ah, Al, Bh, Bl) {
|
|
const l = (Al >>> 0) + (Bl >>> 0);
|
|
return { h: Ah + Bh + (l / 2 ** 32 | 0) | 0, l: l | 0 };
|
|
}
|
|
var add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
|
|
var add3H = (low, Ah, Bh, Ch) => Ah + Bh + Ch + (low / 2 ** 32 | 0) | 0;
|
|
var add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
|
|
var add4H = (low, Ah, Bh, Ch, Dh) => Ah + Bh + Ch + Dh + (low / 2 ** 32 | 0) | 0;
|
|
var add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
|
|
var add5H = (low, Ah, Bh, Ch, Dh, Eh) => Ah + Bh + Ch + Dh + Eh + (low / 2 ** 32 | 0) | 0;
|
|
var u64 = {
|
|
fromBig,
|
|
split,
|
|
toBig,
|
|
shrSH,
|
|
shrSL,
|
|
rotrSH,
|
|
rotrSL,
|
|
rotrBH,
|
|
rotrBL,
|
|
rotr32H,
|
|
rotr32L,
|
|
rotlSH,
|
|
rotlSL,
|
|
rotlBH,
|
|
rotlBL,
|
|
add,
|
|
add3L,
|
|
add3H,
|
|
add4L,
|
|
add4H,
|
|
add5H,
|
|
add5L
|
|
};
|
|
var u64_default = u64;
|
|
|
|
// node_modules/@noble/hashes/esm/sha512.js
|
|
var [SHA512_Kh, SHA512_Kl] = u64_default.split([
|
|
"0x428a2f98d728ae22",
|
|
"0x7137449123ef65cd",
|
|
"0xb5c0fbcfec4d3b2f",
|
|
"0xe9b5dba58189dbbc",
|
|
"0x3956c25bf348b538",
|
|
"0x59f111f1b605d019",
|
|
"0x923f82a4af194f9b",
|
|
"0xab1c5ed5da6d8118",
|
|
"0xd807aa98a3030242",
|
|
"0x12835b0145706fbe",
|
|
"0x243185be4ee4b28c",
|
|
"0x550c7dc3d5ffb4e2",
|
|
"0x72be5d74f27b896f",
|
|
"0x80deb1fe3b1696b1",
|
|
"0x9bdc06a725c71235",
|
|
"0xc19bf174cf692694",
|
|
"0xe49b69c19ef14ad2",
|
|
"0xefbe4786384f25e3",
|
|
"0x0fc19dc68b8cd5b5",
|
|
"0x240ca1cc77ac9c65",
|
|
"0x2de92c6f592b0275",
|
|
"0x4a7484aa6ea6e483",
|
|
"0x5cb0a9dcbd41fbd4",
|
|
"0x76f988da831153b5",
|
|
"0x983e5152ee66dfab",
|
|
"0xa831c66d2db43210",
|
|
"0xb00327c898fb213f",
|
|
"0xbf597fc7beef0ee4",
|
|
"0xc6e00bf33da88fc2",
|
|
"0xd5a79147930aa725",
|
|
"0x06ca6351e003826f",
|
|
"0x142929670a0e6e70",
|
|
"0x27b70a8546d22ffc",
|
|
"0x2e1b21385c26c926",
|
|
"0x4d2c6dfc5ac42aed",
|
|
"0x53380d139d95b3df",
|
|
"0x650a73548baf63de",
|
|
"0x766a0abb3c77b2a8",
|
|
"0x81c2c92e47edaee6",
|
|
"0x92722c851482353b",
|
|
"0xa2bfe8a14cf10364",
|
|
"0xa81a664bbc423001",
|
|
"0xc24b8b70d0f89791",
|
|
"0xc76c51a30654be30",
|
|
"0xd192e819d6ef5218",
|
|
"0xd69906245565a910",
|
|
"0xf40e35855771202a",
|
|
"0x106aa07032bbd1b8",
|
|
"0x19a4c116b8d2d0c8",
|
|
"0x1e376c085141ab53",
|
|
"0x2748774cdf8eeb99",
|
|
"0x34b0bcb5e19b48a8",
|
|
"0x391c0cb3c5c95a63",
|
|
"0x4ed8aa4ae3418acb",
|
|
"0x5b9cca4f7763e373",
|
|
"0x682e6ff3d6b2b8a3",
|
|
"0x748f82ee5defb2fc",
|
|
"0x78a5636f43172f60",
|
|
"0x84c87814a1f0ab72",
|
|
"0x8cc702081a6439ec",
|
|
"0x90befffa23631e28",
|
|
"0xa4506cebde82bde9",
|
|
"0xbef9a3f7b2c67915",
|
|
"0xc67178f2e372532b",
|
|
"0xca273eceea26619c",
|
|
"0xd186b8c721c0c207",
|
|
"0xeada7dd6cde0eb1e",
|
|
"0xf57d4f7fee6ed178",
|
|
"0x06f067aa72176fba",
|
|
"0x0a637dc5a2c898a6",
|
|
"0x113f9804bef90dae",
|
|
"0x1b710b35131c471b",
|
|
"0x28db77f523047d84",
|
|
"0x32caab7b40c72493",
|
|
"0x3c9ebe0a15c9bebc",
|
|
"0x431d67c49c100d4c",
|
|
"0x4cc5d4becb3e42b6",
|
|
"0x597f299cfc657e2a",
|
|
"0x5fcb6fab3ad6faec",
|
|
"0x6c44198c4a475817"
|
|
].map((n) => BigInt(n)));
|
|
var SHA512_W_H = new Uint32Array(80);
|
|
var SHA512_W_L = new Uint32Array(80);
|
|
var SHA512 = class extends SHA22 {
|
|
constructor() {
|
|
super(128, 64, 16, false);
|
|
this.Ah = 1779033703 | 0;
|
|
this.Al = 4089235720 | 0;
|
|
this.Bh = 3144134277 | 0;
|
|
this.Bl = 2227873595 | 0;
|
|
this.Ch = 1013904242 | 0;
|
|
this.Cl = 4271175723 | 0;
|
|
this.Dh = 2773480762 | 0;
|
|
this.Dl = 1595750129 | 0;
|
|
this.Eh = 1359893119 | 0;
|
|
this.El = 2917565137 | 0;
|
|
this.Fh = 2600822924 | 0;
|
|
this.Fl = 725511199 | 0;
|
|
this.Gh = 528734635 | 0;
|
|
this.Gl = 4215389547 | 0;
|
|
this.Hh = 1541459225 | 0;
|
|
this.Hl = 327033209 | 0;
|
|
}
|
|
get() {
|
|
const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
|
|
}
|
|
set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
|
|
this.Ah = Ah | 0;
|
|
this.Al = Al | 0;
|
|
this.Bh = Bh | 0;
|
|
this.Bl = Bl | 0;
|
|
this.Ch = Ch | 0;
|
|
this.Cl = Cl | 0;
|
|
this.Dh = Dh | 0;
|
|
this.Dl = Dl | 0;
|
|
this.Eh = Eh | 0;
|
|
this.El = El | 0;
|
|
this.Fh = Fh | 0;
|
|
this.Fl = Fl | 0;
|
|
this.Gh = Gh | 0;
|
|
this.Gl = Gl | 0;
|
|
this.Hh = Hh | 0;
|
|
this.Hl = Hl | 0;
|
|
}
|
|
process(view, offset) {
|
|
for (let i2 = 0; i2 < 16; i2++, offset += 4) {
|
|
SHA512_W_H[i2] = view.getUint32(offset);
|
|
SHA512_W_L[i2] = view.getUint32(offset += 4);
|
|
}
|
|
for (let i2 = 16; i2 < 80; i2++) {
|
|
const W15h = SHA512_W_H[i2 - 15] | 0;
|
|
const W15l = SHA512_W_L[i2 - 15] | 0;
|
|
const s0h = u64_default.rotrSH(W15h, W15l, 1) ^ u64_default.rotrSH(W15h, W15l, 8) ^ u64_default.shrSH(W15h, W15l, 7);
|
|
const s0l = u64_default.rotrSL(W15h, W15l, 1) ^ u64_default.rotrSL(W15h, W15l, 8) ^ u64_default.shrSL(W15h, W15l, 7);
|
|
const W2h = SHA512_W_H[i2 - 2] | 0;
|
|
const W2l = SHA512_W_L[i2 - 2] | 0;
|
|
const s1h = u64_default.rotrSH(W2h, W2l, 19) ^ u64_default.rotrBH(W2h, W2l, 61) ^ u64_default.shrSH(W2h, W2l, 6);
|
|
const s1l = u64_default.rotrSL(W2h, W2l, 19) ^ u64_default.rotrBL(W2h, W2l, 61) ^ u64_default.shrSL(W2h, W2l, 6);
|
|
const SUMl = u64_default.add4L(s0l, s1l, SHA512_W_L[i2 - 7], SHA512_W_L[i2 - 16]);
|
|
const SUMh = u64_default.add4H(SUMl, s0h, s1h, SHA512_W_H[i2 - 7], SHA512_W_H[i2 - 16]);
|
|
SHA512_W_H[i2] = SUMh | 0;
|
|
SHA512_W_L[i2] = SUMl | 0;
|
|
}
|
|
let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
for (let i2 = 0; i2 < 80; i2++) {
|
|
const sigma1h = u64_default.rotrSH(Eh, El, 14) ^ u64_default.rotrSH(Eh, El, 18) ^ u64_default.rotrBH(Eh, El, 41);
|
|
const sigma1l = u64_default.rotrSL(Eh, El, 14) ^ u64_default.rotrSL(Eh, El, 18) ^ u64_default.rotrBL(Eh, El, 41);
|
|
const CHIh = Eh & Fh ^ ~Eh & Gh;
|
|
const CHIl = El & Fl ^ ~El & Gl;
|
|
const T1ll = u64_default.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i2], SHA512_W_L[i2]);
|
|
const T1h = u64_default.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i2], SHA512_W_H[i2]);
|
|
const T1l = T1ll | 0;
|
|
const sigma0h = u64_default.rotrSH(Ah, Al, 28) ^ u64_default.rotrBH(Ah, Al, 34) ^ u64_default.rotrBH(Ah, Al, 39);
|
|
const sigma0l = u64_default.rotrSL(Ah, Al, 28) ^ u64_default.rotrBL(Ah, Al, 34) ^ u64_default.rotrBL(Ah, Al, 39);
|
|
const MAJh = Ah & Bh ^ Ah & Ch ^ Bh & Ch;
|
|
const MAJl = Al & Bl ^ Al & Cl ^ Bl & Cl;
|
|
Hh = Gh | 0;
|
|
Hl = Gl | 0;
|
|
Gh = Fh | 0;
|
|
Gl = Fl | 0;
|
|
Fh = Eh | 0;
|
|
Fl = El | 0;
|
|
({ h: Eh, l: El } = u64_default.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
|
|
Dh = Ch | 0;
|
|
Dl = Cl | 0;
|
|
Ch = Bh | 0;
|
|
Cl = Bl | 0;
|
|
Bh = Ah | 0;
|
|
Bl = Al | 0;
|
|
const All = u64_default.add3L(T1l, sigma0l, MAJl);
|
|
Ah = u64_default.add3H(All, T1h, sigma0h, MAJh);
|
|
Al = All | 0;
|
|
}
|
|
({ h: Ah, l: Al } = u64_default.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
|
|
({ h: Bh, l: Bl } = u64_default.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
|
|
({ h: Ch, l: Cl } = u64_default.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
|
|
({ h: Dh, l: Dl } = u64_default.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
|
|
({ h: Eh, l: El } = u64_default.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
|
|
({ h: Fh, l: Fl } = u64_default.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
|
|
({ h: Gh, l: Gl } = u64_default.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
|
|
({ h: Hh, l: Hl } = u64_default.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
|
|
this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
|
|
}
|
|
roundClean() {
|
|
SHA512_W_H.fill(0);
|
|
SHA512_W_L.fill(0);
|
|
}
|
|
destroy() {
|
|
this.buffer.fill(0);
|
|
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
};
|
|
var SHA512_224 = class extends SHA512 {
|
|
constructor() {
|
|
super();
|
|
this.Ah = 2352822216 | 0;
|
|
this.Al = 424955298 | 0;
|
|
this.Bh = 1944164710 | 0;
|
|
this.Bl = 2312950998 | 0;
|
|
this.Ch = 502970286 | 0;
|
|
this.Cl = 855612546 | 0;
|
|
this.Dh = 1738396948 | 0;
|
|
this.Dl = 1479516111 | 0;
|
|
this.Eh = 258812777 | 0;
|
|
this.El = 2077511080 | 0;
|
|
this.Fh = 2011393907 | 0;
|
|
this.Fl = 79989058 | 0;
|
|
this.Gh = 1067287976 | 0;
|
|
this.Gl = 1780299464 | 0;
|
|
this.Hh = 286451373 | 0;
|
|
this.Hl = 2446758561 | 0;
|
|
this.outputLen = 28;
|
|
}
|
|
};
|
|
var SHA512_256 = class extends SHA512 {
|
|
constructor() {
|
|
super();
|
|
this.Ah = 573645204 | 0;
|
|
this.Al = 4230739756 | 0;
|
|
this.Bh = 2673172387 | 0;
|
|
this.Bl = 3360449730 | 0;
|
|
this.Ch = 596883563 | 0;
|
|
this.Cl = 1867755857 | 0;
|
|
this.Dh = 2520282905 | 0;
|
|
this.Dl = 1497426621 | 0;
|
|
this.Eh = 2519219938 | 0;
|
|
this.El = 2827943907 | 0;
|
|
this.Fh = 3193839141 | 0;
|
|
this.Fl = 1401305490 | 0;
|
|
this.Gh = 721525244 | 0;
|
|
this.Gl = 746961066 | 0;
|
|
this.Hh = 246885852 | 0;
|
|
this.Hl = 2177182882 | 0;
|
|
this.outputLen = 32;
|
|
}
|
|
};
|
|
var SHA384 = class extends SHA512 {
|
|
constructor() {
|
|
super();
|
|
this.Ah = 3418070365 | 0;
|
|
this.Al = 3238371032 | 0;
|
|
this.Bh = 1654270250 | 0;
|
|
this.Bl = 914150663 | 0;
|
|
this.Ch = 2438529370 | 0;
|
|
this.Cl = 812702999 | 0;
|
|
this.Dh = 355462360 | 0;
|
|
this.Dl = 4144912697 | 0;
|
|
this.Eh = 1731405415 | 0;
|
|
this.El = 4290775857 | 0;
|
|
this.Fh = 2394180231 | 0;
|
|
this.Fl = 1750603025 | 0;
|
|
this.Gh = 3675008525 | 0;
|
|
this.Gl = 1694076839 | 0;
|
|
this.Hh = 1203062813 | 0;
|
|
this.Hl = 3204075428 | 0;
|
|
this.outputLen = 48;
|
|
}
|
|
};
|
|
var sha512 = wrapConstructor2(() => new SHA512());
|
|
var sha512_224 = wrapConstructor2(() => new SHA512_224());
|
|
var sha512_256 = wrapConstructor2(() => new SHA512_256());
|
|
var sha384 = wrapConstructor2(() => new SHA384());
|
|
|
|
// node_modules/@scure/bip39/esm/index.js
|
|
var isJapanese = (wordlist2) => wordlist2[0] === "\u3042\u3044\u3053\u304F\u3057\u3093";
|
|
function nfkd(str) {
|
|
if (typeof str !== "string")
|
|
throw new TypeError(`Invalid mnemonic type: ${typeof str}`);
|
|
return str.normalize("NFKD");
|
|
}
|
|
function normalize2(str) {
|
|
const norm = nfkd(str);
|
|
const words = norm.split(" ");
|
|
if (![12, 15, 18, 21, 24].includes(words.length))
|
|
throw new Error("Invalid mnemonic");
|
|
return { nfkd: norm, words };
|
|
}
|
|
function assertEntropy(entropy) {
|
|
assert_default.bytes(entropy, 16, 20, 24, 28, 32);
|
|
}
|
|
function generateMnemonic(wordlist2, strength = 128) {
|
|
assert_default.number(strength);
|
|
if (strength % 32 !== 0 || strength > 256)
|
|
throw new TypeError("Invalid entropy");
|
|
return entropyToMnemonic(randomBytes2(strength / 8), wordlist2);
|
|
}
|
|
var calcChecksum = (entropy) => {
|
|
const bitsLeft = 8 - entropy.length / 4;
|
|
return new Uint8Array([sha2562(entropy)[0] >> bitsLeft << bitsLeft]);
|
|
};
|
|
function getCoder(wordlist2) {
|
|
if (!Array.isArray(wordlist2) || wordlist2.length !== 2048 || typeof wordlist2[0] !== "string")
|
|
throw new Error("Worlist: expected array of 2048 strings");
|
|
wordlist2.forEach((i2) => {
|
|
if (typeof i2 !== "string")
|
|
throw new Error(`Wordlist: non-string element: ${i2}`);
|
|
});
|
|
return utils.chain(utils.checksum(1, calcChecksum), utils.radix2(11, true), utils.alphabet(wordlist2));
|
|
}
|
|
function mnemonicToEntropy(mnemonic, wordlist2) {
|
|
const { words } = normalize2(mnemonic);
|
|
const entropy = getCoder(wordlist2).decode(words);
|
|
assertEntropy(entropy);
|
|
return entropy;
|
|
}
|
|
function entropyToMnemonic(entropy, wordlist2) {
|
|
assertEntropy(entropy);
|
|
const words = getCoder(wordlist2).encode(entropy);
|
|
return words.join(isJapanese(wordlist2) ? "\u3000" : " ");
|
|
}
|
|
function validateMnemonic(mnemonic, wordlist2) {
|
|
try {
|
|
mnemonicToEntropy(mnemonic, wordlist2);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
var salt = (passphrase) => nfkd(`mnemonic${passphrase}`);
|
|
function mnemonicToSeedSync(mnemonic, passphrase = "") {
|
|
return pbkdf2(sha512, normalize2(mnemonic).nfkd, salt(passphrase), { c: 2048, dkLen: 64 });
|
|
}
|
|
|
|
// node_modules/@noble/hashes/esm/ripemd160.js
|
|
var Rho = new Uint8Array([7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8]);
|
|
var Id = Uint8Array.from({ length: 16 }, (_, i2) => i2);
|
|
var Pi = Id.map((i2) => (9 * i2 + 5) % 16);
|
|
var idxL = [Id];
|
|
var idxR = [Pi];
|
|
for (let i2 = 0; i2 < 4; i2++)
|
|
for (let j of [idxL, idxR])
|
|
j.push(j[i2].map((k) => Rho[k]));
|
|
var shifts = [
|
|
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
|
|
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
|
|
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
|
|
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
|
|
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
|
|
].map((i2) => new Uint8Array(i2));
|
|
var shiftsL = idxL.map((idx, i2) => idx.map((j) => shifts[i2][j]));
|
|
var shiftsR = idxR.map((idx, i2) => idx.map((j) => shifts[i2][j]));
|
|
var Kl = new Uint32Array([0, 1518500249, 1859775393, 2400959708, 2840853838]);
|
|
var Kr = new Uint32Array([1352829926, 1548603684, 1836072691, 2053994217, 0]);
|
|
var rotl = (word, shift) => word << shift | word >>> 32 - shift;
|
|
function f(group, x, y, z) {
|
|
if (group === 0)
|
|
return x ^ y ^ z;
|
|
else if (group === 1)
|
|
return x & y | ~x & z;
|
|
else if (group === 2)
|
|
return (x | ~y) ^ z;
|
|
else if (group === 3)
|
|
return x & z | y & ~z;
|
|
else
|
|
return x ^ (y | ~z);
|
|
}
|
|
var BUF = new Uint32Array(16);
|
|
var RIPEMD160 = class extends SHA22 {
|
|
constructor() {
|
|
super(64, 20, 8, true);
|
|
this.h0 = 1732584193 | 0;
|
|
this.h1 = 4023233417 | 0;
|
|
this.h2 = 2562383102 | 0;
|
|
this.h3 = 271733878 | 0;
|
|
this.h4 = 3285377520 | 0;
|
|
}
|
|
get() {
|
|
const { h0, h1, h2, h3, h4 } = this;
|
|
return [h0, h1, h2, h3, h4];
|
|
}
|
|
set(h0, h1, h2, h3, h4) {
|
|
this.h0 = h0 | 0;
|
|
this.h1 = h1 | 0;
|
|
this.h2 = h2 | 0;
|
|
this.h3 = h3 | 0;
|
|
this.h4 = h4 | 0;
|
|
}
|
|
process(view, offset) {
|
|
for (let i2 = 0; i2 < 16; i2++, offset += 4)
|
|
BUF[i2] = view.getUint32(offset, true);
|
|
let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
|
|
for (let group = 0; group < 5; group++) {
|
|
const rGroup = 4 - group;
|
|
const hbl = Kl[group], hbr = Kr[group];
|
|
const rl = idxL[group], rr = idxR[group];
|
|
const sl = shiftsL[group], sr = shiftsR[group];
|
|
for (let i2 = 0; i2 < 16; i2++) {
|
|
const tl = rotl(al + f(group, bl, cl, dl) + BUF[rl[i2]] + hbl, sl[i2]) + el | 0;
|
|
al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl;
|
|
}
|
|
for (let i2 = 0; i2 < 16; i2++) {
|
|
const tr = rotl(ar + f(rGroup, br, cr, dr) + BUF[rr[i2]] + hbr, sr[i2]) + er | 0;
|
|
ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr;
|
|
}
|
|
}
|
|
this.set(this.h1 + cl + dr | 0, this.h2 + dl + er | 0, this.h3 + el + ar | 0, this.h4 + al + br | 0, this.h0 + bl + cr | 0);
|
|
}
|
|
roundClean() {
|
|
BUF.fill(0);
|
|
}
|
|
destroy() {
|
|
this.destroyed = true;
|
|
this.buffer.fill(0);
|
|
this.set(0, 0, 0, 0, 0);
|
|
}
|
|
};
|
|
var ripemd160 = wrapConstructor2(() => new RIPEMD160());
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/abstract/utils.js
|
|
var utils_exports3 = {};
|
|
__export(utils_exports3, {
|
|
bitGet: () => bitGet2,
|
|
bitLen: () => bitLen2,
|
|
bitMask: () => bitMask2,
|
|
bitSet: () => bitSet2,
|
|
bytesToHex: () => bytesToHex3,
|
|
bytesToNumberBE: () => bytesToNumberBE2,
|
|
bytesToNumberLE: () => bytesToNumberLE2,
|
|
concatBytes: () => concatBytes4,
|
|
createHmacDrbg: () => createHmacDrbg2,
|
|
ensureBytes: () => ensureBytes2,
|
|
equalBytes: () => equalBytes3,
|
|
hexToBytes: () => hexToBytes3,
|
|
hexToNumber: () => hexToNumber2,
|
|
numberToBytesBE: () => numberToBytesBE2,
|
|
numberToBytesLE: () => numberToBytesLE2,
|
|
numberToHexUnpadded: () => numberToHexUnpadded2,
|
|
numberToVarBytesBE: () => numberToVarBytesBE2,
|
|
utf8ToBytes: () => utf8ToBytes5,
|
|
validateObject: () => validateObject2
|
|
});
|
|
var _0n6 = BigInt(0);
|
|
var _1n6 = BigInt(1);
|
|
var _2n5 = BigInt(2);
|
|
var u8a4 = (a) => a instanceof Uint8Array;
|
|
var hexes3 = Array.from({ length: 256 }, (v, i2) => i2.toString(16).padStart(2, "0"));
|
|
function bytesToHex3(bytes4) {
|
|
if (!u8a4(bytes4))
|
|
throw new Error("Uint8Array expected");
|
|
let hex2 = "";
|
|
for (let i2 = 0; i2 < bytes4.length; i2++) {
|
|
hex2 += hexes3[bytes4[i2]];
|
|
}
|
|
return hex2;
|
|
}
|
|
function numberToHexUnpadded2(num) {
|
|
const hex2 = num.toString(16);
|
|
return hex2.length & 1 ? `0${hex2}` : hex2;
|
|
}
|
|
function hexToNumber2(hex2) {
|
|
if (typeof hex2 !== "string")
|
|
throw new Error("hex string expected, got " + typeof hex2);
|
|
return BigInt(hex2 === "" ? "0" : `0x${hex2}`);
|
|
}
|
|
function hexToBytes3(hex2) {
|
|
if (typeof hex2 !== "string")
|
|
throw new Error("hex string expected, got " + typeof hex2);
|
|
const len = hex2.length;
|
|
if (len % 2)
|
|
throw new Error("padded hex string expected, got unpadded hex of length " + len);
|
|
const array = new Uint8Array(len / 2);
|
|
for (let i2 = 0; i2 < array.length; i2++) {
|
|
const j = i2 * 2;
|
|
const hexByte = hex2.slice(j, j + 2);
|
|
const byte = Number.parseInt(hexByte, 16);
|
|
if (Number.isNaN(byte) || byte < 0)
|
|
throw new Error("Invalid byte sequence");
|
|
array[i2] = byte;
|
|
}
|
|
return array;
|
|
}
|
|
function bytesToNumberBE2(bytes4) {
|
|
return hexToNumber2(bytesToHex3(bytes4));
|
|
}
|
|
function bytesToNumberLE2(bytes4) {
|
|
if (!u8a4(bytes4))
|
|
throw new Error("Uint8Array expected");
|
|
return hexToNumber2(bytesToHex3(Uint8Array.from(bytes4).reverse()));
|
|
}
|
|
function numberToBytesBE2(n, len) {
|
|
return hexToBytes3(n.toString(16).padStart(len * 2, "0"));
|
|
}
|
|
function numberToBytesLE2(n, len) {
|
|
return numberToBytesBE2(n, len).reverse();
|
|
}
|
|
function numberToVarBytesBE2(n) {
|
|
return hexToBytes3(numberToHexUnpadded2(n));
|
|
}
|
|
function ensureBytes2(title, hex2, expectedLength) {
|
|
let res;
|
|
if (typeof hex2 === "string") {
|
|
try {
|
|
res = hexToBytes3(hex2);
|
|
} catch (e) {
|
|
throw new Error(`${title} must be valid hex string, got "${hex2}". Cause: ${e}`);
|
|
}
|
|
} else if (u8a4(hex2)) {
|
|
res = Uint8Array.from(hex2);
|
|
} else {
|
|
throw new Error(`${title} must be hex string or Uint8Array`);
|
|
}
|
|
const len = res.length;
|
|
if (typeof expectedLength === "number" && len !== expectedLength)
|
|
throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
|
|
return res;
|
|
}
|
|
function concatBytes4(...arrays) {
|
|
const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
|
|
let pad2 = 0;
|
|
arrays.forEach((a) => {
|
|
if (!u8a4(a))
|
|
throw new Error("Uint8Array expected");
|
|
r.set(a, pad2);
|
|
pad2 += a.length;
|
|
});
|
|
return r;
|
|
}
|
|
function equalBytes3(b1, b2) {
|
|
if (b1.length !== b2.length)
|
|
return false;
|
|
for (let i2 = 0; i2 < b1.length; i2++)
|
|
if (b1[i2] !== b2[i2])
|
|
return false;
|
|
return true;
|
|
}
|
|
function utf8ToBytes5(str) {
|
|
if (typeof str !== "string")
|
|
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
}
|
|
function bitLen2(n) {
|
|
let len;
|
|
for (len = 0; n > _0n6; n >>= _1n6, len += 1)
|
|
;
|
|
return len;
|
|
}
|
|
function bitGet2(n, pos) {
|
|
return n >> BigInt(pos) & _1n6;
|
|
}
|
|
var bitSet2 = (n, pos, value) => {
|
|
return n | (value ? _1n6 : _0n6) << BigInt(pos);
|
|
};
|
|
var bitMask2 = (n) => (_2n5 << BigInt(n - 1)) - _1n6;
|
|
var u8n2 = (data) => new Uint8Array(data);
|
|
var u8fr2 = (arr) => Uint8Array.from(arr);
|
|
function createHmacDrbg2(hashLen, qByteLen, hmacFn) {
|
|
if (typeof hashLen !== "number" || hashLen < 2)
|
|
throw new Error("hashLen must be a number");
|
|
if (typeof qByteLen !== "number" || qByteLen < 2)
|
|
throw new Error("qByteLen must be a number");
|
|
if (typeof hmacFn !== "function")
|
|
throw new Error("hmacFn must be a function");
|
|
let v = u8n2(hashLen);
|
|
let k = u8n2(hashLen);
|
|
let i2 = 0;
|
|
const reset = () => {
|
|
v.fill(1);
|
|
k.fill(0);
|
|
i2 = 0;
|
|
};
|
|
const h = (...b) => hmacFn(k, v, ...b);
|
|
const reseed = (seed = u8n2()) => {
|
|
k = h(u8fr2([0]), seed);
|
|
v = h();
|
|
if (seed.length === 0)
|
|
return;
|
|
k = h(u8fr2([1]), seed);
|
|
v = h();
|
|
};
|
|
const gen = () => {
|
|
if (i2++ >= 1e3)
|
|
throw new Error("drbg: tried 1000 values");
|
|
let len = 0;
|
|
const out = [];
|
|
while (len < qByteLen) {
|
|
v = h();
|
|
const sl = v.slice();
|
|
out.push(sl);
|
|
len += v.length;
|
|
}
|
|
return concatBytes4(...out);
|
|
};
|
|
const genUntil = (seed, pred) => {
|
|
reset();
|
|
reseed(seed);
|
|
let res = void 0;
|
|
while (!(res = pred(gen())))
|
|
reseed();
|
|
reset();
|
|
return res;
|
|
};
|
|
return genUntil;
|
|
}
|
|
var validatorFns2 = {
|
|
bigint: (val) => typeof val === "bigint",
|
|
function: (val) => typeof val === "function",
|
|
boolean: (val) => typeof val === "boolean",
|
|
string: (val) => typeof val === "string",
|
|
isSafeInteger: (val) => Number.isSafeInteger(val),
|
|
array: (val) => Array.isArray(val),
|
|
field: (val, object) => object.Fp.isValid(val),
|
|
hash: (val) => typeof val === "function" && Number.isSafeInteger(val.outputLen)
|
|
};
|
|
function validateObject2(object, validators, optValidators = {}) {
|
|
const checkField = (fieldName, type, isOptional) => {
|
|
const checkVal = validatorFns2[type];
|
|
if (typeof checkVal !== "function")
|
|
throw new Error(`Invalid validator "${type}", expected function`);
|
|
const val = object[fieldName];
|
|
if (isOptional && val === void 0)
|
|
return;
|
|
if (!checkVal(val, object)) {
|
|
throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
|
|
}
|
|
};
|
|
for (const [fieldName, type] of Object.entries(validators))
|
|
checkField(fieldName, type, false);
|
|
for (const [fieldName, type] of Object.entries(optValidators))
|
|
checkField(fieldName, type, true);
|
|
return object;
|
|
}
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/abstract/modular.js
|
|
var _0n7 = BigInt(0);
|
|
var _1n7 = BigInt(1);
|
|
var _2n6 = BigInt(2);
|
|
var _3n3 = BigInt(3);
|
|
var _4n3 = BigInt(4);
|
|
var _5n2 = BigInt(5);
|
|
var _8n2 = BigInt(8);
|
|
var _9n2 = BigInt(9);
|
|
var _16n2 = BigInt(16);
|
|
function mod2(a, b) {
|
|
const result = a % b;
|
|
return result >= _0n7 ? result : b + result;
|
|
}
|
|
function pow3(num, power, modulo) {
|
|
if (modulo <= _0n7 || power < _0n7)
|
|
throw new Error("Expected power/modulo > 0");
|
|
if (modulo === _1n7)
|
|
return _0n7;
|
|
let res = _1n7;
|
|
while (power > _0n7) {
|
|
if (power & _1n7)
|
|
res = res * num % modulo;
|
|
num = num * num % modulo;
|
|
power >>= _1n7;
|
|
}
|
|
return res;
|
|
}
|
|
function pow22(x, power, modulo) {
|
|
let res = x;
|
|
while (power-- > _0n7) {
|
|
res *= res;
|
|
res %= modulo;
|
|
}
|
|
return res;
|
|
}
|
|
function invert2(number4, modulo) {
|
|
if (number4 === _0n7 || modulo <= _0n7) {
|
|
throw new Error(`invert: expected positive integers, got n=${number4} mod=${modulo}`);
|
|
}
|
|
let a = mod2(number4, modulo);
|
|
let b = modulo;
|
|
let x = _0n7, y = _1n7, u = _1n7, v = _0n7;
|
|
while (a !== _0n7) {
|
|
const q = b / a;
|
|
const r = b % a;
|
|
const m = x - u * q;
|
|
const n = y - v * q;
|
|
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
}
|
|
const gcd2 = b;
|
|
if (gcd2 !== _1n7)
|
|
throw new Error("invert: does not exist");
|
|
return mod2(x, modulo);
|
|
}
|
|
function tonelliShanks2(P) {
|
|
const legendreC = (P - _1n7) / _2n6;
|
|
let Q, S, Z;
|
|
for (Q = P - _1n7, S = 0; Q % _2n6 === _0n7; Q /= _2n6, S++)
|
|
;
|
|
for (Z = _2n6; Z < P && pow3(Z, legendreC, P) !== P - _1n7; Z++)
|
|
;
|
|
if (S === 1) {
|
|
const p1div4 = (P + _1n7) / _4n3;
|
|
return function tonelliFast(Fp3, n) {
|
|
const root = Fp3.pow(n, p1div4);
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
const Q1div2 = (Q + _1n7) / _2n6;
|
|
return function tonelliSlow(Fp3, n) {
|
|
if (Fp3.pow(n, legendreC) === Fp3.neg(Fp3.ONE))
|
|
throw new Error("Cannot find square root");
|
|
let r = S;
|
|
let g = Fp3.pow(Fp3.mul(Fp3.ONE, Z), Q);
|
|
let x = Fp3.pow(n, Q1div2);
|
|
let b = Fp3.pow(n, Q);
|
|
while (!Fp3.eql(b, Fp3.ONE)) {
|
|
if (Fp3.eql(b, Fp3.ZERO))
|
|
return Fp3.ZERO;
|
|
let m = 1;
|
|
for (let t2 = Fp3.sqr(b); m < r; m++) {
|
|
if (Fp3.eql(t2, Fp3.ONE))
|
|
break;
|
|
t2 = Fp3.sqr(t2);
|
|
}
|
|
const ge2 = Fp3.pow(g, _1n7 << BigInt(r - m - 1));
|
|
g = Fp3.sqr(ge2);
|
|
x = Fp3.mul(x, ge2);
|
|
b = Fp3.mul(b, g);
|
|
r = m;
|
|
}
|
|
return x;
|
|
};
|
|
}
|
|
function FpSqrt2(P) {
|
|
if (P % _4n3 === _3n3) {
|
|
const p1div4 = (P + _1n7) / _4n3;
|
|
return function sqrt3mod4(Fp3, n) {
|
|
const root = Fp3.pow(n, p1div4);
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
if (P % _8n2 === _5n2) {
|
|
const c1 = (P - _5n2) / _8n2;
|
|
return function sqrt5mod8(Fp3, n) {
|
|
const n2 = Fp3.mul(n, _2n6);
|
|
const v = Fp3.pow(n2, c1);
|
|
const nv = Fp3.mul(n, v);
|
|
const i2 = Fp3.mul(Fp3.mul(nv, _2n6), v);
|
|
const root = Fp3.mul(nv, Fp3.sub(i2, Fp3.ONE));
|
|
if (!Fp3.eql(Fp3.sqr(root), n))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
};
|
|
}
|
|
if (P % _16n2 === _9n2) {
|
|
}
|
|
return tonelliShanks2(P);
|
|
}
|
|
var FIELD_FIELDS2 = [
|
|
"create",
|
|
"isValid",
|
|
"is0",
|
|
"neg",
|
|
"inv",
|
|
"sqrt",
|
|
"sqr",
|
|
"eql",
|
|
"add",
|
|
"sub",
|
|
"mul",
|
|
"pow",
|
|
"div",
|
|
"addN",
|
|
"subN",
|
|
"mulN",
|
|
"sqrN"
|
|
];
|
|
function validateField2(field) {
|
|
const initial = {
|
|
ORDER: "bigint",
|
|
MASK: "bigint",
|
|
BYTES: "isSafeInteger",
|
|
BITS: "isSafeInteger"
|
|
};
|
|
const opts = FIELD_FIELDS2.reduce((map, val) => {
|
|
map[val] = "function";
|
|
return map;
|
|
}, initial);
|
|
return validateObject2(field, opts);
|
|
}
|
|
function FpPow2(f2, num, power) {
|
|
if (power < _0n7)
|
|
throw new Error("Expected power > 0");
|
|
if (power === _0n7)
|
|
return f2.ONE;
|
|
if (power === _1n7)
|
|
return num;
|
|
let p = f2.ONE;
|
|
let d = num;
|
|
while (power > _0n7) {
|
|
if (power & _1n7)
|
|
p = f2.mul(p, d);
|
|
d = f2.sqr(d);
|
|
power >>= _1n7;
|
|
}
|
|
return p;
|
|
}
|
|
function FpInvertBatch2(f2, nums) {
|
|
const tmp = new Array(nums.length);
|
|
const lastMultiplied = nums.reduce((acc, num, i2) => {
|
|
if (f2.is0(num))
|
|
return acc;
|
|
tmp[i2] = acc;
|
|
return f2.mul(acc, num);
|
|
}, f2.ONE);
|
|
const inverted = f2.inv(lastMultiplied);
|
|
nums.reduceRight((acc, num, i2) => {
|
|
if (f2.is0(num))
|
|
return acc;
|
|
tmp[i2] = f2.mul(acc, tmp[i2]);
|
|
return f2.mul(acc, num);
|
|
}, inverted);
|
|
return tmp;
|
|
}
|
|
function nLength2(n, nBitLength) {
|
|
const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length;
|
|
const nByteLength = Math.ceil(_nBitLength / 8);
|
|
return { nBitLength: _nBitLength, nByteLength };
|
|
}
|
|
function Field2(ORDER, bitLen3, isLE4 = false, redef = {}) {
|
|
if (ORDER <= _0n7)
|
|
throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
|
|
const { nBitLength: BITS, nByteLength: BYTES } = nLength2(ORDER, bitLen3);
|
|
if (BYTES > 2048)
|
|
throw new Error("Field lengths over 2048 bytes are not supported");
|
|
const sqrtP = FpSqrt2(ORDER);
|
|
const f2 = Object.freeze({
|
|
ORDER,
|
|
BITS,
|
|
BYTES,
|
|
MASK: bitMask2(BITS),
|
|
ZERO: _0n7,
|
|
ONE: _1n7,
|
|
create: (num) => mod2(num, ORDER),
|
|
isValid: (num) => {
|
|
if (typeof num !== "bigint")
|
|
throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
|
|
return _0n7 <= num && num < ORDER;
|
|
},
|
|
is0: (num) => num === _0n7,
|
|
isOdd: (num) => (num & _1n7) === _1n7,
|
|
neg: (num) => mod2(-num, ORDER),
|
|
eql: (lhs, rhs) => lhs === rhs,
|
|
sqr: (num) => mod2(num * num, ORDER),
|
|
add: (lhs, rhs) => mod2(lhs + rhs, ORDER),
|
|
sub: (lhs, rhs) => mod2(lhs - rhs, ORDER),
|
|
mul: (lhs, rhs) => mod2(lhs * rhs, ORDER),
|
|
pow: (num, power) => FpPow2(f2, num, power),
|
|
div: (lhs, rhs) => mod2(lhs * invert2(rhs, ORDER), ORDER),
|
|
sqrN: (num) => num * num,
|
|
addN: (lhs, rhs) => lhs + rhs,
|
|
subN: (lhs, rhs) => lhs - rhs,
|
|
mulN: (lhs, rhs) => lhs * rhs,
|
|
inv: (num) => invert2(num, ORDER),
|
|
sqrt: redef.sqrt || ((n) => sqrtP(f2, n)),
|
|
invertBatch: (lst) => FpInvertBatch2(f2, lst),
|
|
cmov: (a, b, c) => c ? b : a,
|
|
toBytes: (num) => isLE4 ? numberToBytesLE2(num, BYTES) : numberToBytesBE2(num, BYTES),
|
|
fromBytes: (bytes4) => {
|
|
if (bytes4.length !== BYTES)
|
|
throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes4.length}`);
|
|
return isLE4 ? bytesToNumberLE2(bytes4) : bytesToNumberBE2(bytes4);
|
|
}
|
|
});
|
|
return Object.freeze(f2);
|
|
}
|
|
function hashToPrivateScalar(hash3, groupOrder, isLE4 = false) {
|
|
hash3 = ensureBytes2("privateHash", hash3);
|
|
const hashLen = hash3.length;
|
|
const minLen = nLength2(groupOrder).nByteLength + 8;
|
|
if (minLen < 24 || hashLen < minLen || hashLen > 1024)
|
|
throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);
|
|
const num = isLE4 ? bytesToNumberLE2(hash3) : bytesToNumberBE2(hash3);
|
|
return mod2(num, groupOrder - _1n7) + _1n7;
|
|
}
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/abstract/curve.js
|
|
var _0n8 = BigInt(0);
|
|
var _1n8 = BigInt(1);
|
|
function wNAF2(c, bits) {
|
|
const constTimeNegate = (condition, item) => {
|
|
const neg = item.negate();
|
|
return condition ? neg : item;
|
|
};
|
|
const opts = (W) => {
|
|
const windows = Math.ceil(bits / W) + 1;
|
|
const windowSize = 2 ** (W - 1);
|
|
return { windows, windowSize };
|
|
};
|
|
return {
|
|
constTimeNegate,
|
|
unsafeLadder(elm, n) {
|
|
let p = c.ZERO;
|
|
let d = elm;
|
|
while (n > _0n8) {
|
|
if (n & _1n8)
|
|
p = p.add(d);
|
|
d = d.double();
|
|
n >>= _1n8;
|
|
}
|
|
return p;
|
|
},
|
|
precomputeWindow(elm, W) {
|
|
const { windows, windowSize } = opts(W);
|
|
const points = [];
|
|
let p = elm;
|
|
let base = p;
|
|
for (let window = 0; window < windows; window++) {
|
|
base = p;
|
|
points.push(base);
|
|
for (let i2 = 1; i2 < windowSize; i2++) {
|
|
base = base.add(p);
|
|
points.push(base);
|
|
}
|
|
p = base.double();
|
|
}
|
|
return points;
|
|
},
|
|
wNAF(W, precomputes, n) {
|
|
const { windows, windowSize } = opts(W);
|
|
let p = c.ZERO;
|
|
let f2 = c.BASE;
|
|
const mask = BigInt(2 ** W - 1);
|
|
const maxNumber = 2 ** W;
|
|
const shiftBy = BigInt(W);
|
|
for (let window = 0; window < windows; window++) {
|
|
const offset = window * windowSize;
|
|
let wbits = Number(n & mask);
|
|
n >>= shiftBy;
|
|
if (wbits > windowSize) {
|
|
wbits -= maxNumber;
|
|
n += _1n8;
|
|
}
|
|
const offset1 = offset;
|
|
const offset2 = offset + Math.abs(wbits) - 1;
|
|
const cond1 = window % 2 !== 0;
|
|
const cond2 = wbits < 0;
|
|
if (wbits === 0) {
|
|
f2 = f2.add(constTimeNegate(cond1, precomputes[offset1]));
|
|
} else {
|
|
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
|
|
}
|
|
}
|
|
return { p, f: f2 };
|
|
},
|
|
wNAFCached(P, precomputesMap, n, transform) {
|
|
const W = P._WINDOW_SIZE || 1;
|
|
let comp = precomputesMap.get(P);
|
|
if (!comp) {
|
|
comp = this.precomputeWindow(P, W);
|
|
if (W !== 1) {
|
|
precomputesMap.set(P, transform(comp));
|
|
}
|
|
}
|
|
return this.wNAF(W, comp, n);
|
|
}
|
|
};
|
|
}
|
|
function validateBasic2(curve) {
|
|
validateField2(curve.Fp);
|
|
validateObject2(curve, {
|
|
n: "bigint",
|
|
h: "bigint",
|
|
Gx: "field",
|
|
Gy: "field"
|
|
}, {
|
|
nBitLength: "isSafeInteger",
|
|
nByteLength: "isSafeInteger"
|
|
});
|
|
return Object.freeze({
|
|
...nLength2(curve.n, curve.nBitLength),
|
|
...curve,
|
|
...{ p: curve.Fp.ORDER }
|
|
});
|
|
}
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/abstract/weierstrass.js
|
|
function validatePointOpts2(curve) {
|
|
const opts = validateBasic2(curve);
|
|
validateObject2(opts, {
|
|
a: "field",
|
|
b: "field"
|
|
}, {
|
|
allowedPrivateKeyLengths: "array",
|
|
wrapPrivateKey: "boolean",
|
|
isTorsionFree: "function",
|
|
clearCofactor: "function",
|
|
allowInfinityPoint: "boolean",
|
|
fromBytes: "function",
|
|
toBytes: "function"
|
|
});
|
|
const { endo, Fp: Fp3, a } = opts;
|
|
if (endo) {
|
|
if (!Fp3.eql(a, Fp3.ZERO)) {
|
|
throw new Error("Endomorphism can only be defined for Koblitz curves that have a=0");
|
|
}
|
|
if (typeof endo !== "object" || typeof endo.beta !== "bigint" || typeof endo.splitScalar !== "function") {
|
|
throw new Error("Expected endomorphism with beta: bigint and splitScalar: function");
|
|
}
|
|
}
|
|
return Object.freeze({ ...opts });
|
|
}
|
|
var { bytesToNumberBE: b2n2, hexToBytes: h2b2 } = utils_exports3;
|
|
var DER2 = {
|
|
Err: class DERErr2 extends Error {
|
|
constructor(m = "") {
|
|
super(m);
|
|
}
|
|
},
|
|
_parseInt(data) {
|
|
const { Err: E } = DER2;
|
|
if (data.length < 2 || data[0] !== 2)
|
|
throw new E("Invalid signature integer tag");
|
|
const len = data[1];
|
|
const res = data.subarray(2, len + 2);
|
|
if (!len || res.length !== len)
|
|
throw new E("Invalid signature integer: wrong length");
|
|
if (res[0] & 128)
|
|
throw new E("Invalid signature integer: negative");
|
|
if (res[0] === 0 && !(res[1] & 128))
|
|
throw new E("Invalid signature integer: unnecessary leading zero");
|
|
return { d: b2n2(res), l: data.subarray(len + 2) };
|
|
},
|
|
toSig(hex2) {
|
|
const { Err: E } = DER2;
|
|
const data = typeof hex2 === "string" ? h2b2(hex2) : hex2;
|
|
if (!(data instanceof Uint8Array))
|
|
throw new Error("ui8a expected");
|
|
let l = data.length;
|
|
if (l < 2 || data[0] != 48)
|
|
throw new E("Invalid signature tag");
|
|
if (data[1] !== l - 2)
|
|
throw new E("Invalid signature: incorrect length");
|
|
const { d: r, l: sBytes } = DER2._parseInt(data.subarray(2));
|
|
const { d: s, l: rBytesLeft } = DER2._parseInt(sBytes);
|
|
if (rBytesLeft.length)
|
|
throw new E("Invalid signature: left bytes after parsing");
|
|
return { r, s };
|
|
},
|
|
hexFromSig(sig) {
|
|
const slice = (s2) => Number.parseInt(s2[0], 16) & 8 ? "00" + s2 : s2;
|
|
const h = (num) => {
|
|
const hex2 = num.toString(16);
|
|
return hex2.length & 1 ? `0${hex2}` : hex2;
|
|
};
|
|
const s = slice(h(sig.s));
|
|
const r = slice(h(sig.r));
|
|
const shl = s.length / 2;
|
|
const rhl = r.length / 2;
|
|
const sl = h(shl);
|
|
const rl = h(rhl);
|
|
return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
|
|
}
|
|
};
|
|
var _0n9 = BigInt(0);
|
|
var _1n9 = BigInt(1);
|
|
var _2n7 = BigInt(2);
|
|
var _3n4 = BigInt(3);
|
|
var _4n4 = BigInt(4);
|
|
function weierstrassPoints2(opts) {
|
|
const CURVE = validatePointOpts2(opts);
|
|
const { Fp: Fp3 } = CURVE;
|
|
const toBytes4 = CURVE.toBytes || ((c, point, isCompressed) => {
|
|
const a = point.toAffine();
|
|
return concatBytes4(Uint8Array.from([4]), Fp3.toBytes(a.x), Fp3.toBytes(a.y));
|
|
});
|
|
const fromBytes = CURVE.fromBytes || ((bytes4) => {
|
|
const tail = bytes4.subarray(1);
|
|
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
|
|
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
|
|
return { x, y };
|
|
});
|
|
function weierstrassEquation(x) {
|
|
const { a, b } = CURVE;
|
|
const x2 = Fp3.sqr(x);
|
|
const x3 = Fp3.mul(x2, x);
|
|
return Fp3.add(Fp3.add(x3, Fp3.mul(x, a)), b);
|
|
}
|
|
if (!Fp3.eql(Fp3.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
|
|
throw new Error("bad generator point: equation left != right");
|
|
function isWithinCurveOrder(num) {
|
|
return typeof num === "bigint" && _0n9 < num && num < CURVE.n;
|
|
}
|
|
function assertGE(num) {
|
|
if (!isWithinCurveOrder(num))
|
|
throw new Error("Expected valid bigint: 0 < bigint < curve.n");
|
|
}
|
|
function normPrivateKeyToScalar(key) {
|
|
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
|
|
if (lengths && typeof key !== "bigint") {
|
|
if (key instanceof Uint8Array)
|
|
key = bytesToHex3(key);
|
|
if (typeof key !== "string" || !lengths.includes(key.length))
|
|
throw new Error("Invalid key");
|
|
key = key.padStart(nByteLength * 2, "0");
|
|
}
|
|
let num;
|
|
try {
|
|
num = typeof key === "bigint" ? key : bytesToNumberBE2(ensureBytes2("private key", key, nByteLength));
|
|
} catch (error) {
|
|
throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
|
|
}
|
|
if (wrapPrivateKey)
|
|
num = mod2(num, n);
|
|
assertGE(num);
|
|
return num;
|
|
}
|
|
const pointPrecomputes = /* @__PURE__ */ new Map();
|
|
function assertPrjPoint(other) {
|
|
if (!(other instanceof Point4))
|
|
throw new Error("ProjectivePoint expected");
|
|
}
|
|
class Point4 {
|
|
constructor(px, py, pz) {
|
|
this.px = px;
|
|
this.py = py;
|
|
this.pz = pz;
|
|
if (px == null || !Fp3.isValid(px))
|
|
throw new Error("x required");
|
|
if (py == null || !Fp3.isValid(py))
|
|
throw new Error("y required");
|
|
if (pz == null || !Fp3.isValid(pz))
|
|
throw new Error("z required");
|
|
}
|
|
static fromAffine(p) {
|
|
const { x, y } = p || {};
|
|
if (!p || !Fp3.isValid(x) || !Fp3.isValid(y))
|
|
throw new Error("invalid affine point");
|
|
if (p instanceof Point4)
|
|
throw new Error("projective point not allowed");
|
|
const is0 = (i2) => Fp3.eql(i2, Fp3.ZERO);
|
|
if (is0(x) && is0(y))
|
|
return Point4.ZERO;
|
|
return new Point4(x, y, Fp3.ONE);
|
|
}
|
|
get x() {
|
|
return this.toAffine().x;
|
|
}
|
|
get y() {
|
|
return this.toAffine().y;
|
|
}
|
|
static normalizeZ(points) {
|
|
const toInv = Fp3.invertBatch(points.map((p) => p.pz));
|
|
return points.map((p, i2) => p.toAffine(toInv[i2])).map(Point4.fromAffine);
|
|
}
|
|
static fromHex(hex2) {
|
|
const P = Point4.fromAffine(fromBytes(ensureBytes2("pointHex", hex2)));
|
|
P.assertValidity();
|
|
return P;
|
|
}
|
|
static fromPrivateKey(privateKey) {
|
|
return Point4.BASE.multiply(normPrivateKeyToScalar(privateKey));
|
|
}
|
|
_setWindowSize(windowSize) {
|
|
this._WINDOW_SIZE = windowSize;
|
|
pointPrecomputes.delete(this);
|
|
}
|
|
assertValidity() {
|
|
if (this.is0()) {
|
|
if (CURVE.allowInfinityPoint)
|
|
return;
|
|
throw new Error("bad point: ZERO");
|
|
}
|
|
const { x, y } = this.toAffine();
|
|
if (!Fp3.isValid(x) || !Fp3.isValid(y))
|
|
throw new Error("bad point: x or y not FE");
|
|
const left = Fp3.sqr(y);
|
|
const right = weierstrassEquation(x);
|
|
if (!Fp3.eql(left, right))
|
|
throw new Error("bad point: equation left != right");
|
|
if (!this.isTorsionFree())
|
|
throw new Error("bad point: not in prime-order subgroup");
|
|
}
|
|
hasEvenY() {
|
|
const { y } = this.toAffine();
|
|
if (Fp3.isOdd)
|
|
return !Fp3.isOdd(y);
|
|
throw new Error("Field doesn't support isOdd");
|
|
}
|
|
equals(other) {
|
|
assertPrjPoint(other);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
const U1 = Fp3.eql(Fp3.mul(X1, Z2), Fp3.mul(X2, Z1));
|
|
const U2 = Fp3.eql(Fp3.mul(Y1, Z2), Fp3.mul(Y2, Z1));
|
|
return U1 && U2;
|
|
}
|
|
negate() {
|
|
return new Point4(this.px, Fp3.neg(this.py), this.pz);
|
|
}
|
|
double() {
|
|
const { a, b } = CURVE;
|
|
const b3 = Fp3.mul(b, _3n4);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
let t0 = Fp3.mul(X1, X1);
|
|
let t1 = Fp3.mul(Y1, Y1);
|
|
let t2 = Fp3.mul(Z1, Z1);
|
|
let t3 = Fp3.mul(X1, Y1);
|
|
t3 = Fp3.add(t3, t3);
|
|
Z3 = Fp3.mul(X1, Z1);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
X3 = Fp3.mul(a, Z3);
|
|
Y3 = Fp3.mul(b3, t2);
|
|
Y3 = Fp3.add(X3, Y3);
|
|
X3 = Fp3.sub(t1, Y3);
|
|
Y3 = Fp3.add(t1, Y3);
|
|
Y3 = Fp3.mul(X3, Y3);
|
|
X3 = Fp3.mul(t3, X3);
|
|
Z3 = Fp3.mul(b3, Z3);
|
|
t2 = Fp3.mul(a, t2);
|
|
t3 = Fp3.sub(t0, t2);
|
|
t3 = Fp3.mul(a, t3);
|
|
t3 = Fp3.add(t3, Z3);
|
|
Z3 = Fp3.add(t0, t0);
|
|
t0 = Fp3.add(Z3, t0);
|
|
t0 = Fp3.add(t0, t2);
|
|
t0 = Fp3.mul(t0, t3);
|
|
Y3 = Fp3.add(Y3, t0);
|
|
t2 = Fp3.mul(Y1, Z1);
|
|
t2 = Fp3.add(t2, t2);
|
|
t0 = Fp3.mul(t2, t3);
|
|
X3 = Fp3.sub(X3, t0);
|
|
Z3 = Fp3.mul(t2, t1);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
Z3 = Fp3.add(Z3, Z3);
|
|
return new Point4(X3, Y3, Z3);
|
|
}
|
|
add(other) {
|
|
assertPrjPoint(other);
|
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
|
let X3 = Fp3.ZERO, Y3 = Fp3.ZERO, Z3 = Fp3.ZERO;
|
|
const a = CURVE.a;
|
|
const b3 = Fp3.mul(CURVE.b, _3n4);
|
|
let t0 = Fp3.mul(X1, X2);
|
|
let t1 = Fp3.mul(Y1, Y2);
|
|
let t2 = Fp3.mul(Z1, Z2);
|
|
let t3 = Fp3.add(X1, Y1);
|
|
let t4 = Fp3.add(X2, Y2);
|
|
t3 = Fp3.mul(t3, t4);
|
|
t4 = Fp3.add(t0, t1);
|
|
t3 = Fp3.sub(t3, t4);
|
|
t4 = Fp3.add(X1, Z1);
|
|
let t5 = Fp3.add(X2, Z2);
|
|
t4 = Fp3.mul(t4, t5);
|
|
t5 = Fp3.add(t0, t2);
|
|
t4 = Fp3.sub(t4, t5);
|
|
t5 = Fp3.add(Y1, Z1);
|
|
X3 = Fp3.add(Y2, Z2);
|
|
t5 = Fp3.mul(t5, X3);
|
|
X3 = Fp3.add(t1, t2);
|
|
t5 = Fp3.sub(t5, X3);
|
|
Z3 = Fp3.mul(a, t4);
|
|
X3 = Fp3.mul(b3, t2);
|
|
Z3 = Fp3.add(X3, Z3);
|
|
X3 = Fp3.sub(t1, Z3);
|
|
Z3 = Fp3.add(t1, Z3);
|
|
Y3 = Fp3.mul(X3, Z3);
|
|
t1 = Fp3.add(t0, t0);
|
|
t1 = Fp3.add(t1, t0);
|
|
t2 = Fp3.mul(a, t2);
|
|
t4 = Fp3.mul(b3, t4);
|
|
t1 = Fp3.add(t1, t2);
|
|
t2 = Fp3.sub(t0, t2);
|
|
t2 = Fp3.mul(a, t2);
|
|
t4 = Fp3.add(t4, t2);
|
|
t0 = Fp3.mul(t1, t4);
|
|
Y3 = Fp3.add(Y3, t0);
|
|
t0 = Fp3.mul(t5, t4);
|
|
X3 = Fp3.mul(t3, X3);
|
|
X3 = Fp3.sub(X3, t0);
|
|
t0 = Fp3.mul(t3, t1);
|
|
Z3 = Fp3.mul(t5, Z3);
|
|
Z3 = Fp3.add(Z3, t0);
|
|
return new Point4(X3, Y3, Z3);
|
|
}
|
|
subtract(other) {
|
|
return this.add(other.negate());
|
|
}
|
|
is0() {
|
|
return this.equals(Point4.ZERO);
|
|
}
|
|
wNAF(n) {
|
|
return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
|
|
const toInv = Fp3.invertBatch(comp.map((p) => p.pz));
|
|
return comp.map((p, i2) => p.toAffine(toInv[i2])).map(Point4.fromAffine);
|
|
});
|
|
}
|
|
multiplyUnsafe(n) {
|
|
const I = Point4.ZERO;
|
|
if (n === _0n9)
|
|
return I;
|
|
assertGE(n);
|
|
if (n === _1n9)
|
|
return this;
|
|
const { endo } = CURVE;
|
|
if (!endo)
|
|
return wnaf.unsafeLadder(this, n);
|
|
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
|
|
let k1p = I;
|
|
let k2p = I;
|
|
let d = this;
|
|
while (k1 > _0n9 || k2 > _0n9) {
|
|
if (k1 & _1n9)
|
|
k1p = k1p.add(d);
|
|
if (k2 & _1n9)
|
|
k2p = k2p.add(d);
|
|
d = d.double();
|
|
k1 >>= _1n9;
|
|
k2 >>= _1n9;
|
|
}
|
|
if (k1neg)
|
|
k1p = k1p.negate();
|
|
if (k2neg)
|
|
k2p = k2p.negate();
|
|
k2p = new Point4(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
return k1p.add(k2p);
|
|
}
|
|
multiply(scalar) {
|
|
assertGE(scalar);
|
|
let n = scalar;
|
|
let point, fake;
|
|
const { endo } = CURVE;
|
|
if (endo) {
|
|
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
|
|
let { p: k1p, f: f1p } = this.wNAF(k1);
|
|
let { p: k2p, f: f2p } = this.wNAF(k2);
|
|
k1p = wnaf.constTimeNegate(k1neg, k1p);
|
|
k2p = wnaf.constTimeNegate(k2neg, k2p);
|
|
k2p = new Point4(Fp3.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
|
|
point = k1p.add(k2p);
|
|
fake = f1p.add(f2p);
|
|
} else {
|
|
const { p, f: f2 } = this.wNAF(n);
|
|
point = p;
|
|
fake = f2;
|
|
}
|
|
return Point4.normalizeZ([point, fake])[0];
|
|
}
|
|
multiplyAndAddUnsafe(Q, a, b) {
|
|
const G = Point4.BASE;
|
|
const mul3 = (P, a2) => a2 === _0n9 || a2 === _1n9 || !P.equals(G) ? P.multiplyUnsafe(a2) : P.multiply(a2);
|
|
const sum = mul3(this, a).add(mul3(Q, b));
|
|
return sum.is0() ? void 0 : sum;
|
|
}
|
|
toAffine(iz) {
|
|
const { px: x, py: y, pz: z } = this;
|
|
const is0 = this.is0();
|
|
if (iz == null)
|
|
iz = is0 ? Fp3.ONE : Fp3.inv(z);
|
|
const ax = Fp3.mul(x, iz);
|
|
const ay = Fp3.mul(y, iz);
|
|
const zz = Fp3.mul(z, iz);
|
|
if (is0)
|
|
return { x: Fp3.ZERO, y: Fp3.ZERO };
|
|
if (!Fp3.eql(zz, Fp3.ONE))
|
|
throw new Error("invZ was invalid");
|
|
return { x: ax, y: ay };
|
|
}
|
|
isTorsionFree() {
|
|
const { h: cofactor, isTorsionFree } = CURVE;
|
|
if (cofactor === _1n9)
|
|
return true;
|
|
if (isTorsionFree)
|
|
return isTorsionFree(Point4, this);
|
|
throw new Error("isTorsionFree() has not been declared for the elliptic curve");
|
|
}
|
|
clearCofactor() {
|
|
const { h: cofactor, clearCofactor } = CURVE;
|
|
if (cofactor === _1n9)
|
|
return this;
|
|
if (clearCofactor)
|
|
return clearCofactor(Point4, this);
|
|
return this.multiplyUnsafe(CURVE.h);
|
|
}
|
|
toRawBytes(isCompressed = true) {
|
|
this.assertValidity();
|
|
return toBytes4(Point4, this, isCompressed);
|
|
}
|
|
toHex(isCompressed = true) {
|
|
return bytesToHex3(this.toRawBytes(isCompressed));
|
|
}
|
|
}
|
|
Point4.BASE = new Point4(CURVE.Gx, CURVE.Gy, Fp3.ONE);
|
|
Point4.ZERO = new Point4(Fp3.ZERO, Fp3.ONE, Fp3.ZERO);
|
|
const _bits = CURVE.nBitLength;
|
|
const wnaf = wNAF2(Point4, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
|
|
return {
|
|
CURVE,
|
|
ProjectivePoint: Point4,
|
|
normPrivateKeyToScalar,
|
|
weierstrassEquation,
|
|
isWithinCurveOrder
|
|
};
|
|
}
|
|
function validateOpts2(curve) {
|
|
const opts = validateBasic2(curve);
|
|
validateObject2(opts, {
|
|
hash: "hash",
|
|
hmac: "function",
|
|
randomBytes: "function"
|
|
}, {
|
|
bits2int: "function",
|
|
bits2int_modN: "function",
|
|
lowS: "boolean"
|
|
});
|
|
return Object.freeze({ lowS: true, ...opts });
|
|
}
|
|
function weierstrass2(curveDef) {
|
|
const CURVE = validateOpts2(curveDef);
|
|
const { Fp: Fp3, n: CURVE_ORDER } = CURVE;
|
|
const compressedLen = Fp3.BYTES + 1;
|
|
const uncompressedLen = 2 * Fp3.BYTES + 1;
|
|
function isValidFieldElement(num) {
|
|
return _0n9 < num && num < Fp3.ORDER;
|
|
}
|
|
function modN2(a) {
|
|
return mod2(a, CURVE_ORDER);
|
|
}
|
|
function invN(a) {
|
|
return invert2(a, CURVE_ORDER);
|
|
}
|
|
const { ProjectivePoint: Point4, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder } = weierstrassPoints2({
|
|
...CURVE,
|
|
toBytes(c, point, isCompressed) {
|
|
const a = point.toAffine();
|
|
const x = Fp3.toBytes(a.x);
|
|
const cat = concatBytes4;
|
|
if (isCompressed) {
|
|
return cat(Uint8Array.from([point.hasEvenY() ? 2 : 3]), x);
|
|
} else {
|
|
return cat(Uint8Array.from([4]), x, Fp3.toBytes(a.y));
|
|
}
|
|
},
|
|
fromBytes(bytes4) {
|
|
const len = bytes4.length;
|
|
const head = bytes4[0];
|
|
const tail = bytes4.subarray(1);
|
|
if (len === compressedLen && (head === 2 || head === 3)) {
|
|
const x = bytesToNumberBE2(tail);
|
|
if (!isValidFieldElement(x))
|
|
throw new Error("Point is not on curve");
|
|
const y2 = weierstrassEquation(x);
|
|
let y = Fp3.sqrt(y2);
|
|
const isYOdd = (y & _1n9) === _1n9;
|
|
const isHeadOdd = (head & 1) === 1;
|
|
if (isHeadOdd !== isYOdd)
|
|
y = Fp3.neg(y);
|
|
return { x, y };
|
|
} else if (len === uncompressedLen && head === 4) {
|
|
const x = Fp3.fromBytes(tail.subarray(0, Fp3.BYTES));
|
|
const y = Fp3.fromBytes(tail.subarray(Fp3.BYTES, 2 * Fp3.BYTES));
|
|
return { x, y };
|
|
} else {
|
|
throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
|
|
}
|
|
}
|
|
});
|
|
const numToNByteStr = (num) => bytesToHex3(numberToBytesBE2(num, CURVE.nByteLength));
|
|
function isBiggerThanHalfOrder(number4) {
|
|
const HALF = CURVE_ORDER >> _1n9;
|
|
return number4 > HALF;
|
|
}
|
|
function normalizeS(s) {
|
|
return isBiggerThanHalfOrder(s) ? modN2(-s) : s;
|
|
}
|
|
const slcNum = (b, from, to) => bytesToNumberBE2(b.slice(from, to));
|
|
class Signature {
|
|
constructor(r, s, recovery) {
|
|
this.r = r;
|
|
this.s = s;
|
|
this.recovery = recovery;
|
|
this.assertValidity();
|
|
}
|
|
static fromCompact(hex2) {
|
|
const l = CURVE.nByteLength;
|
|
hex2 = ensureBytes2("compactSignature", hex2, l * 2);
|
|
return new Signature(slcNum(hex2, 0, l), slcNum(hex2, l, 2 * l));
|
|
}
|
|
static fromDER(hex2) {
|
|
const { r, s } = DER2.toSig(ensureBytes2("DER", hex2));
|
|
return new Signature(r, s);
|
|
}
|
|
assertValidity() {
|
|
if (!isWithinCurveOrder(this.r))
|
|
throw new Error("r must be 0 < r < CURVE.n");
|
|
if (!isWithinCurveOrder(this.s))
|
|
throw new Error("s must be 0 < s < CURVE.n");
|
|
}
|
|
addRecoveryBit(recovery) {
|
|
return new Signature(this.r, this.s, recovery);
|
|
}
|
|
recoverPublicKey(msgHash) {
|
|
const { r, s, recovery: rec } = this;
|
|
const h = bits2int_modN(ensureBytes2("msgHash", msgHash));
|
|
if (rec == null || ![0, 1, 2, 3].includes(rec))
|
|
throw new Error("recovery id invalid");
|
|
const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
|
|
if (radj >= Fp3.ORDER)
|
|
throw new Error("recovery id 2 or 3 invalid");
|
|
const prefix = (rec & 1) === 0 ? "02" : "03";
|
|
const R = Point4.fromHex(prefix + numToNByteStr(radj));
|
|
const ir = invN(radj);
|
|
const u1 = modN2(-h * ir);
|
|
const u2 = modN2(s * ir);
|
|
const Q = Point4.BASE.multiplyAndAddUnsafe(R, u1, u2);
|
|
if (!Q)
|
|
throw new Error("point at infinify");
|
|
Q.assertValidity();
|
|
return Q;
|
|
}
|
|
hasHighS() {
|
|
return isBiggerThanHalfOrder(this.s);
|
|
}
|
|
normalizeS() {
|
|
return this.hasHighS() ? new Signature(this.r, modN2(-this.s), this.recovery) : this;
|
|
}
|
|
toDERRawBytes() {
|
|
return hexToBytes3(this.toDERHex());
|
|
}
|
|
toDERHex() {
|
|
return DER2.hexFromSig({ r: this.r, s: this.s });
|
|
}
|
|
toCompactRawBytes() {
|
|
return hexToBytes3(this.toCompactHex());
|
|
}
|
|
toCompactHex() {
|
|
return numToNByteStr(this.r) + numToNByteStr(this.s);
|
|
}
|
|
}
|
|
const utils2 = {
|
|
isValidPrivateKey(privateKey) {
|
|
try {
|
|
normPrivateKeyToScalar(privateKey);
|
|
return true;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
},
|
|
normPrivateKeyToScalar,
|
|
randomPrivateKey: () => {
|
|
const rand = CURVE.randomBytes(Fp3.BYTES + 8);
|
|
const num = hashToPrivateScalar(rand, CURVE_ORDER);
|
|
return numberToBytesBE2(num, CURVE.nByteLength);
|
|
},
|
|
precompute(windowSize = 8, point = Point4.BASE) {
|
|
point._setWindowSize(windowSize);
|
|
point.multiply(BigInt(3));
|
|
return point;
|
|
}
|
|
};
|
|
function getPublicKey2(privateKey, isCompressed = true) {
|
|
return Point4.fromPrivateKey(privateKey).toRawBytes(isCompressed);
|
|
}
|
|
function isProbPub(item) {
|
|
const arr = item instanceof Uint8Array;
|
|
const str = typeof item === "string";
|
|
const len = (arr || str) && item.length;
|
|
if (arr)
|
|
return len === compressedLen || len === uncompressedLen;
|
|
if (str)
|
|
return len === 2 * compressedLen || len === 2 * uncompressedLen;
|
|
if (item instanceof Point4)
|
|
return true;
|
|
return false;
|
|
}
|
|
function getSharedSecret(privateA, publicB, isCompressed = true) {
|
|
if (isProbPub(privateA))
|
|
throw new Error("first arg must be private key");
|
|
if (!isProbPub(publicB))
|
|
throw new Error("second arg must be public key");
|
|
const b = Point4.fromHex(publicB);
|
|
return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
|
|
}
|
|
const bits2int = CURVE.bits2int || function(bytes4) {
|
|
const num = bytesToNumberBE2(bytes4);
|
|
const delta = bytes4.length * 8 - CURVE.nBitLength;
|
|
return delta > 0 ? num >> BigInt(delta) : num;
|
|
};
|
|
const bits2int_modN = CURVE.bits2int_modN || function(bytes4) {
|
|
return modN2(bits2int(bytes4));
|
|
};
|
|
const ORDER_MASK = bitMask2(CURVE.nBitLength);
|
|
function int2octets(num) {
|
|
if (typeof num !== "bigint")
|
|
throw new Error("bigint expected");
|
|
if (!(_0n9 <= num && num < ORDER_MASK))
|
|
throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
|
|
return numberToBytesBE2(num, CURVE.nByteLength);
|
|
}
|
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
|
if (["recovered", "canonical"].some((k) => k in opts))
|
|
throw new Error("sign() legacy options not supported");
|
|
const { hash: hash3, randomBytes: randomBytes3 } = CURVE;
|
|
let { lowS, prehash, extraEntropy: ent } = opts;
|
|
if (lowS == null)
|
|
lowS = true;
|
|
msgHash = ensureBytes2("msgHash", msgHash);
|
|
if (prehash)
|
|
msgHash = ensureBytes2("prehashed msgHash", hash3(msgHash));
|
|
const h1int = bits2int_modN(msgHash);
|
|
const d = normPrivateKeyToScalar(privateKey);
|
|
const seedArgs = [int2octets(d), int2octets(h1int)];
|
|
if (ent != null) {
|
|
const e = ent === true ? randomBytes3(Fp3.BYTES) : ent;
|
|
seedArgs.push(ensureBytes2("extraEntropy", e, Fp3.BYTES));
|
|
}
|
|
const seed = concatBytes4(...seedArgs);
|
|
const m = h1int;
|
|
function k2sig(kBytes) {
|
|
const k = bits2int(kBytes);
|
|
if (!isWithinCurveOrder(k))
|
|
return;
|
|
const ik = invN(k);
|
|
const q = Point4.BASE.multiply(k).toAffine();
|
|
const r = modN2(q.x);
|
|
if (r === _0n9)
|
|
return;
|
|
const s = modN2(ik * modN2(m + r * d));
|
|
if (s === _0n9)
|
|
return;
|
|
let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n9);
|
|
let normS = s;
|
|
if (lowS && isBiggerThanHalfOrder(s)) {
|
|
normS = normalizeS(s);
|
|
recovery ^= 1;
|
|
}
|
|
return new Signature(r, normS, recovery);
|
|
}
|
|
return { seed, k2sig };
|
|
}
|
|
const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
|
|
const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
|
|
function sign(msgHash, privKey, opts = defaultSigOpts) {
|
|
const { seed, k2sig } = prepSig(msgHash, privKey, opts);
|
|
const C = CURVE;
|
|
const drbg = createHmacDrbg2(C.hash.outputLen, C.nByteLength, C.hmac);
|
|
return drbg(seed, k2sig);
|
|
}
|
|
Point4.BASE._setWindowSize(8);
|
|
function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
|
|
const sg = signature;
|
|
msgHash = ensureBytes2("msgHash", msgHash);
|
|
publicKey = ensureBytes2("publicKey", publicKey);
|
|
if ("strict" in opts)
|
|
throw new Error("options.strict was renamed to lowS");
|
|
const { lowS, prehash } = opts;
|
|
let _sig = void 0;
|
|
let P;
|
|
try {
|
|
if (typeof sg === "string" || sg instanceof Uint8Array) {
|
|
try {
|
|
_sig = Signature.fromDER(sg);
|
|
} catch (derError) {
|
|
if (!(derError instanceof DER2.Err))
|
|
throw derError;
|
|
_sig = Signature.fromCompact(sg);
|
|
}
|
|
} else if (typeof sg === "object" && typeof sg.r === "bigint" && typeof sg.s === "bigint") {
|
|
const { r: r2, s: s2 } = sg;
|
|
_sig = new Signature(r2, s2);
|
|
} else {
|
|
throw new Error("PARSE");
|
|
}
|
|
P = Point4.fromHex(publicKey);
|
|
} catch (error) {
|
|
if (error.message === "PARSE")
|
|
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
|
|
return false;
|
|
}
|
|
if (lowS && _sig.hasHighS())
|
|
return false;
|
|
if (prehash)
|
|
msgHash = CURVE.hash(msgHash);
|
|
const { r, s } = _sig;
|
|
const h = bits2int_modN(msgHash);
|
|
const is = invN(s);
|
|
const u1 = modN2(h * is);
|
|
const u2 = modN2(r * is);
|
|
const R = Point4.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine();
|
|
if (!R)
|
|
return false;
|
|
const v = modN2(R.x);
|
|
return v === r;
|
|
}
|
|
return {
|
|
CURVE,
|
|
getPublicKey: getPublicKey2,
|
|
getSharedSecret,
|
|
sign,
|
|
verify,
|
|
ProjectivePoint: Point4,
|
|
Signature,
|
|
utils: utils2
|
|
};
|
|
}
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/_shortw_utils.js
|
|
function getHash2(hash3) {
|
|
return {
|
|
hash: hash3,
|
|
hmac: (key, ...msgs) => hmac2(hash3, key, concatBytes3(...msgs)),
|
|
randomBytes: randomBytes2
|
|
};
|
|
}
|
|
function createCurve2(curveDef, defHash) {
|
|
const create = (hash3) => weierstrass2({ ...curveDef, ...getHash2(hash3) });
|
|
return Object.freeze({ ...create(defHash), create });
|
|
}
|
|
|
|
// node_modules/@scure/bip32/node_modules/@noble/curves/esm/secp256k1.js
|
|
var secp256k1P2 = BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f");
|
|
var secp256k1N2 = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
|
var _1n10 = BigInt(1);
|
|
var _2n8 = BigInt(2);
|
|
var divNearest2 = (a, b) => (a + b / _2n8) / b;
|
|
function sqrtMod2(y) {
|
|
const P = secp256k1P2;
|
|
const _3n5 = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
|
|
const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
|
|
const b2 = y * y * y % P;
|
|
const b3 = b2 * b2 * y % P;
|
|
const b6 = pow22(b3, _3n5, P) * b3 % P;
|
|
const b9 = pow22(b6, _3n5, P) * b3 % P;
|
|
const b11 = pow22(b9, _2n8, P) * b2 % P;
|
|
const b22 = pow22(b11, _11n, P) * b11 % P;
|
|
const b44 = pow22(b22, _22n, P) * b22 % P;
|
|
const b88 = pow22(b44, _44n, P) * b44 % P;
|
|
const b176 = pow22(b88, _88n, P) * b88 % P;
|
|
const b220 = pow22(b176, _44n, P) * b44 % P;
|
|
const b223 = pow22(b220, _3n5, P) * b3 % P;
|
|
const t1 = pow22(b223, _23n, P) * b22 % P;
|
|
const t2 = pow22(t1, _6n, P) * b2 % P;
|
|
const root = pow22(t2, _2n8, P);
|
|
if (!Fp2.eql(Fp2.sqr(root), y))
|
|
throw new Error("Cannot find square root");
|
|
return root;
|
|
}
|
|
var Fp2 = Field2(secp256k1P2, void 0, void 0, { sqrt: sqrtMod2 });
|
|
var secp256k12 = createCurve2({
|
|
a: BigInt(0),
|
|
b: BigInt(7),
|
|
Fp: Fp2,
|
|
n: secp256k1N2,
|
|
Gx: BigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240"),
|
|
Gy: BigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424"),
|
|
h: BigInt(1),
|
|
lowS: true,
|
|
endo: {
|
|
beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),
|
|
splitScalar: (k) => {
|
|
const n = secp256k1N2;
|
|
const a1 = BigInt("0x3086d221a7d46bcde86c90e49284eb15");
|
|
const b1 = -_1n10 * BigInt("0xe4437ed6010e88286f547fa90abfe4c3");
|
|
const a2 = BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8");
|
|
const b2 = a1;
|
|
const POW_2_128 = BigInt("0x100000000000000000000000000000000");
|
|
const c1 = divNearest2(b2 * k, n);
|
|
const c2 = divNearest2(-b1 * k, n);
|
|
let k1 = mod2(k - c1 * a1 - c2 * a2, n);
|
|
let k2 = mod2(-c1 * b1 - c2 * b2, n);
|
|
const k1neg = k1 > POW_2_128;
|
|
const k2neg = k2 > POW_2_128;
|
|
if (k1neg)
|
|
k1 = n - k1;
|
|
if (k2neg)
|
|
k2 = n - k2;
|
|
if (k1 > POW_2_128 || k2 > POW_2_128) {
|
|
throw new Error("splitScalar: Endomorphism failed, k=" + k);
|
|
}
|
|
return { k1neg, k1, k2neg, k2 };
|
|
}
|
|
}
|
|
}, sha2562);
|
|
var _0n10 = BigInt(0);
|
|
var Point2 = secp256k12.ProjectivePoint;
|
|
|
|
// node_modules/@scure/bip32/lib/esm/index.js
|
|
var Point3 = secp256k12.ProjectivePoint;
|
|
var base58check2 = base58check(sha2562);
|
|
function bytesToNumber(bytes4) {
|
|
return BigInt(`0x${bytesToHex2(bytes4)}`);
|
|
}
|
|
function numberToBytes(num) {
|
|
return hexToBytes2(num.toString(16).padStart(64, "0"));
|
|
}
|
|
var MASTER_SECRET = utf8ToBytes3("Bitcoin seed");
|
|
var BITCOIN_VERSIONS = { private: 76066276, public: 76067358 };
|
|
var HARDENED_OFFSET = 2147483648;
|
|
var hash160 = (data) => ripemd160(sha2562(data));
|
|
var fromU32 = (data) => createView2(data).getUint32(0, false);
|
|
var toU32 = (n) => {
|
|
if (!Number.isSafeInteger(n) || n < 0 || n > 2 ** 32 - 1) {
|
|
throw new Error(`Invalid number=${n}. Should be from 0 to 2 ** 32 - 1`);
|
|
}
|
|
const buf = new Uint8Array(4);
|
|
createView2(buf).setUint32(0, n, false);
|
|
return buf;
|
|
};
|
|
var HDKey = class {
|
|
get fingerprint() {
|
|
if (!this.pubHash) {
|
|
throw new Error("No publicKey set!");
|
|
}
|
|
return fromU32(this.pubHash);
|
|
}
|
|
get identifier() {
|
|
return this.pubHash;
|
|
}
|
|
get pubKeyHash() {
|
|
return this.pubHash;
|
|
}
|
|
get privateKey() {
|
|
return this.privKeyBytes || null;
|
|
}
|
|
get publicKey() {
|
|
return this.pubKey || null;
|
|
}
|
|
get privateExtendedKey() {
|
|
const priv = this.privateKey;
|
|
if (!priv) {
|
|
throw new Error("No private key");
|
|
}
|
|
return base58check2.encode(this.serialize(this.versions.private, concatBytes3(new Uint8Array([0]), priv)));
|
|
}
|
|
get publicExtendedKey() {
|
|
if (!this.pubKey) {
|
|
throw new Error("No public key");
|
|
}
|
|
return base58check2.encode(this.serialize(this.versions.public, this.pubKey));
|
|
}
|
|
static fromMasterSeed(seed, versions = BITCOIN_VERSIONS) {
|
|
bytes2(seed);
|
|
if (8 * seed.length < 128 || 8 * seed.length > 512) {
|
|
throw new Error(`HDKey: wrong seed length=${seed.length}. Should be between 128 and 512 bits; 256 bits is advised)`);
|
|
}
|
|
const I = hmac2(sha512, MASTER_SECRET, seed);
|
|
return new HDKey({
|
|
versions,
|
|
chainCode: I.slice(32),
|
|
privateKey: I.slice(0, 32)
|
|
});
|
|
}
|
|
static fromExtendedKey(base58key, versions = BITCOIN_VERSIONS) {
|
|
const keyBuffer = base58check2.decode(base58key);
|
|
const keyView = createView2(keyBuffer);
|
|
const version = keyView.getUint32(0, false);
|
|
const opt = {
|
|
versions,
|
|
depth: keyBuffer[4],
|
|
parentFingerprint: keyView.getUint32(5, false),
|
|
index: keyView.getUint32(9, false),
|
|
chainCode: keyBuffer.slice(13, 45)
|
|
};
|
|
const key = keyBuffer.slice(45);
|
|
const isPriv = key[0] === 0;
|
|
if (version !== versions[isPriv ? "private" : "public"]) {
|
|
throw new Error("Version mismatch");
|
|
}
|
|
if (isPriv) {
|
|
return new HDKey({ ...opt, privateKey: key.slice(1) });
|
|
} else {
|
|
return new HDKey({ ...opt, publicKey: key });
|
|
}
|
|
}
|
|
static fromJSON(json) {
|
|
return HDKey.fromExtendedKey(json.xpriv);
|
|
}
|
|
constructor(opt) {
|
|
this.depth = 0;
|
|
this.index = 0;
|
|
this.chainCode = null;
|
|
this.parentFingerprint = 0;
|
|
if (!opt || typeof opt !== "object") {
|
|
throw new Error("HDKey.constructor must not be called directly");
|
|
}
|
|
this.versions = opt.versions || BITCOIN_VERSIONS;
|
|
this.depth = opt.depth || 0;
|
|
this.chainCode = opt.chainCode;
|
|
this.index = opt.index || 0;
|
|
this.parentFingerprint = opt.parentFingerprint || 0;
|
|
if (!this.depth) {
|
|
if (this.parentFingerprint || this.index) {
|
|
throw new Error("HDKey: zero depth with non-zero index/parent fingerprint");
|
|
}
|
|
}
|
|
if (opt.publicKey && opt.privateKey) {
|
|
throw new Error("HDKey: publicKey and privateKey at same time.");
|
|
}
|
|
if (opt.privateKey) {
|
|
if (!secp256k12.utils.isValidPrivateKey(opt.privateKey)) {
|
|
throw new Error("Invalid private key");
|
|
}
|
|
this.privKey = typeof opt.privateKey === "bigint" ? opt.privateKey : bytesToNumber(opt.privateKey);
|
|
this.privKeyBytes = numberToBytes(this.privKey);
|
|
this.pubKey = secp256k12.getPublicKey(opt.privateKey, true);
|
|
} else if (opt.publicKey) {
|
|
this.pubKey = Point3.fromHex(opt.publicKey).toRawBytes(true);
|
|
} else {
|
|
throw new Error("HDKey: no public or private key provided");
|
|
}
|
|
this.pubHash = hash160(this.pubKey);
|
|
}
|
|
derive(path) {
|
|
if (!/^[mM]'?/.test(path)) {
|
|
throw new Error('Path must start with "m" or "M"');
|
|
}
|
|
if (/^[mM]'?$/.test(path)) {
|
|
return this;
|
|
}
|
|
const parts = path.replace(/^[mM]'?\//, "").split("/");
|
|
let child = this;
|
|
for (const c of parts) {
|
|
const m = /^(\d+)('?)$/.exec(c);
|
|
if (!m || m.length !== 3) {
|
|
throw new Error(`Invalid child index: ${c}`);
|
|
}
|
|
let idx = +m[1];
|
|
if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET) {
|
|
throw new Error("Invalid index");
|
|
}
|
|
if (m[2] === "'") {
|
|
idx += HARDENED_OFFSET;
|
|
}
|
|
child = child.deriveChild(idx);
|
|
}
|
|
return child;
|
|
}
|
|
deriveChild(index) {
|
|
if (!this.pubKey || !this.chainCode) {
|
|
throw new Error("No publicKey or chainCode set");
|
|
}
|
|
let data = toU32(index);
|
|
if (index >= HARDENED_OFFSET) {
|
|
const priv = this.privateKey;
|
|
if (!priv) {
|
|
throw new Error("Could not derive hardened child key");
|
|
}
|
|
data = concatBytes3(new Uint8Array([0]), priv, data);
|
|
} else {
|
|
data = concatBytes3(this.pubKey, data);
|
|
}
|
|
const I = hmac2(sha512, this.chainCode, data);
|
|
const childTweak = bytesToNumber(I.slice(0, 32));
|
|
const chainCode = I.slice(32);
|
|
if (!secp256k12.utils.isValidPrivateKey(childTweak)) {
|
|
throw new Error("Tweak bigger than curve order");
|
|
}
|
|
const opt = {
|
|
versions: this.versions,
|
|
chainCode,
|
|
depth: this.depth + 1,
|
|
parentFingerprint: this.fingerprint,
|
|
index
|
|
};
|
|
try {
|
|
if (this.privateKey) {
|
|
const added = mod2(this.privKey + childTweak, secp256k12.CURVE.n);
|
|
if (!secp256k12.utils.isValidPrivateKey(added)) {
|
|
throw new Error("The tweak was out of range or the resulted private key is invalid");
|
|
}
|
|
opt.privateKey = added;
|
|
} else {
|
|
const added = Point3.fromHex(this.pubKey).add(Point3.fromPrivateKey(childTweak));
|
|
if (added.equals(Point3.ZERO)) {
|
|
throw new Error("The tweak was equal to negative P, which made the result key invalid");
|
|
}
|
|
opt.publicKey = added.toRawBytes(true);
|
|
}
|
|
return new HDKey(opt);
|
|
} catch (err) {
|
|
return this.deriveChild(index + 1);
|
|
}
|
|
}
|
|
sign(hash3) {
|
|
if (!this.privateKey) {
|
|
throw new Error("No privateKey set!");
|
|
}
|
|
bytes2(hash3, 32);
|
|
return secp256k12.sign(hash3, this.privKey).toCompactRawBytes();
|
|
}
|
|
verify(hash3, signature) {
|
|
bytes2(hash3, 32);
|
|
bytes2(signature, 64);
|
|
if (!this.publicKey) {
|
|
throw new Error("No publicKey set!");
|
|
}
|
|
let sig;
|
|
try {
|
|
sig = secp256k12.Signature.fromCompact(signature);
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
return secp256k12.verify(sig, hash3, this.publicKey);
|
|
}
|
|
wipePrivateData() {
|
|
this.privKey = void 0;
|
|
if (this.privKeyBytes) {
|
|
this.privKeyBytes.fill(0);
|
|
this.privKeyBytes = void 0;
|
|
}
|
|
return this;
|
|
}
|
|
toJSON() {
|
|
return {
|
|
xpriv: this.privateExtendedKey,
|
|
xpub: this.publicExtendedKey
|
|
};
|
|
}
|
|
serialize(version, key) {
|
|
if (!this.chainCode) {
|
|
throw new Error("No chainCode set");
|
|
}
|
|
bytes2(key, 33);
|
|
return concatBytes3(toU32(version), new Uint8Array([this.depth]), toU32(this.parentFingerprint), toU32(this.index), this.chainCode, key);
|
|
}
|
|
};
|
|
|
|
// nip06.ts
|
|
var DERIVATION_PATH = `m/44'/1237'`;
|
|
function privateKeyFromSeedWords(mnemonic, passphrase, accountIndex = 0) {
|
|
let root = HDKey.fromMasterSeed(mnemonicToSeedSync(mnemonic, passphrase));
|
|
let privateKey = root.derive(`${DERIVATION_PATH}/${accountIndex}'/0/0`).privateKey;
|
|
if (!privateKey)
|
|
throw new Error("could not derive private key");
|
|
return privateKey;
|
|
}
|
|
function accountFromSeedWords(mnemonic, passphrase, accountIndex = 0) {
|
|
const root = HDKey.fromMasterSeed(mnemonicToSeedSync(mnemonic, passphrase));
|
|
const seed = root.derive(`${DERIVATION_PATH}/${accountIndex}'/0/0`);
|
|
const publicKey = bytesToHex2(seed.publicKey.slice(1));
|
|
const privateKey = seed.privateKey;
|
|
if (!privateKey || !publicKey) {
|
|
throw new Error("could not derive key pair");
|
|
}
|
|
return { privateKey, publicKey };
|
|
}
|
|
function extendedKeysFromSeedWords(mnemonic, passphrase, extendedAccountIndex = 0) {
|
|
let root = HDKey.fromMasterSeed(mnemonicToSeedSync(mnemonic, passphrase));
|
|
let seed = root.derive(`${DERIVATION_PATH}/${extendedAccountIndex}'`);
|
|
let privateExtendedKey = seed.privateExtendedKey;
|
|
let publicExtendedKey = seed.publicExtendedKey;
|
|
if (!privateExtendedKey && !publicExtendedKey)
|
|
throw new Error("could not derive extended key pair");
|
|
return { privateExtendedKey, publicExtendedKey };
|
|
}
|
|
function accountFromExtendedKey(base58key, accountIndex = 0) {
|
|
let extendedKey = HDKey.fromExtendedKey(base58key);
|
|
let version = base58key.slice(0, 4);
|
|
let child = extendedKey.deriveChild(0).deriveChild(accountIndex);
|
|
let publicKey = bytesToHex2(child.publicKey.slice(1));
|
|
if (!publicKey)
|
|
throw new Error("could not derive public key");
|
|
if (version === "xprv") {
|
|
let privateKey = child.privateKey;
|
|
if (!privateKey)
|
|
throw new Error("could not derive private key");
|
|
return { privateKey, publicKey };
|
|
}
|
|
return { publicKey };
|
|
}
|
|
function generateSeedWords() {
|
|
return generateMnemonic(wordlist);
|
|
}
|
|
function validateWords(words) {
|
|
return validateMnemonic(words, wordlist);
|
|
}
|
|
|
|
// nip10.ts
|
|
var nip10_exports = {};
|
|
__export(nip10_exports, {
|
|
parse: () => parse
|
|
});
|
|
function parse(event) {
|
|
const result = {
|
|
reply: void 0,
|
|
root: void 0,
|
|
mentions: [],
|
|
profiles: [],
|
|
quotes: []
|
|
};
|
|
let maybeParent;
|
|
let maybeRoot;
|
|
for (let i2 = event.tags.length - 1; i2 >= 0; i2--) {
|
|
const tag = event.tags[i2];
|
|
if (tag[0] === "e" && tag[1]) {
|
|
const [_, eTagEventId, eTagRelayUrl, eTagMarker, eTagAuthor] = tag;
|
|
const eventPointer = {
|
|
id: eTagEventId,
|
|
relays: eTagRelayUrl ? [eTagRelayUrl] : [],
|
|
author: eTagAuthor
|
|
};
|
|
if (eTagMarker === "root") {
|
|
result.root = eventPointer;
|
|
continue;
|
|
}
|
|
if (eTagMarker === "reply") {
|
|
result.reply = eventPointer;
|
|
continue;
|
|
}
|
|
if (eTagMarker === "mention") {
|
|
result.mentions.push(eventPointer);
|
|
continue;
|
|
}
|
|
if (!maybeParent) {
|
|
maybeParent = eventPointer;
|
|
} else {
|
|
maybeRoot = eventPointer;
|
|
}
|
|
result.mentions.push(eventPointer);
|
|
continue;
|
|
}
|
|
if (tag[0] === "q" && tag[1]) {
|
|
const [_, eTagEventId, eTagRelayUrl] = tag;
|
|
result.quotes.push({
|
|
id: eTagEventId,
|
|
relays: eTagRelayUrl ? [eTagRelayUrl] : []
|
|
});
|
|
}
|
|
if (tag[0] === "p" && tag[1]) {
|
|
result.profiles.push({
|
|
pubkey: tag[1],
|
|
relays: tag[2] ? [tag[2]] : []
|
|
});
|
|
continue;
|
|
}
|
|
}
|
|
if (!result.root) {
|
|
result.root = maybeRoot || maybeParent || result.reply;
|
|
}
|
|
if (!result.reply) {
|
|
result.reply = maybeParent || result.root;
|
|
}
|
|
;
|
|
[result.reply, result.root].forEach((ref) => {
|
|
if (!ref)
|
|
return;
|
|
let idx = result.mentions.indexOf(ref);
|
|
if (idx !== -1) {
|
|
result.mentions.splice(idx, 1);
|
|
}
|
|
if (ref.author) {
|
|
let author = result.profiles.find((p) => p.pubkey === ref.author);
|
|
if (author && author.relays) {
|
|
if (!ref.relays) {
|
|
ref.relays = [];
|
|
}
|
|
author.relays.forEach((url) => {
|
|
if (ref.relays?.indexOf(url) === -1)
|
|
ref.relays.push(url);
|
|
});
|
|
author.relays = ref.relays;
|
|
}
|
|
}
|
|
});
|
|
result.mentions.forEach((ref) => {
|
|
if (ref.author) {
|
|
let author = result.profiles.find((p) => p.pubkey === ref.author);
|
|
if (author && author.relays) {
|
|
if (!ref.relays) {
|
|
ref.relays = [];
|
|
}
|
|
author.relays.forEach((url) => {
|
|
if (ref.relays.indexOf(url) === -1)
|
|
ref.relays.push(url);
|
|
});
|
|
author.relays = ref.relays;
|
|
}
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
|
|
// nip11.ts
|
|
var nip11_exports = {};
|
|
__export(nip11_exports, {
|
|
fetchRelayInformation: () => fetchRelayInformation,
|
|
useFetchImplementation: () => useFetchImplementation2
|
|
});
|
|
var _fetch2;
|
|
try {
|
|
_fetch2 = fetch;
|
|
} catch {
|
|
}
|
|
function useFetchImplementation2(fetchImplementation) {
|
|
_fetch2 = fetchImplementation;
|
|
}
|
|
async function fetchRelayInformation(url) {
|
|
return await (await fetch(url.replace("ws://", "http://").replace("wss://", "https://"), {
|
|
headers: { Accept: "application/nostr+json" }
|
|
})).json();
|
|
}
|
|
|
|
// nip13.ts
|
|
var nip13_exports = {};
|
|
__export(nip13_exports, {
|
|
fastEventHash: () => fastEventHash,
|
|
getPow: () => getPow,
|
|
minePow: () => minePow
|
|
});
|
|
function getPow(hex2) {
|
|
let count = 0;
|
|
for (let i2 = 0; i2 < 64; i2 += 8) {
|
|
const nibble = parseInt(hex2.substring(i2, i2 + 8), 16);
|
|
if (nibble === 0) {
|
|
count += 32;
|
|
} else {
|
|
count += Math.clz32(nibble);
|
|
break;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
function minePow(unsigned, difficulty) {
|
|
let count = 0;
|
|
const event = unsigned;
|
|
const tag = ["nonce", count.toString(), difficulty.toString()];
|
|
event.tags.push(tag);
|
|
while (true) {
|
|
const now2 = Math.floor(new Date().getTime() / 1e3);
|
|
if (now2 !== event.created_at) {
|
|
count = 0;
|
|
event.created_at = now2;
|
|
}
|
|
tag[1] = (++count).toString();
|
|
event.id = fastEventHash(event);
|
|
if (getPow(event.id) >= difficulty) {
|
|
break;
|
|
}
|
|
}
|
|
return event;
|
|
}
|
|
function fastEventHash(evt) {
|
|
return bytesToHex2(
|
|
sha2562(utf8Encoder.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content])))
|
|
);
|
|
}
|
|
|
|
// nip17.ts
|
|
var nip17_exports = {};
|
|
__export(nip17_exports, {
|
|
unwrapEvent: () => unwrapEvent2,
|
|
unwrapManyEvents: () => unwrapManyEvents2,
|
|
wrapEvent: () => wrapEvent2,
|
|
wrapManyEvents: () => wrapManyEvents2
|
|
});
|
|
|
|
// nip59.ts
|
|
var nip59_exports = {};
|
|
__export(nip59_exports, {
|
|
createRumor: () => createRumor,
|
|
createSeal: () => createSeal,
|
|
createWrap: () => createWrap,
|
|
unwrapEvent: () => unwrapEvent,
|
|
unwrapManyEvents: () => unwrapManyEvents,
|
|
wrapEvent: () => wrapEvent,
|
|
wrapManyEvents: () => wrapManyEvents
|
|
});
|
|
|
|
// nip44.ts
|
|
var nip44_exports = {};
|
|
__export(nip44_exports, {
|
|
decrypt: () => decrypt3,
|
|
encrypt: () => encrypt3,
|
|
getConversationKey: () => getConversationKey,
|
|
v2: () => v2
|
|
});
|
|
|
|
// node_modules/@noble/ciphers/esm/_poly1305.js
|
|
var u8to16 = (a, i2) => a[i2++] & 255 | (a[i2++] & 255) << 8;
|
|
var Poly1305 = class {
|
|
constructor(key) {
|
|
this.blockLen = 16;
|
|
this.outputLen = 16;
|
|
this.buffer = new Uint8Array(16);
|
|
this.r = new Uint16Array(10);
|
|
this.h = new Uint16Array(10);
|
|
this.pad = new Uint16Array(8);
|
|
this.pos = 0;
|
|
this.finished = false;
|
|
key = toBytes3(key);
|
|
bytes3(key, 32);
|
|
const t0 = u8to16(key, 0);
|
|
const t1 = u8to16(key, 2);
|
|
const t2 = u8to16(key, 4);
|
|
const t3 = u8to16(key, 6);
|
|
const t4 = u8to16(key, 8);
|
|
const t5 = u8to16(key, 10);
|
|
const t6 = u8to16(key, 12);
|
|
const t7 = u8to16(key, 14);
|
|
this.r[0] = t0 & 8191;
|
|
this.r[1] = (t0 >>> 13 | t1 << 3) & 8191;
|
|
this.r[2] = (t1 >>> 10 | t2 << 6) & 7939;
|
|
this.r[3] = (t2 >>> 7 | t3 << 9) & 8191;
|
|
this.r[4] = (t3 >>> 4 | t4 << 12) & 255;
|
|
this.r[5] = t4 >>> 1 & 8190;
|
|
this.r[6] = (t4 >>> 14 | t5 << 2) & 8191;
|
|
this.r[7] = (t5 >>> 11 | t6 << 5) & 8065;
|
|
this.r[8] = (t6 >>> 8 | t7 << 8) & 8191;
|
|
this.r[9] = t7 >>> 5 & 127;
|
|
for (let i2 = 0; i2 < 8; i2++)
|
|
this.pad[i2] = u8to16(key, 16 + 2 * i2);
|
|
}
|
|
process(data, offset, isLast = false) {
|
|
const hibit = isLast ? 0 : 1 << 11;
|
|
const { h, r } = this;
|
|
const r0 = r[0];
|
|
const r1 = r[1];
|
|
const r2 = r[2];
|
|
const r3 = r[3];
|
|
const r4 = r[4];
|
|
const r5 = r[5];
|
|
const r6 = r[6];
|
|
const r7 = r[7];
|
|
const r8 = r[8];
|
|
const r9 = r[9];
|
|
const t0 = u8to16(data, offset + 0);
|
|
const t1 = u8to16(data, offset + 2);
|
|
const t2 = u8to16(data, offset + 4);
|
|
const t3 = u8to16(data, offset + 6);
|
|
const t4 = u8to16(data, offset + 8);
|
|
const t5 = u8to16(data, offset + 10);
|
|
const t6 = u8to16(data, offset + 12);
|
|
const t7 = u8to16(data, offset + 14);
|
|
let h0 = h[0] + (t0 & 8191);
|
|
let h1 = h[1] + ((t0 >>> 13 | t1 << 3) & 8191);
|
|
let h2 = h[2] + ((t1 >>> 10 | t2 << 6) & 8191);
|
|
let h3 = h[3] + ((t2 >>> 7 | t3 << 9) & 8191);
|
|
let h4 = h[4] + ((t3 >>> 4 | t4 << 12) & 8191);
|
|
let h5 = h[5] + (t4 >>> 1 & 8191);
|
|
let h6 = h[6] + ((t4 >>> 14 | t5 << 2) & 8191);
|
|
let h7 = h[7] + ((t5 >>> 11 | t6 << 5) & 8191);
|
|
let h8 = h[8] + ((t6 >>> 8 | t7 << 8) & 8191);
|
|
let h9 = h[9] + (t7 >>> 5 | hibit);
|
|
let c = 0;
|
|
let d0 = c + h0 * r0 + h1 * (5 * r9) + h2 * (5 * r8) + h3 * (5 * r7) + h4 * (5 * r6);
|
|
c = d0 >>> 13;
|
|
d0 &= 8191;
|
|
d0 += h5 * (5 * r5) + h6 * (5 * r4) + h7 * (5 * r3) + h8 * (5 * r2) + h9 * (5 * r1);
|
|
c += d0 >>> 13;
|
|
d0 &= 8191;
|
|
let d1 = c + h0 * r1 + h1 * r0 + h2 * (5 * r9) + h3 * (5 * r8) + h4 * (5 * r7);
|
|
c = d1 >>> 13;
|
|
d1 &= 8191;
|
|
d1 += h5 * (5 * r6) + h6 * (5 * r5) + h7 * (5 * r4) + h8 * (5 * r3) + h9 * (5 * r2);
|
|
c += d1 >>> 13;
|
|
d1 &= 8191;
|
|
let d2 = c + h0 * r2 + h1 * r1 + h2 * r0 + h3 * (5 * r9) + h4 * (5 * r8);
|
|
c = d2 >>> 13;
|
|
d2 &= 8191;
|
|
d2 += h5 * (5 * r7) + h6 * (5 * r6) + h7 * (5 * r5) + h8 * (5 * r4) + h9 * (5 * r3);
|
|
c += d2 >>> 13;
|
|
d2 &= 8191;
|
|
let d3 = c + h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * (5 * r9);
|
|
c = d3 >>> 13;
|
|
d3 &= 8191;
|
|
d3 += h5 * (5 * r8) + h6 * (5 * r7) + h7 * (5 * r6) + h8 * (5 * r5) + h9 * (5 * r4);
|
|
c += d3 >>> 13;
|
|
d3 &= 8191;
|
|
let d4 = c + h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0;
|
|
c = d4 >>> 13;
|
|
d4 &= 8191;
|
|
d4 += h5 * (5 * r9) + h6 * (5 * r8) + h7 * (5 * r7) + h8 * (5 * r6) + h9 * (5 * r5);
|
|
c += d4 >>> 13;
|
|
d4 &= 8191;
|
|
let d5 = c + h0 * r5 + h1 * r4 + h2 * r3 + h3 * r2 + h4 * r1;
|
|
c = d5 >>> 13;
|
|
d5 &= 8191;
|
|
d5 += h5 * r0 + h6 * (5 * r9) + h7 * (5 * r8) + h8 * (5 * r7) + h9 * (5 * r6);
|
|
c += d5 >>> 13;
|
|
d5 &= 8191;
|
|
let d6 = c + h0 * r6 + h1 * r5 + h2 * r4 + h3 * r3 + h4 * r2;
|
|
c = d6 >>> 13;
|
|
d6 &= 8191;
|
|
d6 += h5 * r1 + h6 * r0 + h7 * (5 * r9) + h8 * (5 * r8) + h9 * (5 * r7);
|
|
c += d6 >>> 13;
|
|
d6 &= 8191;
|
|
let d7 = c + h0 * r7 + h1 * r6 + h2 * r5 + h3 * r4 + h4 * r3;
|
|
c = d7 >>> 13;
|
|
d7 &= 8191;
|
|
d7 += h5 * r2 + h6 * r1 + h7 * r0 + h8 * (5 * r9) + h9 * (5 * r8);
|
|
c += d7 >>> 13;
|
|
d7 &= 8191;
|
|
let d8 = c + h0 * r8 + h1 * r7 + h2 * r6 + h3 * r5 + h4 * r4;
|
|
c = d8 >>> 13;
|
|
d8 &= 8191;
|
|
d8 += h5 * r3 + h6 * r2 + h7 * r1 + h8 * r0 + h9 * (5 * r9);
|
|
c += d8 >>> 13;
|
|
d8 &= 8191;
|
|
let d9 = c + h0 * r9 + h1 * r8 + h2 * r7 + h3 * r6 + h4 * r5;
|
|
c = d9 >>> 13;
|
|
d9 &= 8191;
|
|
d9 += h5 * r4 + h6 * r3 + h7 * r2 + h8 * r1 + h9 * r0;
|
|
c += d9 >>> 13;
|
|
d9 &= 8191;
|
|
c = (c << 2) + c | 0;
|
|
c = c + d0 | 0;
|
|
d0 = c & 8191;
|
|
c = c >>> 13;
|
|
d1 += c;
|
|
h[0] = d0;
|
|
h[1] = d1;
|
|
h[2] = d2;
|
|
h[3] = d3;
|
|
h[4] = d4;
|
|
h[5] = d5;
|
|
h[6] = d6;
|
|
h[7] = d7;
|
|
h[8] = d8;
|
|
h[9] = d9;
|
|
}
|
|
finalize() {
|
|
const { h, pad: pad2 } = this;
|
|
const g = new Uint16Array(10);
|
|
let c = h[1] >>> 13;
|
|
h[1] &= 8191;
|
|
for (let i2 = 2; i2 < 10; i2++) {
|
|
h[i2] += c;
|
|
c = h[i2] >>> 13;
|
|
h[i2] &= 8191;
|
|
}
|
|
h[0] += c * 5;
|
|
c = h[0] >>> 13;
|
|
h[0] &= 8191;
|
|
h[1] += c;
|
|
c = h[1] >>> 13;
|
|
h[1] &= 8191;
|
|
h[2] += c;
|
|
g[0] = h[0] + 5;
|
|
c = g[0] >>> 13;
|
|
g[0] &= 8191;
|
|
for (let i2 = 1; i2 < 10; i2++) {
|
|
g[i2] = h[i2] + c;
|
|
c = g[i2] >>> 13;
|
|
g[i2] &= 8191;
|
|
}
|
|
g[9] -= 1 << 13;
|
|
let mask = (c ^ 1) - 1;
|
|
for (let i2 = 0; i2 < 10; i2++)
|
|
g[i2] &= mask;
|
|
mask = ~mask;
|
|
for (let i2 = 0; i2 < 10; i2++)
|
|
h[i2] = h[i2] & mask | g[i2];
|
|
h[0] = (h[0] | h[1] << 13) & 65535;
|
|
h[1] = (h[1] >>> 3 | h[2] << 10) & 65535;
|
|
h[2] = (h[2] >>> 6 | h[3] << 7) & 65535;
|
|
h[3] = (h[3] >>> 9 | h[4] << 4) & 65535;
|
|
h[4] = (h[4] >>> 12 | h[5] << 1 | h[6] << 14) & 65535;
|
|
h[5] = (h[6] >>> 2 | h[7] << 11) & 65535;
|
|
h[6] = (h[7] >>> 5 | h[8] << 8) & 65535;
|
|
h[7] = (h[8] >>> 8 | h[9] << 5) & 65535;
|
|
let f2 = h[0] + pad2[0];
|
|
h[0] = f2 & 65535;
|
|
for (let i2 = 1; i2 < 8; i2++) {
|
|
f2 = (h[i2] + pad2[i2] | 0) + (f2 >>> 16) | 0;
|
|
h[i2] = f2 & 65535;
|
|
}
|
|
}
|
|
update(data) {
|
|
exists3(this);
|
|
const { buffer, blockLen } = this;
|
|
data = toBytes3(data);
|
|
const len = data.length;
|
|
for (let pos = 0; pos < len; ) {
|
|
const take = Math.min(blockLen - this.pos, len - pos);
|
|
if (take === blockLen) {
|
|
for (; blockLen <= len - pos; pos += blockLen)
|
|
this.process(data, pos);
|
|
continue;
|
|
}
|
|
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
this.pos += take;
|
|
pos += take;
|
|
if (this.pos === blockLen) {
|
|
this.process(buffer, 0, false);
|
|
this.pos = 0;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
destroy() {
|
|
this.h.fill(0);
|
|
this.r.fill(0);
|
|
this.buffer.fill(0);
|
|
this.pad.fill(0);
|
|
}
|
|
digestInto(out) {
|
|
exists3(this);
|
|
output3(out, this);
|
|
this.finished = true;
|
|
const { buffer, h } = this;
|
|
let { pos } = this;
|
|
if (pos) {
|
|
buffer[pos++] = 1;
|
|
for (; pos < 16; pos++)
|
|
buffer[pos] = 0;
|
|
this.process(buffer, 0, true);
|
|
}
|
|
this.finalize();
|
|
let opos = 0;
|
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
out[opos++] = h[i2] >>> 0;
|
|
out[opos++] = h[i2] >>> 8;
|
|
}
|
|
return out;
|
|
}
|
|
digest() {
|
|
const { buffer, outputLen } = this;
|
|
this.digestInto(buffer);
|
|
const res = buffer.slice(0, outputLen);
|
|
this.destroy();
|
|
return res;
|
|
}
|
|
};
|
|
function wrapConstructorWithKey2(hashCons) {
|
|
const hashC = (msg, key) => hashCons(key).update(toBytes3(msg)).digest();
|
|
const tmp = hashCons(new Uint8Array(32));
|
|
hashC.outputLen = tmp.outputLen;
|
|
hashC.blockLen = tmp.blockLen;
|
|
hashC.create = (key) => hashCons(key);
|
|
return hashC;
|
|
}
|
|
var poly1305 = wrapConstructorWithKey2((key) => new Poly1305(key));
|
|
|
|
// node_modules/@noble/ciphers/esm/_arx.js
|
|
var _utf8ToBytes = (str) => Uint8Array.from(str.split("").map((c) => c.charCodeAt(0)));
|
|
var sigma16 = _utf8ToBytes("expand 16-byte k");
|
|
var sigma32 = _utf8ToBytes("expand 32-byte k");
|
|
var sigma16_32 = u32(sigma16);
|
|
var sigma32_32 = u32(sigma32);
|
|
var sigma = sigma32_32.slice();
|
|
function rotl2(a, b) {
|
|
return a << b | a >>> 32 - b;
|
|
}
|
|
function isAligned32(b) {
|
|
return b.byteOffset % 4 === 0;
|
|
}
|
|
var BLOCK_LEN = 64;
|
|
var BLOCK_LEN32 = 16;
|
|
var MAX_COUNTER = 2 ** 32 - 1;
|
|
var U32_EMPTY = new Uint32Array();
|
|
function runCipher(core, sigma2, key, nonce, data, output4, counter, rounds) {
|
|
const len = data.length;
|
|
const block = new Uint8Array(BLOCK_LEN);
|
|
const b32 = u32(block);
|
|
const isAligned = isAligned32(data) && isAligned32(output4);
|
|
const d32 = isAligned ? u32(data) : U32_EMPTY;
|
|
const o32 = isAligned ? u32(output4) : U32_EMPTY;
|
|
for (let pos = 0; pos < len; counter++) {
|
|
core(sigma2, key, nonce, b32, counter, rounds);
|
|
if (counter >= MAX_COUNTER)
|
|
throw new Error("arx: counter overflow");
|
|
const take = Math.min(BLOCK_LEN, len - pos);
|
|
if (isAligned && take === BLOCK_LEN) {
|
|
const pos32 = pos / 4;
|
|
if (pos % 4 !== 0)
|
|
throw new Error("arx: invalid block position");
|
|
for (let j = 0, posj; j < BLOCK_LEN32; j++) {
|
|
posj = pos32 + j;
|
|
o32[posj] = d32[posj] ^ b32[j];
|
|
}
|
|
pos += BLOCK_LEN;
|
|
continue;
|
|
}
|
|
for (let j = 0, posj; j < take; j++) {
|
|
posj = pos + j;
|
|
output4[posj] = data[posj] ^ block[j];
|
|
}
|
|
pos += take;
|
|
}
|
|
}
|
|
function createCipher(core, opts) {
|
|
const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts2({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);
|
|
if (typeof core !== "function")
|
|
throw new Error("core must be a function");
|
|
number3(counterLength);
|
|
number3(rounds);
|
|
bool2(counterRight);
|
|
bool2(allowShortKeys);
|
|
return (key, nonce, data, output4, counter = 0) => {
|
|
bytes3(key);
|
|
bytes3(nonce);
|
|
bytes3(data);
|
|
const len = data.length;
|
|
if (!output4)
|
|
output4 = new Uint8Array(len);
|
|
bytes3(output4);
|
|
number3(counter);
|
|
if (counter < 0 || counter >= MAX_COUNTER)
|
|
throw new Error("arx: counter overflow");
|
|
if (output4.length < len)
|
|
throw new Error(`arx: output (${output4.length}) is shorter than data (${len})`);
|
|
const toClean = [];
|
|
let l = key.length, k, sigma2;
|
|
if (l === 32) {
|
|
k = key.slice();
|
|
toClean.push(k);
|
|
sigma2 = sigma32_32;
|
|
} else if (l === 16 && allowShortKeys) {
|
|
k = new Uint8Array(32);
|
|
k.set(key);
|
|
k.set(key, 16);
|
|
sigma2 = sigma16_32;
|
|
toClean.push(k);
|
|
} else {
|
|
throw new Error(`arx: invalid 32-byte key, got length=${l}`);
|
|
}
|
|
if (!isAligned32(nonce)) {
|
|
nonce = nonce.slice();
|
|
toClean.push(nonce);
|
|
}
|
|
const k32 = u32(k);
|
|
if (extendNonceFn) {
|
|
if (nonce.length !== 24)
|
|
throw new Error(`arx: extended nonce must be 24 bytes`);
|
|
extendNonceFn(sigma2, k32, u32(nonce.subarray(0, 16)), k32);
|
|
nonce = nonce.subarray(16);
|
|
}
|
|
const nonceNcLen = 16 - counterLength;
|
|
if (nonceNcLen !== nonce.length)
|
|
throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);
|
|
if (nonceNcLen !== 12) {
|
|
const nc = new Uint8Array(12);
|
|
nc.set(nonce, counterRight ? 0 : 12 - nonce.length);
|
|
nonce = nc;
|
|
toClean.push(nonce);
|
|
}
|
|
const n32 = u32(nonce);
|
|
runCipher(core, sigma2, k32, n32, data, output4, counter, rounds);
|
|
while (toClean.length > 0)
|
|
toClean.pop().fill(0);
|
|
return output4;
|
|
};
|
|
}
|
|
|
|
// node_modules/@noble/ciphers/esm/chacha.js
|
|
function chachaCore(s, k, n, out, cnt, rounds = 20) {
|
|
let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2];
|
|
let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
|
|
for (let r = 0; r < rounds; r += 2) {
|
|
x00 = x00 + x04 | 0;
|
|
x12 = rotl2(x12 ^ x00, 16);
|
|
x08 = x08 + x12 | 0;
|
|
x04 = rotl2(x04 ^ x08, 12);
|
|
x00 = x00 + x04 | 0;
|
|
x12 = rotl2(x12 ^ x00, 8);
|
|
x08 = x08 + x12 | 0;
|
|
x04 = rotl2(x04 ^ x08, 7);
|
|
x01 = x01 + x05 | 0;
|
|
x13 = rotl2(x13 ^ x01, 16);
|
|
x09 = x09 + x13 | 0;
|
|
x05 = rotl2(x05 ^ x09, 12);
|
|
x01 = x01 + x05 | 0;
|
|
x13 = rotl2(x13 ^ x01, 8);
|
|
x09 = x09 + x13 | 0;
|
|
x05 = rotl2(x05 ^ x09, 7);
|
|
x02 = x02 + x06 | 0;
|
|
x14 = rotl2(x14 ^ x02, 16);
|
|
x10 = x10 + x14 | 0;
|
|
x06 = rotl2(x06 ^ x10, 12);
|
|
x02 = x02 + x06 | 0;
|
|
x14 = rotl2(x14 ^ x02, 8);
|
|
x10 = x10 + x14 | 0;
|
|
x06 = rotl2(x06 ^ x10, 7);
|
|
x03 = x03 + x07 | 0;
|
|
x15 = rotl2(x15 ^ x03, 16);
|
|
x11 = x11 + x15 | 0;
|
|
x07 = rotl2(x07 ^ x11, 12);
|
|
x03 = x03 + x07 | 0;
|
|
x15 = rotl2(x15 ^ x03, 8);
|
|
x11 = x11 + x15 | 0;
|
|
x07 = rotl2(x07 ^ x11, 7);
|
|
x00 = x00 + x05 | 0;
|
|
x15 = rotl2(x15 ^ x00, 16);
|
|
x10 = x10 + x15 | 0;
|
|
x05 = rotl2(x05 ^ x10, 12);
|
|
x00 = x00 + x05 | 0;
|
|
x15 = rotl2(x15 ^ x00, 8);
|
|
x10 = x10 + x15 | 0;
|
|
x05 = rotl2(x05 ^ x10, 7);
|
|
x01 = x01 + x06 | 0;
|
|
x12 = rotl2(x12 ^ x01, 16);
|
|
x11 = x11 + x12 | 0;
|
|
x06 = rotl2(x06 ^ x11, 12);
|
|
x01 = x01 + x06 | 0;
|
|
x12 = rotl2(x12 ^ x01, 8);
|
|
x11 = x11 + x12 | 0;
|
|
x06 = rotl2(x06 ^ x11, 7);
|
|
x02 = x02 + x07 | 0;
|
|
x13 = rotl2(x13 ^ x02, 16);
|
|
x08 = x08 + x13 | 0;
|
|
x07 = rotl2(x07 ^ x08, 12);
|
|
x02 = x02 + x07 | 0;
|
|
x13 = rotl2(x13 ^ x02, 8);
|
|
x08 = x08 + x13 | 0;
|
|
x07 = rotl2(x07 ^ x08, 7);
|
|
x03 = x03 + x04 | 0;
|
|
x14 = rotl2(x14 ^ x03, 16);
|
|
x09 = x09 + x14 | 0;
|
|
x04 = rotl2(x04 ^ x09, 12);
|
|
x03 = x03 + x04 | 0;
|
|
x14 = rotl2(x14 ^ x03, 8);
|
|
x09 = x09 + x14 | 0;
|
|
x04 = rotl2(x04 ^ x09, 7);
|
|
}
|
|
let oi = 0;
|
|
out[oi++] = y00 + x00 | 0;
|
|
out[oi++] = y01 + x01 | 0;
|
|
out[oi++] = y02 + x02 | 0;
|
|
out[oi++] = y03 + x03 | 0;
|
|
out[oi++] = y04 + x04 | 0;
|
|
out[oi++] = y05 + x05 | 0;
|
|
out[oi++] = y06 + x06 | 0;
|
|
out[oi++] = y07 + x07 | 0;
|
|
out[oi++] = y08 + x08 | 0;
|
|
out[oi++] = y09 + x09 | 0;
|
|
out[oi++] = y10 + x10 | 0;
|
|
out[oi++] = y11 + x11 | 0;
|
|
out[oi++] = y12 + x12 | 0;
|
|
out[oi++] = y13 + x13 | 0;
|
|
out[oi++] = y14 + x14 | 0;
|
|
out[oi++] = y15 + x15 | 0;
|
|
}
|
|
function hchacha(s, k, i2, o32) {
|
|
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 = i2[0], x13 = i2[1], x14 = i2[2], x15 = i2[3];
|
|
for (let r = 0; r < 20; r += 2) {
|
|
x00 = x00 + x04 | 0;
|
|
x12 = rotl2(x12 ^ x00, 16);
|
|
x08 = x08 + x12 | 0;
|
|
x04 = rotl2(x04 ^ x08, 12);
|
|
x00 = x00 + x04 | 0;
|
|
x12 = rotl2(x12 ^ x00, 8);
|
|
x08 = x08 + x12 | 0;
|
|
x04 = rotl2(x04 ^ x08, 7);
|
|
x01 = x01 + x05 | 0;
|
|
x13 = rotl2(x13 ^ x01, 16);
|
|
x09 = x09 + x13 | 0;
|
|
x05 = rotl2(x05 ^ x09, 12);
|
|
x01 = x01 + x05 | 0;
|
|
x13 = rotl2(x13 ^ x01, 8);
|
|
x09 = x09 + x13 | 0;
|
|
x05 = rotl2(x05 ^ x09, 7);
|
|
x02 = x02 + x06 | 0;
|
|
x14 = rotl2(x14 ^ x02, 16);
|
|
x10 = x10 + x14 | 0;
|
|
x06 = rotl2(x06 ^ x10, 12);
|
|
x02 = x02 + x06 | 0;
|
|
x14 = rotl2(x14 ^ x02, 8);
|
|
x10 = x10 + x14 | 0;
|
|
x06 = rotl2(x06 ^ x10, 7);
|
|
x03 = x03 + x07 | 0;
|
|
x15 = rotl2(x15 ^ x03, 16);
|
|
x11 = x11 + x15 | 0;
|
|
x07 = rotl2(x07 ^ x11, 12);
|
|
x03 = x03 + x07 | 0;
|
|
x15 = rotl2(x15 ^ x03, 8);
|
|
x11 = x11 + x15 | 0;
|
|
x07 = rotl2(x07 ^ x11, 7);
|
|
x00 = x00 + x05 | 0;
|
|
x15 = rotl2(x15 ^ x00, 16);
|
|
x10 = x10 + x15 | 0;
|
|
x05 = rotl2(x05 ^ x10, 12);
|
|
x00 = x00 + x05 | 0;
|
|
x15 = rotl2(x15 ^ x00, 8);
|
|
x10 = x10 + x15 | 0;
|
|
x05 = rotl2(x05 ^ x10, 7);
|
|
x01 = x01 + x06 | 0;
|
|
x12 = rotl2(x12 ^ x01, 16);
|
|
x11 = x11 + x12 | 0;
|
|
x06 = rotl2(x06 ^ x11, 12);
|
|
x01 = x01 + x06 | 0;
|
|
x12 = rotl2(x12 ^ x01, 8);
|
|
x11 = x11 + x12 | 0;
|
|
x06 = rotl2(x06 ^ x11, 7);
|
|
x02 = x02 + x07 | 0;
|
|
x13 = rotl2(x13 ^ x02, 16);
|
|
x08 = x08 + x13 | 0;
|
|
x07 = rotl2(x07 ^ x08, 12);
|
|
x02 = x02 + x07 | 0;
|
|
x13 = rotl2(x13 ^ x02, 8);
|
|
x08 = x08 + x13 | 0;
|
|
x07 = rotl2(x07 ^ x08, 7);
|
|
x03 = x03 + x04 | 0;
|
|
x14 = rotl2(x14 ^ x03, 16);
|
|
x09 = x09 + x14 | 0;
|
|
x04 = rotl2(x04 ^ x09, 12);
|
|
x03 = x03 + x04 | 0;
|
|
x14 = rotl2(x14 ^ x03, 8);
|
|
x09 = x09 + x14 | 0;
|
|
x04 = rotl2(x04 ^ x09, 7);
|
|
}
|
|
let oi = 0;
|
|
o32[oi++] = x00;
|
|
o32[oi++] = x01;
|
|
o32[oi++] = x02;
|
|
o32[oi++] = x03;
|
|
o32[oi++] = x12;
|
|
o32[oi++] = x13;
|
|
o32[oi++] = x14;
|
|
o32[oi++] = x15;
|
|
}
|
|
var chacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
|
counterRight: false,
|
|
counterLength: 4,
|
|
allowShortKeys: false
|
|
});
|
|
var xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
|
counterRight: false,
|
|
counterLength: 8,
|
|
extendNonceFn: hchacha,
|
|
allowShortKeys: false
|
|
});
|
|
var ZEROS162 = /* @__PURE__ */ new Uint8Array(16);
|
|
var updatePadded = (h, msg) => {
|
|
h.update(msg);
|
|
const left = msg.length % 16;
|
|
if (left)
|
|
h.update(ZEROS162.subarray(left));
|
|
};
|
|
var ZEROS322 = /* @__PURE__ */ new Uint8Array(32);
|
|
function computeTag2(fn, key, nonce, data, AAD) {
|
|
const authKey = fn(key, nonce, ZEROS322);
|
|
const h = poly1305.create(authKey);
|
|
if (AAD)
|
|
updatePadded(h, AAD);
|
|
updatePadded(h, data);
|
|
const num = new Uint8Array(16);
|
|
const view = createView3(num);
|
|
setBigUint643(view, 0, BigInt(AAD ? AAD.length : 0), true);
|
|
setBigUint643(view, 8, BigInt(data.length), true);
|
|
h.update(num);
|
|
const res = h.digest();
|
|
authKey.fill(0);
|
|
return res;
|
|
}
|
|
var _poly1305_aead = (xorStream) => (key, nonce, AAD) => {
|
|
const tagLength = 16;
|
|
bytes3(key, 32);
|
|
bytes3(nonce);
|
|
return {
|
|
encrypt: (plaintext, output4) => {
|
|
const plength = plaintext.length;
|
|
const clength = plength + tagLength;
|
|
if (output4) {
|
|
bytes3(output4, clength);
|
|
} else {
|
|
output4 = new Uint8Array(clength);
|
|
}
|
|
xorStream(key, nonce, plaintext, output4, 1);
|
|
const tag = computeTag2(xorStream, key, nonce, output4.subarray(0, -tagLength), AAD);
|
|
output4.set(tag, plength);
|
|
return output4;
|
|
},
|
|
decrypt: (ciphertext, output4) => {
|
|
const clength = ciphertext.length;
|
|
const plength = clength - tagLength;
|
|
if (clength < tagLength)
|
|
throw new Error(`encrypted data must be at least ${tagLength} bytes`);
|
|
if (output4) {
|
|
bytes3(output4, plength);
|
|
} else {
|
|
output4 = new Uint8Array(plength);
|
|
}
|
|
const data = ciphertext.subarray(0, -tagLength);
|
|
const passedTag = ciphertext.subarray(-tagLength);
|
|
const tag = computeTag2(xorStream, key, nonce, data, AAD);
|
|
if (!equalBytes2(passedTag, tag))
|
|
throw new Error("invalid tag");
|
|
xorStream(key, nonce, data, output4, 1);
|
|
return output4;
|
|
}
|
|
};
|
|
};
|
|
var chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));
|
|
var xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));
|
|
|
|
// node_modules/@noble/hashes/esm/hkdf.js
|
|
function extract(hash3, ikm, salt2) {
|
|
assert_default.hash(hash3);
|
|
if (salt2 === void 0)
|
|
salt2 = new Uint8Array(hash3.outputLen);
|
|
return hmac2(hash3, toBytes2(salt2), toBytes2(ikm));
|
|
}
|
|
var HKDF_COUNTER = new Uint8Array([0]);
|
|
var EMPTY_BUFFER = new Uint8Array();
|
|
function expand(hash3, prk, info, length = 32) {
|
|
assert_default.hash(hash3);
|
|
assert_default.number(length);
|
|
if (length > 255 * hash3.outputLen)
|
|
throw new Error("Length should be <= 255*HashLen");
|
|
const blocks = Math.ceil(length / hash3.outputLen);
|
|
if (info === void 0)
|
|
info = EMPTY_BUFFER;
|
|
const okm = new Uint8Array(blocks * hash3.outputLen);
|
|
const HMAC3 = hmac2.create(hash3, prk);
|
|
const HMACTmp = HMAC3._cloneInto();
|
|
const T = new Uint8Array(HMAC3.outputLen);
|
|
for (let counter = 0; counter < blocks; counter++) {
|
|
HKDF_COUNTER[0] = counter + 1;
|
|
HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
|
|
okm.set(T, hash3.outputLen * counter);
|
|
HMAC3._cloneInto(HMACTmp);
|
|
}
|
|
HMAC3.destroy();
|
|
HMACTmp.destroy();
|
|
T.fill(0);
|
|
HKDF_COUNTER.fill(0);
|
|
return okm.slice(0, length);
|
|
}
|
|
|
|
// nip44.ts
|
|
var minPlaintextSize = 1;
|
|
var maxPlaintextSize = 65535;
|
|
function getConversationKey(privkeyA, pubkeyB) {
|
|
const sharedX = secp256k1.getSharedSecret(privkeyA, "02" + pubkeyB).subarray(1, 33);
|
|
return extract(sha2562, sharedX, "nip44-v2");
|
|
}
|
|
function getMessageKeys(conversationKey, nonce) {
|
|
const keys = expand(sha2562, conversationKey, nonce, 76);
|
|
return {
|
|
chacha_key: keys.subarray(0, 32),
|
|
chacha_nonce: keys.subarray(32, 44),
|
|
hmac_key: keys.subarray(44, 76)
|
|
};
|
|
}
|
|
function calcPaddedLen(len) {
|
|
if (!Number.isSafeInteger(len) || len < 1)
|
|
throw new Error("expected positive integer");
|
|
if (len <= 32)
|
|
return 32;
|
|
const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;
|
|
const chunk = nextPower <= 256 ? 32 : nextPower / 8;
|
|
return chunk * (Math.floor((len - 1) / chunk) + 1);
|
|
}
|
|
function writeU16BE(num) {
|
|
if (!Number.isSafeInteger(num) || num < minPlaintextSize || num > maxPlaintextSize)
|
|
throw new Error("invalid plaintext size: must be between 1 and 65535 bytes");
|
|
const arr = new Uint8Array(2);
|
|
new DataView(arr.buffer).setUint16(0, num, false);
|
|
return arr;
|
|
}
|
|
function pad(plaintext) {
|
|
const unpadded = utf8Encoder.encode(plaintext);
|
|
const unpaddedLen = unpadded.length;
|
|
const prefix = writeU16BE(unpaddedLen);
|
|
const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen);
|
|
return concatBytes3(prefix, unpadded, suffix);
|
|
}
|
|
function unpad(padded) {
|
|
const unpaddedLen = new DataView(padded.buffer).getUint16(0);
|
|
const unpadded = padded.subarray(2, 2 + unpaddedLen);
|
|
if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + calcPaddedLen(unpaddedLen))
|
|
throw new Error("invalid padding");
|
|
return utf8Decoder.decode(unpadded);
|
|
}
|
|
function hmacAad(key, message, aad) {
|
|
if (aad.length !== 32)
|
|
throw new Error("AAD associated data must be 32 bytes");
|
|
const combined = concatBytes3(aad, message);
|
|
return hmac2(sha2562, key, combined);
|
|
}
|
|
function decodePayload(payload) {
|
|
if (typeof payload !== "string")
|
|
throw new Error("payload must be a valid string");
|
|
const plen = payload.length;
|
|
if (plen < 132 || plen > 87472)
|
|
throw new Error("invalid payload length: " + plen);
|
|
if (payload[0] === "#")
|
|
throw new Error("unknown encryption version");
|
|
let data;
|
|
try {
|
|
data = base64.decode(payload);
|
|
} catch (error) {
|
|
throw new Error("invalid base64: " + error.message);
|
|
}
|
|
const dlen = data.length;
|
|
if (dlen < 99 || dlen > 65603)
|
|
throw new Error("invalid data length: " + dlen);
|
|
const vers = data[0];
|
|
if (vers !== 2)
|
|
throw new Error("unknown encryption version " + vers);
|
|
return {
|
|
nonce: data.subarray(1, 33),
|
|
ciphertext: data.subarray(33, -32),
|
|
mac: data.subarray(-32)
|
|
};
|
|
}
|
|
function encrypt3(plaintext, conversationKey, nonce = randomBytes2(32)) {
|
|
const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);
|
|
const padded = pad(plaintext);
|
|
const ciphertext = chacha20(chacha_key, chacha_nonce, padded);
|
|
const mac = hmacAad(hmac_key, ciphertext, nonce);
|
|
return base64.encode(concatBytes3(new Uint8Array([2]), nonce, ciphertext, mac));
|
|
}
|
|
function decrypt3(payload, conversationKey) {
|
|
const { nonce, ciphertext, mac } = decodePayload(payload);
|
|
const { chacha_key, chacha_nonce, hmac_key } = getMessageKeys(conversationKey, nonce);
|
|
const calculatedMac = hmacAad(hmac_key, ciphertext, nonce);
|
|
if (!equalBytes2(calculatedMac, mac))
|
|
throw new Error("invalid MAC");
|
|
const padded = chacha20(chacha_key, chacha_nonce, ciphertext);
|
|
return unpad(padded);
|
|
}
|
|
var v2 = {
|
|
utils: {
|
|
getConversationKey,
|
|
calcPaddedLen
|
|
},
|
|
encrypt: encrypt3,
|
|
decrypt: decrypt3
|
|
};
|
|
|
|
// nip59.ts
|
|
var TWO_DAYS = 2 * 24 * 60 * 60;
|
|
var now = () => Math.round(Date.now() / 1e3);
|
|
var randomNow = () => Math.round(now() - Math.random() * TWO_DAYS);
|
|
var nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey);
|
|
var nip44Encrypt = (data, privateKey, publicKey) => encrypt3(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey));
|
|
var nip44Decrypt = (data, privateKey) => JSON.parse(decrypt3(data.content, nip44ConversationKey(privateKey, data.pubkey)));
|
|
function createRumor(event, privateKey) {
|
|
const rumor = {
|
|
created_at: now(),
|
|
content: "",
|
|
tags: [],
|
|
...event,
|
|
pubkey: getPublicKey(privateKey)
|
|
};
|
|
rumor.id = getEventHash(rumor);
|
|
return rumor;
|
|
}
|
|
function createSeal(rumor, privateKey, recipientPublicKey) {
|
|
return finalizeEvent(
|
|
{
|
|
kind: Seal,
|
|
content: nip44Encrypt(rumor, privateKey, recipientPublicKey),
|
|
created_at: randomNow(),
|
|
tags: []
|
|
},
|
|
privateKey
|
|
);
|
|
}
|
|
function createWrap(seal, recipientPublicKey) {
|
|
const randomKey = generateSecretKey();
|
|
return finalizeEvent(
|
|
{
|
|
kind: GiftWrap,
|
|
content: nip44Encrypt(seal, randomKey, recipientPublicKey),
|
|
created_at: randomNow(),
|
|
tags: [["p", recipientPublicKey]]
|
|
},
|
|
randomKey
|
|
);
|
|
}
|
|
function wrapEvent(event, senderPrivateKey, recipientPublicKey) {
|
|
const rumor = createRumor(event, senderPrivateKey);
|
|
const seal = createSeal(rumor, senderPrivateKey, recipientPublicKey);
|
|
return createWrap(seal, recipientPublicKey);
|
|
}
|
|
function wrapManyEvents(event, senderPrivateKey, recipientsPublicKeys) {
|
|
if (!recipientsPublicKeys || recipientsPublicKeys.length === 0) {
|
|
throw new Error("At least one recipient is required.");
|
|
}
|
|
const senderPublicKey = getPublicKey(senderPrivateKey);
|
|
const wrappeds = [wrapEvent(event, senderPrivateKey, senderPublicKey)];
|
|
recipientsPublicKeys.forEach((recipientPublicKey) => {
|
|
wrappeds.push(wrapEvent(event, senderPrivateKey, recipientPublicKey));
|
|
});
|
|
return wrappeds;
|
|
}
|
|
function unwrapEvent(wrap, recipientPrivateKey) {
|
|
const unwrappedSeal = nip44Decrypt(wrap, recipientPrivateKey);
|
|
return nip44Decrypt(unwrappedSeal, recipientPrivateKey);
|
|
}
|
|
function unwrapManyEvents(wrappedEvents, recipientPrivateKey) {
|
|
let unwrappedEvents = [];
|
|
wrappedEvents.forEach((e) => {
|
|
unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey));
|
|
});
|
|
unwrappedEvents.sort((a, b) => a.created_at - b.created_at);
|
|
return unwrappedEvents;
|
|
}
|
|
|
|
// nip17.ts
|
|
function createEvent(recipients, message, conversationTitle, replyTo) {
|
|
const baseEvent = {
|
|
created_at: Math.ceil(Date.now() / 1e3),
|
|
kind: PrivateDirectMessage,
|
|
tags: [],
|
|
content: message
|
|
};
|
|
const recipientsArray = Array.isArray(recipients) ? recipients : [recipients];
|
|
recipientsArray.forEach(({ publicKey, relayUrl }) => {
|
|
baseEvent.tags.push(relayUrl ? ["p", publicKey, relayUrl] : ["p", publicKey]);
|
|
});
|
|
if (replyTo) {
|
|
baseEvent.tags.push(["e", replyTo.eventId, replyTo.relayUrl || "", "reply"]);
|
|
}
|
|
if (conversationTitle) {
|
|
baseEvent.tags.push(["subject", conversationTitle]);
|
|
}
|
|
return baseEvent;
|
|
}
|
|
function wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo) {
|
|
const event = createEvent(recipient, message, conversationTitle, replyTo);
|
|
return wrapEvent(event, senderPrivateKey, recipient.publicKey);
|
|
}
|
|
function wrapManyEvents2(senderPrivateKey, recipients, message, conversationTitle, replyTo) {
|
|
if (!recipients || recipients.length === 0) {
|
|
throw new Error("At least one recipient is required.");
|
|
}
|
|
const senderPublicKey = getPublicKey(senderPrivateKey);
|
|
return [{ publicKey: senderPublicKey }, ...recipients].map(
|
|
(recipient) => wrapEvent2(senderPrivateKey, recipient, message, conversationTitle, replyTo)
|
|
);
|
|
}
|
|
var unwrapEvent2 = unwrapEvent;
|
|
var unwrapManyEvents2 = unwrapManyEvents;
|
|
|
|
// nip18.ts
|
|
var nip18_exports = {};
|
|
__export(nip18_exports, {
|
|
finishRepostEvent: () => finishRepostEvent,
|
|
getRepostedEvent: () => getRepostedEvent,
|
|
getRepostedEventPointer: () => getRepostedEventPointer
|
|
});
|
|
function finishRepostEvent(t, reposted, relayUrl, privateKey) {
|
|
let kind;
|
|
const tags = [...t.tags ?? [], ["e", reposted.id, relayUrl], ["p", reposted.pubkey]];
|
|
if (reposted.kind === ShortTextNote) {
|
|
kind = Repost;
|
|
} else {
|
|
kind = GenericRepost;
|
|
tags.push(["k", String(reposted.kind)]);
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind,
|
|
tags,
|
|
content: t.content === "" || reposted.tags?.find((tag) => tag[0] === "-") ? "" : JSON.stringify(reposted),
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
}
|
|
function getRepostedEventPointer(event) {
|
|
if (![Repost, GenericRepost].includes(event.kind)) {
|
|
return void 0;
|
|
}
|
|
let lastETag;
|
|
let lastPTag;
|
|
for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {
|
|
const tag = event.tags[i2];
|
|
if (tag.length >= 2) {
|
|
if (tag[0] === "e" && lastETag === void 0) {
|
|
lastETag = tag;
|
|
} else if (tag[0] === "p" && lastPTag === void 0) {
|
|
lastPTag = tag;
|
|
}
|
|
}
|
|
}
|
|
if (lastETag === void 0) {
|
|
return void 0;
|
|
}
|
|
return {
|
|
id: lastETag[1],
|
|
relays: [lastETag[2], lastPTag?.[2]].filter((x) => typeof x === "string"),
|
|
author: lastPTag?.[1]
|
|
};
|
|
}
|
|
function getRepostedEvent(event, { skipVerification } = {}) {
|
|
const pointer = getRepostedEventPointer(event);
|
|
if (pointer === void 0 || event.content === "") {
|
|
return void 0;
|
|
}
|
|
let repostedEvent;
|
|
try {
|
|
repostedEvent = JSON.parse(event.content);
|
|
} catch (error) {
|
|
return void 0;
|
|
}
|
|
if (repostedEvent.id !== pointer.id) {
|
|
return void 0;
|
|
}
|
|
if (!skipVerification && !verifyEvent(repostedEvent)) {
|
|
return void 0;
|
|
}
|
|
return repostedEvent;
|
|
}
|
|
|
|
// nip21.ts
|
|
var nip21_exports = {};
|
|
__export(nip21_exports, {
|
|
NOSTR_URI_REGEX: () => NOSTR_URI_REGEX,
|
|
parse: () => parse2,
|
|
test: () => test
|
|
});
|
|
var NOSTR_URI_REGEX = new RegExp(`nostr:(${BECH32_REGEX.source})`);
|
|
function test(value) {
|
|
return typeof value === "string" && new RegExp(`^${NOSTR_URI_REGEX.source}$`).test(value);
|
|
}
|
|
function parse2(uri) {
|
|
const match = uri.match(new RegExp(`^${NOSTR_URI_REGEX.source}$`));
|
|
if (!match)
|
|
throw new Error(`Invalid Nostr URI: ${uri}`);
|
|
return {
|
|
uri: match[0],
|
|
value: match[1],
|
|
decoded: decode(match[1])
|
|
};
|
|
}
|
|
|
|
// nip25.ts
|
|
var nip25_exports = {};
|
|
__export(nip25_exports, {
|
|
finishReactionEvent: () => finishReactionEvent,
|
|
getReactedEventPointer: () => getReactedEventPointer
|
|
});
|
|
function finishReactionEvent(t, reacted, privateKey) {
|
|
const inheritedTags = reacted.tags.filter((tag) => tag.length >= 2 && (tag[0] === "e" || tag[0] === "p"));
|
|
return finalizeEvent(
|
|
{
|
|
...t,
|
|
kind: Reaction,
|
|
tags: [...t.tags ?? [], ...inheritedTags, ["e", reacted.id], ["p", reacted.pubkey]],
|
|
content: t.content ?? "+"
|
|
},
|
|
privateKey
|
|
);
|
|
}
|
|
function getReactedEventPointer(event) {
|
|
if (event.kind !== Reaction) {
|
|
return void 0;
|
|
}
|
|
let lastETag;
|
|
let lastPTag;
|
|
for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {
|
|
const tag = event.tags[i2];
|
|
if (tag.length >= 2) {
|
|
if (tag[0] === "e" && lastETag === void 0) {
|
|
lastETag = tag;
|
|
} else if (tag[0] === "p" && lastPTag === void 0) {
|
|
lastPTag = tag;
|
|
}
|
|
}
|
|
}
|
|
if (lastETag === void 0 || lastPTag === void 0) {
|
|
return void 0;
|
|
}
|
|
return {
|
|
id: lastETag[1],
|
|
relays: [lastETag[2], lastPTag[2]].filter((x) => x !== void 0),
|
|
author: lastPTag[1]
|
|
};
|
|
}
|
|
|
|
// nip27.ts
|
|
var nip27_exports = {};
|
|
__export(nip27_exports, {
|
|
parse: () => parse3
|
|
});
|
|
var noCharacter = /\W/m;
|
|
var noURLCharacter = /\W |\W$|$|,| /m;
|
|
function* parse3(content) {
|
|
const max = content.length;
|
|
let prevIndex = 0;
|
|
let index = 0;
|
|
while (index < max) {
|
|
let u = content.indexOf(":", index);
|
|
if (u === -1) {
|
|
break;
|
|
}
|
|
if (content.substring(u - 5, u) === "nostr") {
|
|
const m = content.substring(u + 60).match(noCharacter);
|
|
const end = m ? u + 60 + m.index : max;
|
|
try {
|
|
let pointer;
|
|
let { data, type } = decode(content.substring(u + 1, end));
|
|
switch (type) {
|
|
case "npub":
|
|
pointer = { pubkey: data };
|
|
break;
|
|
case "nsec":
|
|
case "note":
|
|
index = end + 1;
|
|
continue;
|
|
default:
|
|
pointer = data;
|
|
}
|
|
if (prevIndex !== u - 5) {
|
|
yield { type: "text", text: content.substring(prevIndex, u - 5) };
|
|
}
|
|
yield { type: "reference", pointer };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
} catch (_err) {
|
|
index = u + 1;
|
|
continue;
|
|
}
|
|
} else if (content.substring(u - 5, u) === "https" || content.substring(u - 4, u) === "http") {
|
|
const m = content.substring(u + 4).match(noURLCharacter);
|
|
const end = m ? u + 4 + m.index : max;
|
|
const prefixLen = content[u - 1] === "s" ? 5 : 4;
|
|
try {
|
|
let url = new URL(content.substring(u - prefixLen, end));
|
|
if (url.hostname.indexOf(".") === -1) {
|
|
throw new Error("invalid url");
|
|
}
|
|
if (prevIndex !== u - prefixLen) {
|
|
yield { type: "text", text: content.substring(prevIndex, u - prefixLen) };
|
|
}
|
|
if (/\.(png|jpe?g|gif|webp)$/i.test(url.pathname)) {
|
|
yield { type: "image", url: url.toString() };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
}
|
|
if (/\.(mp4|avi|webm|mkv)$/i.test(url.pathname)) {
|
|
yield { type: "video", url: url.toString() };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
}
|
|
if (/\.(mp3|aac|ogg|opus)$/i.test(url.pathname)) {
|
|
yield { type: "audio", url: url.toString() };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
}
|
|
yield { type: "url", url: url.toString() };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
} catch (_err) {
|
|
index = end + 1;
|
|
continue;
|
|
}
|
|
} else if (content.substring(u - 3, u) === "wss" || content.substring(u - 2, u) === "ws") {
|
|
const m = content.substring(u + 4).match(noURLCharacter);
|
|
const end = m ? u + 4 + m.index : max;
|
|
const prefixLen = content[u - 1] === "s" ? 3 : 2;
|
|
try {
|
|
let url = new URL(content.substring(u - prefixLen, end));
|
|
if (url.hostname.indexOf(".") === -1) {
|
|
throw new Error("invalid ws url");
|
|
}
|
|
if (prevIndex !== u - prefixLen) {
|
|
yield { type: "text", text: content.substring(prevIndex, u - prefixLen) };
|
|
}
|
|
yield { type: "relay", url: url.toString() };
|
|
index = end;
|
|
prevIndex = index;
|
|
continue;
|
|
} catch (_err) {
|
|
index = end + 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
index = u + 1;
|
|
continue;
|
|
}
|
|
}
|
|
if (prevIndex !== max) {
|
|
yield { type: "text", text: content.substring(prevIndex) };
|
|
}
|
|
}
|
|
|
|
// nip28.ts
|
|
var nip28_exports = {};
|
|
__export(nip28_exports, {
|
|
channelCreateEvent: () => channelCreateEvent,
|
|
channelHideMessageEvent: () => channelHideMessageEvent,
|
|
channelMessageEvent: () => channelMessageEvent,
|
|
channelMetadataEvent: () => channelMetadataEvent,
|
|
channelMuteUserEvent: () => channelMuteUserEvent
|
|
});
|
|
var channelCreateEvent = (t, privateKey) => {
|
|
let content;
|
|
if (typeof t.content === "object") {
|
|
content = JSON.stringify(t.content);
|
|
} else if (typeof t.content === "string") {
|
|
content = t.content;
|
|
} else {
|
|
return void 0;
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind: ChannelCreation,
|
|
tags: [...t.tags ?? []],
|
|
content,
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
};
|
|
var channelMetadataEvent = (t, privateKey) => {
|
|
let content;
|
|
if (typeof t.content === "object") {
|
|
content = JSON.stringify(t.content);
|
|
} else if (typeof t.content === "string") {
|
|
content = t.content;
|
|
} else {
|
|
return void 0;
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind: ChannelMetadata,
|
|
tags: [["e", t.channel_create_event_id], ...t.tags ?? []],
|
|
content,
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
};
|
|
var channelMessageEvent = (t, privateKey) => {
|
|
const tags = [["e", t.channel_create_event_id, t.relay_url, "root"]];
|
|
if (t.reply_to_channel_message_event_id) {
|
|
tags.push(["e", t.reply_to_channel_message_event_id, t.relay_url, "reply"]);
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind: ChannelMessage,
|
|
tags: [...tags, ...t.tags ?? []],
|
|
content: t.content,
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
};
|
|
var channelHideMessageEvent = (t, privateKey) => {
|
|
let content;
|
|
if (typeof t.content === "object") {
|
|
content = JSON.stringify(t.content);
|
|
} else if (typeof t.content === "string") {
|
|
content = t.content;
|
|
} else {
|
|
return void 0;
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind: ChannelHideMessage,
|
|
tags: [["e", t.channel_message_event_id], ...t.tags ?? []],
|
|
content,
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
};
|
|
var channelMuteUserEvent = (t, privateKey) => {
|
|
let content;
|
|
if (typeof t.content === "object") {
|
|
content = JSON.stringify(t.content);
|
|
} else if (typeof t.content === "string") {
|
|
content = t.content;
|
|
} else {
|
|
return void 0;
|
|
}
|
|
return finalizeEvent(
|
|
{
|
|
kind: ChannelMuteUser,
|
|
tags: [["p", t.pubkey_to_mute], ...t.tags ?? []],
|
|
content,
|
|
created_at: t.created_at
|
|
},
|
|
privateKey
|
|
);
|
|
};
|
|
|
|
// nip30.ts
|
|
var nip30_exports = {};
|
|
__export(nip30_exports, {
|
|
EMOJI_SHORTCODE_REGEX: () => EMOJI_SHORTCODE_REGEX,
|
|
matchAll: () => matchAll,
|
|
regex: () => regex,
|
|
replaceAll: () => replaceAll
|
|
});
|
|
var EMOJI_SHORTCODE_REGEX = /:(\w+):/;
|
|
var regex = () => new RegExp(`\\B${EMOJI_SHORTCODE_REGEX.source}\\B`, "g");
|
|
function* matchAll(content) {
|
|
const matches = content.matchAll(regex());
|
|
for (const match of matches) {
|
|
try {
|
|
const [shortcode, name] = match;
|
|
yield {
|
|
shortcode,
|
|
name,
|
|
start: match.index,
|
|
end: match.index + shortcode.length
|
|
};
|
|
} catch (_e) {
|
|
}
|
|
}
|
|
}
|
|
function replaceAll(content, replacer) {
|
|
return content.replaceAll(regex(), (shortcode, name) => {
|
|
return replacer({
|
|
shortcode,
|
|
name
|
|
});
|
|
});
|
|
}
|
|
|
|
// nip39.ts
|
|
var nip39_exports = {};
|
|
__export(nip39_exports, {
|
|
useFetchImplementation: () => useFetchImplementation3,
|
|
validateGithub: () => validateGithub
|
|
});
|
|
var _fetch3;
|
|
try {
|
|
_fetch3 = fetch;
|
|
} catch {
|
|
}
|
|
function useFetchImplementation3(fetchImplementation) {
|
|
_fetch3 = fetchImplementation;
|
|
}
|
|
async function validateGithub(pubkey, username, proof) {
|
|
try {
|
|
let res = await (await _fetch3(`https://gist.github.com/${username}/${proof}/raw`)).text();
|
|
return res === `Verifying that I control the following Nostr public key: ${pubkey}`;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// nip46.ts
|
|
var nip46_exports = {};
|
|
__export(nip46_exports, {
|
|
BUNKER_REGEX: () => BUNKER_REGEX,
|
|
BunkerSigner: () => BunkerSigner,
|
|
createAccount: () => createAccount,
|
|
createNostrConnectURI: () => createNostrConnectURI,
|
|
fetchBunkerProviders: () => fetchBunkerProviders,
|
|
parseBunkerInput: () => parseBunkerInput,
|
|
parseNostrConnectURI: () => parseNostrConnectURI,
|
|
queryBunkerProfile: () => queryBunkerProfile,
|
|
toBunkerURL: () => toBunkerURL,
|
|
useFetchImplementation: () => useFetchImplementation4
|
|
});
|
|
var _fetch4;
|
|
try {
|
|
_fetch4 = fetch;
|
|
} catch {
|
|
}
|
|
function useFetchImplementation4(fetchImplementation) {
|
|
_fetch4 = fetchImplementation;
|
|
}
|
|
var BUNKER_REGEX = /^bunker:\/\/([0-9a-f]{64})\??([?\/\w:.=&%-]*)$/;
|
|
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
function toBunkerURL(bunkerPointer) {
|
|
let bunkerURL = new URL(`bunker://${bunkerPointer.pubkey}`);
|
|
bunkerPointer.relays.forEach((relay) => {
|
|
bunkerURL.searchParams.append("relay", relay);
|
|
});
|
|
if (bunkerPointer.secret) {
|
|
bunkerURL.searchParams.set("secret", bunkerPointer.secret);
|
|
}
|
|
return bunkerURL.toString();
|
|
}
|
|
async function parseBunkerInput(input) {
|
|
let match = input.match(BUNKER_REGEX);
|
|
if (match) {
|
|
try {
|
|
const pubkey = match[1];
|
|
const qs = new URLSearchParams(match[2]);
|
|
return {
|
|
pubkey,
|
|
relays: qs.getAll("relay"),
|
|
secret: qs.get("secret")
|
|
};
|
|
} catch (_err) {
|
|
}
|
|
}
|
|
return queryBunkerProfile(input);
|
|
}
|
|
async function queryBunkerProfile(nip05) {
|
|
const match = nip05.match(NIP05_REGEX);
|
|
if (!match)
|
|
return null;
|
|
const [_, name = "_", domain] = match;
|
|
try {
|
|
const url = `https://${domain}/.well-known/nostr.json?name=${name}`;
|
|
const res = await (await _fetch4(url, { redirect: "error" })).json();
|
|
let pubkey = res.names[name];
|
|
let relays = res.nip46[pubkey] || [];
|
|
return { pubkey, relays, secret: null };
|
|
} catch (_err) {
|
|
return null;
|
|
}
|
|
}
|
|
function createNostrConnectURI(params) {
|
|
if (!params.clientPubkey) {
|
|
throw new Error("clientPubkey is required.");
|
|
}
|
|
if (!params.relays || params.relays.length === 0) {
|
|
throw new Error("At least one relay is required.");
|
|
}
|
|
if (!params.secret) {
|
|
throw new Error("secret is required.");
|
|
}
|
|
const queryParams = new URLSearchParams();
|
|
params.relays.forEach((relay) => {
|
|
queryParams.append("relay", relay);
|
|
});
|
|
queryParams.append("secret", params.secret);
|
|
if (params.perms && params.perms.length > 0) {
|
|
queryParams.append("perms", params.perms.join(","));
|
|
}
|
|
if (params.name) {
|
|
queryParams.append("name", params.name);
|
|
}
|
|
if (params.url) {
|
|
queryParams.append("url", params.url);
|
|
}
|
|
if (params.image) {
|
|
queryParams.append("image", params.image);
|
|
}
|
|
return `nostrconnect://${params.clientPubkey}?${queryParams.toString()}`;
|
|
}
|
|
function parseNostrConnectURI(uri) {
|
|
if (!uri.startsWith("nostrconnect://")) {
|
|
throw new Error('Invalid nostrconnect URI: Must start with "nostrconnect://".');
|
|
}
|
|
const [protocolAndPubkey, queryString] = uri.split("?");
|
|
if (!protocolAndPubkey || !queryString) {
|
|
throw new Error("Invalid nostrconnect URI: Missing query string.");
|
|
}
|
|
const clientPubkey = protocolAndPubkey.substring("nostrconnect://".length);
|
|
if (!clientPubkey) {
|
|
throw new Error("Invalid nostrconnect URI: Missing client-pubkey.");
|
|
}
|
|
const queryParams = new URLSearchParams(queryString);
|
|
const relays = queryParams.getAll("relay");
|
|
if (relays.length === 0) {
|
|
throw new Error('Invalid nostrconnect URI: Missing "relay" parameter.');
|
|
}
|
|
const secret = queryParams.get("secret");
|
|
if (!secret) {
|
|
throw new Error('Invalid nostrconnect URI: Missing "secret" parameter.');
|
|
}
|
|
const permsString = queryParams.get("perms");
|
|
const perms = permsString ? permsString.split(",") : void 0;
|
|
const name = queryParams.get("name") || void 0;
|
|
const url = queryParams.get("url") || void 0;
|
|
const image = queryParams.get("image") || void 0;
|
|
return {
|
|
protocol: "nostrconnect",
|
|
clientPubkey,
|
|
params: {
|
|
relays,
|
|
secret,
|
|
perms,
|
|
name,
|
|
url,
|
|
image
|
|
},
|
|
originalString: uri
|
|
};
|
|
}
|
|
var BunkerSigner = class {
|
|
params;
|
|
pool;
|
|
subCloser;
|
|
isOpen;
|
|
serial;
|
|
idPrefix;
|
|
listeners;
|
|
waitingForAuth;
|
|
secretKey;
|
|
conversationKey;
|
|
bp;
|
|
cachedPubKey;
|
|
constructor(clientSecretKey, params) {
|
|
this.params = params;
|
|
this.pool = params.pool || new SimplePool();
|
|
this.secretKey = clientSecretKey;
|
|
this.isOpen = false;
|
|
this.idPrefix = Math.random().toString(36).substring(7);
|
|
this.serial = 0;
|
|
this.listeners = {};
|
|
this.waitingForAuth = {};
|
|
}
|
|
static fromBunker(clientSecretKey, bp, params = {}) {
|
|
if (bp.relays.length === 0) {
|
|
throw new Error("No relays specified for this bunker");
|
|
}
|
|
const signer = new BunkerSigner(clientSecretKey, params);
|
|
signer.conversationKey = getConversationKey(clientSecretKey, bp.pubkey);
|
|
signer.bp = bp;
|
|
signer.setupSubscription(params);
|
|
return signer;
|
|
}
|
|
static async fromURI(clientSecretKey, connectionURI, params = {}, maxWait = 3e5) {
|
|
const signer = new BunkerSigner(clientSecretKey, params);
|
|
const parsedURI = parseNostrConnectURI(connectionURI);
|
|
const clientPubkey = getPublicKey(clientSecretKey);
|
|
return new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => {
|
|
sub.close();
|
|
reject(new Error(`Connection timed out after ${maxWait / 1e3} seconds`));
|
|
}, maxWait);
|
|
const sub = signer.pool.subscribe(
|
|
parsedURI.params.relays,
|
|
{ kinds: [NostrConnect], "#p": [clientPubkey] },
|
|
{
|
|
onevent: async (event) => {
|
|
try {
|
|
const tempConvKey = getConversationKey(clientSecretKey, event.pubkey);
|
|
const decryptedContent = decrypt3(event.content, tempConvKey);
|
|
const response = JSON.parse(decryptedContent);
|
|
if (response.result === parsedURI.params.secret) {
|
|
clearTimeout(timer);
|
|
sub.close();
|
|
signer.bp = {
|
|
pubkey: event.pubkey,
|
|
relays: parsedURI.params.relays,
|
|
secret: parsedURI.params.secret
|
|
};
|
|
signer.conversationKey = getConversationKey(clientSecretKey, event.pubkey);
|
|
signer.setupSubscription(params);
|
|
resolve(signer);
|
|
}
|
|
} catch (e) {
|
|
console.warn("Failed to process potential connection event", e);
|
|
}
|
|
},
|
|
onclose: () => {
|
|
clearTimeout(timer);
|
|
reject(new Error("Subscription closed before connection was established."));
|
|
},
|
|
maxWait
|
|
}
|
|
);
|
|
});
|
|
}
|
|
setupSubscription(params) {
|
|
const listeners = this.listeners;
|
|
const waitingForAuth = this.waitingForAuth;
|
|
const convKey = this.conversationKey;
|
|
this.subCloser = this.pool.subscribe(
|
|
this.bp.relays,
|
|
{ kinds: [NostrConnect], authors: [this.bp.pubkey], "#p": [getPublicKey(this.secretKey)] },
|
|
{
|
|
onevent: async (event) => {
|
|
const o = JSON.parse(decrypt3(event.content, convKey));
|
|
const { id, result, error } = o;
|
|
if (result === "auth_url" && waitingForAuth[id]) {
|
|
delete waitingForAuth[id];
|
|
if (params.onauth) {
|
|
params.onauth(error);
|
|
} else {
|
|
console.warn(
|
|
`nostr-tools/nip46: remote signer ${this.bp.pubkey} tried to send an "auth_url"='${error}' but there was no onauth() callback configured.`
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
let handler = listeners[id];
|
|
if (handler) {
|
|
if (error)
|
|
handler.reject(error);
|
|
else if (result)
|
|
handler.resolve(result);
|
|
delete listeners[id];
|
|
}
|
|
},
|
|
onclose: () => {
|
|
this.subCloser = void 0;
|
|
}
|
|
}
|
|
);
|
|
this.isOpen = true;
|
|
}
|
|
async close() {
|
|
this.isOpen = false;
|
|
this.subCloser.close();
|
|
}
|
|
async sendRequest(method, params) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
if (!this.isOpen)
|
|
throw new Error("this signer is not open anymore, create a new one");
|
|
if (!this.subCloser)
|
|
this.setupSubscription(this.params);
|
|
this.serial++;
|
|
const id = `${this.idPrefix}-${this.serial}`;
|
|
const encryptedContent = encrypt3(JSON.stringify({ id, method, params }), this.conversationKey);
|
|
const verifiedEvent = finalizeEvent(
|
|
{
|
|
kind: NostrConnect,
|
|
tags: [["p", this.bp.pubkey]],
|
|
content: encryptedContent,
|
|
created_at: Math.floor(Date.now() / 1e3)
|
|
},
|
|
this.secretKey
|
|
);
|
|
this.listeners[id] = { resolve, reject };
|
|
this.waitingForAuth[id] = true;
|
|
await Promise.any(this.pool.publish(this.bp.relays, verifiedEvent));
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
});
|
|
}
|
|
async ping() {
|
|
let resp = await this.sendRequest("ping", []);
|
|
if (resp !== "pong")
|
|
throw new Error(`result is not pong: ${resp}`);
|
|
}
|
|
async connect() {
|
|
await this.sendRequest("connect", [this.bp.pubkey, this.bp.secret || ""]);
|
|
}
|
|
async getPublicKey() {
|
|
if (!this.cachedPubKey) {
|
|
this.cachedPubKey = await this.sendRequest("get_public_key", []);
|
|
}
|
|
return this.cachedPubKey;
|
|
}
|
|
async signEvent(event) {
|
|
let resp = await this.sendRequest("sign_event", [JSON.stringify(event)]);
|
|
let signed = JSON.parse(resp);
|
|
if (verifyEvent(signed)) {
|
|
return signed;
|
|
} else {
|
|
throw new Error(`event returned from bunker is improperly signed: ${JSON.stringify(signed)}`);
|
|
}
|
|
}
|
|
async nip04Encrypt(thirdPartyPubkey, plaintext) {
|
|
return await this.sendRequest("nip04_encrypt", [thirdPartyPubkey, plaintext]);
|
|
}
|
|
async nip04Decrypt(thirdPartyPubkey, ciphertext) {
|
|
return await this.sendRequest("nip04_decrypt", [thirdPartyPubkey, ciphertext]);
|
|
}
|
|
async nip44Encrypt(thirdPartyPubkey, plaintext) {
|
|
return await this.sendRequest("nip44_encrypt", [thirdPartyPubkey, plaintext]);
|
|
}
|
|
async nip44Decrypt(thirdPartyPubkey, ciphertext) {
|
|
return await this.sendRequest("nip44_decrypt", [thirdPartyPubkey, ciphertext]);
|
|
}
|
|
};
|
|
async function createAccount(bunker, params, username, domain, email, localSecretKey = generateSecretKey()) {
|
|
if (email && !EMAIL_REGEX.test(email))
|
|
throw new Error("Invalid email");
|
|
let rpc = BunkerSigner.fromBunker(localSecretKey, bunker.bunkerPointer, params);
|
|
let pubkey = await rpc.sendRequest("create_account", [username, domain, email || ""]);
|
|
rpc.bp.pubkey = pubkey;
|
|
await rpc.connect();
|
|
return rpc;
|
|
}
|
|
async function fetchBunkerProviders(pool, relays) {
|
|
const events = await pool.querySync(relays, {
|
|
kinds: [Handlerinformation],
|
|
"#k": [NostrConnect.toString()]
|
|
});
|
|
events.sort((a, b) => b.created_at - a.created_at);
|
|
const validatedBunkers = await Promise.all(
|
|
events.map(async (event, i2) => {
|
|
try {
|
|
const content = JSON.parse(event.content);
|
|
try {
|
|
if (events.findIndex((ev) => JSON.parse(ev.content).nip05 === content.nip05) !== i2)
|
|
return void 0;
|
|
} catch (err) {
|
|
}
|
|
const bp = await queryBunkerProfile(content.nip05);
|
|
if (bp && bp.pubkey === event.pubkey && bp.relays.length) {
|
|
return {
|
|
bunkerPointer: bp,
|
|
nip05: content.nip05,
|
|
domain: content.nip05.split("@")[1],
|
|
name: content.name || content.display_name,
|
|
picture: content.picture,
|
|
about: content.about,
|
|
website: content.website,
|
|
local: false
|
|
};
|
|
}
|
|
} catch (err) {
|
|
return void 0;
|
|
}
|
|
})
|
|
);
|
|
return validatedBunkers.filter((b) => b !== void 0);
|
|
}
|
|
|
|
// nip47.ts
|
|
var nip47_exports = {};
|
|
__export(nip47_exports, {
|
|
makeNwcRequestEvent: () => makeNwcRequestEvent,
|
|
parseConnectionString: () => parseConnectionString
|
|
});
|
|
function parseConnectionString(connectionString) {
|
|
const { host, pathname, searchParams } = new URL(connectionString);
|
|
const pubkey = pathname || host;
|
|
const relay = searchParams.get("relay");
|
|
const secret = searchParams.get("secret");
|
|
if (!pubkey || !relay || !secret) {
|
|
throw new Error("invalid connection string");
|
|
}
|
|
return { pubkey, relay, secret };
|
|
}
|
|
async function makeNwcRequestEvent(pubkey, secretKey, invoice) {
|
|
const content = {
|
|
method: "pay_invoice",
|
|
params: {
|
|
invoice
|
|
}
|
|
};
|
|
const encryptedContent = encrypt2(secretKey, pubkey, JSON.stringify(content));
|
|
const eventTemplate = {
|
|
kind: NWCWalletRequest,
|
|
created_at: Math.round(Date.now() / 1e3),
|
|
content: encryptedContent,
|
|
tags: [["p", pubkey]]
|
|
};
|
|
return finalizeEvent(eventTemplate, secretKey);
|
|
}
|
|
|
|
// nip54.ts
|
|
var nip54_exports = {};
|
|
__export(nip54_exports, {
|
|
normalizeIdentifier: () => normalizeIdentifier
|
|
});
|
|
function normalizeIdentifier(name) {
|
|
name = name.trim().toLowerCase();
|
|
name = name.normalize("NFKC");
|
|
return Array.from(name).map((char) => {
|
|
if (/\p{Letter}/u.test(char) || /\p{Number}/u.test(char)) {
|
|
return char;
|
|
}
|
|
return "-";
|
|
}).join("");
|
|
}
|
|
|
|
// nip57.ts
|
|
var nip57_exports = {};
|
|
__export(nip57_exports, {
|
|
getSatoshisAmountFromBolt11: () => getSatoshisAmountFromBolt11,
|
|
getZapEndpoint: () => getZapEndpoint,
|
|
makeZapReceipt: () => makeZapReceipt,
|
|
makeZapRequest: () => makeZapRequest,
|
|
useFetchImplementation: () => useFetchImplementation5,
|
|
validateZapRequest: () => validateZapRequest
|
|
});
|
|
var _fetch5;
|
|
try {
|
|
_fetch5 = fetch;
|
|
} catch {
|
|
}
|
|
function useFetchImplementation5(fetchImplementation) {
|
|
_fetch5 = fetchImplementation;
|
|
}
|
|
async function getZapEndpoint(metadata) {
|
|
try {
|
|
let lnurl = "";
|
|
let { lud06, lud16 } = JSON.parse(metadata.content);
|
|
if (lud06) {
|
|
let { words } = bech32.decode(lud06, 1e3);
|
|
let data = bech32.fromWords(words);
|
|
lnurl = utf8Decoder.decode(data);
|
|
} else if (lud16) {
|
|
let [name, domain] = lud16.split("@");
|
|
lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString();
|
|
} else {
|
|
return null;
|
|
}
|
|
let res = await _fetch5(lnurl);
|
|
let body = await res.json();
|
|
if (body.allowsNostr && body.nostrPubkey) {
|
|
return body.callback;
|
|
}
|
|
} catch (err) {
|
|
}
|
|
return null;
|
|
}
|
|
function makeZapRequest(params) {
|
|
let zr = {
|
|
kind: 9734,
|
|
created_at: Math.round(Date.now() / 1e3),
|
|
content: params.comment || "",
|
|
tags: [
|
|
["p", "pubkey" in params ? params.pubkey : params.event.pubkey],
|
|
["amount", params.amount.toString()],
|
|
["relays", ...params.relays]
|
|
]
|
|
};
|
|
if ("event" in params) {
|
|
zr.tags.push(["e", params.event.id]);
|
|
if (isReplaceableKind(params.event.kind)) {
|
|
const a = ["a", `${params.event.kind}:${params.event.pubkey}:`];
|
|
zr.tags.push(a);
|
|
} else if (isAddressableKind(params.event.kind)) {
|
|
let d = params.event.tags.find(([t, v]) => t === "d" && v);
|
|
if (!d)
|
|
throw new Error("d tag not found or is empty");
|
|
const a = ["a", `${params.event.kind}:${params.event.pubkey}:${d[1]}`];
|
|
zr.tags.push(a);
|
|
}
|
|
zr.tags.push(["k", params.event.kind.toString()]);
|
|
}
|
|
return zr;
|
|
}
|
|
function validateZapRequest(zapRequestString) {
|
|
let zapRequest;
|
|
try {
|
|
zapRequest = JSON.parse(zapRequestString);
|
|
} catch (err) {
|
|
return "Invalid zap request JSON.";
|
|
}
|
|
if (!validateEvent(zapRequest))
|
|
return "Zap request is not a valid Nostr event.";
|
|
if (!verifyEvent(zapRequest))
|
|
return "Invalid signature on zap request.";
|
|
let p = zapRequest.tags.find(([t, v]) => t === "p" && v);
|
|
if (!p)
|
|
return "Zap request doesn't have a 'p' tag.";
|
|
if (!p[1].match(/^[a-f0-9]{64}$/))
|
|
return "Zap request 'p' tag is not valid hex.";
|
|
let e = zapRequest.tags.find(([t, v]) => t === "e" && v);
|
|
if (e && !e[1].match(/^[a-f0-9]{64}$/))
|
|
return "Zap request 'e' tag is not valid hex.";
|
|
let relays = zapRequest.tags.find(([t, v]) => t === "relays" && v);
|
|
if (!relays)
|
|
return "Zap request doesn't have a 'relays' tag.";
|
|
return null;
|
|
}
|
|
function makeZapReceipt({
|
|
zapRequest,
|
|
preimage,
|
|
bolt11,
|
|
paidAt
|
|
}) {
|
|
let zr = JSON.parse(zapRequest);
|
|
let tagsFromZapRequest = zr.tags.filter(([t]) => t === "e" || t === "p" || t === "a");
|
|
let zap = {
|
|
kind: 9735,
|
|
created_at: Math.round(paidAt.getTime() / 1e3),
|
|
content: "",
|
|
tags: [...tagsFromZapRequest, ["P", zr.pubkey], ["bolt11", bolt11], ["description", zapRequest]]
|
|
};
|
|
if (preimage) {
|
|
zap.tags.push(["preimage", preimage]);
|
|
}
|
|
return zap;
|
|
}
|
|
function getSatoshisAmountFromBolt11(bolt11) {
|
|
if (bolt11.length < 50) {
|
|
return 0;
|
|
}
|
|
bolt11 = bolt11.substring(0, 50);
|
|
const idx = bolt11.lastIndexOf("1");
|
|
if (idx === -1) {
|
|
return 0;
|
|
}
|
|
const hrp = bolt11.substring(0, idx);
|
|
if (!hrp.startsWith("lnbc")) {
|
|
return 0;
|
|
}
|
|
const amount = hrp.substring(4);
|
|
if (amount.length < 1) {
|
|
return 0;
|
|
}
|
|
const char = amount[amount.length - 1];
|
|
const digit = char.charCodeAt(0) - "0".charCodeAt(0);
|
|
const isDigit = digit >= 0 && digit <= 9;
|
|
let cutPoint = amount.length - 1;
|
|
if (isDigit) {
|
|
cutPoint++;
|
|
}
|
|
if (cutPoint < 1) {
|
|
return 0;
|
|
}
|
|
const num = parseInt(amount.substring(0, cutPoint));
|
|
switch (char) {
|
|
case "m":
|
|
return num * 1e5;
|
|
case "u":
|
|
return num * 100;
|
|
case "n":
|
|
return num / 10;
|
|
case "p":
|
|
return num / 1e4;
|
|
default:
|
|
return num * 1e8;
|
|
}
|
|
}
|
|
|
|
// nip98.ts
|
|
var nip98_exports = {};
|
|
__export(nip98_exports, {
|
|
getToken: () => getToken,
|
|
hashPayload: () => hashPayload,
|
|
unpackEventFromToken: () => unpackEventFromToken,
|
|
validateEvent: () => validateEvent2,
|
|
validateEventKind: () => validateEventKind,
|
|
validateEventMethodTag: () => validateEventMethodTag,
|
|
validateEventPayloadTag: () => validateEventPayloadTag,
|
|
validateEventTimestamp: () => validateEventTimestamp,
|
|
validateEventUrlTag: () => validateEventUrlTag,
|
|
validateToken: () => validateToken
|
|
});
|
|
var _authorizationScheme = "Nostr ";
|
|
async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false, payload) {
|
|
const event = {
|
|
kind: HTTPAuth,
|
|
tags: [
|
|
["u", loginUrl],
|
|
["method", httpMethod]
|
|
],
|
|
created_at: Math.round(new Date().getTime() / 1e3),
|
|
content: ""
|
|
};
|
|
if (payload) {
|
|
event.tags.push(["payload", hashPayload(payload)]);
|
|
}
|
|
const signedEvent = await sign(event);
|
|
const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : "";
|
|
return authorizationScheme + base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
|
|
}
|
|
async function validateToken(token, url, method) {
|
|
const event = await unpackEventFromToken(token).catch((error) => {
|
|
throw error;
|
|
});
|
|
const valid = await validateEvent2(event, url, method).catch((error) => {
|
|
throw error;
|
|
});
|
|
return valid;
|
|
}
|
|
async function unpackEventFromToken(token) {
|
|
if (!token) {
|
|
throw new Error("Missing token");
|
|
}
|
|
token = token.replace(_authorizationScheme, "");
|
|
const eventB64 = utf8Decoder.decode(base64.decode(token));
|
|
if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith("{")) {
|
|
throw new Error("Invalid token");
|
|
}
|
|
const event = JSON.parse(eventB64);
|
|
return event;
|
|
}
|
|
function validateEventTimestamp(event) {
|
|
if (!event.created_at) {
|
|
return false;
|
|
}
|
|
return Math.round(new Date().getTime() / 1e3) - event.created_at < 60;
|
|
}
|
|
function validateEventKind(event) {
|
|
return event.kind === HTTPAuth;
|
|
}
|
|
function validateEventUrlTag(event, url) {
|
|
const urlTag = event.tags.find((t) => t[0] === "u");
|
|
if (!urlTag) {
|
|
return false;
|
|
}
|
|
return urlTag.length > 0 && urlTag[1] === url;
|
|
}
|
|
function validateEventMethodTag(event, method) {
|
|
const methodTag = event.tags.find((t) => t[0] === "method");
|
|
if (!methodTag) {
|
|
return false;
|
|
}
|
|
return methodTag.length > 0 && methodTag[1].toLowerCase() === method.toLowerCase();
|
|
}
|
|
function hashPayload(payload) {
|
|
const hash3 = sha2562(utf8Encoder.encode(JSON.stringify(payload)));
|
|
return bytesToHex2(hash3);
|
|
}
|
|
function validateEventPayloadTag(event, payload) {
|
|
const payloadTag = event.tags.find((t) => t[0] === "payload");
|
|
if (!payloadTag) {
|
|
return false;
|
|
}
|
|
const payloadHash = hashPayload(payload);
|
|
return payloadTag.length > 0 && payloadTag[1] === payloadHash;
|
|
}
|
|
async function validateEvent2(event, url, method, body) {
|
|
if (!verifyEvent(event)) {
|
|
throw new Error("Invalid nostr event, signature invalid");
|
|
}
|
|
if (!validateEventKind(event)) {
|
|
throw new Error("Invalid nostr event, kind invalid");
|
|
}
|
|
if (!validateEventTimestamp(event)) {
|
|
throw new Error("Invalid nostr event, created_at timestamp invalid");
|
|
}
|
|
if (!validateEventUrlTag(event, url)) {
|
|
throw new Error("Invalid nostr event, url tag invalid");
|
|
}
|
|
if (!validateEventMethodTag(event, method)) {
|
|
throw new Error("Invalid nostr event, method tag invalid");
|
|
}
|
|
if (Boolean(body) && typeof body === "object" && Object.keys(body).length > 0) {
|
|
if (!validateEventPayloadTag(event, body)) {
|
|
throw new Error("Invalid nostr event, payload tag does not match request body hash");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return __toCommonJS(nostr_tools_exports);
|
|
})();
|