@orangecheck/sdk 1.12.0 → 1.13.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 +9 -4
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +28 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { bech32 } from '@scure/base';
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
3
|
import { verifySignature as verifySignature$1, decodeAddress } from '@orangecheck/bip322';
|
|
4
|
+
import { hmac } from '@noble/hashes/hmac.js';
|
|
4
5
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
5
6
|
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
6
7
|
import { schnorr } from '@noble/curves/secp256k1.js';
|
|
@@ -1449,11 +1450,12 @@ async function verifyChallenge(opts) {
|
|
|
1449
1450
|
};
|
|
1450
1451
|
}
|
|
1451
1452
|
var HEADER = "orangecheck-bond";
|
|
1452
|
-
var ACK = "I
|
|
1453
|
+
var ACK = "I back this subject with this coin. It stays in my wallet.";
|
|
1453
1454
|
var FIELDS = ["address", "outpoint", "subject", "nonce", "issued_at", "expires_at"];
|
|
1454
1455
|
var BOND_SATS_FLOORS = [1e3, 1e4, 1e5, 1e6, 1e7];
|
|
1455
1456
|
var BOND_DAYS_FLOORS = [7, 30, 90, 365];
|
|
1456
1457
|
var BOND_MIN_CONFIRMATIONS = 6;
|
|
1458
|
+
var BOND_MAX_WINDOW_SECONDS = 3600;
|
|
1457
1459
|
var OUTPOINT_RE = /^[0-9a-f]{64}:(0|[1-9][0-9]{0,9})$/;
|
|
1458
1460
|
var NONCE_RE = /^[0-9a-f]{32}$/;
|
|
1459
1461
|
var TIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
|
|
@@ -1461,13 +1463,17 @@ var SUBJECT_RE = /^[\x21-\x7e]{1,256}$/;
|
|
|
1461
1463
|
function iso2(d) {
|
|
1462
1464
|
return d.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
1463
1465
|
}
|
|
1466
|
+
function instant(s) {
|
|
1467
|
+
const t = Date.parse(s);
|
|
1468
|
+
return TIME_RE.test(s) && Number.isFinite(t) && iso2(new Date(t)) === s;
|
|
1469
|
+
}
|
|
1464
1470
|
function randomNonce2() {
|
|
1465
1471
|
const b = new Uint8Array(16);
|
|
1466
1472
|
globalThis.crypto.getRandomValues(b);
|
|
1467
1473
|
return bytesToHex(b);
|
|
1468
1474
|
}
|
|
1469
1475
|
function wellFormed(f) {
|
|
1470
|
-
return decodeAddress(f.address) !== null && OUTPOINT_RE.test(f.outpoint) && SUBJECT_RE.test(f.subject) && NONCE_RE.test(f.nonce) &&
|
|
1476
|
+
return 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);
|
|
1471
1477
|
}
|
|
1472
1478
|
function buildBondMessage(fields) {
|
|
1473
1479
|
if (!wellFormed(fields)) throw new Error("bond fields are malformed");
|
|
@@ -1505,10 +1511,12 @@ function parseBondMessage(message) {
|
|
|
1505
1511
|
function bondId(message) {
|
|
1506
1512
|
return bytesToHex(sha256(utf8ToBytes(message)));
|
|
1507
1513
|
}
|
|
1508
|
-
function bondNullifier(audience, outpoint) {
|
|
1509
|
-
|
|
1514
|
+
function bondNullifier(key, audience, outpoint) {
|
|
1515
|
+
if (key.length < 32) throw new Error("bond nullifier key must be at least 32 bytes");
|
|
1516
|
+
const message = utf8ToBytes(`orangecheck-bond-nullifier
|
|
1510
1517
|
${audience}
|
|
1511
|
-
${outpoint}`)
|
|
1518
|
+
${outpoint}`);
|
|
1519
|
+
return bytesToHex(hmac(sha256, key, message));
|
|
1512
1520
|
}
|
|
1513
1521
|
function bondFloors(sats, ageBlocks) {
|
|
1514
1522
|
const days = Math.floor(ageBlocks / 144);
|
|
@@ -1521,6 +1529,10 @@ function verifyBondSignature(opts) {
|
|
|
1521
1529
|
if (opts.subject !== void 0 && fields.subject !== opts.subject) {
|
|
1522
1530
|
return { ok: false, reason: "bond_subject_mismatch" };
|
|
1523
1531
|
}
|
|
1532
|
+
const window2 = Date.parse(fields.expires_at) - Date.parse(fields.issued_at);
|
|
1533
|
+
if (window2 > (opts.maxWindowSeconds ?? BOND_MAX_WINDOW_SECONDS) * 1e3) {
|
|
1534
|
+
return { ok: false, reason: "bond_window_too_long" };
|
|
1535
|
+
}
|
|
1524
1536
|
const now = (opts.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
1525
1537
|
const skew = (opts.skewSeconds ?? 60) * 1e3;
|
|
1526
1538
|
if (Date.parse(fields.issued_at) - skew > now) return { ok: false, reason: "bond_not_yet_valid" };
|
|
@@ -1576,22 +1588,28 @@ async function verifyBond(opts) {
|
|
|
1576
1588
|
};
|
|
1577
1589
|
}
|
|
1578
1590
|
function esploraSource(base = "https://mempool.space/api", opts = {}) {
|
|
1579
|
-
const get = async (path) => {
|
|
1591
|
+
const get = async (path, missingOk = false) => {
|
|
1580
1592
|
const r = await (opts.fetch ?? fetch)(`${base}${path}`, {
|
|
1581
1593
|
signal: AbortSignal.timeout(opts.timeoutMs ?? 5e3)
|
|
1582
1594
|
});
|
|
1583
|
-
if (!r.ok && r.status
|
|
1595
|
+
if (!r.ok && !(missingOk && r.status === 404)) {
|
|
1596
|
+
throw new Error(`esplora ${path}: HTTP ${r.status}`);
|
|
1597
|
+
}
|
|
1584
1598
|
return r;
|
|
1585
1599
|
};
|
|
1586
1600
|
return {
|
|
1587
1601
|
async tip() {
|
|
1588
1602
|
const [h, hash] = await Promise.all([get("/blocks/tip/height"), get("/blocks/tip/hash")]);
|
|
1589
|
-
|
|
1603
|
+
const tip = { height: Number(await h.text()), hash: (await hash.text()).trim() };
|
|
1604
|
+
if (!Number.isSafeInteger(tip.height) || !/^[0-9a-f]{64}$/.test(tip.hash)) {
|
|
1605
|
+
throw new Error("esplora tip: malformed");
|
|
1606
|
+
}
|
|
1607
|
+
return tip;
|
|
1590
1608
|
},
|
|
1591
1609
|
async coin(outpoint) {
|
|
1592
1610
|
const [txid, voutStr] = outpoint.split(":");
|
|
1593
1611
|
const vout = Number(voutStr);
|
|
1594
|
-
const txr = await get(`/tx/${txid}
|
|
1612
|
+
const txr = await get(`/tx/${txid}`, true);
|
|
1595
1613
|
if (txr.status === 404) return null;
|
|
1596
1614
|
const tx = await txr.json();
|
|
1597
1615
|
const out = tx.vout[vout];
|
|
@@ -2395,6 +2413,6 @@ var STATUS_META = {
|
|
|
2395
2413
|
}
|
|
2396
2414
|
};
|
|
2397
2415
|
|
|
2398
|
-
export { BOND_DAYS_FLOORS, BOND_MIN_CONFIRMATIONS, BOND_SATS_FLOORS, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, bondFloors, bondId, bondNullifier, buildBondMessage, buildCanonicalMessage, check, checkBondCoin, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, esploraSource, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueBondMessage, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseBondMessage, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, requiresManualVerification, signNostrEvent, supportsAutomaticVerification, verify, verifyAllIdentities, verifyAttestationById, verifyBond, verifyBondSignature, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
|
|
2416
|
+
export { BOND_DAYS_FLOORS, BOND_MAX_WINDOW_SECONDS, BOND_MIN_CONFIRMATIONS, BOND_SATS_FLOORS, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, bondFloors, bondId, bondNullifier, buildBondMessage, buildCanonicalMessage, check, checkBondCoin, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, esploraSource, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueBondMessage, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseBondMessage, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, requiresManualVerification, signNostrEvent, supportsAutomaticVerification, verify, verifyAllIdentities, verifyAttestationById, verifyBond, verifyBondSignature, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
|
|
2399
2417
|
//# sourceMappingURL=index.mjs.map
|
|
2400
2418
|
//# sourceMappingURL=index.mjs.map
|