@invisi-labs/primitives 0.0.0-stage → 1.2.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 CHANGED
@@ -1,3 +1,5 @@
1
- # Temporary Holding Version
1
+ # @invisi-labs/primitives
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Invisi Protocol pure cryptographic primitives.
4
+
5
+ Install with `npm install @invisi-labs/primitives@1.2.0`. API documentation and runnable examples are in the [SDK repository](https://github.com/invisi-lab/invisi-sdk-ts).
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
19
+
20
+ // src/address-entry.ts
21
+ var address_entry_exports = {};
22
+ __export(address_entry_exports, {
23
+ ReceivingAddress: () => ReceivingAddress,
24
+ decodeAddress: () => decodeAddress
25
+ });
26
+ module.exports = __toCommonJS(address_entry_exports);
27
+
28
+ // src/address/address.ts
29
+ var import_secp256k1 = require("@noble/curves/secp256k1");
30
+ var import_sha3 = require("@noble/hashes/sha3");
31
+ var import_utils2 = require("@noble/hashes/utils");
32
+ var import_ethers = require("ethers");
33
+
34
+ // src/fmd/fmd.ts
35
+ var import_blake2b2 = require("@noble/hashes/blake2b");
36
+ var import_utils = require("@noble/hashes/utils");
37
+
38
+ // src/fmd/decaf377.ts
39
+ var import_edwards = require("@noble/curves/abstract/edwards");
40
+ var import_modular = require("@noble/curves/abstract/modular");
41
+ var import_blake2b = require("@noble/hashes/blake2b");
42
+ var FQ = 8444461749428370424248824938781546531375899335154063827935233455917409239041n;
43
+ var FR = 2111115437357092606062206234695386632838870926408408195193685246394721360383n;
44
+ var field = (0, import_modular.Field)(FQ, 253, true);
45
+ var f = (n) => (0, import_modular.mod)(n, FQ);
46
+ function secureRandomBytes(length) {
47
+ const webCrypto = globalThis.crypto;
48
+ if (!webCrypto?.getRandomValues) throw new Error("WebCrypto secure randomness is unavailable");
49
+ return webCrypto.getRandomValues(new Uint8Array(length));
50
+ }
51
+ var curve = (0, import_edwards.twistedEdwards)({
52
+ a: FQ - 1n,
53
+ d: 3021n,
54
+ Fp: field,
55
+ n: FR,
56
+ h: 4n,
57
+ Gx: 4959445789346820725352484487855828915252512307947624787834978378872129235627n,
58
+ Gy: 6060471950081851567114691557659790004756535011754163002297540472747064943288n,
59
+ hash: import_blake2b.blake2b,
60
+ randomBytes: (length = 32) => secureRandomBytes(length)
61
+ });
62
+ var generator = curve.ExtendedPoint.BASE;
63
+ function readLE(bytes) {
64
+ let n = 0n;
65
+ for (let i = bytes.length - 1; i >= 0; i--) n = n << 8n | BigInt(bytes[i]);
66
+ return n;
67
+ }
68
+ function decodePoint(bytes) {
69
+ if (!(bytes instanceof Uint8Array) || bytes.length !== 32)
70
+ throw new Error("Invalid Decaf377 encoding length");
71
+ const s = readLE(bytes);
72
+ if (s >= FQ || (s & 1n) !== 0n || bytes[31] >> 5 !== 0)
73
+ throw new Error("Invalid Decaf377 encoding");
74
+ const ss = f(s * s);
75
+ const u1 = f(1n - ss);
76
+ const u2 = f(u1 * u1 - 4n * 3021n * ss);
77
+ const denominator = f(u2 * u1 * u1);
78
+ if (denominator === 0n) throw new Error("Invalid Decaf377 encoding");
79
+ let v;
80
+ try {
81
+ v = field.sqrt(field.inv(denominator));
82
+ } catch {
83
+ throw new Error("Invalid Decaf377 encoding");
84
+ }
85
+ const twoSU1 = f(2n * s * u1);
86
+ if ((f(twoSU1 * v) & 1n) !== 0n) v = f(-v);
87
+ const x = f(twoSU1 * v * v * u2);
88
+ const y = f((1n + ss) * v * u1);
89
+ return curve.ExtendedPoint.fromAffine({ x, y });
90
+ }
91
+ function isIdentity(point) {
92
+ return point.ex === 0n;
93
+ }
94
+
95
+ // src/fmd/fmd.ts
96
+ function requireBytes(value, length, name) {
97
+ if (!(value instanceof Uint8Array) || value.length !== length)
98
+ throw new TypeError(`${name} must be a ${length}-byte Uint8Array`);
99
+ }
100
+ function validateClueKey(clueKey) {
101
+ requireBytes(clueKey, 32, "Clue key");
102
+ if (isIdentity(decodePoint(clueKey))) throw new Error("Clue key must not be the identity");
103
+ }
104
+
105
+ // src/address/address.ts
106
+ var ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
107
+ function identityBytes(value) {
108
+ if (typeof value !== "bigint" && (typeof value !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(value)))
109
+ throw new Error("invalid owner address encoding");
110
+ const n = BigInt(value);
111
+ if (n <= 0n || n >= 1n << 160n)
112
+ throw new RangeError("owner address must be a nonzero EVM owner address");
113
+ return (0, import_utils2.hexToBytes)(n.toString(16).padStart(40, "0"));
114
+ }
115
+ function receivingKeys(keys) {
116
+ const publicKey = keys.viewingPublicKey;
117
+ if (!(publicKey instanceof Uint8Array) || publicKey.length !== 33 || publicKey[0] !== 2 && publicKey[0] !== 3)
118
+ throw new Error("invalid compressed viewing public key");
119
+ import_secp256k1.secp256k1.ProjectivePoint.fromHex(publicKey).assertValidity();
120
+ validateClueKey(keys.clueKey);
121
+ return { viewingPublicKey: Uint8Array.from(publicKey), clueKey: Uint8Array.from(keys.clueKey) };
122
+ }
123
+ function checkedText(prefix, data) {
124
+ const digest = (0, import_sha3.keccak_256)((0, import_utils2.utf8ToBytes)("Invisi.AddressCaseChecksum.v1:" + prefix + data));
125
+ return prefix + Array.from(
126
+ data,
127
+ (character, i) => digest[i >> 3] >> 7 - (i & 7) & 1 ? character.toUpperCase() : character
128
+ ).join("");
129
+ }
130
+ function encode(prefix, payload) {
131
+ let buffer = 0, bits = 0, data = "";
132
+ for (const byte of payload) {
133
+ buffer = buffer << 8 | byte;
134
+ bits += 8;
135
+ while (bits >= 5) {
136
+ bits -= 5;
137
+ data += ALPHABET[buffer >>> bits & 31];
138
+ }
139
+ buffer &= (1 << bits) - 1;
140
+ }
141
+ if (bits) data += ALPHABET[buffer << 5 - bits & 31];
142
+ return checkedText(prefix, data);
143
+ }
144
+ function encodeLongAddress(recipient) {
145
+ const identity = identityBytes(recipient.ownerAddress), keys = receivingKeys(recipient);
146
+ return encode("0i", (0, import_utils2.concatBytes)(identity, keys.viewingPublicKey, keys.clueKey));
147
+ }
148
+ function encodeShortAddress(ownerAddress) {
149
+ const identity = identityBytes(ownerAddress);
150
+ return (0, import_ethers.getAddress)(
151
+ typeof ownerAddress === "string" ? ownerAddress : `0x${(0, import_utils2.bytesToHex)(identity)}`
152
+ );
153
+ }
154
+ function decodeAddress(address) {
155
+ if (typeof address !== "string") throw new TypeError("address must be text");
156
+ if (address.startsWith("0x")) {
157
+ const owner = (0, import_ethers.getAddress)(address);
158
+ return { kind: "short", ownerAddress: `0x${(0, import_utils2.bytesToHex)(identityBytes(owner))}` };
159
+ }
160
+ if (!address.startsWith("0i")) throw new Error("invalid Invisi address prefix");
161
+ const prefix = "0i";
162
+ if (address.length !== 138) throw new Error("invalid address length");
163
+ const data = address.slice(prefix.length).toLowerCase();
164
+ if (Array.from(data).some((character) => !ALPHABET.includes(character)))
165
+ throw new Error("invalid address alphabet");
166
+ if (checkedText(prefix, data) !== address) throw new Error("invalid address case checksum");
167
+ let buffer = 0, bits = 0;
168
+ const payload = [];
169
+ for (const character of data) {
170
+ buffer = buffer << 5 | ALPHABET.indexOf(character);
171
+ bits += 5;
172
+ if (bits >= 8) {
173
+ bits -= 8;
174
+ payload.push(buffer >>> bits & 255);
175
+ }
176
+ buffer &= (1 << bits) - 1;
177
+ }
178
+ if (bits !== 0 || buffer !== 0) throw new Error("noncanonical address padding");
179
+ const raw = Uint8Array.from(payload);
180
+ const ownerAddress = `0x${(0, import_utils2.bytesToHex)(identityBytes(`0x${(0, import_utils2.bytesToHex)(raw.subarray(0, 20))}`))}`;
181
+ return {
182
+ kind: "long",
183
+ ownerAddress,
184
+ ...receivingKeys({ viewingPublicKey: raw.slice(20, 53), clueKey: raw.slice(53) })
185
+ };
186
+ }
187
+
188
+ // src/errors.ts
189
+ var MissingCapabilityError = class extends Error {
190
+ constructor(capability) {
191
+ super(`Missing ${capability} capability`);
192
+ this.capability = capability;
193
+ this.name = "MissingCapabilityError";
194
+ }
195
+ code = "MISSING_CAPABILITY";
196
+ };
197
+
198
+ // src/address/receiving-address.ts
199
+ var ReceivingAddress = class _ReceivingAddress {
200
+ #text;
201
+ constructor(text) {
202
+ const decoded = decodeAddress(text);
203
+ this.#text = decoded.kind === "short" ? encodeShortAddress(decoded.ownerAddress) : text;
204
+ Object.freeze(this);
205
+ }
206
+ static parse(text) {
207
+ return new _ReceivingAddress(text);
208
+ }
209
+ static from(recipient) {
210
+ return new _ReceivingAddress(encodeLongAddress(recipient));
211
+ }
212
+ static fromIdentity(identity) {
213
+ return new _ReceivingAddress(encodeShortAddress(identity));
214
+ }
215
+ get ownerAddress() {
216
+ return decodeAddress(this.#text).ownerAddress;
217
+ }
218
+ get kind() {
219
+ return decodeAddress(this.#text).kind;
220
+ }
221
+ getReceivingKeys() {
222
+ const decoded = decodeAddress(this.#text);
223
+ if (decoded.kind === "short") {
224
+ throw new MissingCapabilityError("resolved receiving keys");
225
+ }
226
+ return { viewingPublicKey: decoded.viewingPublicKey, clueKey: decoded.clueKey };
227
+ }
228
+ async resolve(lookup) {
229
+ if (this.kind === "long") {
230
+ return this;
231
+ }
232
+ if (!lookup) {
233
+ throw new MissingCapabilityError("explicit registry lookup");
234
+ }
235
+ const keys = await lookup(this.ownerAddress);
236
+ if (!keys) {
237
+ throw new Error("owner address is not registered");
238
+ }
239
+ return _ReceivingAddress.from({
240
+ ownerAddress: this.ownerAddress,
241
+ viewingPublicKey: keys.viewingPublicKey,
242
+ clueKey: keys.clueKey
243
+ });
244
+ }
245
+ get viewingPublicKey() {
246
+ return this.getReceivingKeys().viewingPublicKey;
247
+ }
248
+ get clueKey() {
249
+ return this.getReceivingKeys().clueKey;
250
+ }
251
+ toString() {
252
+ return this.#text;
253
+ }
254
+ toJSON() {
255
+ return this.#text;
256
+ }
257
+ };
258
+ // Annotate the CommonJS export names for ESM import in node:
259
+ 0 && (module.exports = {
260
+ ReceivingAddress,
261
+ decodeAddress
262
+ });
263
+ //# sourceMappingURL=address.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/address-entry.ts","../src/address/address.ts","../src/fmd/fmd.ts","../src/fmd/decaf377.ts","../src/errors.ts","../src/address/receiving-address.ts"],"sourcesContent":["/** Public receiving addresses without wallet key derivation or a hashing backend. */\nexport { decodeAddress } from \"./address/address\";\nexport type { DecodedAddress, ReceivingKeyLookup } from \"./address/address\";\nexport { ReceivingAddress } from \"./address/receiving-address\";\nexport type { ReceivingKeys } from \"./types\";\n","import { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { keccak_256 } from \"@noble/hashes/sha3\";\nimport { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from \"@noble/hashes/utils\";\nimport { getAddress } from \"ethers\";\nimport { validateClueKey } from \"../fmd/fmd\";\n\nexport interface ReceivingAddress {\n ownerAddress: `0x${string}`;\n viewingPublicKey: Uint8Array;\n clueKey: Uint8Array;\n}\nexport type DecodedAddress =\n ({ kind: \"long\" } & ReceivingAddress) | { kind: \"short\"; ownerAddress: `0x${string}` };\nexport type ReceivingKeyLookup = (\n ownerAddress: `0x${string}`\n) => Promise<Pick<ReceivingAddress, \"viewingPublicKey\" | \"clueKey\"> | null | undefined>;\nconst ALPHABET = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\ntype Identity = bigint | `0x${string}`;\n\nfunction identityBytes(value: Identity): Uint8Array {\n if (\n typeof value !== \"bigint\" &&\n (typeof value !== \"string\" || !/^0x[0-9a-fA-F]{40}$/.test(value))\n )\n throw new Error(\"invalid owner address encoding\");\n const n = BigInt(value);\n if (n <= 0n || n >= 1n << 160n)\n throw new RangeError(\"owner address must be a nonzero EVM owner address\");\n return hexToBytes(n.toString(16).padStart(40, \"0\"));\n}\nfunction receivingKeys(keys: Pick<ReceivingAddress, \"viewingPublicKey\" | \"clueKey\">) {\n const publicKey = keys.viewingPublicKey;\n if (\n !(publicKey instanceof Uint8Array) ||\n publicKey.length !== 33 ||\n (publicKey[0] !== 2 && publicKey[0] !== 3)\n )\n throw new Error(\"invalid compressed viewing public key\");\n secp256k1.ProjectivePoint.fromHex(publicKey).assertValidity();\n validateClueKey(keys.clueKey);\n return { viewingPublicKey: Uint8Array.from(publicKey), clueKey: Uint8Array.from(keys.clueKey) };\n}\nfunction checkedText(prefix: string, data: string): string {\n const digest = keccak_256(utf8ToBytes(\"Invisi.AddressCaseChecksum.v1:\" + prefix + data));\n return (\n prefix +\n Array.from(data, (character, i) =>\n (digest[i >> 3]! >> (7 - (i & 7))) & 1 ? character.toUpperCase() : character\n ).join(\"\")\n );\n}\nfunction encode(prefix: string, payload: Uint8Array): string {\n let buffer = 0,\n bits = 0,\n data = \"\";\n for (const byte of payload) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n bits -= 5;\n data += ALPHABET[(buffer >>> bits) & 31];\n }\n buffer &= (1 << bits) - 1;\n }\n if (bits) data += ALPHABET[(buffer << (5 - bits)) & 31];\n return checkedText(prefix, data);\n}\n\n/** 138 characters: 0i plus the complete offline receiving materials. */\nexport function encodeLongAddress(recipient: ReceivingAddress): string {\n const identity = identityBytes(recipient.ownerAddress),\n keys = receivingKeys(recipient);\n return encode(\"0i\", concatBytes(identity, keys.viewingPublicKey, keys.clueKey));\n}\n/** The owner's 42-character checksummed EVM address; receiving keys require a chosen registry. */\nexport function encodeShortAddress(ownerAddress: Identity): string {\n const identity = identityBytes(ownerAddress);\n return getAddress(\n typeof ownerAddress === \"string\" ? ownerAddress : `0x${bytesToHex(identity)}`\n );\n}\n\n/** Standard EVM short addresses or a full 0i address with a strict custom Base32 case checksum. */\nexport function decodeAddress(address: string): DecodedAddress {\n if (typeof address !== \"string\") throw new TypeError(\"address must be text\");\n if (address.startsWith(\"0x\")) {\n const owner = getAddress(address) as `0x${string}`;\n return { kind: \"short\", ownerAddress: `0x${bytesToHex(identityBytes(owner))}` };\n }\n if (!address.startsWith(\"0i\")) throw new Error(\"invalid Invisi address prefix\");\n const prefix = \"0i\";\n if (address.length !== 138) throw new Error(\"invalid address length\");\n const data = address.slice(prefix.length).toLowerCase();\n if (Array.from(data).some((character) => !ALPHABET.includes(character)))\n throw new Error(\"invalid address alphabet\");\n if (checkedText(prefix, data) !== address) throw new Error(\"invalid address case checksum\");\n let buffer = 0,\n bits = 0;\n const payload: number[] = [];\n for (const character of data) {\n buffer = (buffer << 5) | ALPHABET.indexOf(character);\n bits += 5;\n if (bits >= 8) {\n bits -= 8;\n payload.push((buffer >>> bits) & 255);\n }\n buffer &= (1 << bits) - 1;\n }\n if (bits !== 0 || buffer !== 0) throw new Error(\"noncanonical address padding\");\n const raw = Uint8Array.from(payload);\n const ownerAddress =\n `0x${bytesToHex(identityBytes(`0x${bytesToHex(raw.subarray(0, 20))}`))}` as const;\n return {\n kind: \"long\",\n ownerAddress,\n ...receivingKeys({ viewingPublicKey: raw.slice(20, 53), clueKey: raw.slice(53) }),\n };\n}\n\n/** Normalize either address into the same payment input. Long addresses never query. */\nexport async function resolveAddress(\n address: string,\n options: { lookup?: ReceivingKeyLookup } = {}\n): Promise<ReceivingAddress> {\n const decoded = decodeAddress(address);\n if (decoded.kind === \"long\")\n return {\n ownerAddress: decoded.ownerAddress,\n viewingPublicKey: decoded.viewingPublicKey,\n clueKey: decoded.clueKey,\n };\n if (!options.lookup) throw new Error(\"short address requires an explicit registry lookup\");\n const keys = await options.lookup(decoded.ownerAddress);\n if (!keys) throw new Error(\"owner address is not registered\");\n return { ownerAddress: decoded.ownerAddress, ...receivingKeys(keys) };\n}\n","/**\n * Frozen S-FMD profile: decaf377-fmd 2.1.1, 24-bit clues (68 bytes).\n * Only FMD detection keys belong here; these are not transaction ownership keys.\n *\n * SECURITY: the noble Edwards arithmetic and this exact Decaf codec port use\n * JavaScript BigInt. They do not provide constant-time execution or reliable\n * secret erasure. This new composition has not received an independent audit.\n */\nimport { blake2b } from \"@noble/hashes/blake2b\";\nimport { concatBytes, utf8ToBytes } from \"@noble/hashes/utils\";\nimport {\n FR,\n decodePoint,\n encodePoint,\n generator,\n inverseScalar,\n isIdentity,\n multiply,\n readLE,\n secureRandomBytes,\n writeLE,\n} from \"./decaf377.js\";\n\nconst PRECISION = 24;\nfunction requireBytes(value: Uint8Array, length: number, name: string): void {\n if (!(value instanceof Uint8Array) || value.length !== length)\n throw new TypeError(`${name} must be a ${length}-byte Uint8Array`);\n}\nfunction detectionScalar(key: Uint8Array): bigint {\n requireBytes(key, 32, \"Detection key\");\n const scalar = readLE(key);\n if (scalar === 0n || scalar >= FR)\n throw new Error(\"Detection key must be a canonical nonzero Decaf377 scalar\");\n return scalar;\n}\nfunction hash(domain: string, ...parts: Uint8Array[]): Uint8Array {\n // Rust blake2b_simd defaults to 64 output bytes and zero-pads personalization.\n const personalization = new Uint8Array(16);\n personalization.set(utf8ToBytes(`decaf377-fmd.${domain}`));\n return blake2b(concatBytes(...parts), { dkLen: 64, personalization });\n}\nconst hashScalar = (domain: string, ...parts: Uint8Array[]) => readLE(hash(domain, ...parts)) % FR;\nconst childOffset = (clueKey: Uint8Array, index: number) =>\n hashScalar(\"hkd\", clueKey, Uint8Array.of(index));\nconst hashBit = (p: Uint8Array, shared: Uint8Array, q: Uint8Array) =>\n hash(\"bit\", p, shared, q)[0]! & 1;\n\n/** Derive the canonical 32-byte Decaf377 clue key from a nonzero FMD scalar. */\nexport function deriveClueKey(detectionKey: Uint8Array): Uint8Array {\n return encodePoint(multiply(generator, detectionScalar(detectionKey)));\n}\n/** Reject malformed, noncanonical, or identity clue keys. */\nexport function validateClueKey(clueKey: Uint8Array): void {\n requireBytes(clueKey, 32, \"Clue key\");\n if (isIdentity(decodePoint(clueKey))) throw new Error(\"Clue key must not be the identity\");\n}\n/** Create a fixed 24-bit clue using a fresh WebCrypto random seed. */\nexport function createClue(clueKey: Uint8Array): Uint8Array {\n validateClueKey(clueKey);\n return createClueFromSeed(clueKey, secureRandomBytes(32));\n}\n/**\n * Deterministic interoperability/backend entry point. Seed must be independently\n * generated with a CSPRNG for every production clue; never reuse a fixed seed.\n */\nexport function createClueFromSeed(clueKey: Uint8Array, seed32: Uint8Array): Uint8Array {\n validateClueKey(clueKey);\n requireBytes(seed32, 32, \"Clue seed\");\n const root = decodePoint(clueKey);\n const r = hashScalar(\"rdv\", clueKey, seed32);\n const z = hashScalar(\"zdv\", clueKey, seed32);\n if (r === 0n) throw new Error(\"Degenerate clue seed\");\n const p = encodePoint(multiply(generator, r));\n const q = encodePoint(multiply(generator, z));\n const ciphertext = new Uint8Array(3);\n for (let i = 0; i < PRECISION; i++) {\n const child = root.add(multiply(generator, childOffset(clueKey, i)));\n const shared = encodePoint(multiply(child, r));\n ciphertext[i >> 3] = ciphertext[i >> 3]! | ((hashBit(p, shared, q) ^ 1) << (i & 7));\n }\n const m = hashScalar(\"sca\", p, Uint8Array.of(PRECISION), ciphertext);\n const y = ((z - m + FR) * inverseScalar(r)) % FR;\n if (y === 0n) throw new Error(\"Degenerate clue seed\");\n return concatBytes(p, writeLE(y), Uint8Array.of(PRECISION), ciphertext);\n}\n\n/** Check a full-precision clue locally without exporting the detection key. */\nexport function detectClue(detectionKey: Uint8Array, clue: Uint8Array): boolean {\n const scalar = detectionScalar(detectionKey);\n requireBytes(clue, 68, \"Clue\");\n if (clue[64] !== PRECISION) return false;\n const p = clue.slice(0, 32),\n y = readLE(clue.slice(32, 64));\n if (y === 0n || y >= FR) return false;\n let point;\n try {\n point = decodePoint(p);\n } catch {\n return false;\n }\n if (isIdentity(point)) return false;\n const ciphertext = clue.slice(65);\n const m = hashScalar(\"sca\", p, Uint8Array.of(PRECISION), ciphertext);\n const q = encodePoint(multiply(generator, m).add(multiply(point, y)));\n const clueKey = deriveClueKey(detectionKey);\n for (let i = 0; i < PRECISION; i++) {\n const child = (scalar + childOffset(clueKey, i)) % FR;\n const bit = hashBit(p, encodePoint(multiply(point, child)), q);\n if ((bit ^ ((ciphertext[i >> 3]! >> (i & 7)) & 1)) !== 1) return false;\n }\n return true;\n}\n","/**\n * Internal Decaf377 codec, ported from decaf377 0.10.1 min_curve/element.rs.\n * Edwards group/field arithmetic is supplied by @noble/curves 1.9.1. The\n * Montgomery constants below are converted to ordinary field integers.\n * This JavaScript BigInt backend is NOT constant-time and has not been audited.\n */\nimport { twistedEdwards, type ExtPointType } from \"@noble/curves/abstract/edwards\";\nimport { Field, mod } from \"@noble/curves/abstract/modular\";\nimport { blake2b } from \"@noble/hashes/blake2b\";\n\nexport const FQ = 8444461749428370424248824938781546531375899335154063827935233455917409239041n;\nexport const FR = 2111115437357092606062206234695386632838870926408408195193685246394721360383n;\nconst field = Field(FQ, 253, true);\nconst f = (n: bigint) => mod(n, FQ);\nconst abs = (n: bigint) => ((n & 1n) === 0n ? n : f(-n));\n\nexport function secureRandomBytes(length: number): Uint8Array {\n const webCrypto = (\n globalThis as { crypto?: { getRandomValues(array: Uint8Array): Uint8Array } }\n ).crypto;\n if (!webCrypto?.getRandomValues) throw new Error(\"WebCrypto secure randomness is unavailable\");\n return webCrypto.getRandomValues(new Uint8Array(length));\n}\n\nconst curve = twistedEdwards({\n a: FQ - 1n,\n d: 3021n,\n Fp: field,\n n: FR,\n h: 4n,\n Gx: 4959445789346820725352484487855828915252512307947624787834978378872129235627n,\n Gy: 6060471950081851567114691557659790004756535011754163002297540472747064943288n,\n hash: blake2b,\n randomBytes: (length = 32) => secureRandomBytes(length),\n});\nexport type DecafPoint = ExtPointType;\nexport const generator: DecafPoint = curve.ExtendedPoint.BASE;\n\nexport function readLE(bytes: Uint8Array): bigint {\n let n = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) n = (n << 8n) | BigInt(bytes[i]!);\n return n;\n}\nexport function writeLE(n: bigint): Uint8Array {\n const bytes = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n bytes[i] = Number(n & 255n);\n n >>= 8n;\n }\n return bytes;\n}\nexport function multiply(point: DecafPoint, scalar: bigint): DecafPoint {\n return scalar === 0n ? curve.ExtendedPoint.ZERO : point.multiply(scalar);\n}\nexport function inverseScalar(scalar: bigint): bigint {\n // Noble's field inversion uses Euclid. Neither this nor BigInt is constant-time.\n return Field(FR).inv(scalar);\n}\n\n/** Canonical Decaf decoding, including the low-bit sign convention. */\nexport function decodePoint(bytes: Uint8Array): DecafPoint {\n if (!(bytes instanceof Uint8Array) || bytes.length !== 32)\n throw new Error(\"Invalid Decaf377 encoding length\");\n const s = readLE(bytes);\n if (s >= FQ || (s & 1n) !== 0n || bytes[31]! >> 5 !== 0)\n throw new Error(\"Invalid Decaf377 encoding\");\n const ss = f(s * s);\n const u1 = f(1n - ss);\n const u2 = f(u1 * u1 - 4n * 3021n * ss);\n const denominator = f(u2 * u1 * u1);\n // This is the square branch of Rust sqrt_ratio_zeta(1, denominator).\n // Decompression rejects the nonsquare branch; root sign is fixed below.\n if (denominator === 0n) throw new Error(\"Invalid Decaf377 encoding\");\n let v: bigint;\n try {\n v = field.sqrt(field.inv(denominator));\n } catch {\n throw new Error(\"Invalid Decaf377 encoding\");\n }\n const twoSU1 = f(2n * s * u1);\n if ((f(twoSU1 * v) & 1n) !== 0n) v = f(-v);\n const x = f(twoSU1 * v * v * u2);\n const y = f((1n + ss) * v * u1);\n return curve.ExtendedPoint.fromAffine({ x, y });\n}\nexport function encodePoint(point: DecafPoint): Uint8Array {\n const { ex: x, ez: z, et: t } = point;\n if (x === 0n) return new Uint8Array(32);\n const aMinusD = -3022n;\n const u1 = f((x + t) * (x - t));\n const denominator = f(u1 * aMinusD * x * x);\n const v = field.sqrt(field.inv(denominator));\n const u2 = abs(f(v * u1));\n const u3 = f(u2 * z - t);\n return writeLE(abs(f(aMinusD * v * u3 * x)));\n}\nexport function isIdentity(point: DecafPoint): boolean {\n return point.ex === 0n;\n}\n","/** A requested permission was not explicitly supplied to this component. */\nexport class MissingCapabilityError extends Error {\n readonly code = \"MISSING_CAPABILITY\";\n constructor(readonly capability: string) {\n super(`Missing ${capability} capability`);\n this.name = \"MissingCapabilityError\";\n }\n}\n","import { MissingCapabilityError } from \"../errors\";\nimport type { ReceivingKeys } from \"../types\";\nimport {\n decodeAddress,\n encodeLongAddress,\n encodeShortAddress,\n type ReceivingAddress as ReceivingData,\n type ReceivingKeyLookup,\n} from \"./address\";\n\n/** Validated public receiving material. A short address requires an explicit resolver. */\nexport class ReceivingAddress {\n readonly #text: string;\n\n private constructor(text: string) {\n const decoded = decodeAddress(text);\n this.#text = decoded.kind === \"short\" ? encodeShortAddress(decoded.ownerAddress) : text;\n Object.freeze(this);\n }\n\n static parse(text: string): ReceivingAddress {\n return new ReceivingAddress(text);\n }\n\n static from(recipient: ReceivingData): ReceivingAddress {\n return new ReceivingAddress(encodeLongAddress(recipient));\n }\n\n static fromIdentity(identity: bigint | `0x${string}`): ReceivingAddress {\n return new ReceivingAddress(encodeShortAddress(identity));\n }\n\n get ownerAddress(): `0x${string}` {\n return decodeAddress(this.#text).ownerAddress;\n }\n\n get kind(): \"long\" | \"short\" {\n return decodeAddress(this.#text).kind;\n }\n\n getReceivingKeys(): ReceivingKeys {\n const decoded = decodeAddress(this.#text);\n if (decoded.kind === \"short\") {\n throw new MissingCapabilityError(\"resolved receiving keys\");\n }\n return { viewingPublicKey: decoded.viewingPublicKey, clueKey: decoded.clueKey };\n }\n\n async resolve(lookup?: ReceivingKeyLookup): Promise<ReceivingAddress> {\n if (this.kind === \"long\") {\n return this;\n }\n if (!lookup) {\n throw new MissingCapabilityError(\"explicit registry lookup\");\n }\n const keys = await lookup(this.ownerAddress);\n if (!keys) {\n throw new Error(\"owner address is not registered\");\n }\n return ReceivingAddress.from({\n ownerAddress: this.ownerAddress,\n viewingPublicKey: keys.viewingPublicKey,\n clueKey: keys.clueKey,\n });\n }\n\n get viewingPublicKey(): Uint8Array {\n return this.getReceivingKeys().viewingPublicKey;\n }\n\n get clueKey(): Uint8Array {\n return this.getReceivingKeys().clueKey;\n }\n\n toString(): string {\n return this.#text;\n }\n\n toJSON(): string {\n return this.#text;\n }\n}\n"],"mappings":"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","names":["import_utils","import_blake2b"]}
@@ -0,0 +1,35 @@
1
+ import { R as ReceivingKeys } from './types-CEAuh35C.cjs';
2
+
3
+ interface ReceivingAddress$1 {
4
+ ownerAddress: `0x${string}`;
5
+ viewingPublicKey: Uint8Array;
6
+ clueKey: Uint8Array;
7
+ }
8
+ type DecodedAddress = ({
9
+ kind: "long";
10
+ } & ReceivingAddress$1) | {
11
+ kind: "short";
12
+ ownerAddress: `0x${string}`;
13
+ };
14
+ type ReceivingKeyLookup = (ownerAddress: `0x${string}`) => Promise<Pick<ReceivingAddress$1, "viewingPublicKey" | "clueKey"> | null | undefined>;
15
+ /** Standard EVM short addresses or a full 0i address with a strict custom Base32 case checksum. */
16
+ declare function decodeAddress(address: string): DecodedAddress;
17
+
18
+ /** Validated public receiving material. A short address requires an explicit resolver. */
19
+ declare class ReceivingAddress {
20
+ #private;
21
+ private constructor();
22
+ static parse(text: string): ReceivingAddress;
23
+ static from(recipient: ReceivingAddress$1): ReceivingAddress;
24
+ static fromIdentity(identity: bigint | `0x${string}`): ReceivingAddress;
25
+ get ownerAddress(): `0x${string}`;
26
+ get kind(): "long" | "short";
27
+ getReceivingKeys(): ReceivingKeys;
28
+ resolve(lookup?: ReceivingKeyLookup): Promise<ReceivingAddress>;
29
+ get viewingPublicKey(): Uint8Array;
30
+ get clueKey(): Uint8Array;
31
+ toString(): string;
32
+ toJSON(): string;
33
+ }
34
+
35
+ export { type DecodedAddress, ReceivingAddress, type ReceivingKeyLookup, ReceivingKeys, decodeAddress };
@@ -0,0 +1,35 @@
1
+ import { R as ReceivingKeys } from './types-CEAuh35C.js';
2
+
3
+ interface ReceivingAddress$1 {
4
+ ownerAddress: `0x${string}`;
5
+ viewingPublicKey: Uint8Array;
6
+ clueKey: Uint8Array;
7
+ }
8
+ type DecodedAddress = ({
9
+ kind: "long";
10
+ } & ReceivingAddress$1) | {
11
+ kind: "short";
12
+ ownerAddress: `0x${string}`;
13
+ };
14
+ type ReceivingKeyLookup = (ownerAddress: `0x${string}`) => Promise<Pick<ReceivingAddress$1, "viewingPublicKey" | "clueKey"> | null | undefined>;
15
+ /** Standard EVM short addresses or a full 0i address with a strict custom Base32 case checksum. */
16
+ declare function decodeAddress(address: string): DecodedAddress;
17
+
18
+ /** Validated public receiving material. A short address requires an explicit resolver. */
19
+ declare class ReceivingAddress {
20
+ #private;
21
+ private constructor();
22
+ static parse(text: string): ReceivingAddress;
23
+ static from(recipient: ReceivingAddress$1): ReceivingAddress;
24
+ static fromIdentity(identity: bigint | `0x${string}`): ReceivingAddress;
25
+ get ownerAddress(): `0x${string}`;
26
+ get kind(): "long" | "short";
27
+ getReceivingKeys(): ReceivingKeys;
28
+ resolve(lookup?: ReceivingKeyLookup): Promise<ReceivingAddress>;
29
+ get viewingPublicKey(): Uint8Array;
30
+ get clueKey(): Uint8Array;
31
+ toString(): string;
32
+ toJSON(): string;
33
+ }
34
+
35
+ export { type DecodedAddress, ReceivingAddress, type ReceivingKeyLookup, ReceivingKeys, decodeAddress };
@@ -0,0 +1,10 @@
1
+ import {
2
+ ReceivingAddress,
3
+ decodeAddress
4
+ } from "./chunk-3SEC7POH.js";
5
+ import "./chunk-Q3NNEKKR.js";
6
+ export {
7
+ ReceivingAddress,
8
+ decodeAddress
9
+ };
10
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,168 @@
1
+ import {
2
+ validateClueKey
3
+ } from "./chunk-Q3NNEKKR.js";
4
+
5
+ // src/address/address.ts
6
+ import { secp256k1 } from "@noble/curves/secp256k1";
7
+ import { keccak_256 } from "@noble/hashes/sha3";
8
+ import { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from "@noble/hashes/utils";
9
+ import { getAddress } from "ethers";
10
+ var ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
11
+ function identityBytes(value) {
12
+ if (typeof value !== "bigint" && (typeof value !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(value)))
13
+ throw new Error("invalid owner address encoding");
14
+ const n = BigInt(value);
15
+ if (n <= 0n || n >= 1n << 160n)
16
+ throw new RangeError("owner address must be a nonzero EVM owner address");
17
+ return hexToBytes(n.toString(16).padStart(40, "0"));
18
+ }
19
+ function receivingKeys(keys) {
20
+ const publicKey = keys.viewingPublicKey;
21
+ if (!(publicKey instanceof Uint8Array) || publicKey.length !== 33 || publicKey[0] !== 2 && publicKey[0] !== 3)
22
+ throw new Error("invalid compressed viewing public key");
23
+ secp256k1.ProjectivePoint.fromHex(publicKey).assertValidity();
24
+ validateClueKey(keys.clueKey);
25
+ return { viewingPublicKey: Uint8Array.from(publicKey), clueKey: Uint8Array.from(keys.clueKey) };
26
+ }
27
+ function checkedText(prefix, data) {
28
+ const digest = keccak_256(utf8ToBytes("Invisi.AddressCaseChecksum.v1:" + prefix + data));
29
+ return prefix + Array.from(
30
+ data,
31
+ (character, i) => digest[i >> 3] >> 7 - (i & 7) & 1 ? character.toUpperCase() : character
32
+ ).join("");
33
+ }
34
+ function encode(prefix, payload) {
35
+ let buffer = 0, bits = 0, data = "";
36
+ for (const byte of payload) {
37
+ buffer = buffer << 8 | byte;
38
+ bits += 8;
39
+ while (bits >= 5) {
40
+ bits -= 5;
41
+ data += ALPHABET[buffer >>> bits & 31];
42
+ }
43
+ buffer &= (1 << bits) - 1;
44
+ }
45
+ if (bits) data += ALPHABET[buffer << 5 - bits & 31];
46
+ return checkedText(prefix, data);
47
+ }
48
+ function encodeLongAddress(recipient) {
49
+ const identity = identityBytes(recipient.ownerAddress), keys = receivingKeys(recipient);
50
+ return encode("0i", concatBytes(identity, keys.viewingPublicKey, keys.clueKey));
51
+ }
52
+ function encodeShortAddress(ownerAddress) {
53
+ const identity = identityBytes(ownerAddress);
54
+ return getAddress(
55
+ typeof ownerAddress === "string" ? ownerAddress : `0x${bytesToHex(identity)}`
56
+ );
57
+ }
58
+ function decodeAddress(address) {
59
+ if (typeof address !== "string") throw new TypeError("address must be text");
60
+ if (address.startsWith("0x")) {
61
+ const owner = getAddress(address);
62
+ return { kind: "short", ownerAddress: `0x${bytesToHex(identityBytes(owner))}` };
63
+ }
64
+ if (!address.startsWith("0i")) throw new Error("invalid Invisi address prefix");
65
+ const prefix = "0i";
66
+ if (address.length !== 138) throw new Error("invalid address length");
67
+ const data = address.slice(prefix.length).toLowerCase();
68
+ if (Array.from(data).some((character) => !ALPHABET.includes(character)))
69
+ throw new Error("invalid address alphabet");
70
+ if (checkedText(prefix, data) !== address) throw new Error("invalid address case checksum");
71
+ let buffer = 0, bits = 0;
72
+ const payload = [];
73
+ for (const character of data) {
74
+ buffer = buffer << 5 | ALPHABET.indexOf(character);
75
+ bits += 5;
76
+ if (bits >= 8) {
77
+ bits -= 8;
78
+ payload.push(buffer >>> bits & 255);
79
+ }
80
+ buffer &= (1 << bits) - 1;
81
+ }
82
+ if (bits !== 0 || buffer !== 0) throw new Error("noncanonical address padding");
83
+ const raw = Uint8Array.from(payload);
84
+ const ownerAddress = `0x${bytesToHex(identityBytes(`0x${bytesToHex(raw.subarray(0, 20))}`))}`;
85
+ return {
86
+ kind: "long",
87
+ ownerAddress,
88
+ ...receivingKeys({ viewingPublicKey: raw.slice(20, 53), clueKey: raw.slice(53) })
89
+ };
90
+ }
91
+
92
+ // src/errors.ts
93
+ var MissingCapabilityError = class extends Error {
94
+ constructor(capability) {
95
+ super(`Missing ${capability} capability`);
96
+ this.capability = capability;
97
+ this.name = "MissingCapabilityError";
98
+ }
99
+ code = "MISSING_CAPABILITY";
100
+ };
101
+
102
+ // src/address/receiving-address.ts
103
+ var ReceivingAddress = class _ReceivingAddress {
104
+ #text;
105
+ constructor(text) {
106
+ const decoded = decodeAddress(text);
107
+ this.#text = decoded.kind === "short" ? encodeShortAddress(decoded.ownerAddress) : text;
108
+ Object.freeze(this);
109
+ }
110
+ static parse(text) {
111
+ return new _ReceivingAddress(text);
112
+ }
113
+ static from(recipient) {
114
+ return new _ReceivingAddress(encodeLongAddress(recipient));
115
+ }
116
+ static fromIdentity(identity) {
117
+ return new _ReceivingAddress(encodeShortAddress(identity));
118
+ }
119
+ get ownerAddress() {
120
+ return decodeAddress(this.#text).ownerAddress;
121
+ }
122
+ get kind() {
123
+ return decodeAddress(this.#text).kind;
124
+ }
125
+ getReceivingKeys() {
126
+ const decoded = decodeAddress(this.#text);
127
+ if (decoded.kind === "short") {
128
+ throw new MissingCapabilityError("resolved receiving keys");
129
+ }
130
+ return { viewingPublicKey: decoded.viewingPublicKey, clueKey: decoded.clueKey };
131
+ }
132
+ async resolve(lookup) {
133
+ if (this.kind === "long") {
134
+ return this;
135
+ }
136
+ if (!lookup) {
137
+ throw new MissingCapabilityError("explicit registry lookup");
138
+ }
139
+ const keys = await lookup(this.ownerAddress);
140
+ if (!keys) {
141
+ throw new Error("owner address is not registered");
142
+ }
143
+ return _ReceivingAddress.from({
144
+ ownerAddress: this.ownerAddress,
145
+ viewingPublicKey: keys.viewingPublicKey,
146
+ clueKey: keys.clueKey
147
+ });
148
+ }
149
+ get viewingPublicKey() {
150
+ return this.getReceivingKeys().viewingPublicKey;
151
+ }
152
+ get clueKey() {
153
+ return this.getReceivingKeys().clueKey;
154
+ }
155
+ toString() {
156
+ return this.#text;
157
+ }
158
+ toJSON() {
159
+ return this.#text;
160
+ }
161
+ };
162
+
163
+ export {
164
+ decodeAddress,
165
+ MissingCapabilityError,
166
+ ReceivingAddress
167
+ };
168
+ //# sourceMappingURL=chunk-3SEC7POH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/address/address.ts","../src/errors.ts","../src/address/receiving-address.ts"],"sourcesContent":["import { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { keccak_256 } from \"@noble/hashes/sha3\";\nimport { bytesToHex, concatBytes, hexToBytes, utf8ToBytes } from \"@noble/hashes/utils\";\nimport { getAddress } from \"ethers\";\nimport { validateClueKey } from \"../fmd/fmd\";\n\nexport interface ReceivingAddress {\n ownerAddress: `0x${string}`;\n viewingPublicKey: Uint8Array;\n clueKey: Uint8Array;\n}\nexport type DecodedAddress =\n ({ kind: \"long\" } & ReceivingAddress) | { kind: \"short\"; ownerAddress: `0x${string}` };\nexport type ReceivingKeyLookup = (\n ownerAddress: `0x${string}`\n) => Promise<Pick<ReceivingAddress, \"viewingPublicKey\" | \"clueKey\"> | null | undefined>;\nconst ALPHABET = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\ntype Identity = bigint | `0x${string}`;\n\nfunction identityBytes(value: Identity): Uint8Array {\n if (\n typeof value !== \"bigint\" &&\n (typeof value !== \"string\" || !/^0x[0-9a-fA-F]{40}$/.test(value))\n )\n throw new Error(\"invalid owner address encoding\");\n const n = BigInt(value);\n if (n <= 0n || n >= 1n << 160n)\n throw new RangeError(\"owner address must be a nonzero EVM owner address\");\n return hexToBytes(n.toString(16).padStart(40, \"0\"));\n}\nfunction receivingKeys(keys: Pick<ReceivingAddress, \"viewingPublicKey\" | \"clueKey\">) {\n const publicKey = keys.viewingPublicKey;\n if (\n !(publicKey instanceof Uint8Array) ||\n publicKey.length !== 33 ||\n (publicKey[0] !== 2 && publicKey[0] !== 3)\n )\n throw new Error(\"invalid compressed viewing public key\");\n secp256k1.ProjectivePoint.fromHex(publicKey).assertValidity();\n validateClueKey(keys.clueKey);\n return { viewingPublicKey: Uint8Array.from(publicKey), clueKey: Uint8Array.from(keys.clueKey) };\n}\nfunction checkedText(prefix: string, data: string): string {\n const digest = keccak_256(utf8ToBytes(\"Invisi.AddressCaseChecksum.v1:\" + prefix + data));\n return (\n prefix +\n Array.from(data, (character, i) =>\n (digest[i >> 3]! >> (7 - (i & 7))) & 1 ? character.toUpperCase() : character\n ).join(\"\")\n );\n}\nfunction encode(prefix: string, payload: Uint8Array): string {\n let buffer = 0,\n bits = 0,\n data = \"\";\n for (const byte of payload) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n bits -= 5;\n data += ALPHABET[(buffer >>> bits) & 31];\n }\n buffer &= (1 << bits) - 1;\n }\n if (bits) data += ALPHABET[(buffer << (5 - bits)) & 31];\n return checkedText(prefix, data);\n}\n\n/** 138 characters: 0i plus the complete offline receiving materials. */\nexport function encodeLongAddress(recipient: ReceivingAddress): string {\n const identity = identityBytes(recipient.ownerAddress),\n keys = receivingKeys(recipient);\n return encode(\"0i\", concatBytes(identity, keys.viewingPublicKey, keys.clueKey));\n}\n/** The owner's 42-character checksummed EVM address; receiving keys require a chosen registry. */\nexport function encodeShortAddress(ownerAddress: Identity): string {\n const identity = identityBytes(ownerAddress);\n return getAddress(\n typeof ownerAddress === \"string\" ? ownerAddress : `0x${bytesToHex(identity)}`\n );\n}\n\n/** Standard EVM short addresses or a full 0i address with a strict custom Base32 case checksum. */\nexport function decodeAddress(address: string): DecodedAddress {\n if (typeof address !== \"string\") throw new TypeError(\"address must be text\");\n if (address.startsWith(\"0x\")) {\n const owner = getAddress(address) as `0x${string}`;\n return { kind: \"short\", ownerAddress: `0x${bytesToHex(identityBytes(owner))}` };\n }\n if (!address.startsWith(\"0i\")) throw new Error(\"invalid Invisi address prefix\");\n const prefix = \"0i\";\n if (address.length !== 138) throw new Error(\"invalid address length\");\n const data = address.slice(prefix.length).toLowerCase();\n if (Array.from(data).some((character) => !ALPHABET.includes(character)))\n throw new Error(\"invalid address alphabet\");\n if (checkedText(prefix, data) !== address) throw new Error(\"invalid address case checksum\");\n let buffer = 0,\n bits = 0;\n const payload: number[] = [];\n for (const character of data) {\n buffer = (buffer << 5) | ALPHABET.indexOf(character);\n bits += 5;\n if (bits >= 8) {\n bits -= 8;\n payload.push((buffer >>> bits) & 255);\n }\n buffer &= (1 << bits) - 1;\n }\n if (bits !== 0 || buffer !== 0) throw new Error(\"noncanonical address padding\");\n const raw = Uint8Array.from(payload);\n const ownerAddress =\n `0x${bytesToHex(identityBytes(`0x${bytesToHex(raw.subarray(0, 20))}`))}` as const;\n return {\n kind: \"long\",\n ownerAddress,\n ...receivingKeys({ viewingPublicKey: raw.slice(20, 53), clueKey: raw.slice(53) }),\n };\n}\n\n/** Normalize either address into the same payment input. Long addresses never query. */\nexport async function resolveAddress(\n address: string,\n options: { lookup?: ReceivingKeyLookup } = {}\n): Promise<ReceivingAddress> {\n const decoded = decodeAddress(address);\n if (decoded.kind === \"long\")\n return {\n ownerAddress: decoded.ownerAddress,\n viewingPublicKey: decoded.viewingPublicKey,\n clueKey: decoded.clueKey,\n };\n if (!options.lookup) throw new Error(\"short address requires an explicit registry lookup\");\n const keys = await options.lookup(decoded.ownerAddress);\n if (!keys) throw new Error(\"owner address is not registered\");\n return { ownerAddress: decoded.ownerAddress, ...receivingKeys(keys) };\n}\n","/** A requested permission was not explicitly supplied to this component. */\nexport class MissingCapabilityError extends Error {\n readonly code = \"MISSING_CAPABILITY\";\n constructor(readonly capability: string) {\n super(`Missing ${capability} capability`);\n this.name = \"MissingCapabilityError\";\n }\n}\n","import { MissingCapabilityError } from \"../errors\";\nimport type { ReceivingKeys } from \"../types\";\nimport {\n decodeAddress,\n encodeLongAddress,\n encodeShortAddress,\n type ReceivingAddress as ReceivingData,\n type ReceivingKeyLookup,\n} from \"./address\";\n\n/** Validated public receiving material. A short address requires an explicit resolver. */\nexport class ReceivingAddress {\n readonly #text: string;\n\n private constructor(text: string) {\n const decoded = decodeAddress(text);\n this.#text = decoded.kind === \"short\" ? encodeShortAddress(decoded.ownerAddress) : text;\n Object.freeze(this);\n }\n\n static parse(text: string): ReceivingAddress {\n return new ReceivingAddress(text);\n }\n\n static from(recipient: ReceivingData): ReceivingAddress {\n return new ReceivingAddress(encodeLongAddress(recipient));\n }\n\n static fromIdentity(identity: bigint | `0x${string}`): ReceivingAddress {\n return new ReceivingAddress(encodeShortAddress(identity));\n }\n\n get ownerAddress(): `0x${string}` {\n return decodeAddress(this.#text).ownerAddress;\n }\n\n get kind(): \"long\" | \"short\" {\n return decodeAddress(this.#text).kind;\n }\n\n getReceivingKeys(): ReceivingKeys {\n const decoded = decodeAddress(this.#text);\n if (decoded.kind === \"short\") {\n throw new MissingCapabilityError(\"resolved receiving keys\");\n }\n return { viewingPublicKey: decoded.viewingPublicKey, clueKey: decoded.clueKey };\n }\n\n async resolve(lookup?: ReceivingKeyLookup): Promise<ReceivingAddress> {\n if (this.kind === \"long\") {\n return this;\n }\n if (!lookup) {\n throw new MissingCapabilityError(\"explicit registry lookup\");\n }\n const keys = await lookup(this.ownerAddress);\n if (!keys) {\n throw new Error(\"owner address is not registered\");\n }\n return ReceivingAddress.from({\n ownerAddress: this.ownerAddress,\n viewingPublicKey: keys.viewingPublicKey,\n clueKey: keys.clueKey,\n });\n }\n\n get viewingPublicKey(): Uint8Array {\n return this.getReceivingKeys().viewingPublicKey;\n }\n\n get clueKey(): Uint8Array {\n return this.getReceivingKeys().clueKey;\n }\n\n toString(): string {\n return this.#text;\n }\n\n toJSON(): string {\n return this.#text;\n }\n}\n"],"mappings":"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","names":[]}