@x1id/resolve 0.19.2 → 0.22.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.
@@ -0,0 +1,378 @@
1
+ /**
2
+ * TLD creator pricing (docs/specs/tld-creator-pricing.md): the SDK side of a
3
+ * TLD creator's own price table for names under their TLD.
4
+ *
5
+ * - `["ns_pricing", label]` holds a `NamespacePricing` account: a flat lamport
6
+ * price per length band (index = `tier_index(len)`: 0 = 1 char … 8 = 9 chars,
7
+ * 9 = 10+), written ONLY by the namespace creator via `set_namespace_pricing`.
8
+ * - `register_under_namespace_v2` (v1's accounts + the pricing PDA as the
9
+ * first remaining account) charges that band FLAT (no launch ramp) when
10
+ * the account exists, else the legacy root price (`Config.tier_lamports` ×
11
+ * the time/volume ramp), and refuses to charge more than the buyer's
12
+ * `max_price_lamports`.
13
+ * - The legacy `register_under_namespace` (v1) fails closed
14
+ * (`NamespacePricingRequiresV2`, 6117) on any TLD whose creator opted in.
15
+ *
16
+ * {@link quoteScopedName} reproduces the program's price selection exactly, so
17
+ * pass its `lamports` as `maxPriceLamports` to {@link buildRegisterUnderNamespaceV2Ix}.
18
+ *
19
+ * Hand-rolled like the rest of this package: no Anchor client, no
20
+ * `@solana/web3.js` import, no `@types/node`. PDAs are derived through an
21
+ * INJECTED `find_program_address` (see {@link PdaFinder}) because this package
22
+ * never hand-rolls the ed25519 on-curve check.
23
+ */
24
+ import { encodeBase58, decodeBase58_32 } from "./base58.js";
25
+ // ---------------------------------------------------------------------------
26
+ // constants (mirror programs/x1-handles/src/{lib,state}.rs)
27
+ // ---------------------------------------------------------------------------
28
+ /** Seed prefix of the `["ns_pricing", label]` PDA. */
29
+ export const NAMESPACE_PRICING_SEED = "ns_pricing";
30
+ /** `NAMESPACE_TIER_FLOOR_LAMPORTS`: every creator tier must be >= 1 XNT. */
31
+ export const NAMESPACE_TIER_FLOOR_LAMPORTS = 1000000000n;
32
+ /** `NAMESPACE_TIER_MAX_LAMPORTS`: every creator tier must be <= 100,000,000 XNT. */
33
+ export const NAMESPACE_TIER_MAX_LAMPORTS = 100000000n * 1000000000n;
34
+ /** Number of length bands (same banding as the root `Config.tier_lamports`). */
35
+ export const NAMESPACE_TIER_COUNT = 10;
36
+ /** `sha256("global:set_namespace_pricing")[0..8]`. */
37
+ export const SET_NAMESPACE_PRICING_DISCRIMINATOR = Uint8Array.from([
38
+ 245, 190, 192, 77, 94, 146, 50, 246,
39
+ ]);
40
+ /** `sha256("global:register_under_namespace_v2")[0..8]`. */
41
+ export const REGISTER_UNDER_NAMESPACE_V2_DISCRIMINATOR = Uint8Array.from([
42
+ 233, 132, 213, 179, 60, 113, 18, 247,
43
+ ]);
44
+ /** `sha256("account:NamespacePricing")[0..8]`. */
45
+ export const NAMESPACE_PRICING_ACCOUNT_DISCRIMINATOR = Uint8Array.from([
46
+ 197, 197, 26, 252, 150, 176, 211, 188,
47
+ ]);
48
+ /** `Namespace::PRICING_FLAG_EXT_OFFSET` — the one-byte "creator pricing is on"
49
+ * marker past the Anchor-allocated `Namespace` (8 + INIT_SPACE = 107). */
50
+ export const NAMESPACE_PRICING_MARKER_OFFSET = 107;
51
+ /** Program error codes added by this feature (6000 + variant index). */
52
+ export const NAMESPACE_PRICING_ERRORS = {
53
+ NamespacePricingMismatch: 6116,
54
+ NamespacePricingRequiresV2: 6117,
55
+ PriceExceedsMax: 6118,
56
+ NamespaceTierBelowFloor: 6119,
57
+ NamespaceTierAboveMax: 6120,
58
+ };
59
+ /** Anchor's `InstructionFallbackNotFound`: the deployed program does not know
60
+ * the instruction (i.e. it predates this feature). */
61
+ const ANCHOR_INSTRUCTION_FALLBACK_NOT_FOUND = 101;
62
+ // Root pricing curve — mirrors lib.rs `ramp_bps` / `quarters_elapsed` /
63
+ // `compute_price` / `price_now` exactly (same constants as app/src/lib/x1/pricing.ts).
64
+ const INTRO_START_BPS = 5000n;
65
+ const INTRO_STEP_BPS = 1250n;
66
+ const QUARTER_SECS = 91n * 24n * 60n * 60n;
67
+ const VOLUME_START_BPS = 5000n;
68
+ const VOLUME_STEP_BPS = 1250n;
69
+ const VOLUME_STEP_COUNT = 500n;
70
+ // Config byte offsets (state.rs): disc(8) admin(32) treasury(32) launch_ts(8)
71
+ // tier_lamports(80) nft_tier_lamports(80) total_handles_sold(8) ...
72
+ const CONFIG_LAUNCH_TS_OFFSET = 72;
73
+ const CONFIG_TIERS_OFFSET = 80;
74
+ const CONFIG_TOTAL_SOLD_OFFSET = 240;
75
+ const SYSTEM_PROGRAM = "11111111111111111111111111111111";
76
+ const TE = new TextEncoder();
77
+ // ---------------------------------------------------------------------------
78
+ // pure helpers
79
+ // ---------------------------------------------------------------------------
80
+ function toBytes32(v, what) {
81
+ if (typeof v === "string") {
82
+ const b = decodeBase58_32(v);
83
+ if (!b)
84
+ throw new Error(`${what} is not a valid base58 address`);
85
+ return b;
86
+ }
87
+ if (v.length !== 32)
88
+ throw new Error(`${what} must be exactly 32 bytes`);
89
+ return v;
90
+ }
91
+ function toBase58(v, what) {
92
+ return encodeBase58(toBytes32(v, what));
93
+ }
94
+ function key(pubkey, what, isSigner, isWritable) {
95
+ return { pubkey: toBase58(pubkey, what), isSigner, isWritable };
96
+ }
97
+ function borshString(s) {
98
+ const b = TE.encode(s);
99
+ const out = new Uint8Array(4 + b.length);
100
+ new DataView(out.buffer).setUint32(0, b.length, true);
101
+ out.set(b, 4);
102
+ return out;
103
+ }
104
+ function u64le(n) {
105
+ const out = new Uint8Array(8);
106
+ new DataView(out.buffer).setBigUint64(0, n, true);
107
+ return out;
108
+ }
109
+ function concat(...parts) {
110
+ const out = new Uint8Array(parts.reduce((a, p) => a + p.length, 0));
111
+ let o = 0;
112
+ for (const p of parts) {
113
+ out.set(p, o);
114
+ o += p.length;
115
+ }
116
+ return out;
117
+ }
118
+ /** lib.rs `tier_index`: 1 char -> 0 … 10+ -> 9 (0 clamps to 0). */
119
+ export function scopedTierIndex(len) {
120
+ return Math.min(Math.max(len, 1), 10) - 1;
121
+ }
122
+ /** lib.rs `price_now` (registration price), in bigint like the program's u128. */
123
+ export function rootPriceNow(tierLamports, launchTs, nowSecs, totalHandlesSold) {
124
+ const elapsed = nowSecs > launchTs ? nowSecs - launchTs : 0n;
125
+ const quarters = elapsed / QUARTER_SECS;
126
+ const ramp = (start, step, n) => {
127
+ const v = start + step * n;
128
+ return v > 10000n ? 10000n : v;
129
+ };
130
+ const timeBps = ramp(INTRO_START_BPS, INTRO_STEP_BPS, quarters);
131
+ const volumeBps = ramp(VOLUME_START_BPS, VOLUME_STEP_BPS, totalHandlesSold / VOLUME_STEP_COUNT);
132
+ return (tierLamports * timeBps * volumeBps) / 10000n / 10000n;
133
+ }
134
+ /** Problems with a creator tier table, or null when the program would accept
135
+ * it (exactly `validate_namespace_tiers`). */
136
+ export function namespaceTiersProblem(tiers) {
137
+ if (tiers.length !== NAMESPACE_TIER_COUNT)
138
+ return `expected ${NAMESPACE_TIER_COUNT} tiers, got ${tiers.length}`;
139
+ for (let i = 0; i < tiers.length; i++) {
140
+ const t = tiers[i];
141
+ if (t < NAMESPACE_TIER_FLOOR_LAMPORTS)
142
+ return `tier ${i} is below the 1 XNT protocol floor`;
143
+ if (t > NAMESPACE_TIER_MAX_LAMPORTS)
144
+ return `tier ${i} is above the 100,000,000 XNT protocol maximum`;
145
+ }
146
+ return null;
147
+ }
148
+ /** The seeds of `["ns_pricing", label]`. */
149
+ export function namespacePricingSeeds(label) {
150
+ return [TE.encode(NAMESPACE_PRICING_SEED), TE.encode(label)];
151
+ }
152
+ /** Derive the canonical `["ns_pricing", label]` PDA. */
153
+ export async function deriveNamespacePricingPda(label, programId, find) {
154
+ return find(namespacePricingSeeds(label), toBase58(programId, "programId"));
155
+ }
156
+ /**
157
+ * Decode a `NamespacePricing` account's raw data (discriminator included):
158
+ * disc(8) | version(u8) | bump(u8) | tier_lamports([u64;10]) | updated_at(i64)
159
+ * | label(String). Returns null when the bytes are not a `NamespacePricing`.
160
+ */
161
+ export function decodeNamespacePricing(data) {
162
+ if (data.length < 8 + 1 + 1 + 80 + 8 + 4)
163
+ return null;
164
+ for (let i = 0; i < 8; i++) {
165
+ if (data[i] !== NAMESPACE_PRICING_ACCOUNT_DISCRIMINATOR[i])
166
+ return null;
167
+ }
168
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
169
+ const tierLamports = [];
170
+ for (let i = 0; i < NAMESPACE_TIER_COUNT; i++)
171
+ tierLamports.push(dv.getBigUint64(10 + 8 * i, true));
172
+ const updatedAt = dv.getBigInt64(90, true);
173
+ const labelLen = dv.getUint32(98, true);
174
+ if (data.length < 102 + labelLen)
175
+ return null;
176
+ let label;
177
+ try {
178
+ label = new TextDecoder("utf-8", { fatal: true }).decode(data.subarray(102, 102 + labelLen));
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ return { version: data[8], bump: data[9], tierLamports, updatedAt, label };
184
+ }
185
+ /** Whether a raw `Namespace` account carries the "creator pricing is on"
186
+ * marker (any nonzero byte at offset 107; a shorter account = off). */
187
+ export function namespaceHasPricingMarker(namespaceData) {
188
+ const b = namespaceData[NAMESPACE_PRICING_MARKER_OFFSET];
189
+ return b !== undefined && b !== 0;
190
+ }
191
+ /**
192
+ * Build `set_namespace_pricing(label, tier_lamports)`. Accounts IN ORDER
193
+ * (`SetNamespacePricing`): creator(s,w), namespace(w), namespace_pricing(w),
194
+ * system_program. Validates the table client-side with the program's exact
195
+ * bounds so a bad table never reaches a wallet prompt.
196
+ */
197
+ export function buildSetNamespacePricingIx(p) {
198
+ const problem = namespaceTiersProblem(p.tierLamports);
199
+ if (problem)
200
+ throw new Error(problem);
201
+ return {
202
+ programId: toBase58(p.programId, "programId"),
203
+ keys: [
204
+ key(p.creator, "creator", true, true),
205
+ key(p.namespace, "namespace", false, true),
206
+ key(p.namespacePricing, "namespacePricing", false, true),
207
+ key(SYSTEM_PROGRAM, "systemProgram", false, false),
208
+ ],
209
+ data: concat(SET_NAMESPACE_PRICING_DISCRIMINATOR, borshString(p.label), ...p.tierLamports.map(u64le)),
210
+ };
211
+ }
212
+ const TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
213
+ const ASSOCIATED_TOKEN_PROGRAM = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
214
+ const TOKEN_METADATA_PROGRAM = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
215
+ const SYSVAR_INSTRUCTIONS = "Sysvar1nstructions1111111111111111111111111";
216
+ /**
217
+ * Build `register_under_namespace_v2(name, handle_type, max_price_lamports)`.
218
+ * Accounts IN ORDER: the exact v1 `RegisterUnderNamespace` list (payer(s,w),
219
+ * owner, config(w), treasury(w), namespace, creator_payout(w), handle(w),
220
+ * mint(w), owner_token_account(w), metadata(w), master_edition(w),
221
+ * token_record(w), collection_mint, collection_metadata(w),
222
+ * collection_master_edition, collection_authority, token_metadata_program,
223
+ * token_program, associated_token_program, system_program,
224
+ * sysvar_instructions), then the three optional slots ALWAYS present
225
+ * (integrator, integrator_allowlist, minter_authorization — each the program
226
+ * id when absent, Anchor's "explicitly None"), then `namespace_pricing` as
227
+ * `remaining_accounts[0]`. The program fails closed if it is missing or
228
+ * shifted.
229
+ */
230
+ export function buildRegisterUnderNamespaceV2Ix(p) {
231
+ if (!Number.isInteger(p.handleType) || p.handleType < 0 || p.handleType > 3) {
232
+ throw new Error("handleType must be 0 (Human), 1 (Merchant), 2 (Org) or 3 (Agent)");
233
+ }
234
+ if (typeof p.maxPriceLamports !== "bigint" || p.maxPriceLamports < 0n || p.maxPriceLamports > 0xffffffffffffffffn) {
235
+ throw new Error("maxPriceLamports must be a u64 bigint");
236
+ }
237
+ if ((p.integrator === undefined) !== (p.integratorAllowlist === undefined)) {
238
+ throw new Error("integrator and integratorAllowlist must be supplied together");
239
+ }
240
+ const programId = toBase58(p.programId, "programId");
241
+ const none = () => ({ pubkey: programId, isSigner: false, isWritable: false });
242
+ const keys = [
243
+ key(p.payer, "payer", true, true),
244
+ key(p.owner, "owner", false, false),
245
+ key(p.config, "config", false, true),
246
+ key(p.treasury, "treasury", false, true),
247
+ key(p.namespace, "namespace", false, false),
248
+ key(p.creatorPayout, "creatorPayout", false, true),
249
+ key(p.handle, "handle", false, true),
250
+ key(p.mint, "mint", false, true),
251
+ key(p.ownerTokenAccount, "ownerTokenAccount", false, true),
252
+ key(p.metadata, "metadata", false, true),
253
+ key(p.masterEdition, "masterEdition", false, true),
254
+ key(p.tokenRecord, "tokenRecord", false, true),
255
+ key(p.collectionMint, "collectionMint", false, false),
256
+ key(p.collectionMetadata, "collectionMetadata", false, true),
257
+ key(p.collectionMasterEdition, "collectionMasterEdition", false, false),
258
+ key(p.collectionAuthority, "collectionAuthority", false, false),
259
+ key(TOKEN_METADATA_PROGRAM, "tokenMetadataProgram", false, false),
260
+ key(TOKEN_PROGRAM, "tokenProgram", false, false),
261
+ key(ASSOCIATED_TOKEN_PROGRAM, "associatedTokenProgram", false, false),
262
+ key(SYSTEM_PROGRAM, "systemProgram", false, false),
263
+ key(SYSVAR_INSTRUCTIONS, "sysvarInstructions", false, false),
264
+ p.integrator !== undefined ? key(p.integrator, "integrator", false, true) : none(),
265
+ p.integratorAllowlist !== undefined ? key(p.integratorAllowlist, "integratorAllowlist", false, false) : none(),
266
+ p.minterAuthorization !== undefined ? key(p.minterAuthorization, "minterAuthorization", false, false) : none(),
267
+ key(p.namespacePricing, "namespacePricing", false, false),
268
+ ];
269
+ return {
270
+ programId,
271
+ keys,
272
+ data: concat(REGISTER_UNDER_NAMESPACE_V2_DISCRIMINATOR, borshString(p.name), Uint8Array.of(p.handleType), u64le(p.maxPriceLamports)),
273
+ };
274
+ }
275
+ /** Read `launch_ts`, `tier_lamports` and `total_handles_sold` from raw Config bytes. */
276
+ export function decodeRootPricingInputs(config) {
277
+ if (config.length < CONFIG_TOTAL_SOLD_OFFSET + 8)
278
+ return null;
279
+ const dv = new DataView(config.buffer, config.byteOffset, config.byteLength);
280
+ const tierLamports = [];
281
+ for (let i = 0; i < NAMESPACE_TIER_COUNT; i++)
282
+ tierLamports.push(dv.getBigUint64(CONFIG_TIERS_OFFSET + 8 * i, true));
283
+ return {
284
+ launchTs: dv.getBigInt64(CONFIG_LAUNCH_TS_OFFSET, true),
285
+ tierLamports,
286
+ totalHandlesSold: dv.getBigUint64(CONFIG_TOTAL_SOLD_OFFSET, true),
287
+ };
288
+ }
289
+ /**
290
+ * The price `register_under_namespace_v2` charges, from already-read state —
291
+ * `scoped_registration_price` in lib.rs: the creator's band flat when a table
292
+ * exists, else the root band × the ramp.
293
+ */
294
+ export function scopedRegistrationPrice(pricing, root, nameLen, nowSecs) {
295
+ const i = scopedTierIndex(nameLen);
296
+ if (pricing)
297
+ return pricing.tierLamports[i];
298
+ return rootPriceNow(root.tierLamports[i], root.launchTs, nowSecs, root.totalHandlesSold);
299
+ }
300
+ async function readAccount(rpc, address) {
301
+ const res = (await rpc("getAccountInfo", [address, { encoding: "base64", commitment: "confirmed" }]));
302
+ const v = res?.value;
303
+ if (!v)
304
+ return null;
305
+ const bin = atob(v.data[0]);
306
+ const data = new Uint8Array(bin.length);
307
+ for (let i = 0; i < bin.length; i++)
308
+ data[i] = bin.charCodeAt(i);
309
+ return { owner: v.owner, data };
310
+ }
311
+ /**
312
+ * Quote `name.label` exactly like the program prices it (pricing-or-fallback).
313
+ * Throws when Config is missing, or when the pricing account exists but is not
314
+ * a valid `NamespacePricing` owned by the program (the program would refuse
315
+ * too), so a caller never shows a price the chain will not honour.
316
+ */
317
+ export async function quoteScopedName(label, name, opts) {
318
+ const programId = toBase58(opts.programId, "programId");
319
+ const [config, pricingAccount] = await Promise.all([
320
+ opts.find([TE.encode("config")], programId),
321
+ deriveNamespacePricingPda(label, programId, opts.find),
322
+ ]);
323
+ const [configAcct, pricingAcct] = await Promise.all([readAccount(opts.rpc, config), readAccount(opts.rpc, pricingAccount)]);
324
+ if (!configAcct)
325
+ throw new Error("registry Config not found");
326
+ const root = decodeRootPricingInputs(configAcct.data);
327
+ if (!root)
328
+ throw new Error("registry Config is too short to read pricing");
329
+ let pricing = null;
330
+ if (pricingAcct && pricingAcct.owner === programId) {
331
+ pricing = decodeNamespacePricing(pricingAcct.data);
332
+ if (!pricing)
333
+ throw new Error(`.${label} pricing account is not a valid NamespacePricing`);
334
+ }
335
+ const nowSecs = opts.nowSecs ?? BigInt(Math.floor(Date.now() / 1000));
336
+ const nameLen = TE.encode(name).length;
337
+ return {
338
+ lamports: scopedRegistrationPrice(pricing, root, nameLen, nowSecs),
339
+ source: pricing ? "custom" : "fallback",
340
+ tierIndex: scopedTierIndex(nameLen),
341
+ pricingAccount,
342
+ pricing,
343
+ };
344
+ }
345
+ // ---------------------------------------------------------------------------
346
+ // upgrade probe
347
+ // ---------------------------------------------------------------------------
348
+ /**
349
+ * The instruction to SIMULATE (never send) to learn whether the deployed
350
+ * program has this feature: `set_namespace_pricing` with no accounts. An
351
+ * upgraded program recognizes the discriminator and fails account validation
352
+ * (e.g. 3005 `AccountNotEnoughKeys`); a pre-upgrade program fails with
353
+ * Anchor's `InstructionFallbackNotFound` (101). Interpret the simulation's
354
+ * `err` with {@link interpretNamespacePricingProbe}.
355
+ */
356
+ export function buildNamespacePricingProbeIx(programId) {
357
+ return { programId: toBase58(programId, "programId"), keys: [], data: SET_NAMESPACE_PRICING_DISCRIMINATOR.slice() };
358
+ }
359
+ /**
360
+ * Read a `simulateTransaction` result's `value.err` for the probe tx (whose
361
+ * probe instruction is at `probeIndex`). `true` = the program knows the
362
+ * instruction; `false` = it does not, or the result is not the shape we
363
+ * expect (fail closed: hide the feature rather than show a broken button).
364
+ */
365
+ export function interpretNamespacePricingProbe(err, probeIndex) {
366
+ if (!err || typeof err !== "object")
367
+ return false;
368
+ const ie = err.InstructionError;
369
+ if (!Array.isArray(ie) || ie.length !== 2 || ie[0] !== probeIndex)
370
+ return false;
371
+ const detail = ie[1];
372
+ // Anchor reports both outcomes as `Custom` codes; anything else is an
373
+ // unexpected shape and reads as "not supported".
374
+ if (typeof detail === "object" && detail !== null && typeof detail.Custom === "number") {
375
+ return detail.Custom !== ANCHOR_INSTRUCTION_FALLBACK_NOT_FOUND;
376
+ }
377
+ return false;
378
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Minimal synchronous SHA-256 (FIPS 180-4). This SDK is zero-dependency and
3
+ * cannot assume WebCrypto is present AND synchronous (`crypto.subtle.digest`
4
+ * is async), so the x402 request-reference derivation (x402.ts) uses this
5
+ * pure implementation. Cross-checked against node:crypto in sdk/test/x402.test.js.
6
+ */
7
+ /** SHA-256 of `data` (bytes, or a string hashed as its UTF-8 encoding). */
8
+ export declare function sha256(data: Uint8Array | string): Uint8Array;
9
+ /** Lowercase hex of `bytes`. */
10
+ export declare function toHex(bytes: Uint8Array): string;
package/dist/sha256.js ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Minimal synchronous SHA-256 (FIPS 180-4). This SDK is zero-dependency and
3
+ * cannot assume WebCrypto is present AND synchronous (`crypto.subtle.digest`
4
+ * is async), so the x402 request-reference derivation (x402.ts) uses this
5
+ * pure implementation. Cross-checked against node:crypto in sdk/test/x402.test.js.
6
+ */
7
+ const K = new Uint32Array([
8
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
9
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
10
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
11
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
12
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
13
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
14
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
15
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
16
+ ]);
17
+ /** SHA-256 of `data` (bytes, or a string hashed as its UTF-8 encoding). */
18
+ export function sha256(data) {
19
+ const msg = typeof data === "string" ? new TextEncoder().encode(data) : data;
20
+ const bitLen = BigInt(msg.length) * 8n;
21
+ const padded = new Uint8Array(Math.ceil((msg.length + 9) / 64) * 64);
22
+ padded.set(msg);
23
+ padded[msg.length] = 0x80;
24
+ const dv = new DataView(padded.buffer);
25
+ dv.setBigUint64(padded.length - 8, bitLen, false);
26
+ const H = new Uint32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]);
27
+ const W = new Uint32Array(64);
28
+ const rotr = (x, n) => (x >>> n) | (x << (32 - n));
29
+ for (let off = 0; off < padded.length; off += 64) {
30
+ for (let t = 0; t < 16; t++)
31
+ W[t] = dv.getUint32(off + t * 4, false);
32
+ for (let t = 16; t < 64; t++) {
33
+ const w15 = W[t - 15];
34
+ const w2 = W[t - 2];
35
+ const s0 = rotr(w15, 7) ^ rotr(w15, 18) ^ (w15 >>> 3);
36
+ const s1 = rotr(w2, 17) ^ rotr(w2, 19) ^ (w2 >>> 10);
37
+ W[t] = (W[t - 16] + s0 + W[t - 7] + s1) >>> 0;
38
+ }
39
+ let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
40
+ for (let t = 0; t < 64; t++) {
41
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
42
+ const ch = (e & f) ^ (~e & g);
43
+ const t1 = (h + S1 + ch + K[t] + W[t]) >>> 0;
44
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
45
+ const maj = (a & b) ^ (a & c) ^ (b & c);
46
+ const t2 = (S0 + maj) >>> 0;
47
+ h = g;
48
+ g = f;
49
+ f = e;
50
+ e = (d + t1) >>> 0;
51
+ d = c;
52
+ c = b;
53
+ b = a;
54
+ a = (t1 + t2) >>> 0;
55
+ }
56
+ H[0] = (H[0] + a) >>> 0;
57
+ H[1] = (H[1] + b) >>> 0;
58
+ H[2] = (H[2] + c) >>> 0;
59
+ H[3] = (H[3] + d) >>> 0;
60
+ H[4] = (H[4] + e) >>> 0;
61
+ H[5] = (H[5] + f) >>> 0;
62
+ H[6] = (H[6] + g) >>> 0;
63
+ H[7] = (H[7] + h) >>> 0;
64
+ }
65
+ const out = new Uint8Array(32);
66
+ const odv = new DataView(out.buffer);
67
+ for (let i = 0; i < 8; i++)
68
+ odv.setUint32(i * 4, H[i], false);
69
+ return out;
70
+ }
71
+ /** Lowercase hex of `bytes`. */
72
+ export function toHex(bytes) {
73
+ let s = "";
74
+ for (const b of bytes)
75
+ s += b.toString(16).padStart(2, "0");
76
+ return s;
77
+ }