@orangecheck/sdk 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -6
- package/dist/attestation.js +3 -1
- package/dist/attestation.js.map +1 -1
- package/dist/attestation.mjs +3 -1
- package/dist/attestation.mjs.map +1 -1
- package/dist/identity.js +3 -1
- package/dist/identity.js.map +1 -1
- package/dist/identity.mjs +3 -1
- package/dist/identity.mjs.map +1 -1
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +31 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -11
- package/dist/index.mjs.map +1 -1
- package/dist/nostr.js +3 -1
- package/dist/nostr.js.map +1 -1
- package/dist/nostr.mjs +3 -1
- package/dist/nostr.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var base = require('@scure/base');
|
|
4
4
|
var buffer = require('buffer');
|
|
5
5
|
var bip322 = require('@orangecheck/bip322');
|
|
6
|
+
var hmac_js = require('@noble/hashes/hmac.js');
|
|
6
7
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
7
8
|
var utils_js = require('@noble/hashes/utils.js');
|
|
8
9
|
var secp256k1_js = require('@noble/curves/secp256k1.js');
|
|
@@ -219,7 +220,9 @@ var ATTESTATION_EVENT_KIND = 30078;
|
|
|
219
220
|
var DEFAULT_RELAYS = [
|
|
220
221
|
"wss://relay.damus.io",
|
|
221
222
|
"wss://nos.lol",
|
|
222
|
-
|
|
223
|
+
// relay.snort.social sat here until 2026-10-21. It now runs in memory: it
|
|
224
|
+
// answered OK true to family events and served none of them back.
|
|
225
|
+
"wss://nostr.oxtr.dev",
|
|
223
226
|
"wss://relay.ochk.io"
|
|
224
227
|
];
|
|
225
228
|
var FANOUT_DEADLINE_MS = 4e3;
|
|
@@ -1451,11 +1454,12 @@ async function verifyChallenge(opts) {
|
|
|
1451
1454
|
};
|
|
1452
1455
|
}
|
|
1453
1456
|
var HEADER = "orangecheck-bond";
|
|
1454
|
-
var ACK = "I
|
|
1457
|
+
var ACK = "I back this subject with this coin. It stays in my wallet.";
|
|
1455
1458
|
var FIELDS = ["address", "outpoint", "subject", "nonce", "issued_at", "expires_at"];
|
|
1456
1459
|
var BOND_SATS_FLOORS = [1e3, 1e4, 1e5, 1e6, 1e7];
|
|
1457
1460
|
var BOND_DAYS_FLOORS = [7, 30, 90, 365];
|
|
1458
1461
|
var BOND_MIN_CONFIRMATIONS = 6;
|
|
1462
|
+
var BOND_MAX_WINDOW_SECONDS = 3600;
|
|
1459
1463
|
var OUTPOINT_RE = /^[0-9a-f]{64}:(0|[1-9][0-9]{0,9})$/;
|
|
1460
1464
|
var NONCE_RE = /^[0-9a-f]{32}$/;
|
|
1461
1465
|
var TIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
|
|
@@ -1463,13 +1467,17 @@ var SUBJECT_RE = /^[\x21-\x7e]{1,256}$/;
|
|
|
1463
1467
|
function iso2(d) {
|
|
1464
1468
|
return d.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
1465
1469
|
}
|
|
1470
|
+
function instant(s) {
|
|
1471
|
+
const t = Date.parse(s);
|
|
1472
|
+
return TIME_RE.test(s) && Number.isFinite(t) && iso2(new Date(t)) === s;
|
|
1473
|
+
}
|
|
1466
1474
|
function randomNonce2() {
|
|
1467
1475
|
const b = new Uint8Array(16);
|
|
1468
1476
|
globalThis.crypto.getRandomValues(b);
|
|
1469
1477
|
return utils_js.bytesToHex(b);
|
|
1470
1478
|
}
|
|
1471
1479
|
function wellFormed(f) {
|
|
1472
|
-
return bip322.decodeAddress(f.address) !== null && OUTPOINT_RE.test(f.outpoint) && SUBJECT_RE.test(f.subject) && NONCE_RE.test(f.nonce) &&
|
|
1480
|
+
return bip322.decodeAddress(f.address) !== null && OUTPOINT_RE.test(f.outpoint) && SUBJECT_RE.test(f.subject) && NONCE_RE.test(f.nonce) && instant(f.issued_at) && instant(f.expires_at) && Date.parse(f.expires_at) > Date.parse(f.issued_at);
|
|
1473
1481
|
}
|
|
1474
1482
|
function buildBondMessage(fields) {
|
|
1475
1483
|
if (!wellFormed(fields)) throw new Error("bond fields are malformed");
|
|
@@ -1507,10 +1515,12 @@ function parseBondMessage(message) {
|
|
|
1507
1515
|
function bondId(message) {
|
|
1508
1516
|
return utils_js.bytesToHex(sha2_js.sha256(utils_js.utf8ToBytes(message)));
|
|
1509
1517
|
}
|
|
1510
|
-
function bondNullifier(audience, outpoint) {
|
|
1511
|
-
|
|
1518
|
+
function bondNullifier(key, audience, outpoint) {
|
|
1519
|
+
if (key.length < 32) throw new Error("bond nullifier key must be at least 32 bytes");
|
|
1520
|
+
const message = utils_js.utf8ToBytes(`orangecheck-bond-nullifier
|
|
1512
1521
|
${audience}
|
|
1513
|
-
${outpoint}`)
|
|
1522
|
+
${outpoint}`);
|
|
1523
|
+
return utils_js.bytesToHex(hmac_js.hmac(sha2_js.sha256, key, message));
|
|
1514
1524
|
}
|
|
1515
1525
|
function bondFloors(sats, ageBlocks) {
|
|
1516
1526
|
const days = Math.floor(ageBlocks / 144);
|
|
@@ -1523,6 +1533,10 @@ function verifyBondSignature(opts) {
|
|
|
1523
1533
|
if (opts.subject !== void 0 && fields.subject !== opts.subject) {
|
|
1524
1534
|
return { ok: false, reason: "bond_subject_mismatch" };
|
|
1525
1535
|
}
|
|
1536
|
+
const window2 = Date.parse(fields.expires_at) - Date.parse(fields.issued_at);
|
|
1537
|
+
if (window2 > (opts.maxWindowSeconds ?? BOND_MAX_WINDOW_SECONDS) * 1e3) {
|
|
1538
|
+
return { ok: false, reason: "bond_window_too_long" };
|
|
1539
|
+
}
|
|
1526
1540
|
const now = (opts.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
1527
1541
|
const skew = (opts.skewSeconds ?? 60) * 1e3;
|
|
1528
1542
|
if (Date.parse(fields.issued_at) - skew > now) return { ok: false, reason: "bond_not_yet_valid" };
|
|
@@ -1578,22 +1592,28 @@ async function verifyBond(opts) {
|
|
|
1578
1592
|
};
|
|
1579
1593
|
}
|
|
1580
1594
|
function esploraSource(base = "https://mempool.space/api", opts = {}) {
|
|
1581
|
-
const get = async (path) => {
|
|
1595
|
+
const get = async (path, missingOk = false) => {
|
|
1582
1596
|
const r = await (opts.fetch ?? fetch)(`${base}${path}`, {
|
|
1583
1597
|
signal: AbortSignal.timeout(opts.timeoutMs ?? 5e3)
|
|
1584
1598
|
});
|
|
1585
|
-
if (!r.ok && r.status
|
|
1599
|
+
if (!r.ok && !(missingOk && r.status === 404)) {
|
|
1600
|
+
throw new Error(`esplora ${path}: HTTP ${r.status}`);
|
|
1601
|
+
}
|
|
1586
1602
|
return r;
|
|
1587
1603
|
};
|
|
1588
1604
|
return {
|
|
1589
1605
|
async tip() {
|
|
1590
1606
|
const [h, hash] = await Promise.all([get("/blocks/tip/height"), get("/blocks/tip/hash")]);
|
|
1591
|
-
|
|
1607
|
+
const tip = { height: Number(await h.text()), hash: (await hash.text()).trim() };
|
|
1608
|
+
if (!Number.isSafeInteger(tip.height) || !/^[0-9a-f]{64}$/.test(tip.hash)) {
|
|
1609
|
+
throw new Error("esplora tip: malformed");
|
|
1610
|
+
}
|
|
1611
|
+
return tip;
|
|
1592
1612
|
},
|
|
1593
1613
|
async coin(outpoint) {
|
|
1594
1614
|
const [txid, voutStr] = outpoint.split(":");
|
|
1595
1615
|
const vout = Number(voutStr);
|
|
1596
|
-
const txr = await get(`/tx/${txid}
|
|
1616
|
+
const txr = await get(`/tx/${txid}`, true);
|
|
1597
1617
|
if (txr.status === 404) return null;
|
|
1598
1618
|
const tx = await txr.json();
|
|
1599
1619
|
const out = tx.vout[vout];
|
|
@@ -2398,6 +2418,7 @@ var STATUS_META = {
|
|
|
2398
2418
|
};
|
|
2399
2419
|
|
|
2400
2420
|
exports.BOND_DAYS_FLOORS = BOND_DAYS_FLOORS;
|
|
2421
|
+
exports.BOND_MAX_WINDOW_SECONDS = BOND_MAX_WINDOW_SECONDS;
|
|
2401
2422
|
exports.BOND_MIN_CONFIRMATIONS = BOND_MIN_CONFIRMATIONS;
|
|
2402
2423
|
exports.BOND_SATS_FLOORS = BOND_SATS_FLOORS;
|
|
2403
2424
|
exports.DEFAULT_RELAYS = DEFAULT_RELAYS;
|