@oma3/omatrust 0.1.0-alpha.1 → 0.1.0-alpha.11

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.
Files changed (44) hide show
  1. package/README.md +21 -7
  2. package/dist/identity/index.cjs +544 -1
  3. package/dist/identity/index.cjs.map +1 -1
  4. package/dist/identity/index.d.cts +2 -1
  5. package/dist/identity/index.d.ts +2 -1
  6. package/dist/identity/index.js +528 -2
  7. package/dist/identity/index.js.map +1 -1
  8. package/dist/index-BOvk-7Ku.d.cts +235 -0
  9. package/dist/index-C2w5EvFH.d.ts +329 -0
  10. package/dist/index-QueRiudB.d.cts +329 -0
  11. package/dist/index-R78TpAhN.d.ts +235 -0
  12. package/dist/index.cjs +2020 -145
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +4 -2
  15. package/dist/index.d.ts +4 -2
  16. package/dist/index.js +2021 -146
  17. package/dist/index.js.map +1 -1
  18. package/dist/reputation/index.browser.cjs +3010 -0
  19. package/dist/reputation/index.browser.cjs.map +1 -0
  20. package/dist/reputation/index.browser.d.cts +14 -0
  21. package/dist/reputation/index.browser.d.ts +14 -0
  22. package/dist/reputation/index.browser.js +2946 -0
  23. package/dist/reputation/index.browser.js.map +1 -0
  24. package/dist/reputation/index.cjs +1884 -123
  25. package/dist/reputation/index.cjs.map +1 -1
  26. package/dist/reputation/index.d.cts +3 -1
  27. package/dist/reputation/index.d.ts +3 -1
  28. package/dist/reputation/index.js +1861 -123
  29. package/dist/reputation/index.js.map +1 -1
  30. package/dist/subject-ownership-B7cFlm8c.d.cts +664 -0
  31. package/dist/subject-ownership-B7cFlm8c.d.ts +664 -0
  32. package/dist/types-dpYxRq8N.d.cts +281 -0
  33. package/dist/types-dpYxRq8N.d.ts +281 -0
  34. package/dist/widgets/index.cjs +238 -0
  35. package/dist/widgets/index.cjs.map +1 -0
  36. package/dist/widgets/index.d.cts +158 -0
  37. package/dist/widgets/index.d.ts +158 -0
  38. package/dist/widgets/index.js +226 -0
  39. package/dist/widgets/index.js.map +1 -0
  40. package/package.json +35 -7
  41. package/dist/index-ChbJxwOA.d.cts +0 -415
  42. package/dist/index-ChbJxwOA.d.ts +0 -415
  43. package/dist/index-QZDExA4I.d.cts +0 -90
  44. package/dist/index-QZDExA4I.d.ts +0 -90
@@ -0,0 +1,238 @@
1
+ 'use strict';
2
+
3
+ // src/widgets/protocol.ts
4
+ var OMATRUST_READY = "omatrust:ready";
5
+ var OMATRUST_HOST_READY = "omatrust:hostReady";
6
+ var OMATRUST_SIGN_TYPED_DATA = "omatrust:signTypedData";
7
+ var OMATRUST_SIGNATURE = "omatrust:signature";
8
+ var OMATRUST_SIGNATURE_ERROR = "omatrust:signatureError";
9
+
10
+ // src/shared/errors.ts
11
+ var OmaTrustError = class extends Error {
12
+ code;
13
+ details;
14
+ constructor(code, message, details) {
15
+ super(message);
16
+ this.name = "OmaTrustError";
17
+ this.code = code;
18
+ this.details = details;
19
+ }
20
+ };
21
+
22
+ // src/shared/trust-anchors.ts
23
+ var DEFAULT_TRUST_ANCHORS_URL = "https://api.omatrust.org/v1/trust-anchors";
24
+ var TRUST_ANCHORS_URL = DEFAULT_TRUST_ANCHORS_URL;
25
+ var cachedAnchors = null;
26
+ var cacheTimestamp = 0;
27
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
28
+ async function fetchTrustAnchors(url) {
29
+ const now = Date.now();
30
+ if (cachedAnchors && now - cacheTimestamp < CACHE_TTL_MS) {
31
+ return cachedAnchors;
32
+ }
33
+ let res;
34
+ try {
35
+ res = await fetch(url ?? TRUST_ANCHORS_URL);
36
+ } catch (err) {
37
+ throw new OmaTrustError("NETWORK_ERROR", "Failed to fetch trust anchors", { err });
38
+ }
39
+ if (!res.ok) {
40
+ throw new OmaTrustError("NETWORK_ERROR", `Failed to fetch trust anchors: ${res.status} ${res.statusText}`);
41
+ }
42
+ const anchors = await res.json();
43
+ if (!anchors.version || !anchors.chains || typeof anchors.chains !== "object") {
44
+ throw new OmaTrustError("INVALID_INPUT", "Invalid trust anchors format");
45
+ }
46
+ cachedAnchors = anchors;
47
+ cacheTimestamp = now;
48
+ return anchors;
49
+ }
50
+ function getChainAnchors(anchors, caip2) {
51
+ const chain = anchors.chains[caip2];
52
+ if (!chain) {
53
+ throw new OmaTrustError("UNSUPPORTED_CHAIN", `Chain ${caip2} is not in the trust anchors`, {
54
+ caip2,
55
+ supportedChains: Object.keys(anchors.chains)
56
+ });
57
+ }
58
+ return chain;
59
+ }
60
+ function getSchemaAnchor(anchors, caip2, schemaName) {
61
+ const chain = getChainAnchors(anchors, caip2);
62
+ const uid = chain.schemas[schemaName];
63
+ if (!uid) {
64
+ throw new OmaTrustError("INVALID_INPUT", `Schema "${schemaName}" not found in trust anchors for chain ${caip2}`, {
65
+ caip2,
66
+ schemaName,
67
+ availableSchemas: Object.keys(chain.schemas)
68
+ });
69
+ }
70
+ return uid;
71
+ }
72
+ function extractAllowlists(anchors) {
73
+ const contracts = [];
74
+ const schemas = [];
75
+ for (const chain of Object.values(anchors.chains)) {
76
+ if (chain.easContract) contracts.push(chain.easContract);
77
+ if (chain.schemas && typeof chain.schemas === "object") {
78
+ schemas.push(...Object.values(chain.schemas));
79
+ }
80
+ }
81
+ return {
82
+ allowedContracts: [...new Set(contracts)],
83
+ allowedSchemas: [...new Set(schemas)]
84
+ };
85
+ }
86
+
87
+ // src/widgets/bridge.ts
88
+ function getTrustedBaseDomain() {
89
+ try {
90
+ const hostname = new URL(TRUST_ANCHORS_URL).hostname;
91
+ const parts = hostname.split(".");
92
+ return parts.length >= 2 ? parts.slice(-2).join(".") : hostname;
93
+ } catch {
94
+ return "omatrust.org";
95
+ }
96
+ }
97
+ function isOriginTrusted(messageOrigin, baseDomain, policyOrigins, devOverride) {
98
+ if (devOverride && messageOrigin === devOverride) return true;
99
+ try {
100
+ const hostname = new URL(messageOrigin).hostname;
101
+ if (hostname === baseDomain || hostname.endsWith(`.${baseDomain}`)) return true;
102
+ } catch {
103
+ }
104
+ if (policyOrigins.includes(messageOrigin)) return true;
105
+ return false;
106
+ }
107
+ var HEX_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
108
+ var BYTES32_RE = /^0x[a-fA-F0-9]{64}$/;
109
+ function validateEasSigningRequest(data, allowedSchemas, allowedContracts) {
110
+ const { id, domain, types, message } = data;
111
+ if (!id || typeof id !== "string") {
112
+ return { valid: false, reason: "Missing or invalid request id" };
113
+ }
114
+ if (!domain || typeof domain !== "object") {
115
+ return { valid: false, reason: "Missing domain object" };
116
+ }
117
+ const d = domain;
118
+ if (d.name !== "EAS") {
119
+ return { valid: false, reason: `Unexpected domain name: "${d.name}" (expected "EAS")` };
120
+ }
121
+ if (d.version !== "1.4.0") {
122
+ return { valid: false, reason: `Unexpected domain version: "${d.version}" (expected "1.4.0")` };
123
+ }
124
+ const chainId = Number(d.chainId);
125
+ if (!Number.isInteger(chainId) || chainId <= 0) {
126
+ return { valid: false, reason: `Invalid domain chainId: ${d.chainId}` };
127
+ }
128
+ if (typeof d.verifyingContract !== "string" || !HEX_ADDRESS_RE.test(d.verifyingContract)) {
129
+ return { valid: false, reason: `Invalid verifyingContract: ${d.verifyingContract}` };
130
+ }
131
+ const contractLower = d.verifyingContract.toLowerCase();
132
+ if (!allowedContracts.some((c) => c.toLowerCase() === contractLower)) {
133
+ return { valid: false, reason: `Contract ${d.verifyingContract} is not in the OMA3 trust anchors` };
134
+ }
135
+ if (!types || typeof types !== "object") {
136
+ return { valid: false, reason: "Missing types object" };
137
+ }
138
+ if (!message || typeof message !== "object") {
139
+ return { valid: false, reason: "Missing message object" };
140
+ }
141
+ const m = message;
142
+ if (typeof m.schema !== "string" || !BYTES32_RE.test(m.schema)) {
143
+ return { valid: false, reason: `Invalid schema UID: ${m.schema}` };
144
+ }
145
+ const schemaLower = m.schema.toLowerCase();
146
+ if (!allowedSchemas.some((s) => s.toLowerCase() === schemaLower)) {
147
+ return { valid: false, reason: `Schema ${m.schema} is not in the OMA3 trust anchors` };
148
+ }
149
+ if (typeof m.attester !== "string" || !HEX_ADDRESS_RE.test(m.attester)) {
150
+ return { valid: false, reason: `Invalid attester address: ${m.attester}` };
151
+ }
152
+ const deadline = Number(m.deadline);
153
+ if (!Number.isFinite(deadline) || deadline <= 0) {
154
+ return { valid: false, reason: `Invalid deadline: ${m.deadline}` };
155
+ }
156
+ const now = Math.floor(Date.now() / 1e3);
157
+ if (deadline <= now) {
158
+ return { valid: false, reason: `Deadline has passed: ${deadline} <= ${now}` };
159
+ }
160
+ return { valid: true };
161
+ }
162
+ async function createSigningBridge(options) {
163
+ const { iframeId, signTypedData, devOriginOverride } = options;
164
+ const anchors = await fetchTrustAnchors();
165
+ const { allowedContracts, allowedSchemas } = extractAllowlists(anchors);
166
+ if (allowedContracts.length === 0 || allowedSchemas.length === 0) {
167
+ throw new Error("Trust anchors contain no allowed contracts or schemas");
168
+ }
169
+ const baseDomain = getTrustedBaseDomain();
170
+ const anchorOrigins = anchors.widgetOrigins ?? [];
171
+ async function handleMessage(event) {
172
+ const data = event.data;
173
+ if (!data || typeof data !== "object" || typeof data.type !== "string") return;
174
+ if (!String(data.type).startsWith("omatrust:")) return;
175
+ if (!isOriginTrusted(event.origin, baseDomain, anchorOrigins, devOriginOverride)) {
176
+ return;
177
+ }
178
+ const iframe = document.getElementById(iframeId);
179
+ if (!iframe) return;
180
+ if (event.source !== iframe.contentWindow) {
181
+ return;
182
+ }
183
+ const source = event.source;
184
+ const replyOrigin = devOriginOverride ?? (() => {
185
+ try {
186
+ return new URL(iframe.src).origin;
187
+ } catch {
188
+ return "*";
189
+ }
190
+ })();
191
+ function reply(msg) {
192
+ source.postMessage(msg, replyOrigin);
193
+ }
194
+ if (data.type === OMATRUST_READY) {
195
+ reply({ type: OMATRUST_HOST_READY });
196
+ return;
197
+ }
198
+ if (data.type === OMATRUST_SIGN_TYPED_DATA) {
199
+ const { id, domain, types, message } = data;
200
+ const validation = validateEasSigningRequest(data, allowedSchemas, allowedContracts);
201
+ if (!validation.valid) {
202
+ reply({
203
+ type: OMATRUST_SIGNATURE_ERROR,
204
+ id: id ?? "unknown",
205
+ error: `Signing request rejected: ${validation.reason}`
206
+ });
207
+ return;
208
+ }
209
+ try {
210
+ const signature = await signTypedData(domain, types, message);
211
+ reply({ type: OMATRUST_SIGNATURE, id, signature });
212
+ } catch (err) {
213
+ const error = err instanceof Error ? err.message : "Signing failed";
214
+ reply({ type: OMATRUST_SIGNATURE_ERROR, id, error });
215
+ }
216
+ }
217
+ }
218
+ window.addEventListener("message", handleMessage);
219
+ return {
220
+ destroy() {
221
+ window.removeEventListener("message", handleMessage);
222
+ }
223
+ };
224
+ }
225
+
226
+ exports.OMATRUST_HOST_READY = OMATRUST_HOST_READY;
227
+ exports.OMATRUST_READY = OMATRUST_READY;
228
+ exports.OMATRUST_SIGNATURE = OMATRUST_SIGNATURE;
229
+ exports.OMATRUST_SIGNATURE_ERROR = OMATRUST_SIGNATURE_ERROR;
230
+ exports.OMATRUST_SIGN_TYPED_DATA = OMATRUST_SIGN_TYPED_DATA;
231
+ exports.TRUST_ANCHORS_URL = TRUST_ANCHORS_URL;
232
+ exports.createSigningBridge = createSigningBridge;
233
+ exports.extractAllowlists = extractAllowlists;
234
+ exports.fetchTrustAnchors = fetchTrustAnchors;
235
+ exports.getChainAnchors = getChainAnchors;
236
+ exports.getSchemaAnchor = getSchemaAnchor;
237
+ //# sourceMappingURL=index.cjs.map
238
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/widgets/protocol.ts","../../src/shared/errors.ts","../../src/shared/trust-anchors.ts","../../src/widgets/bridge.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * postMessage protocol constants and types for the OMATrust widget bridge.\n *\n * Widget (iframe) → Host:\n * omatrust:ready — widget loaded, requesting handshake\n * omatrust:signTypedData — widget requests EIP-712 signature\n *\n * Host → Widget (iframe):\n * omatrust:hostReady — host acknowledges the widget\n * omatrust:signature — host returns a signature\n * omatrust:signatureError — host reports a signing failure\n */\n\nexport const OMATRUST_READY = \"omatrust:ready\" as const;\nexport const OMATRUST_HOST_READY = \"omatrust:hostReady\" as const;\nexport const OMATRUST_SIGN_TYPED_DATA = \"omatrust:signTypedData\" as const;\nexport const OMATRUST_SIGNATURE = \"omatrust:signature\" as const;\nexport const OMATRUST_SIGNATURE_ERROR = \"omatrust:signatureError\" as const;\n\nexport type OmaTrustReadyMessage = {\n type: typeof OMATRUST_READY;\n};\n\nexport type OmaTrustHostReadyMessage = {\n type: typeof OMATRUST_HOST_READY;\n};\n\nexport type OmaTrustSignTypedDataMessage = {\n type: typeof OMATRUST_SIGN_TYPED_DATA;\n id: string;\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n message: Record<string, unknown>;\n};\n\nexport type OmaTrustSignatureMessage = {\n type: typeof OMATRUST_SIGNATURE;\n id: string;\n signature: string;\n};\n\nexport type OmaTrustSignatureErrorMessage = {\n type: typeof OMATRUST_SIGNATURE_ERROR;\n id: string;\n error: string;\n};\n\nexport type OmaTrustMessage =\n | OmaTrustReadyMessage\n | OmaTrustHostReadyMessage\n | OmaTrustSignTypedDataMessage\n | OmaTrustSignatureMessage\n | OmaTrustSignatureErrorMessage;\n","export class OmaTrustError extends Error {\n code: string;\n details?: unknown;\n\n constructor(code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"OmaTrustError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport function toOmaTrustError(\n code: string,\n message: string,\n details?: unknown\n): OmaTrustError {\n return new OmaTrustError(code, message, details);\n}\n","/**\n * Trust anchors: fetches the OMA3 allowlist of EAS contracts and schemas.\n *\n * Used by the widget signing bridge for request validation and by the\n * reputation module for chain/contract resolution.\n *\n * Chain keys use CAIP-2 identifiers (e.g., \"eip155:66238\").\n */\n\nimport { OmaTrustError } from \"./errors\";\n\nconst DEFAULT_TRUST_ANCHORS_URL = \"https://api.omatrust.org/v1/trust-anchors\";\n\nexport const TRUST_ANCHORS_URL = DEFAULT_TRUST_ANCHORS_URL;\n\nexport type ChainAnchors = {\n name: string;\n easContract: string;\n /** Schema name → schema UID mapping */\n schemas: Record<string, string>;\n};\n\nexport type ApprovedIssuer = {\n address: string;\n label: string;\n schemas: string[];\n};\n\nexport type TrustAnchors = {\n version: number;\n updatedAt: string;\n widgetOrigins?: string[];\n /** CAIP-2 chain identifier → chain-specific trust anchors */\n chains: Record<string, ChainAnchors>;\n registries?: Array<{\n type: \"approved-issuers\";\n issuers: ApprovedIssuer[];\n }>;\n};\n\nlet cachedAnchors: TrustAnchors | null = null;\nlet cacheTimestamp = 0;\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Fetch the trust anchors from the OMA3 API gateway.\n * Caches the result for 5 minutes.\n *\n * @param url Override the trust anchors URL (for testing or custom deployments)\n */\nexport async function fetchTrustAnchors(url?: string): Promise<TrustAnchors> {\n const now = Date.now();\n if (cachedAnchors && now - cacheTimestamp < CACHE_TTL_MS) {\n return cachedAnchors;\n }\n\n let res: Response;\n try {\n res = await fetch(url ?? TRUST_ANCHORS_URL);\n } catch (err) {\n throw new OmaTrustError(\"NETWORK_ERROR\", \"Failed to fetch trust anchors\", { err });\n }\n\n if (!res.ok) {\n throw new OmaTrustError(\"NETWORK_ERROR\", `Failed to fetch trust anchors: ${res.status} ${res.statusText}`);\n }\n\n const anchors: TrustAnchors = await res.json();\n\n if (!anchors.version || !anchors.chains || typeof anchors.chains !== \"object\") {\n throw new OmaTrustError(\"INVALID_INPUT\", \"Invalid trust anchors format\");\n }\n\n cachedAnchors = anchors;\n cacheTimestamp = now;\n return anchors;\n}\n\n/**\n * Look up chain anchors by CAIP-2 identifier.\n * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.\n */\nexport function getChainAnchors(anchors: TrustAnchors, caip2: string): ChainAnchors {\n const chain = anchors.chains[caip2];\n if (!chain) {\n throw new OmaTrustError(\"UNSUPPORTED_CHAIN\", `Chain ${caip2} is not in the trust anchors`, {\n caip2,\n supportedChains: Object.keys(anchors.chains),\n });\n }\n return chain;\n}\n\n/**\n * Look up a schema UID by name for a given chain.\n * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.\n * Throws INVALID_INPUT if the schema is not deployed on this chain.\n */\nexport function getSchemaAnchor(anchors: TrustAnchors, caip2: string, schemaName: string): string {\n const chain = getChainAnchors(anchors, caip2);\n const uid = chain.schemas[schemaName];\n if (!uid) {\n throw new OmaTrustError(\"INVALID_INPUT\", `Schema \"${schemaName}\" not found in trust anchors for chain ${caip2}`, {\n caip2,\n schemaName,\n availableSchemas: Object.keys(chain.schemas),\n });\n }\n return uid;\n}\n\n/**\n * Extract the allowed contracts and schema UIDs from trust anchors.\n * Returns all contracts and schema UIDs across all chains.\n */\nexport function extractAllowlists(anchors: TrustAnchors): {\n allowedContracts: string[];\n allowedSchemas: string[];\n} {\n const contracts: string[] = [];\n const schemas: string[] = [];\n\n for (const chain of Object.values(anchors.chains)) {\n if (chain.easContract) contracts.push(chain.easContract);\n if (chain.schemas && typeof chain.schemas === \"object\") {\n schemas.push(...Object.values(chain.schemas));\n }\n }\n\n return {\n allowedContracts: [...new Set(contracts)],\n allowedSchemas: [...new Set(schemas)],\n };\n}\n","/**\n * Host-side signing bridge for OMATrust widget iframes.\n *\n * Handles the postMessage protocol between a host page and an embedded\n * OMATrust widget. Validates incoming EAS signing requests against the\n * OMA3 trust anchors before forwarding to the host's wallet.\n *\n * The bridge resolves the iframe element lazily by ID when messages arrive,\n * avoiding React ref timing issues with conditionally rendered iframes.\n *\n * Usage:\n * import { createSigningBridge } from \"@oma3/omatrust/widgets\";\n *\n * const bridge = await createSigningBridge({\n * iframeId: \"omatrust-widget\",\n * signTypedData: async (domain, types, message) => {\n * return await signer.signTypedData(domain, types, message);\n * },\n * });\n *\n * bridge.destroy();\n */\n\nimport {\n OMATRUST_READY,\n OMATRUST_HOST_READY,\n OMATRUST_SIGN_TYPED_DATA,\n OMATRUST_SIGNATURE,\n OMATRUST_SIGNATURE_ERROR,\n} from \"./protocol\";\nimport { fetchTrustAnchors, extractAllowlists, TRUST_ANCHORS_URL } from \"../shared/trust-anchors\";\n\nexport type SigningBridgeOptions = {\n /**\n * The ID of the iframe element containing the widget.\n * The bridge looks up the element by ID when messages arrive,\n * so the iframe doesn't need to exist when the bridge is created.\n */\n iframeId: string;\n\n /**\n * Callback to sign EIP-712 typed data using the host's wallet.\n * Must return the hex-encoded signature string.\n */\n signTypedData: (\n domain: Record<string, unknown>,\n types: Record<string, unknown>,\n message: Record<string, unknown>\n ) => Promise<string>;\n\n /**\n * Override the allowed widget origin for local development.\n * In production, the origin is derived from the trust anchors domain\n * (*.omatrust.org) plus any widgetOrigins in the trust anchors.\n * Only set this for local dev (e.g., \"http://localhost:3000\").\n */\n devOriginOverride?: string;\n};\n\nexport type SigningBridge = {\n /** Remove all event listeners and stop the bridge. */\n destroy: () => void;\n};\n\n// ---------------------------------------------------------------------------\n// Origin resolution\n// ---------------------------------------------------------------------------\n\nfunction getTrustedBaseDomain(): string {\n try {\n const hostname = new URL(TRUST_ANCHORS_URL).hostname;\n const parts = hostname.split(\".\");\n return parts.length >= 2 ? parts.slice(-2).join(\".\") : hostname;\n } catch {\n return \"omatrust.org\";\n }\n}\n\nfunction isOriginTrusted(\n messageOrigin: string,\n baseDomain: string,\n policyOrigins: string[],\n devOverride?: string\n): boolean {\n if (devOverride && messageOrigin === devOverride) return true;\n\n try {\n const hostname = new URL(messageOrigin).hostname;\n if (hostname === baseDomain || hostname.endsWith(`.${baseDomain}`)) return true;\n } catch {\n // Invalid origin\n }\n\n if (policyOrigins.includes(messageOrigin)) return true;\n\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// EAS request validation\n// ---------------------------------------------------------------------------\n\nconst HEX_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;\nconst BYTES32_RE = /^0x[a-fA-F0-9]{64}$/;\n\ntype ValidationResult =\n | { valid: true }\n | { valid: false; reason: string };\n\nfunction validateEasSigningRequest(\n data: Record<string, unknown>,\n allowedSchemas: string[],\n allowedContracts: string[]\n): ValidationResult {\n const { id, domain, types, message } = data;\n\n if (!id || typeof id !== \"string\") {\n return { valid: false, reason: \"Missing or invalid request id\" };\n }\n if (!domain || typeof domain !== \"object\") {\n return { valid: false, reason: \"Missing domain object\" };\n }\n\n const d = domain as Record<string, unknown>;\n\n if (d.name !== \"EAS\") {\n return { valid: false, reason: `Unexpected domain name: \"${d.name}\" (expected \"EAS\")` };\n }\n if (d.version !== \"1.4.0\") {\n return { valid: false, reason: `Unexpected domain version: \"${d.version}\" (expected \"1.4.0\")` };\n }\n const chainId = Number(d.chainId);\n if (!Number.isInteger(chainId) || chainId <= 0) {\n return { valid: false, reason: `Invalid domain chainId: ${d.chainId}` };\n }\n if (typeof d.verifyingContract !== \"string\" || !HEX_ADDRESS_RE.test(d.verifyingContract)) {\n return { valid: false, reason: `Invalid verifyingContract: ${d.verifyingContract}` };\n }\n\n const contractLower = (d.verifyingContract as string).toLowerCase();\n if (!allowedContracts.some(c => c.toLowerCase() === contractLower)) {\n return { valid: false, reason: `Contract ${d.verifyingContract} is not in the OMA3 trust anchors` };\n }\n\n if (!types || typeof types !== \"object\") {\n return { valid: false, reason: \"Missing types object\" };\n }\n if (!message || typeof message !== \"object\") {\n return { valid: false, reason: \"Missing message object\" };\n }\n\n const m = message as Record<string, unknown>;\n\n if (typeof m.schema !== \"string\" || !BYTES32_RE.test(m.schema)) {\n return { valid: false, reason: `Invalid schema UID: ${m.schema}` };\n }\n\n const schemaLower = m.schema.toLowerCase();\n if (!allowedSchemas.some(s => s.toLowerCase() === schemaLower)) {\n return { valid: false, reason: `Schema ${m.schema} is not in the OMA3 trust anchors` };\n }\n\n if (typeof m.attester !== \"string\" || !HEX_ADDRESS_RE.test(m.attester)) {\n return { valid: false, reason: `Invalid attester address: ${m.attester}` };\n }\n\n const deadline = Number(m.deadline);\n if (!Number.isFinite(deadline) || deadline <= 0) {\n return { valid: false, reason: `Invalid deadline: ${m.deadline}` };\n }\n const now = Math.floor(Date.now() / 1000);\n if (deadline <= now) {\n return { valid: false, reason: `Deadline has passed: ${deadline} <= ${now}` };\n }\n\n return { valid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Bridge implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Create a signing bridge between the host page and an OMATrust widget iframe.\n *\n * The bridge resolves the iframe element by ID when messages arrive, not at\n * creation time. This avoids React ref timing issues — the bridge can be\n * created before the iframe is in the DOM.\n *\n * Fetches the OMA3 trust anchors on creation. Fails closed if unavailable.\n */\nexport async function createSigningBridge(options: SigningBridgeOptions): Promise<SigningBridge> {\n const { iframeId, signTypedData, devOriginOverride } = options;\n\n // Fetch the trust anchors: fail closed if unavailable.\n const anchors = await fetchTrustAnchors();\n const { allowedContracts, allowedSchemas } = extractAllowlists(anchors);\n\n if (allowedContracts.length === 0 || allowedSchemas.length === 0) {\n throw new Error(\"Trust anchors contain no allowed contracts or schemas\");\n }\n\n const baseDomain = getTrustedBaseDomain();\n const anchorOrigins = anchors.widgetOrigins ?? [];\n\n async function handleMessage(event: MessageEvent) {\n const data = event.data;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!String(data.type).startsWith(\"omatrust:\")) return;\n\n // Origin check\n if (!isOriginTrusted(event.origin, baseDomain, anchorOrigins, devOriginOverride)) {\n return;\n }\n\n // Resolve the iframe element lazily by ID.\n // This works even if the iframe was mounted after the bridge was created.\n const iframe = document.getElementById(iframeId) as HTMLIFrameElement | null;\n if (!iframe) return;\n\n // Source check — must come from this specific iframe\n if (event.source !== iframe.contentWindow) {\n return;\n }\n\n const source = event.source as WindowProxy;\n\n // Determine reply origin from the iframe's current src\n const replyOrigin = devOriginOverride ?? (() => {\n try { return new URL(iframe.src).origin; }\n catch { return \"*\"; }\n })();\n\n function reply(msg: Record<string, unknown>) {\n source.postMessage(msg, replyOrigin);\n }\n\n // Handshake\n if (data.type === OMATRUST_READY) {\n reply({ type: OMATRUST_HOST_READY });\n return;\n }\n\n // Signing request\n if (data.type === OMATRUST_SIGN_TYPED_DATA) {\n const { id, domain, types, message } = data;\n\n const validation = validateEasSigningRequest(data, allowedSchemas, allowedContracts);\n if (!validation.valid) {\n reply({\n type: OMATRUST_SIGNATURE_ERROR,\n id: id ?? \"unknown\",\n error: `Signing request rejected: ${validation.reason}`,\n });\n return;\n }\n\n try {\n const signature = await signTypedData(domain, types, message);\n reply({ type: OMATRUST_SIGNATURE, id, signature });\n } catch (err) {\n const error = err instanceof Error ? err.message : \"Signing failed\";\n reply({ type: OMATRUST_SIGNATURE_ERROR, id, error });\n }\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n\n return {\n destroy() {\n window.removeEventListener(\"message\", handleMessage);\n },\n };\n}\n"]}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Host-side signing bridge for OMATrust widget iframes.
3
+ *
4
+ * Handles the postMessage protocol between a host page and an embedded
5
+ * OMATrust widget. Validates incoming EAS signing requests against the
6
+ * OMA3 trust anchors before forwarding to the host's wallet.
7
+ *
8
+ * The bridge resolves the iframe element lazily by ID when messages arrive,
9
+ * avoiding React ref timing issues with conditionally rendered iframes.
10
+ *
11
+ * Usage:
12
+ * import { createSigningBridge } from "@oma3/omatrust/widgets";
13
+ *
14
+ * const bridge = await createSigningBridge({
15
+ * iframeId: "omatrust-widget",
16
+ * signTypedData: async (domain, types, message) => {
17
+ * return await signer.signTypedData(domain, types, message);
18
+ * },
19
+ * });
20
+ *
21
+ * bridge.destroy();
22
+ */
23
+ type SigningBridgeOptions = {
24
+ /**
25
+ * The ID of the iframe element containing the widget.
26
+ * The bridge looks up the element by ID when messages arrive,
27
+ * so the iframe doesn't need to exist when the bridge is created.
28
+ */
29
+ iframeId: string;
30
+ /**
31
+ * Callback to sign EIP-712 typed data using the host's wallet.
32
+ * Must return the hex-encoded signature string.
33
+ */
34
+ signTypedData: (domain: Record<string, unknown>, types: Record<string, unknown>, message: Record<string, unknown>) => Promise<string>;
35
+ /**
36
+ * Override the allowed widget origin for local development.
37
+ * In production, the origin is derived from the trust anchors domain
38
+ * (*.omatrust.org) plus any widgetOrigins in the trust anchors.
39
+ * Only set this for local dev (e.g., "http://localhost:3000").
40
+ */
41
+ devOriginOverride?: string;
42
+ };
43
+ type SigningBridge = {
44
+ /** Remove all event listeners and stop the bridge. */
45
+ destroy: () => void;
46
+ };
47
+ /**
48
+ * Create a signing bridge between the host page and an OMATrust widget iframe.
49
+ *
50
+ * The bridge resolves the iframe element by ID when messages arrive, not at
51
+ * creation time. This avoids React ref timing issues — the bridge can be
52
+ * created before the iframe is in the DOM.
53
+ *
54
+ * Fetches the OMA3 trust anchors on creation. Fails closed if unavailable.
55
+ */
56
+ declare function createSigningBridge(options: SigningBridgeOptions): Promise<SigningBridge>;
57
+
58
+ /**
59
+ * Trust anchors: fetches the OMA3 allowlist of EAS contracts and schemas.
60
+ *
61
+ * Used by the widget signing bridge for request validation and by the
62
+ * reputation module for chain/contract resolution.
63
+ *
64
+ * Chain keys use CAIP-2 identifiers (e.g., "eip155:66238").
65
+ */
66
+ declare const TRUST_ANCHORS_URL = "https://api.omatrust.org/v1/trust-anchors";
67
+ type ChainAnchors = {
68
+ name: string;
69
+ easContract: string;
70
+ /** Schema name → schema UID mapping */
71
+ schemas: Record<string, string>;
72
+ };
73
+ type ApprovedIssuer = {
74
+ address: string;
75
+ label: string;
76
+ schemas: string[];
77
+ };
78
+ type TrustAnchors = {
79
+ version: number;
80
+ updatedAt: string;
81
+ widgetOrigins?: string[];
82
+ /** CAIP-2 chain identifier → chain-specific trust anchors */
83
+ chains: Record<string, ChainAnchors>;
84
+ registries?: Array<{
85
+ type: "approved-issuers";
86
+ issuers: ApprovedIssuer[];
87
+ }>;
88
+ };
89
+ /**
90
+ * Fetch the trust anchors from the OMA3 API gateway.
91
+ * Caches the result for 5 minutes.
92
+ *
93
+ * @param url Override the trust anchors URL (for testing or custom deployments)
94
+ */
95
+ declare function fetchTrustAnchors(url?: string): Promise<TrustAnchors>;
96
+ /**
97
+ * Look up chain anchors by CAIP-2 identifier.
98
+ * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.
99
+ */
100
+ declare function getChainAnchors(anchors: TrustAnchors, caip2: string): ChainAnchors;
101
+ /**
102
+ * Look up a schema UID by name for a given chain.
103
+ * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.
104
+ * Throws INVALID_INPUT if the schema is not deployed on this chain.
105
+ */
106
+ declare function getSchemaAnchor(anchors: TrustAnchors, caip2: string, schemaName: string): string;
107
+ /**
108
+ * Extract the allowed contracts and schema UIDs from trust anchors.
109
+ * Returns all contracts and schema UIDs across all chains.
110
+ */
111
+ declare function extractAllowlists(anchors: TrustAnchors): {
112
+ allowedContracts: string[];
113
+ allowedSchemas: string[];
114
+ };
115
+
116
+ /**
117
+ * postMessage protocol constants and types for the OMATrust widget bridge.
118
+ *
119
+ * Widget (iframe) → Host:
120
+ * omatrust:ready — widget loaded, requesting handshake
121
+ * omatrust:signTypedData — widget requests EIP-712 signature
122
+ *
123
+ * Host → Widget (iframe):
124
+ * omatrust:hostReady — host acknowledges the widget
125
+ * omatrust:signature — host returns a signature
126
+ * omatrust:signatureError — host reports a signing failure
127
+ */
128
+ declare const OMATRUST_READY: "omatrust:ready";
129
+ declare const OMATRUST_HOST_READY: "omatrust:hostReady";
130
+ declare const OMATRUST_SIGN_TYPED_DATA: "omatrust:signTypedData";
131
+ declare const OMATRUST_SIGNATURE: "omatrust:signature";
132
+ declare const OMATRUST_SIGNATURE_ERROR: "omatrust:signatureError";
133
+ type OmaTrustReadyMessage = {
134
+ type: typeof OMATRUST_READY;
135
+ };
136
+ type OmaTrustHostReadyMessage = {
137
+ type: typeof OMATRUST_HOST_READY;
138
+ };
139
+ type OmaTrustSignTypedDataMessage = {
140
+ type: typeof OMATRUST_SIGN_TYPED_DATA;
141
+ id: string;
142
+ domain: Record<string, unknown>;
143
+ types: Record<string, unknown>;
144
+ message: Record<string, unknown>;
145
+ };
146
+ type OmaTrustSignatureMessage = {
147
+ type: typeof OMATRUST_SIGNATURE;
148
+ id: string;
149
+ signature: string;
150
+ };
151
+ type OmaTrustSignatureErrorMessage = {
152
+ type: typeof OMATRUST_SIGNATURE_ERROR;
153
+ id: string;
154
+ error: string;
155
+ };
156
+ type OmaTrustMessage = OmaTrustReadyMessage | OmaTrustHostReadyMessage | OmaTrustSignTypedDataMessage | OmaTrustSignatureMessage | OmaTrustSignatureErrorMessage;
157
+
158
+ export { type ApprovedIssuer, type ChainAnchors, OMATRUST_HOST_READY, OMATRUST_READY, OMATRUST_SIGNATURE, OMATRUST_SIGNATURE_ERROR, OMATRUST_SIGN_TYPED_DATA, type OmaTrustHostReadyMessage, type OmaTrustMessage, type OmaTrustReadyMessage, type OmaTrustSignTypedDataMessage, type OmaTrustSignatureErrorMessage, type OmaTrustSignatureMessage, type SigningBridge, type SigningBridgeOptions, TRUST_ANCHORS_URL, type TrustAnchors, createSigningBridge, extractAllowlists, fetchTrustAnchors, getChainAnchors, getSchemaAnchor };
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Host-side signing bridge for OMATrust widget iframes.
3
+ *
4
+ * Handles the postMessage protocol between a host page and an embedded
5
+ * OMATrust widget. Validates incoming EAS signing requests against the
6
+ * OMA3 trust anchors before forwarding to the host's wallet.
7
+ *
8
+ * The bridge resolves the iframe element lazily by ID when messages arrive,
9
+ * avoiding React ref timing issues with conditionally rendered iframes.
10
+ *
11
+ * Usage:
12
+ * import { createSigningBridge } from "@oma3/omatrust/widgets";
13
+ *
14
+ * const bridge = await createSigningBridge({
15
+ * iframeId: "omatrust-widget",
16
+ * signTypedData: async (domain, types, message) => {
17
+ * return await signer.signTypedData(domain, types, message);
18
+ * },
19
+ * });
20
+ *
21
+ * bridge.destroy();
22
+ */
23
+ type SigningBridgeOptions = {
24
+ /**
25
+ * The ID of the iframe element containing the widget.
26
+ * The bridge looks up the element by ID when messages arrive,
27
+ * so the iframe doesn't need to exist when the bridge is created.
28
+ */
29
+ iframeId: string;
30
+ /**
31
+ * Callback to sign EIP-712 typed data using the host's wallet.
32
+ * Must return the hex-encoded signature string.
33
+ */
34
+ signTypedData: (domain: Record<string, unknown>, types: Record<string, unknown>, message: Record<string, unknown>) => Promise<string>;
35
+ /**
36
+ * Override the allowed widget origin for local development.
37
+ * In production, the origin is derived from the trust anchors domain
38
+ * (*.omatrust.org) plus any widgetOrigins in the trust anchors.
39
+ * Only set this for local dev (e.g., "http://localhost:3000").
40
+ */
41
+ devOriginOverride?: string;
42
+ };
43
+ type SigningBridge = {
44
+ /** Remove all event listeners and stop the bridge. */
45
+ destroy: () => void;
46
+ };
47
+ /**
48
+ * Create a signing bridge between the host page and an OMATrust widget iframe.
49
+ *
50
+ * The bridge resolves the iframe element by ID when messages arrive, not at
51
+ * creation time. This avoids React ref timing issues — the bridge can be
52
+ * created before the iframe is in the DOM.
53
+ *
54
+ * Fetches the OMA3 trust anchors on creation. Fails closed if unavailable.
55
+ */
56
+ declare function createSigningBridge(options: SigningBridgeOptions): Promise<SigningBridge>;
57
+
58
+ /**
59
+ * Trust anchors: fetches the OMA3 allowlist of EAS contracts and schemas.
60
+ *
61
+ * Used by the widget signing bridge for request validation and by the
62
+ * reputation module for chain/contract resolution.
63
+ *
64
+ * Chain keys use CAIP-2 identifiers (e.g., "eip155:66238").
65
+ */
66
+ declare const TRUST_ANCHORS_URL = "https://api.omatrust.org/v1/trust-anchors";
67
+ type ChainAnchors = {
68
+ name: string;
69
+ easContract: string;
70
+ /** Schema name → schema UID mapping */
71
+ schemas: Record<string, string>;
72
+ };
73
+ type ApprovedIssuer = {
74
+ address: string;
75
+ label: string;
76
+ schemas: string[];
77
+ };
78
+ type TrustAnchors = {
79
+ version: number;
80
+ updatedAt: string;
81
+ widgetOrigins?: string[];
82
+ /** CAIP-2 chain identifier → chain-specific trust anchors */
83
+ chains: Record<string, ChainAnchors>;
84
+ registries?: Array<{
85
+ type: "approved-issuers";
86
+ issuers: ApprovedIssuer[];
87
+ }>;
88
+ };
89
+ /**
90
+ * Fetch the trust anchors from the OMA3 API gateway.
91
+ * Caches the result for 5 minutes.
92
+ *
93
+ * @param url Override the trust anchors URL (for testing or custom deployments)
94
+ */
95
+ declare function fetchTrustAnchors(url?: string): Promise<TrustAnchors>;
96
+ /**
97
+ * Look up chain anchors by CAIP-2 identifier.
98
+ * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.
99
+ */
100
+ declare function getChainAnchors(anchors: TrustAnchors, caip2: string): ChainAnchors;
101
+ /**
102
+ * Look up a schema UID by name for a given chain.
103
+ * Throws UNSUPPORTED_CHAIN if the chain is not in the trust anchors.
104
+ * Throws INVALID_INPUT if the schema is not deployed on this chain.
105
+ */
106
+ declare function getSchemaAnchor(anchors: TrustAnchors, caip2: string, schemaName: string): string;
107
+ /**
108
+ * Extract the allowed contracts and schema UIDs from trust anchors.
109
+ * Returns all contracts and schema UIDs across all chains.
110
+ */
111
+ declare function extractAllowlists(anchors: TrustAnchors): {
112
+ allowedContracts: string[];
113
+ allowedSchemas: string[];
114
+ };
115
+
116
+ /**
117
+ * postMessage protocol constants and types for the OMATrust widget bridge.
118
+ *
119
+ * Widget (iframe) → Host:
120
+ * omatrust:ready — widget loaded, requesting handshake
121
+ * omatrust:signTypedData — widget requests EIP-712 signature
122
+ *
123
+ * Host → Widget (iframe):
124
+ * omatrust:hostReady — host acknowledges the widget
125
+ * omatrust:signature — host returns a signature
126
+ * omatrust:signatureError — host reports a signing failure
127
+ */
128
+ declare const OMATRUST_READY: "omatrust:ready";
129
+ declare const OMATRUST_HOST_READY: "omatrust:hostReady";
130
+ declare const OMATRUST_SIGN_TYPED_DATA: "omatrust:signTypedData";
131
+ declare const OMATRUST_SIGNATURE: "omatrust:signature";
132
+ declare const OMATRUST_SIGNATURE_ERROR: "omatrust:signatureError";
133
+ type OmaTrustReadyMessage = {
134
+ type: typeof OMATRUST_READY;
135
+ };
136
+ type OmaTrustHostReadyMessage = {
137
+ type: typeof OMATRUST_HOST_READY;
138
+ };
139
+ type OmaTrustSignTypedDataMessage = {
140
+ type: typeof OMATRUST_SIGN_TYPED_DATA;
141
+ id: string;
142
+ domain: Record<string, unknown>;
143
+ types: Record<string, unknown>;
144
+ message: Record<string, unknown>;
145
+ };
146
+ type OmaTrustSignatureMessage = {
147
+ type: typeof OMATRUST_SIGNATURE;
148
+ id: string;
149
+ signature: string;
150
+ };
151
+ type OmaTrustSignatureErrorMessage = {
152
+ type: typeof OMATRUST_SIGNATURE_ERROR;
153
+ id: string;
154
+ error: string;
155
+ };
156
+ type OmaTrustMessage = OmaTrustReadyMessage | OmaTrustHostReadyMessage | OmaTrustSignTypedDataMessage | OmaTrustSignatureMessage | OmaTrustSignatureErrorMessage;
157
+
158
+ export { type ApprovedIssuer, type ChainAnchors, OMATRUST_HOST_READY, OMATRUST_READY, OMATRUST_SIGNATURE, OMATRUST_SIGNATURE_ERROR, OMATRUST_SIGN_TYPED_DATA, type OmaTrustHostReadyMessage, type OmaTrustMessage, type OmaTrustReadyMessage, type OmaTrustSignTypedDataMessage, type OmaTrustSignatureErrorMessage, type OmaTrustSignatureMessage, type SigningBridge, type SigningBridgeOptions, TRUST_ANCHORS_URL, type TrustAnchors, createSigningBridge, extractAllowlists, fetchTrustAnchors, getChainAnchors, getSchemaAnchor };