@renown/sdk 6.2.3-dev.5 → 6.2.3-dev.50

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 (86) hide show
  1. package/dist/{browser-key-storage-e3RQsnLS.js → browser-key-storage-wjSwTnhs.js} +3 -2
  2. package/dist/browser-key-storage-wjSwTnhs.js.map +1 -0
  3. package/dist/{constants-BexAR53F.js → constants-DVOF17NB.js} +1 -1
  4. package/dist/{constants-BexAR53F.js.map → constants-DVOF17NB.js.map} +1 -1
  5. package/dist/crypto.d.ts +4 -3
  6. package/dist/crypto.js +2 -2
  7. package/dist/{index-BLIpkdF7.d.ts → index-DbiBjqs6.d.ts} +11 -20
  8. package/dist/index-DbiBjqs6.d.ts.map +1 -0
  9. package/dist/index.d.ts +12 -11
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +11 -7
  12. package/dist/index.js.map +1 -1
  13. package/dist/{meta-D-5kvwx8.js → meta-4NmijIbE.js} +2 -2
  14. package/dist/{meta-D-5kvwx8.js.map → meta-4NmijIbE.js.map} +1 -1
  15. package/dist/{meta-CHgd9Qd0.js → meta-B2fHYlPD.js} +2 -2
  16. package/dist/{meta-CHgd9Qd0.js.map → meta-B2fHYlPD.js.map} +1 -1
  17. package/dist/{meta-BesJP74N.d.ts → meta-Dpmn2Ywp.d.ts} +3 -3
  18. package/dist/meta-Dpmn2Ywp.d.ts.map +1 -0
  19. package/dist/{meta-bV7L-1yb.d.ts → meta-qadFdiX7.d.ts} +3 -3
  20. package/dist/meta-qadFdiX7.d.ts.map +1 -0
  21. package/dist/node.d.ts +42 -25
  22. package/dist/node.d.ts.map +1 -1
  23. package/dist/node.js +23 -7
  24. package/dist/node.js.map +1 -1
  25. package/dist/signed-message-Cp5oRPLN.js +468 -0
  26. package/dist/signed-message-Cp5oRPLN.js.map +1 -0
  27. package/dist/{signer-DrjINLqt.js → signer-GzTlZLjR.js} +38 -106
  28. package/dist/signer-GzTlZLjR.js.map +1 -0
  29. package/dist/signer-trust-FmbMTn39.d.ts +53 -0
  30. package/dist/signer-trust-FmbMTn39.d.ts.map +1 -0
  31. package/dist/signer-trust-H1rNzUcd.js +708 -0
  32. package/dist/signer-trust-H1rNzUcd.js.map +1 -0
  33. package/dist/trust.d.ts +3 -0
  34. package/dist/trust.js +2 -0
  35. package/dist/{types-C-hJrsQg.d.ts → types-7xgrEnx7.d.ts} +3 -3
  36. package/dist/types-7xgrEnx7.d.ts.map +1 -0
  37. package/dist/{types-BGQKPoUr.d.ts → types-Ceiz2dkk.d.ts} +36 -12
  38. package/dist/types-Ceiz2dkk.d.ts.map +1 -0
  39. package/dist/{types-DInveFLz.d.ts → types-DRnq2URw.d.ts} +3 -3
  40. package/dist/types-DRnq2URw.d.ts.map +1 -0
  41. package/dist/{types-C_qc_62W.js → types-Dwy6khXb.js} +1 -1
  42. package/dist/{types-C_qc_62W.js.map → types-Dwy6khXb.js.map} +1 -1
  43. package/dist/utils-DLQ5VVqT.js +75 -0
  44. package/dist/utils-DLQ5VVqT.js.map +1 -0
  45. package/dist/{utils-DtWREYeO.d.ts → utils-DkVxP7Ug.d.ts} +19 -12
  46. package/dist/utils-DkVxP7Ug.d.ts.map +1 -0
  47. package/dist/wallet/index.d.ts +5 -5
  48. package/dist/wallet/index.d.ts.map +1 -1
  49. package/dist/wallet/index.js +1 -1
  50. package/dist/wallet/index.js.map +1 -1
  51. package/dist/wallet/mock/factory.d.ts +4 -5
  52. package/dist/wallet/mock/factory.d.ts.map +1 -1
  53. package/dist/wallet/mock/factory.js +1 -1
  54. package/dist/wallet/mock/factory.js.map +1 -1
  55. package/dist/wallet/mock/index.d.ts +5 -5
  56. package/dist/wallet/mock/index.d.ts.map +1 -1
  57. package/dist/wallet/mock/index.js +1 -1
  58. package/dist/wallet/mock/index.js.map +1 -1
  59. package/dist/wallet/privy/factory.d.ts +9 -11
  60. package/dist/wallet/privy/factory.d.ts.map +1 -1
  61. package/dist/wallet/privy/factory.js +2 -2
  62. package/dist/wallet/privy/factory.js.map +1 -1
  63. package/dist/wallet/privy/index.d.ts +5 -5
  64. package/dist/wallet/privy/index.d.ts.map +1 -1
  65. package/dist/wallet/privy/index.js +1 -1
  66. package/dist/wallet/privy/index.js.map +1 -1
  67. package/dist/wallet/rainbow/factory.d.ts +5 -4
  68. package/dist/wallet/rainbow/factory.d.ts.map +1 -1
  69. package/dist/wallet/rainbow/factory.js +2 -2
  70. package/dist/wallet/rainbow/factory.js.map +1 -1
  71. package/dist/wallet/rainbow/index.d.ts +5 -5
  72. package/dist/wallet/rainbow/index.d.ts.map +1 -1
  73. package/dist/wallet/rainbow/index.js +1 -1
  74. package/dist/wallet/rainbow/index.js.map +1 -1
  75. package/package.json +12 -5
  76. package/dist/browser-key-storage-e3RQsnLS.js.map +0 -1
  77. package/dist/index-BLIpkdF7.d.ts.map +0 -1
  78. package/dist/local-credential-verifier-CU8hmFlR.js +0 -907
  79. package/dist/local-credential-verifier-CU8hmFlR.js.map +0 -1
  80. package/dist/meta-BesJP74N.d.ts.map +0 -1
  81. package/dist/meta-bV7L-1yb.d.ts.map +0 -1
  82. package/dist/signer-DrjINLqt.js.map +0 -1
  83. package/dist/types-BGQKPoUr.d.ts.map +0 -1
  84. package/dist/types-C-hJrsQg.d.ts.map +0 -1
  85. package/dist/types-DInveFLz.d.ts.map +0 -1
  86. package/dist/utils-DtWREYeO.d.ts.map +0 -1
@@ -0,0 +1,708 @@
1
+ import { a as DEFAULT_RENOWN_NETWORK_ID, r as CREDENTIAL_TYPES } from "./constants-DVOF17NB.js";
2
+ import { a as verifyAuthBearerToken } from "./utils-DLQ5VVqT.js";
3
+ import { recoverTypedDataAddress } from "viem";
4
+ import { createAction } from "@powerhousedao/shared/document-model";
5
+ //#region src/discovery.ts
6
+ const DEFAULT_DISCOVERY_TIMEOUT_MS = 3e3;
7
+ async function resolveSwitchboardEndpoint(options) {
8
+ const { switchboardUrl, baseUrl, timeoutMs } = options;
9
+ if (switchboardUrl) return switchboardUrl;
10
+ if (!baseUrl) return;
11
+ const controller = new AbortController();
12
+ const timeout = setTimeout(() => controller.abort(), timeoutMs ?? DEFAULT_DISCOVERY_TIMEOUT_MS);
13
+ try {
14
+ const url = new URL("/api/switchboard", baseUrl);
15
+ const response = await fetch(url, {
16
+ method: "GET",
17
+ signal: controller.signal
18
+ });
19
+ if (!response.ok) return;
20
+ return (await response.json()).endpoint || void 0;
21
+ } catch {
22
+ return;
23
+ } finally {
24
+ clearTimeout(timeout);
25
+ }
26
+ }
27
+ //#endregion
28
+ //#region src/switchboard.ts
29
+ /** Thrown by `signIn` when the instance has no switchboard to write the
30
+ * credential to, so a host can fall back to the Renown redirect flow. */
31
+ var MissingSwitchboardError = class MissingSwitchboardError extends Error {
32
+ constructor() {
33
+ super("signIn requires a switchboard endpoint. Set switchboardUrl or a discoverable baseUrl.");
34
+ this.name = "MissingSwitchboardError";
35
+ }
36
+ /** `instanceof` fails across duplicate SDK copies, so match by name too. */
37
+ static is(error) {
38
+ return error instanceof MissingSwitchboardError || error instanceof Error && error.name === "MissingSwitchboardError";
39
+ }
40
+ };
41
+ function userDriveId(address) {
42
+ return `renown-${address.toLowerCase()}`;
43
+ }
44
+ const CREDENTIALS_QUERY = `
45
+ query RenownCredentials($input: RenownCredentialsInput!) {
46
+ renownCredentials(input: $input) {
47
+ documentId
48
+ credentialId
49
+ context
50
+ type
51
+ issuerId
52
+ issuerEthereumAddress
53
+ issuanceDate
54
+ expirationDate
55
+ credentialSubjectId
56
+ credentialSubjectApp
57
+ credentialStatusId
58
+ credentialStatusType
59
+ credentialSchemaId
60
+ credentialSchemaType
61
+ proofVerificationMethod
62
+ proofEthereumAddress
63
+ proofCreated
64
+ proofPurpose
65
+ proofType
66
+ proofValue
67
+ proofEip712Domain
68
+ proofEip712PrimaryType
69
+ revoked
70
+ }
71
+ }
72
+ `;
73
+ const USERS_QUERY = `
74
+ query RenownUsers($input: RenownUsersInput!) {
75
+ renownUsers(input: $input) {
76
+ documentId
77
+ username
78
+ ethAddress
79
+ userImage
80
+ createdAt
81
+ updatedAt
82
+ }
83
+ }
84
+ `;
85
+ const CREATE_EMPTY_DOCUMENT_MUTATION = `
86
+ mutation CreateEmptyDocument(
87
+ $documentType: String!
88
+ $parentIdentifier: String
89
+ ) {
90
+ createEmptyDocument(
91
+ documentType: $documentType
92
+ parentIdentifier: $parentIdentifier
93
+ ) {
94
+ id
95
+ }
96
+ }
97
+ `;
98
+ const MUTATE_DOCUMENT_MUTATION = `
99
+ mutation MutateDocument(
100
+ $documentIdentifier: String!
101
+ $actions: [ActionInput!]!
102
+ ) {
103
+ mutateDocument: execute(
104
+ documentIdentifier: $documentIdentifier
105
+ actions: $actions
106
+ ) {
107
+ id
108
+ }
109
+ }
110
+ `;
111
+ const LEGACY_MUTATE_DOCUMENT_MUTATION = `
112
+ mutation MutateDocument(
113
+ $documentIdentifier: String!
114
+ $actions: [JSONObject!]!
115
+ ) {
116
+ mutateDocument(documentIdentifier: $documentIdentifier, actions: $actions) {
117
+ id
118
+ }
119
+ }
120
+ `;
121
+ function isUnknownExecuteField(error) {
122
+ return error instanceof Error && /Cannot query field "execute" on type "Mutation"/.test(error.message);
123
+ }
124
+ const ISSUE_CREDENTIAL_MUTATION = `
125
+ mutation RenownIssueCredential(
126
+ $input: RenownCredential_InitInput!
127
+ $username: String
128
+ $userImage: String
129
+ $userDocId: PHID
130
+ ) {
131
+ renown_issueCredential(
132
+ input: $input
133
+ username: $username
134
+ userImage: $userImage
135
+ userDocId: $userDocId
136
+ )
137
+ }
138
+ `;
139
+ const UPSERT_PROFILE_MUTATION = `
140
+ mutation RenownUpsertProfile(
141
+ $address: String!
142
+ $username: String
143
+ $userImage: String
144
+ $signature: String
145
+ $timestamp: String
146
+ ) {
147
+ renown_upsertProfile(
148
+ address: $address
149
+ username: $username
150
+ userImage: $userImage
151
+ signature: $signature
152
+ timestamp: $timestamp
153
+ )
154
+ }
155
+ `;
156
+ const REVOKE_CREDENTIAL_MUTATION = `
157
+ mutation RenownRevokeCredential(
158
+ $credentialId: String!
159
+ $signature: String
160
+ $timestamp: String
161
+ ) {
162
+ renown_revokeCredential(
163
+ credentialId: $credentialId
164
+ signature: $signature
165
+ timestamp: $timestamp
166
+ )
167
+ }
168
+ `;
169
+ function authParts(auth) {
170
+ return "token" in auth ? {
171
+ token: auth.token,
172
+ signed: {}
173
+ } : { signed: {
174
+ signature: auth.signature,
175
+ timestamp: auth.timestamp
176
+ } };
177
+ }
178
+ const RENOWN_CREDENTIAL_DOC_TYPE = "powerhouse/renown-credential";
179
+ const RENOWN_USER_DOC_TYPE = "powerhouse/renown-user";
180
+ function quoted(name) {
181
+ return `\\\\?"${name}\\\\?"`;
182
+ }
183
+ function isUnknownSchemaError(error, field, ...types) {
184
+ const message = error instanceof Error ? error.message : String(error);
185
+ if (new RegExp(`Cannot query field ${quoted(field)}`).test(message)) return true;
186
+ return !message.includes("got invalid value") && types.some((type) => new RegExp(`Unknown type ${quoted(type)}`).test(message));
187
+ }
188
+ function reshapeCredential(row) {
189
+ const domain = JSON.parse(row.proofEip712Domain);
190
+ return {
191
+ "@context": row.context,
192
+ type: row.type,
193
+ id: row.credentialId,
194
+ issuer: {
195
+ id: row.issuerId,
196
+ ethereumAddress: row.issuerEthereumAddress
197
+ },
198
+ credentialSubject: {
199
+ id: row.credentialSubjectId ?? "",
200
+ app: row.credentialSubjectApp
201
+ },
202
+ credentialSchema: {
203
+ id: row.credentialSchemaId,
204
+ type: row.credentialSchemaType
205
+ },
206
+ ...row.credentialStatusId ? { credentialStatus: {
207
+ id: row.credentialStatusId,
208
+ type: row.credentialStatusType ?? ""
209
+ } } : {},
210
+ issuanceDate: row.issuanceDate,
211
+ expirationDate: row.expirationDate ?? "",
212
+ proof: {
213
+ type: row.proofType,
214
+ created: row.proofCreated,
215
+ verificationMethod: row.proofVerificationMethod,
216
+ proofPurpose: row.proofPurpose,
217
+ proofValue: row.proofValue,
218
+ ethereumAddress: row.proofEthereumAddress,
219
+ eip712: {
220
+ domain,
221
+ types: CREDENTIAL_TYPES,
222
+ primaryType: "VerifiableCredential"
223
+ }
224
+ }
225
+ };
226
+ }
227
+ function issuerChainId(issuerId) {
228
+ return issuerId.split(":")[3];
229
+ }
230
+ function issuerDidAddress(issuerId) {
231
+ return issuerId.split(":")[4];
232
+ }
233
+ function bindsTo$1(row, address, chainId, appDid) {
234
+ return !row.revoked && issuedTo(row, address, chainId, appDid);
235
+ }
236
+ function issuedTo(row, address, chainId, appDid) {
237
+ const expected = address.toLowerCase();
238
+ return row.credentialSubjectId === appDid && issuerChainId(row.issuerId) === String(chainId) && issuerDidAddress(row.issuerId)?.toLowerCase() === expected && row.issuerEthereumAddress.toLowerCase() === expected;
239
+ }
240
+ var SwitchboardClient = class {
241
+ #endpoint;
242
+ #transport;
243
+ #legacyMutate = false;
244
+ constructor(source) {
245
+ if (typeof source === "string") {
246
+ this.#endpoint = source;
247
+ this.#transport = (query, variables, options) => this.#post(source, query, variables, options?.token);
248
+ } else this.#transport = source;
249
+ }
250
+ /** The HTTP endpoint, or undefined when reading through a local executor. */
251
+ get endpoint() {
252
+ return this.#endpoint;
253
+ }
254
+ async #post(endpoint, query, variables, token) {
255
+ const response = await fetch(endpoint, {
256
+ method: "POST",
257
+ headers: {
258
+ "Content-Type": "application/json",
259
+ ...token ? { Authorization: `Bearer ${token}` } : {}
260
+ },
261
+ body: JSON.stringify({
262
+ query,
263
+ variables
264
+ })
265
+ });
266
+ const body = await response.json().catch(() => void 0);
267
+ if (body?.errors?.length) throw new Error(body.errors.map((e) => e.message).join("; "));
268
+ if (!response.ok || !body) throw new Error(`Switchboard request failed: ${response.status}`);
269
+ return body.data;
270
+ }
271
+ async #request(query, variables, token) {
272
+ const data = await (token ? this.#transport(query, variables, { token }) : this.#transport(query, variables));
273
+ if (!data) throw new Error("Switchboard returned no data");
274
+ return data;
275
+ }
276
+ async getCredential(params) {
277
+ const { address, chainId, appDid } = params;
278
+ const { renownCredentials } = await this.#request(CREDENTIALS_QUERY, { input: {
279
+ driveId: userDriveId(address),
280
+ ethAddress: address.toLowerCase(),
281
+ did: appDid,
282
+ includeRevoked: false
283
+ } });
284
+ const now = Date.now();
285
+ const mostRecent = renownCredentials.filter((row) => bindsTo$1(row, address, chainId, appDid)).filter((row) => {
286
+ if (!row.expirationDate) return true;
287
+ const expiresAt = Date.parse(row.expirationDate);
288
+ return !Number.isNaN(expiresAt) && expiresAt > now;
289
+ }).sort((a, b) => Date.parse(b.issuanceDate) - Date.parse(a.issuanceDate)).at(0);
290
+ return mostRecent ? reshapeCredential(mostRecent) : void 0;
291
+ }
292
+ async getIssuedCredentials(params) {
293
+ const { address, chainId, appDid } = params;
294
+ const { renownCredentials } = await this.#request(CREDENTIALS_QUERY, { input: {
295
+ driveId: userDriveId(address),
296
+ ethAddress: address.toLowerCase(),
297
+ did: appDid,
298
+ includeRevoked: true
299
+ } });
300
+ const credentials = [];
301
+ for (const row of renownCredentials) {
302
+ if (!issuedTo(row, address, chainId, appDid)) continue;
303
+ try {
304
+ credentials.push(reshapeCredential(row));
305
+ } catch {}
306
+ }
307
+ return credentials;
308
+ }
309
+ async getProfileByAddress(address) {
310
+ const { renownUsers } = await this.#request(USERS_QUERY, { input: {
311
+ driveId: userDriveId(address),
312
+ ethAddresses: [address.toLowerCase()]
313
+ } });
314
+ const user = renownUsers.at(0);
315
+ if (!user) return void 0;
316
+ return {
317
+ documentId: user.documentId,
318
+ username: user.username,
319
+ ethAddress: user.ethAddress,
320
+ userImage: user.userImage,
321
+ createdAt: user.createdAt,
322
+ updatedAt: user.updatedAt
323
+ };
324
+ }
325
+ async createEmptyDocument(documentType, parentIdentifier, token) {
326
+ const { createEmptyDocument } = await this.#request(CREATE_EMPTY_DOCUMENT_MUTATION, {
327
+ documentType,
328
+ parentIdentifier
329
+ }, token);
330
+ return createEmptyDocument.id;
331
+ }
332
+ async mutateDocument(documentIdentifier, actions, token) {
333
+ const variables = {
334
+ documentIdentifier,
335
+ actions
336
+ };
337
+ if (!this.#legacyMutate) try {
338
+ const { mutateDocument } = await this.#request(MUTATE_DOCUMENT_MUTATION, variables, token);
339
+ return mutateDocument.id;
340
+ } catch (error) {
341
+ if (!isUnknownExecuteField(error)) throw error;
342
+ this.#legacyMutate = true;
343
+ }
344
+ const { mutateDocument } = await this.#request(LEGACY_MUTATE_DOCUMENT_MUTATION, variables, token);
345
+ return mutateDocument.id;
346
+ }
347
+ async issueCredential(credential, parentIdentifier) {
348
+ const input = {
349
+ id: credential.id,
350
+ context: credential["@context"],
351
+ type: credential.type,
352
+ issuer: {
353
+ id: credential.issuer.id,
354
+ ethereumAddress: credential.issuer.ethereumAddress
355
+ },
356
+ credentialSubject: {
357
+ id: credential.credentialSubject.id,
358
+ app: credential.credentialSubject.app
359
+ },
360
+ credentialSchema: {
361
+ id: credential.credentialSchema.id,
362
+ type: credential.credentialSchema.type
363
+ },
364
+ issuanceDate: credential.issuanceDate,
365
+ expirationDate: credential.expirationDate || void 0,
366
+ proof: {
367
+ type: credential.proof.type,
368
+ created: credential.proof.created,
369
+ verificationMethod: credential.proof.verificationMethod,
370
+ proofPurpose: credential.proof.proofPurpose,
371
+ proofValue: credential.proof.proofValue,
372
+ ethereumAddress: credential.proof.ethereumAddress,
373
+ eip712: {
374
+ domain: {
375
+ version: credential.proof.eip712.domain.version,
376
+ chainId: credential.proof.eip712.domain.chainId
377
+ },
378
+ primaryType: credential.proof.eip712.primaryType
379
+ }
380
+ }
381
+ };
382
+ try {
383
+ const { renown_issueCredential } = await this.#request(ISSUE_CREDENTIAL_MUTATION, { input });
384
+ return renown_issueCredential;
385
+ } catch (error) {
386
+ if (!isUnknownSchemaError(error, "renown_issueCredential", "RenownCredential_InitInput")) throw error;
387
+ const documentId = await this.createEmptyDocument(RENOWN_CREDENTIAL_DOC_TYPE, parentIdentifier);
388
+ await this.mutateDocument(documentId, [createAction("INIT", input)]);
389
+ return documentId;
390
+ }
391
+ }
392
+ async upsertUserProfile(address, profile, auth) {
393
+ const { token, signed } = authParts(auth);
394
+ try {
395
+ const { renown_upsertProfile } = await this.#request(UPSERT_PROFILE_MUTATION, {
396
+ address,
397
+ username: profile.username,
398
+ userImage: profile.userImage,
399
+ ...signed
400
+ }, token);
401
+ return renown_upsertProfile;
402
+ } catch (error) {
403
+ if (!isUnknownSchemaError(error, "renown_upsertProfile")) throw error;
404
+ return this.#legacyUpsertUserProfile(address, profile, token);
405
+ }
406
+ }
407
+ async #legacyUpsertUserProfile(address, profile, token) {
408
+ const updates = [];
409
+ if (profile.username != null) updates.push(createAction("SET_USERNAME", { username: profile.username }));
410
+ if (profile.userImage != null) updates.push(createAction("SET_USER_IMAGE", { userImage: profile.userImage }));
411
+ const existing = await this.getProfileByAddress(address);
412
+ if (existing) {
413
+ if (updates.length) await this.mutateDocument(existing.documentId, updates, token);
414
+ return existing.documentId;
415
+ }
416
+ const documentId = await this.createEmptyDocument(RENOWN_USER_DOC_TYPE, void 0, token);
417
+ await this.mutateDocument(documentId, [createAction("SET_ETH_ADDRESS", { ethAddress: address }), ...updates], token);
418
+ return documentId;
419
+ }
420
+ async revokeCredential(credentialId, auth) {
421
+ const { token, signed } = authParts(auth);
422
+ try {
423
+ await this.#request(REVOKE_CREDENTIAL_MUTATION, {
424
+ credentialId,
425
+ ...signed
426
+ }, token);
427
+ } catch (error) {
428
+ if (!isUnknownSchemaError(error, "renown_revokeCredential")) throw error;
429
+ await this.#legacyRevokeCredential(credentialId, token);
430
+ }
431
+ }
432
+ async #legacyRevokeCredential(credentialId, token) {
433
+ const { renownCredentials } = await this.#request(CREDENTIALS_QUERY, { input: { includeRevoked: false } }, token);
434
+ const documentIds = renownCredentials.filter((row) => row.credentialId === credentialId).map((row) => row.documentId);
435
+ if (!documentIds.length) throw new Error(`Credential not found: ${credentialId}`);
436
+ const revokedAt = (/* @__PURE__ */ new Date()).toISOString();
437
+ for (const documentId of documentIds) await this.mutateDocument(documentId, [createAction("REVOKE", {
438
+ revokedAt,
439
+ reason: null
440
+ })], token);
441
+ }
442
+ profileFetcher = (user) => this.getProfileByAddress(user.address).catch(() => void 0);
443
+ };
444
+ //#endregion
445
+ //#region src/credential.ts
446
+ /** Assemble a Renown delegation VC and sign it with the provided signer. */
447
+ async function buildAndSignCredential(params) {
448
+ const { signTypedData, address, chainId, app, appId, expiresInDays = 7 } = params;
449
+ const issuerId = `did:pkh:${DEFAULT_RENOWN_NETWORK_ID}:${chainId}:${address.toLowerCase()}`;
450
+ const credentialId = `urn:uuid:${globalThis.crypto.randomUUID()}`;
451
+ const now = /* @__PURE__ */ new Date();
452
+ const expirationDate = new Date(now.getTime() + expiresInDays * 24 * 60 * 60 * 1e3);
453
+ const message = {
454
+ "@context": ["https://www.w3.org/2018/credentials/v1"],
455
+ type: ["VerifiableCredential", "RenownCredential"],
456
+ id: credentialId,
457
+ issuer: {
458
+ id: issuerId,
459
+ ethereumAddress: address
460
+ },
461
+ credentialSubject: {
462
+ id: appId,
463
+ app
464
+ },
465
+ credentialSchema: {
466
+ id: "https://renown.id/schemas/renown-credential/v1",
467
+ type: "JsonSchemaValidator2018"
468
+ },
469
+ issuanceDate: now.toISOString(),
470
+ expirationDate: expirationDate.toISOString()
471
+ };
472
+ const domain = {
473
+ version: "1",
474
+ chainId
475
+ };
476
+ const { EIP712Domain, ...signTypes } = CREDENTIAL_TYPES;
477
+ const signature = await signTypedData({
478
+ domain,
479
+ types: signTypes,
480
+ primaryType: "VerifiableCredential",
481
+ message
482
+ });
483
+ return {
484
+ ...message,
485
+ proof: {
486
+ type: "EthereumEip712Signature2021",
487
+ created: message.issuanceDate,
488
+ verificationMethod: issuerId,
489
+ proofPurpose: "assertionMethod",
490
+ proofValue: signature,
491
+ ethereumAddress: address,
492
+ eip712: {
493
+ domain,
494
+ types: CREDENTIAL_TYPES,
495
+ primaryType: "VerifiableCredential"
496
+ }
497
+ }
498
+ };
499
+ }
500
+ /** Recover the address that signed a credential's EIP-712 proof. */
501
+ async function recoverCredentialSigner(credential) {
502
+ const { proof, ...message } = credential;
503
+ const { EIP712Domain, ...types } = CREDENTIAL_TYPES;
504
+ return recoverTypedDataAddress({
505
+ domain: proof.eip712.domain,
506
+ types,
507
+ primaryType: "VerifiableCredential",
508
+ message,
509
+ signature: proof.proofValue
510
+ });
511
+ }
512
+ /** True when the proof was signed by the credential's declared issuer address. */
513
+ async function verifyCredentialSignature(credential) {
514
+ try {
515
+ return (await recoverCredentialSigner(credential)).toLowerCase() === credential.issuer.ethereumAddress.toLowerCase();
516
+ } catch {
517
+ return false;
518
+ }
519
+ }
520
+ function withEip712Domain(credential, chainId) {
521
+ if (credential.proof.eip712?.domain) return credential;
522
+ return {
523
+ ...credential,
524
+ proof: {
525
+ ...credential.proof,
526
+ eip712: {
527
+ domain: {
528
+ version: "1",
529
+ chainId
530
+ },
531
+ types: CREDENTIAL_TYPES,
532
+ primaryType: "VerifiableCredential"
533
+ }
534
+ }
535
+ };
536
+ }
537
+ async function fetchDelegationCredentialRest(params) {
538
+ const { address, chainId, appDid, baseUrl } = params;
539
+ const url = new URL(`/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`, baseUrl);
540
+ const response = await fetch(url, { method: "GET" });
541
+ if (!response.ok) return void 0;
542
+ const { credential } = await response.json();
543
+ if (!credential) return void 0;
544
+ const [, , , issuerChainId, issuerAddress] = credential.issuer.id.split(":");
545
+ if (credential.credentialSubject.id !== appDid || issuerChainId !== String(chainId) || issuerAddress.toLowerCase() !== address.toLowerCase() || credential.issuer.ethereumAddress.toLowerCase() !== address.toLowerCase()) return;
546
+ if (credential.expirationDate) {
547
+ const expiresAt = Date.parse(credential.expirationDate);
548
+ if (Number.isNaN(expiresAt) || expiresAt <= Date.now()) return;
549
+ }
550
+ return credential;
551
+ }
552
+ /** True when the credential's EIP-712 proof, on `chainId`, was signed by its
553
+ * issuer address. Binding and expiry are the caller's to check. */
554
+ async function verifyDelegationProof(credential, chainId) {
555
+ const withDomain = withEip712Domain(credential, chainId);
556
+ return withDomain.proof.eip712.domain.chainId === chainId && await verifyCredentialSignature(withDomain);
557
+ }
558
+ async function finalizeCredential(credential, chainId, verifySignature) {
559
+ if (!verifySignature) return credential;
560
+ if (!await verifyDelegationProof(credential, chainId)) return;
561
+ return withEip712Domain(credential, chainId);
562
+ }
563
+ async function fetchDelegationCredential(options) {
564
+ const { address, chainId, appDid, switchboardUrl, switchboardRequest, discover = true, verifySignature = true } = options;
565
+ const explicitBaseUrl = options.baseUrl;
566
+ const baseUrl = explicitBaseUrl ?? "https://www.renown.id";
567
+ try {
568
+ const source = switchboardRequest ?? (switchboardUrl ? switchboardUrl : discover && explicitBaseUrl ? await resolveSwitchboardEndpoint({ baseUrl }) : void 0);
569
+ const credential = source ? await new SwitchboardClient(source).getCredential({
570
+ address,
571
+ chainId,
572
+ appDid
573
+ }) : await fetchDelegationCredentialRest({
574
+ address,
575
+ chainId,
576
+ appDid,
577
+ baseUrl
578
+ });
579
+ if (!credential) return void 0;
580
+ return await finalizeCredential(credential, chainId, verifySignature);
581
+ } catch {
582
+ return;
583
+ }
584
+ }
585
+ async function verifyAuthCredential(jwt, options = {}) {
586
+ const verified = await verifyAuthBearerToken(jwt, { audience: options.audience });
587
+ if (!verified) return void 0;
588
+ const { address, chainId, networkId } = verified.verifiableCredential.credentialSubject;
589
+ const appDid = verified.issuer;
590
+ const credential = await fetchDelegationCredential({
591
+ address,
592
+ chainId,
593
+ appDid,
594
+ baseUrl: options.renownUrl,
595
+ switchboardUrl: options.switchboardUrl,
596
+ switchboardRequest: options.switchboardRequest,
597
+ verifySignature: options.verifySignature
598
+ });
599
+ if (!credential) return void 0;
600
+ return {
601
+ address,
602
+ chainId,
603
+ networkId,
604
+ did: credential.issuer.id,
605
+ appDid,
606
+ credential
607
+ };
608
+ }
609
+ //#endregion
610
+ //#region src/signer-trust.ts
611
+ const DEFAULT_MAX_ACCEPTED = 1e4;
612
+ const DEFAULT_REFUSAL_TTL_MS = 6e4;
613
+ /**
614
+ * Accepts a key the user's EIP-712 Renown credential delegates to, ignoring
615
+ * expiry and revocation. Verdicts are cached per (address, key); this node's
616
+ * own key is checked before the cache and never cached.
617
+ */
618
+ function createRenownTrustPolicy(options = {}) {
619
+ const maxAccepted = options.maxAccepted ?? DEFAULT_MAX_ACCEPTED;
620
+ const refusalTtlMs = options.refusalTtlMs ?? DEFAULT_REFUSAL_TTL_MS;
621
+ const client = options.switchboard ? new SwitchboardClient(options.switchboard) : void 0;
622
+ const renownUrl = options.renownUrl ?? "https://www.renown.id";
623
+ const accepted = /* @__PURE__ */ new Set();
624
+ const refusedUntil = /* @__PURE__ */ new Map();
625
+ const pending = /* @__PURE__ */ new Map();
626
+ const issued = (user, key) => client ? client.getIssuedCredentials({
627
+ address: user.address,
628
+ chainId: user.chainId,
629
+ appDid: key
630
+ }) : fetchIssuedCredentialRest(user, key, renownUrl);
631
+ async function lookup(user, key) {
632
+ for (const credential of await issued(user, key)) if (bindsTo(credential, user, key) && await verifyDelegationProof(credential, user.chainId)) return true;
633
+ return false;
634
+ }
635
+ function remember(entry, verdict) {
636
+ if (verdict) {
637
+ if (accepted.size >= maxAccepted) {
638
+ const oldest = accepted.values().next().value;
639
+ if (oldest !== void 0) accepted.delete(oldest);
640
+ }
641
+ accepted.add(entry);
642
+ refusedUntil.delete(entry);
643
+ } else refusedUntil.set(entry, Date.now() + refusalTtlMs);
644
+ }
645
+ return { authorizeSigner(signer, key) {
646
+ const user = signer.user;
647
+ const self = ownIdentity(options);
648
+ if (self && isSelf(self, user, key)) return Promise.resolve(true);
649
+ if (!user || !isLookupable(user, key)) return Promise.resolve(false);
650
+ const entry = `${user.networkId}|${user.chainId}|${user.address.toLowerCase()}|${key}`;
651
+ if (accepted.has(entry)) return Promise.resolve(true);
652
+ const until = refusedUntil.get(entry);
653
+ if (until !== void 0 && until > Date.now()) return Promise.resolve(false);
654
+ const inFlight = pending.get(entry);
655
+ if (inFlight) return inFlight;
656
+ const verdict = lookup(user, key).then((result) => {
657
+ pending.delete(entry);
658
+ remember(entry, result);
659
+ return result;
660
+ }, (error) => {
661
+ pending.delete(entry);
662
+ throw error;
663
+ });
664
+ pending.set(entry, verdict);
665
+ return verdict;
666
+ } };
667
+ }
668
+ function ownIdentity(options) {
669
+ if (!options.ownSigner) return options.self;
670
+ const { app, user } = options.ownSigner;
671
+ return {
672
+ key: app?.key ?? "",
673
+ user: {
674
+ address: user?.address ?? "",
675
+ networkId: user?.networkId ?? "",
676
+ chainId: user?.chainId ?? 0
677
+ }
678
+ };
679
+ }
680
+ function isSelf(self, user, key) {
681
+ return self.key !== "" && key === self.key && (user?.address ?? "").toLowerCase() === self.user.address.toLowerCase() && (user?.networkId ?? "") === self.user.networkId && (user?.chainId ?? 0) === self.user.chainId;
682
+ }
683
+ function isLookupable(user, key) {
684
+ return key.startsWith("did:key:") && /^0x[0-9a-fA-F]{40}$/.test(user.address) && user.networkId !== "" && Number.isInteger(user.chainId) && user.chainId > 0;
685
+ }
686
+ function bindsTo(credential, user, key) {
687
+ const address = user.address.toLowerCase();
688
+ const issuer = credential.issuer.id.split(":");
689
+ if (issuer.length !== 5) return false;
690
+ const [scheme, method, networkId, chainId, issuerAddress] = issuer;
691
+ return credential.credentialSubject.id === key && scheme === "did" && method === "pkh" && networkId === user.networkId && chainId === String(user.chainId) && issuerAddress.toLowerCase() === address && credential.issuer.ethereumAddress.toLowerCase() === address;
692
+ }
693
+ async function fetchIssuedCredentialRest(user, key, renownUrl) {
694
+ const url = new URL("/api/auth/credential", renownUrl);
695
+ url.searchParams.set("address", user.address);
696
+ url.searchParams.set("chainId", String(user.chainId));
697
+ url.searchParams.set("connectId", key);
698
+ url.searchParams.set("appId", key);
699
+ const response = await fetch(url, { method: "GET" });
700
+ if (response.status === 404) return [];
701
+ if (!response.ok) throw new Error(`Renown credential lookup failed: ${response.status}`);
702
+ const { credential } = await response.json();
703
+ return credential ? [credential] : [];
704
+ }
705
+ //#endregion
706
+ export { verifyAuthCredential as a, MissingSwitchboardError as c, recoverCredentialSigner as i, SwitchboardClient as l, buildAndSignCredential as n, verifyCredentialSignature as o, fetchDelegationCredential as r, verifyDelegationProof as s, createRenownTrustPolicy as t, resolveSwitchboardEndpoint as u };
707
+
708
+ //# sourceMappingURL=signer-trust-H1rNzUcd.js.map