@renown/sdk 6.0.2-staging.2 → 6.0.2-staging.3
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 +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +136 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +305 -0
- package/dist/node.js.map +1 -0
- package/dist/renown-builder-xQpZet3I.js +816 -0
- package/dist/renown-builder-xQpZet3I.js.map +1 -0
- package/dist/utils-D7B6E7_Z.d.ts +682 -0
- package/dist/utils-D7B6E7_Z.d.ts.map +1 -0
- package/package.json +14 -13
- package/dist/src/common.d.ts +0 -23
- package/dist/src/common.d.ts.map +0 -1
- package/dist/src/common.js +0 -145
- package/dist/src/common.js.map +0 -1
- package/dist/src/constants.d.ts +0 -130
- package/dist/src/constants.d.ts.map +0 -1
- package/dist/src/constants.js +0 -40
- package/dist/src/constants.js.map +0 -1
- package/dist/src/crypto/browser-key-storage.d.ts +0 -10
- package/dist/src/crypto/browser-key-storage.d.ts.map +0 -1
- package/dist/src/crypto/browser-key-storage.js +0 -76
- package/dist/src/crypto/browser-key-storage.js.map +0 -1
- package/dist/src/crypto/common.d.ts +0 -6
- package/dist/src/crypto/common.d.ts.map +0 -1
- package/dist/src/crypto/common.js +0 -8
- package/dist/src/crypto/common.js.map +0 -1
- package/dist/src/crypto/index.d.ts +0 -3
- package/dist/src/crypto/index.d.ts.map +0 -1
- package/dist/src/crypto/index.js +0 -3
- package/dist/src/crypto/index.js.map +0 -1
- package/dist/src/crypto/memory-key-storage.d.ts +0 -9
- package/dist/src/crypto/memory-key-storage.d.ts.map +0 -1
- package/dist/src/crypto/memory-key-storage.js +0 -18
- package/dist/src/crypto/memory-key-storage.js.map +0 -1
- package/dist/src/crypto/node-key-storage.d.ts +0 -21
- package/dist/src/crypto/node-key-storage.d.ts.map +0 -1
- package/dist/src/crypto/node-key-storage.js +0 -107
- package/dist/src/crypto/node-key-storage.js.map +0 -1
- package/dist/src/crypto/node.d.ts +0 -3
- package/dist/src/crypto/node.d.ts.map +0 -1
- package/dist/src/crypto/node.js +0 -3
- package/dist/src/crypto/node.js.map +0 -1
- package/dist/src/crypto/renown-crypto-builder.d.ts +0 -11
- package/dist/src/crypto/renown-crypto-builder.d.ts.map +0 -1
- package/dist/src/crypto/renown-crypto-builder.js +0 -34
- package/dist/src/crypto/renown-crypto-builder.js.map +0 -1
- package/dist/src/crypto/renown-crypto.d.ts +0 -26
- package/dist/src/crypto/renown-crypto.d.ts.map +0 -1
- package/dist/src/crypto/renown-crypto.js +0 -56
- package/dist/src/crypto/renown-crypto.js.map +0 -1
- package/dist/src/crypto/signer.d.ts +0 -74
- package/dist/src/crypto/signer.d.ts.map +0 -1
- package/dist/src/crypto/signer.js +0 -306
- package/dist/src/crypto/signer.js.map +0 -1
- package/dist/src/crypto/types.d.ts +0 -27
- package/dist/src/crypto/types.d.ts.map +0 -1
- package/dist/src/crypto/types.js +0 -2
- package/dist/src/crypto/types.js.map +0 -1
- package/dist/src/crypto/utils.d.ts +0 -13
- package/dist/src/crypto/utils.d.ts.map +0 -1
- package/dist/src/crypto/utils.js +0 -39
- package/dist/src/crypto/utils.js.map +0 -1
- package/dist/src/event/event.browser.d.ts +0 -10
- package/dist/src/event/event.browser.d.ts.map +0 -1
- package/dist/src/event/event.browser.js +0 -24
- package/dist/src/event/event.browser.js.map +0 -1
- package/dist/src/event/event.node.d.ts +0 -8
- package/dist/src/event/event.node.d.ts.map +0 -1
- package/dist/src/event/event.node.js +0 -17
- package/dist/src/event/event.node.js.map +0 -1
- package/dist/src/event/memory.d.ts +0 -8
- package/dist/src/event/memory.d.ts.map +0 -1
- package/dist/src/event/memory.js +0 -16
- package/dist/src/event/memory.js.map +0 -1
- package/dist/src/event/types.d.ts +0 -16
- package/dist/src/event/types.d.ts.map +0 -1
- package/dist/src/event/types.js +0 -2
- package/dist/src/event/types.js.map +0 -1
- package/dist/src/index.d.ts +0 -8
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -8
- package/dist/src/index.js.map +0 -1
- package/dist/src/init.browser.d.ts +0 -52
- package/dist/src/init.browser.d.ts.map +0 -1
- package/dist/src/init.browser.js +0 -66
- package/dist/src/init.browser.js.map +0 -1
- package/dist/src/init.node.d.ts +0 -29
- package/dist/src/init.node.d.ts.map +0 -1
- package/dist/src/init.node.js +0 -30
- package/dist/src/init.node.js.map +0 -1
- package/dist/src/node.d.ts +0 -10
- package/dist/src/node.d.ts.map +0 -1
- package/dist/src/node.js +0 -10
- package/dist/src/node.js.map +0 -1
- package/dist/src/profile.d.ts +0 -3
- package/dist/src/profile.d.ts.map +0 -1
- package/dist/src/profile.js +0 -22
- package/dist/src/profile.js.map +0 -1
- package/dist/src/renown-builder.d.ts +0 -68
- package/dist/src/renown-builder.d.ts.map +0 -1
- package/dist/src/renown-builder.js +0 -130
- package/dist/src/renown-builder.js.map +0 -1
- package/dist/src/storage/common.d.ts +0 -17
- package/dist/src/storage/common.d.ts.map +0 -1
- package/dist/src/storage/common.js +0 -20
- package/dist/src/storage/common.js.map +0 -1
- package/dist/src/storage/storage.browser.d.ts +0 -10
- package/dist/src/storage/storage.browser.d.ts.map +0 -1
- package/dist/src/storage/storage.browser.js +0 -27
- package/dist/src/storage/storage.browser.js.map +0 -1
- package/dist/src/storage/storage.node.d.ts +0 -11
- package/dist/src/storage/storage.node.d.ts.map +0 -1
- package/dist/src/storage/storage.node.js +0 -42
- package/dist/src/storage/storage.node.js.map +0 -1
- package/dist/src/types.d.ts +0 -126
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils.d.ts +0 -24
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/utils.js +0 -94
- package/dist/src/utils.js.map +0 -1
- package/dist/test/auth.test.d.ts +0 -2
- package/dist/test/auth.test.d.ts.map +0 -1
- package/dist/test/auth.test.js +0 -13
- package/dist/test/auth.test.js.map +0 -1
- package/dist/test/crypto/signer.test.d.ts +0 -2
- package/dist/test/crypto/signer.test.d.ts.map +0 -1
- package/dist/test/crypto/signer.test.js +0 -184
- package/dist/test/crypto/signer.test.js.map +0 -1
- package/dist/test/renown.test.d.ts +0 -2
- package/dist/test/renown.test.d.ts.map +0 -1
- package/dist/test/renown.test.js +0 -287
- package/dist/test/renown.test.js.map +0 -1
- package/dist/test/storage.node.test.d.ts +0 -2
- package/dist/test/storage.node.test.d.ts.map +0 -1
- package/dist/test/storage.node.test.js +0 -66
- package/dist/test/storage.node.test.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/vitest.config.d.ts +0 -3
- package/dist/vitest.config.d.ts.map +0 -1
- package/dist/vitest.config.js +0 -7
- package/dist/vitest.config.js.map +0 -1
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
import { bytesToBase64url } from "did-jwt";
|
|
2
|
+
import { fromString } from "uint8arrays";
|
|
3
|
+
import { createVerifiableCredentialJwt, verifyCredential } from "did-jwt-vc";
|
|
4
|
+
import { Resolver } from "did-resolver";
|
|
5
|
+
import { getResolver } from "key-did-resolver";
|
|
6
|
+
import { compressedKeyInHexfromRaw, encodeDIDfromHexString, rawKeyInHexfromUncompressed } from "did-key-creator";
|
|
7
|
+
//#region src/constants.ts
|
|
8
|
+
const DEFAULT_RENOWN_URL = "https://www.renown.id";
|
|
9
|
+
const DEFAULT_RENOWN_NETWORK_ID = "eip155";
|
|
10
|
+
const DEFAULT_RENOWN_CHAIN_ID = "1";
|
|
11
|
+
const DOMAIN_TYPE = [
|
|
12
|
+
{
|
|
13
|
+
name: "name",
|
|
14
|
+
type: "string"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "version",
|
|
18
|
+
type: "string"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "chainId",
|
|
22
|
+
type: "uint256"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "verifyingContract",
|
|
26
|
+
type: "address"
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
const VERIFIABLE_CREDENTIAL_EIP712_TYPE = [
|
|
30
|
+
{
|
|
31
|
+
name: "@context",
|
|
32
|
+
type: "string[]"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "type",
|
|
36
|
+
type: "string[]"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "id",
|
|
40
|
+
type: "string"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "issuer",
|
|
44
|
+
type: "Issuer"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "credentialSubject",
|
|
48
|
+
type: "CredentialSubject"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "credentialSchema",
|
|
52
|
+
type: "CredentialSchema"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "issuanceDate",
|
|
56
|
+
type: "string"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "expirationDate",
|
|
60
|
+
type: "string"
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
const CREDENTIAL_SCHEMA_EIP712_TYPE = [{
|
|
64
|
+
name: "id",
|
|
65
|
+
type: "string"
|
|
66
|
+
}, {
|
|
67
|
+
name: "type",
|
|
68
|
+
type: "string"
|
|
69
|
+
}];
|
|
70
|
+
const CREDENTIAL_SUBJECT_TYPE = [
|
|
71
|
+
{
|
|
72
|
+
name: "app",
|
|
73
|
+
type: "string"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "id",
|
|
77
|
+
type: "string"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "name",
|
|
81
|
+
type: "string"
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
const ISSUER_TYPE = [{
|
|
85
|
+
name: "id",
|
|
86
|
+
type: "string"
|
|
87
|
+
}, {
|
|
88
|
+
name: "ethereumAddress",
|
|
89
|
+
type: "string"
|
|
90
|
+
}];
|
|
91
|
+
const CREDENTIAL_TYPES = {
|
|
92
|
+
EIP712Domain: DOMAIN_TYPE,
|
|
93
|
+
VerifiableCredential: VERIFIABLE_CREDENTIAL_EIP712_TYPE,
|
|
94
|
+
CredentialSchema: CREDENTIAL_SCHEMA_EIP712_TYPE,
|
|
95
|
+
CredentialSubject: CREDENTIAL_SUBJECT_TYPE,
|
|
96
|
+
Issuer: ISSUER_TYPE
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/utils.ts
|
|
100
|
+
/**
|
|
101
|
+
* Parse a DID:pkh string to extract network, chain ID, and address information
|
|
102
|
+
* @param did - The DID string in format "did:pkh:networkId:chainId:address"
|
|
103
|
+
* @returns Parsed DID information
|
|
104
|
+
* @throws Error if the DID format is invalid
|
|
105
|
+
*/
|
|
106
|
+
function parsePkhDid(did) {
|
|
107
|
+
const parts = did.split(":");
|
|
108
|
+
if (!did.startsWith("did:pkh:") || parts.length !== 5) throw new Error("Invalid pkh did");
|
|
109
|
+
const [, , networkId, chainIdStr, address] = parts;
|
|
110
|
+
if (!address.startsWith("0x")) throw new Error(`Invalid address: ${address}`);
|
|
111
|
+
const chainId = Number(chainIdStr);
|
|
112
|
+
if (isNaN(chainId)) throw new Error(`Invalid chain id: ${chainIdStr}`);
|
|
113
|
+
return {
|
|
114
|
+
chainId,
|
|
115
|
+
networkId,
|
|
116
|
+
address
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
async function verifyAuthBearerToken(jwt) {
|
|
120
|
+
try {
|
|
121
|
+
const now = parseInt(String(Date.now() / 1e3));
|
|
122
|
+
const verified = await verifyCredential(jwt, getResolver$1(), { policies: {
|
|
123
|
+
now: parseInt(String(Date.now() / 1e3)),
|
|
124
|
+
expirationDate: true,
|
|
125
|
+
issuanceDate: true
|
|
126
|
+
} });
|
|
127
|
+
if (verified.payload.exp && verified.payload.exp < now) return false;
|
|
128
|
+
assertIsAuthCredential(verified);
|
|
129
|
+
return verified;
|
|
130
|
+
} catch (e) {
|
|
131
|
+
console.error(e);
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function assertIsAuthCredential(credential) {
|
|
136
|
+
const subjectKeys = Object.keys(credential.verifiableCredential.credentialSubject);
|
|
137
|
+
if (![
|
|
138
|
+
"address",
|
|
139
|
+
"chainId",
|
|
140
|
+
"networkId"
|
|
141
|
+
].every((key) => subjectKeys.includes(key))) throw new Error("Invalid Auth Credential Subject:" + JSON.stringify(credential.verifiableCredential.credentialSubject, null, 2));
|
|
142
|
+
}
|
|
143
|
+
async function createAuthBearerToken(chainId, networkId, address, issuer, options) {
|
|
144
|
+
return await createVerifiableCredentialJwt({
|
|
145
|
+
sub: issuer.did,
|
|
146
|
+
vc: {
|
|
147
|
+
"@context": ["https://www.w3.org/2018/credentials/v1"],
|
|
148
|
+
type: ["VerifiableCredential"],
|
|
149
|
+
credentialSubject: {
|
|
150
|
+
chainId,
|
|
151
|
+
networkId,
|
|
152
|
+
address
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
aud: options?.aud
|
|
156
|
+
}, issuer, { expiresIn: options?.expiresIn });
|
|
157
|
+
}
|
|
158
|
+
const getResolver$1 = () => {
|
|
159
|
+
const keyResolver = getResolver();
|
|
160
|
+
if (!keyResolver) throw new Error("Failed to get key resolver");
|
|
161
|
+
return new Resolver(keyResolver);
|
|
162
|
+
};
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/crypto/utils.ts
|
|
165
|
+
const ECDSA_ALGORITHM = {
|
|
166
|
+
name: "ECDSA",
|
|
167
|
+
namedCurve: "P-256"
|
|
168
|
+
};
|
|
169
|
+
const ECDSA_SIGN_ALGORITHM = {
|
|
170
|
+
name: "ECDSA",
|
|
171
|
+
namedCurve: "P-256",
|
|
172
|
+
hash: "SHA-256"
|
|
173
|
+
};
|
|
174
|
+
function ab2hex(ab) {
|
|
175
|
+
return Array.prototype.map.call(new Uint8Array(ab), (x) => ("00" + x.toString(16)).slice(-2)).join("");
|
|
176
|
+
}
|
|
177
|
+
async function parseDid(keyPair, subtleCrypto) {
|
|
178
|
+
return encodeDIDfromHexString("p256-pub", compressedKeyInHexfromRaw(rawKeyInHexfromUncompressed(ab2hex(await subtleCrypto.exportKey("raw", keyPair.publicKey)))));
|
|
179
|
+
}
|
|
180
|
+
async function exportKeyPair(keyPair, subtleCrypto) {
|
|
181
|
+
return {
|
|
182
|
+
publicKey: await subtleCrypto.exportKey("jwk", keyPair.publicKey),
|
|
183
|
+
privateKey: await subtleCrypto.exportKey("jwk", keyPair.privateKey)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function importKeyPair(jwkKeyPair, subtleCrypto, algorithm = ECDSA_ALGORITHM) {
|
|
187
|
+
return {
|
|
188
|
+
publicKey: await subtleCrypto.importKey("jwk", jwkKeyPair.publicKey, algorithm, true, ["verify"]),
|
|
189
|
+
privateKey: await subtleCrypto.importKey("jwk", jwkKeyPair.privateKey, algorithm, true, ["sign"])
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function generateKeyPair(subtleCrypto, algorithm = ECDSA_ALGORITHM) {
|
|
193
|
+
return subtleCrypto.generateKey(algorithm, true, ["sign", "verify"]);
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/crypto/renown-crypto.ts
|
|
197
|
+
const RENOWN_NETWORK_ID = "eip155";
|
|
198
|
+
const RENOWN_CHAIN_ID = 1;
|
|
199
|
+
var RenownCrypto = class RenownCrypto {
|
|
200
|
+
#subtleCrypto;
|
|
201
|
+
#keyPair;
|
|
202
|
+
#keyPairStorage;
|
|
203
|
+
did;
|
|
204
|
+
static algorithm = ECDSA_ALGORITHM;
|
|
205
|
+
static signAlgorithm = ECDSA_SIGN_ALGORITHM;
|
|
206
|
+
constructor(keyPairStorage, crypto, keyPair, did) {
|
|
207
|
+
this.#keyPairStorage = keyPairStorage;
|
|
208
|
+
this.#subtleCrypto = crypto;
|
|
209
|
+
this.#keyPair = keyPair;
|
|
210
|
+
this.did = did;
|
|
211
|
+
}
|
|
212
|
+
get publicKey() {
|
|
213
|
+
return this.#keyPair.publicKey;
|
|
214
|
+
}
|
|
215
|
+
async getBearerToken(address, options) {
|
|
216
|
+
return await createAuthBearerToken(Number(RENOWN_CHAIN_ID), RENOWN_NETWORK_ID, address || this.did, this.issuer, options);
|
|
217
|
+
}
|
|
218
|
+
async removeDid() {
|
|
219
|
+
await this.#keyPairStorage.removeKeyPair();
|
|
220
|
+
}
|
|
221
|
+
#stringToBytes(s) {
|
|
222
|
+
return fromString(s, "utf-8");
|
|
223
|
+
}
|
|
224
|
+
async sign(data) {
|
|
225
|
+
const dataBytes = typeof data === "string" ? this.#stringToBytes(data) : data;
|
|
226
|
+
const arrayBuffer = await this.#subtleCrypto.sign(RenownCrypto.signAlgorithm, this.#keyPair.privateKey, dataBytes.buffer);
|
|
227
|
+
return new Uint8Array(arrayBuffer);
|
|
228
|
+
}
|
|
229
|
+
async verify(data, signature) {
|
|
230
|
+
return this.#subtleCrypto.verify({
|
|
231
|
+
name: "ECDSA",
|
|
232
|
+
hash: "SHA-256"
|
|
233
|
+
}, this.#keyPair.publicKey, signature.buffer, data.buffer);
|
|
234
|
+
}
|
|
235
|
+
get issuer() {
|
|
236
|
+
return {
|
|
237
|
+
did: this.did,
|
|
238
|
+
signer: async (data) => {
|
|
239
|
+
return bytesToBase64url(await this.sign(typeof data === "string" ? new TextEncoder().encode(data) : data));
|
|
240
|
+
},
|
|
241
|
+
alg: "ES256"
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* @deprecated Use RenownCrypto instead
|
|
247
|
+
*/
|
|
248
|
+
var ConnectCrypto = class extends RenownCrypto {};
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/crypto/renown-crypto-builder.ts
|
|
251
|
+
var RenownCryptoBuilder = class {
|
|
252
|
+
keyPairStorage;
|
|
253
|
+
subtleCrypto;
|
|
254
|
+
withKeyPairStorage(storage) {
|
|
255
|
+
this.keyPairStorage = storage;
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
withSubtleCrypto(crypto) {
|
|
259
|
+
this.subtleCrypto = crypto;
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
async build() {
|
|
263
|
+
if (!this.keyPairStorage) throw new Error("KeyPairStorage is required. Use withKeyPairStorage() to set it.");
|
|
264
|
+
const subtleCrypto = this.subtleCrypto ?? globalThis.crypto.subtle;
|
|
265
|
+
const keyPair = await this.#initializeKeyPair(subtleCrypto, this.keyPairStorage);
|
|
266
|
+
const did = await parseDid(keyPair, subtleCrypto);
|
|
267
|
+
return new RenownCrypto(this.keyPairStorage, subtleCrypto, keyPair, did);
|
|
268
|
+
}
|
|
269
|
+
async #initializeKeyPair(subtleCrypto, keyPairStorage) {
|
|
270
|
+
const loadedKeyPair = await keyPairStorage.loadKeyPair();
|
|
271
|
+
if (loadedKeyPair) return importKeyPair(loadedKeyPair, subtleCrypto);
|
|
272
|
+
const keyPair = await generateKeyPair(subtleCrypto);
|
|
273
|
+
const exported = await exportKeyPair(keyPair, subtleCrypto);
|
|
274
|
+
await keyPairStorage.saveKeyPair(exported);
|
|
275
|
+
return keyPair;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/crypto/memory-key-storage.ts
|
|
280
|
+
var MemoryKeyStorage = class {
|
|
281
|
+
keyPair;
|
|
282
|
+
constructor(keyPair) {
|
|
283
|
+
this.keyPair = keyPair;
|
|
284
|
+
}
|
|
285
|
+
loadKeyPair() {
|
|
286
|
+
return Promise.resolve(this.keyPair);
|
|
287
|
+
}
|
|
288
|
+
saveKeyPair(keyPair) {
|
|
289
|
+
this.keyPair = keyPair;
|
|
290
|
+
return Promise.resolve();
|
|
291
|
+
}
|
|
292
|
+
removeKeyPair() {
|
|
293
|
+
this.keyPair = void 0;
|
|
294
|
+
return Promise.resolve();
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/crypto/signer.ts
|
|
299
|
+
var InvalidSignatureError = class extends Error {
|
|
300
|
+
constructor() {
|
|
301
|
+
super("Invalid signature");
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
var RenownCryptoSigner = class {
|
|
305
|
+
app;
|
|
306
|
+
constructor(crypto, appName, user) {
|
|
307
|
+
this.crypto = crypto;
|
|
308
|
+
this.appName = appName;
|
|
309
|
+
this.user = user;
|
|
310
|
+
this.app = {
|
|
311
|
+
key: this.crypto.did,
|
|
312
|
+
name: this.appName
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
get publicKey() {
|
|
316
|
+
return this.crypto.publicKey;
|
|
317
|
+
}
|
|
318
|
+
async sign(data) {
|
|
319
|
+
return this.crypto.sign(data);
|
|
320
|
+
}
|
|
321
|
+
async verify(data, signature) {
|
|
322
|
+
if (!await this.crypto.verify(data, signature)) throw new InvalidSignatureError();
|
|
323
|
+
}
|
|
324
|
+
async signAction(action, abortSignal) {
|
|
325
|
+
const hashField = action.context?.prevOpHash ?? "";
|
|
326
|
+
return this._signAction(action, hashField, abortSignal);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Signs an action including a predicted resulting state hash.
|
|
330
|
+
*
|
|
331
|
+
* The resulting hash is packed into the signature tuple's 4th element (index 3)
|
|
332
|
+
* using the format: `${prevStateHash}:${resultingStateHash}`
|
|
333
|
+
*
|
|
334
|
+
* This allows offline verification of documents without reducer logic:
|
|
335
|
+
* - Verifier can check that the signature is valid for the claimed resulting state
|
|
336
|
+
* - Verifier can compare claimed resulting state to actual operation.hash
|
|
337
|
+
*
|
|
338
|
+
* @param action - The action to sign
|
|
339
|
+
* @param resultingStateHash - The predicted hash of document state AFTER this action runs
|
|
340
|
+
* @param abortSignal - Optional abort signal
|
|
341
|
+
* @returns A Signature tuple with the resulting hash encoded in element [3]
|
|
342
|
+
*/
|
|
343
|
+
async signActionWithResultingState(action, resultingStateHash, abortSignal) {
|
|
344
|
+
const hashField = `${action.context?.prevOpHash ?? ""}:${resultingStateHash}`;
|
|
345
|
+
return this._signAction(action, hashField, abortSignal);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Internal signing implementation shared by signAction and signActionWithResultingState.
|
|
349
|
+
*/
|
|
350
|
+
async _signAction(action, hashField, abortSignal) {
|
|
351
|
+
if (abortSignal?.aborted) throw new Error("Signing aborted");
|
|
352
|
+
const timestamp = ((/* @__PURE__ */ new Date()).getTime() / 1e3).toFixed(0);
|
|
353
|
+
const hash = await this.hashAction(action);
|
|
354
|
+
if (abortSignal?.aborted) throw new Error("Signing aborted");
|
|
355
|
+
const params = [
|
|
356
|
+
timestamp,
|
|
357
|
+
this.crypto.did,
|
|
358
|
+
hash,
|
|
359
|
+
hashField
|
|
360
|
+
];
|
|
361
|
+
const message = this.buildSignatureMessage(params);
|
|
362
|
+
const signatureBytes = await this.crypto.sign(message);
|
|
363
|
+
const signatureHex = `0x${this.arrayBufferToHex(signatureBytes)}`;
|
|
364
|
+
if (abortSignal?.aborted) throw new Error("Signing aborted");
|
|
365
|
+
return [...params, signatureHex];
|
|
366
|
+
}
|
|
367
|
+
async hashAction(action) {
|
|
368
|
+
const payload = [
|
|
369
|
+
action.scope,
|
|
370
|
+
action.type,
|
|
371
|
+
JSON.stringify(action.input)
|
|
372
|
+
].join("");
|
|
373
|
+
const data = new TextEncoder().encode(payload);
|
|
374
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
375
|
+
return this.arrayBufferToBase64(hashBuffer);
|
|
376
|
+
}
|
|
377
|
+
buildSignatureMessage(params) {
|
|
378
|
+
const message = params.join("");
|
|
379
|
+
const prefix = "Signed Operation:\n" + message.length.toString();
|
|
380
|
+
return new TextEncoder().encode(prefix + message);
|
|
381
|
+
}
|
|
382
|
+
arrayBufferToHex(buffer) {
|
|
383
|
+
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
384
|
+
return Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
385
|
+
}
|
|
386
|
+
arrayBufferToBase64(buffer) {
|
|
387
|
+
const bytes = new Uint8Array(buffer);
|
|
388
|
+
let binary = "";
|
|
389
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
390
|
+
return btoa(binary);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* Creates a signature verification handler that verifies signatures using the Web Crypto API.
|
|
395
|
+
* The verification uses ECDSA with P-256 curve and SHA-256 hash, matching the RenownCrypto signing algorithm.
|
|
396
|
+
*/
|
|
397
|
+
function createSignatureVerifier(requireSignature = false) {
|
|
398
|
+
return async (operation, publicKey) => {
|
|
399
|
+
const signer = operation.action.context?.signer;
|
|
400
|
+
if (!signer || !publicKey) return !requireSignature;
|
|
401
|
+
const signatures = signer.signatures;
|
|
402
|
+
if (signatures.length === 0) return false;
|
|
403
|
+
const [timestamp, signerKey, hash, prevStateHash, signatureHex] = signatures[signatures.length - 1];
|
|
404
|
+
if (signerKey !== publicKey) return false;
|
|
405
|
+
const message = buildSignatureMessage([
|
|
406
|
+
timestamp,
|
|
407
|
+
signerKey,
|
|
408
|
+
hash,
|
|
409
|
+
prevStateHash
|
|
410
|
+
]);
|
|
411
|
+
const signatureBytes = hexToUint8Array(signatureHex);
|
|
412
|
+
const cryptoKey = await importPublicKey(publicKey);
|
|
413
|
+
return await crypto.subtle.verify({
|
|
414
|
+
name: "ECDSA",
|
|
415
|
+
hash: "SHA-256"
|
|
416
|
+
}, cryptoKey, signatureBytes.buffer, message.buffer);
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function buildSignatureMessage(params) {
|
|
420
|
+
const message = params.join("");
|
|
421
|
+
const prefix = "Signed Operation:\n" + message.length.toString();
|
|
422
|
+
return new TextEncoder().encode(prefix + message);
|
|
423
|
+
}
|
|
424
|
+
function hexToUint8Array(hex) {
|
|
425
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
426
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
427
|
+
for (let i = 0; i < cleanHex.length; i += 2) bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16);
|
|
428
|
+
return bytes;
|
|
429
|
+
}
|
|
430
|
+
async function importPublicKey(did) {
|
|
431
|
+
const keyData = extractKeyFromDid(did);
|
|
432
|
+
return crypto.subtle.importKey("raw", keyData.buffer, {
|
|
433
|
+
name: "ECDSA",
|
|
434
|
+
namedCurve: "P-256"
|
|
435
|
+
}, true, ["verify"]);
|
|
436
|
+
}
|
|
437
|
+
function extractKeyFromDid(did) {
|
|
438
|
+
const parts = did.split(":");
|
|
439
|
+
if (parts.length < 3 || parts[0] !== "did" || parts[1] !== "key") throw new Error(`Invalid DID format: ${did}`);
|
|
440
|
+
const multibaseKey = parts[2];
|
|
441
|
+
if (!multibaseKey.startsWith("z")) throw new Error(`Unsupported multibase encoding: ${multibaseKey[0]}`);
|
|
442
|
+
const decoded = base58Decode(multibaseKey.slice(1));
|
|
443
|
+
if (decoded[0] !== 128 || decoded[1] !== 36) throw new Error("Not a P-256 public key multicodec");
|
|
444
|
+
return decompressP256PublicKey(decoded.slice(2));
|
|
445
|
+
}
|
|
446
|
+
function base58Decode(input) {
|
|
447
|
+
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
448
|
+
const ALPHABET_MAP = /* @__PURE__ */ new Map();
|
|
449
|
+
for (let i = 0; i < 58; i++) ALPHABET_MAP.set(ALPHABET[i], i);
|
|
450
|
+
if (input.length === 0) return new Uint8Array(0);
|
|
451
|
+
const bytes = [0];
|
|
452
|
+
for (const char of input) {
|
|
453
|
+
const value = ALPHABET_MAP.get(char);
|
|
454
|
+
if (value === void 0) throw new Error(`Invalid base58 character: ${char}`);
|
|
455
|
+
let carry = value;
|
|
456
|
+
for (let j = 0; j < bytes.length; j++) {
|
|
457
|
+
carry += bytes[j] * 58;
|
|
458
|
+
bytes[j] = carry & 255;
|
|
459
|
+
carry >>= 8;
|
|
460
|
+
}
|
|
461
|
+
while (carry > 0) {
|
|
462
|
+
bytes.push(carry & 255);
|
|
463
|
+
carry >>= 8;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
for (const char of input) {
|
|
467
|
+
if (char !== "1") break;
|
|
468
|
+
bytes.push(0);
|
|
469
|
+
}
|
|
470
|
+
return new Uint8Array(bytes.reverse());
|
|
471
|
+
}
|
|
472
|
+
function decompressP256PublicKey(compressed) {
|
|
473
|
+
if (compressed.length !== 33) throw new Error(`Invalid compressed key length: ${compressed.length}`);
|
|
474
|
+
const prefix = compressed[0];
|
|
475
|
+
if (prefix !== 2 && prefix !== 3) throw new Error(`Invalid compression prefix: ${prefix}`);
|
|
476
|
+
const p = BigInt("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff");
|
|
477
|
+
const a = BigInt("0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc");
|
|
478
|
+
const b = BigInt("0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b");
|
|
479
|
+
let x = BigInt(0);
|
|
480
|
+
for (let i = 1; i < compressed.length; i++) x = x << BigInt(8) | BigInt(compressed[i]);
|
|
481
|
+
let y = modPow((modPow(x, BigInt(3), p) + a * x + b) % p, (p + BigInt(1)) / BigInt(4), p);
|
|
482
|
+
if (y % BigInt(2) === BigInt(0) !== (prefix === 2)) y = p - y;
|
|
483
|
+
const uncompressed = new Uint8Array(65);
|
|
484
|
+
uncompressed[0] = 4;
|
|
485
|
+
const xBytes = bigIntToBytes(x, 32);
|
|
486
|
+
const yBytes = bigIntToBytes(y, 32);
|
|
487
|
+
uncompressed.set(xBytes, 1);
|
|
488
|
+
uncompressed.set(yBytes, 33);
|
|
489
|
+
return uncompressed;
|
|
490
|
+
}
|
|
491
|
+
function modPow(base, exp, mod) {
|
|
492
|
+
let result = BigInt(1);
|
|
493
|
+
base = base % mod;
|
|
494
|
+
while (exp > BigInt(0)) {
|
|
495
|
+
if (exp % BigInt(2) === BigInt(1)) result = result * base % mod;
|
|
496
|
+
exp = exp >> BigInt(1);
|
|
497
|
+
base = base * base % mod;
|
|
498
|
+
}
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
function bigIntToBytes(n, length) {
|
|
502
|
+
const bytes = new Uint8Array(length);
|
|
503
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
504
|
+
bytes[i] = Number(n & BigInt(255));
|
|
505
|
+
n = n >> BigInt(8);
|
|
506
|
+
}
|
|
507
|
+
return bytes;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Parses the hash field (element [3]) from a signature tuple.
|
|
511
|
+
*
|
|
512
|
+
* Supports two formats:
|
|
513
|
+
* - Old format: just `prevStateHash` (no colon)
|
|
514
|
+
* - New format: `prevStateHash:resultingStateHash` (colon-separated)
|
|
515
|
+
*
|
|
516
|
+
* @param hashField - The 4th element of a Signature tuple
|
|
517
|
+
* @returns Object with prevStateHash and optional resultingStateHash
|
|
518
|
+
*/
|
|
519
|
+
function parseSignatureHashField(hashField) {
|
|
520
|
+
const colonIndex = hashField.indexOf(":");
|
|
521
|
+
if (colonIndex === -1) return {
|
|
522
|
+
prevStateHash: hashField,
|
|
523
|
+
resultingStateHash: void 0
|
|
524
|
+
};
|
|
525
|
+
return {
|
|
526
|
+
prevStateHash: hashField.substring(0, colonIndex),
|
|
527
|
+
resultingStateHash: hashField.substring(colonIndex + 1)
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Extracts the resulting state hash from a signature, if present.
|
|
532
|
+
*
|
|
533
|
+
* @param signature - A Signature tuple
|
|
534
|
+
* @returns The resulting state hash, or undefined if not present
|
|
535
|
+
*/
|
|
536
|
+
function extractResultingHashFromSignature(signature) {
|
|
537
|
+
const hashField = signature[3];
|
|
538
|
+
const { resultingStateHash } = parseSignatureHashField(hashField);
|
|
539
|
+
return resultingStateHash;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Checks if a signature includes a resulting state hash.
|
|
543
|
+
*
|
|
544
|
+
* @param signature - A Signature tuple
|
|
545
|
+
* @returns true if the signature includes a resulting state hash
|
|
546
|
+
*/
|
|
547
|
+
function signatureHasResultingHash(signature) {
|
|
548
|
+
return extractResultingHashFromSignature(signature) !== void 0;
|
|
549
|
+
}
|
|
550
|
+
//#endregion
|
|
551
|
+
//#region src/storage/common.ts
|
|
552
|
+
var BaseStorage = class {};
|
|
553
|
+
var MemoryStorage = class extends BaseStorage {
|
|
554
|
+
data = /* @__PURE__ */ new Map();
|
|
555
|
+
get(key) {
|
|
556
|
+
return this.data.get(key);
|
|
557
|
+
}
|
|
558
|
+
set(key, value) {
|
|
559
|
+
if (value === void 0) this.data.delete(key);
|
|
560
|
+
else this.data.set(key, value);
|
|
561
|
+
}
|
|
562
|
+
delete(key) {
|
|
563
|
+
this.data.delete(key);
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
//#endregion
|
|
567
|
+
//#region src/common.ts
|
|
568
|
+
var RenownMemoryStorage = class extends MemoryStorage {};
|
|
569
|
+
var Renown = class {
|
|
570
|
+
#baseUrl;
|
|
571
|
+
#store;
|
|
572
|
+
#eventEmitter;
|
|
573
|
+
#appName;
|
|
574
|
+
#crypto;
|
|
575
|
+
#signer;
|
|
576
|
+
#profileFetcher;
|
|
577
|
+
#status = "initial";
|
|
578
|
+
constructor(store, eventEmitter, crypto, appName, baseUrl = DEFAULT_RENOWN_URL, profileFetcher) {
|
|
579
|
+
this.#store = store;
|
|
580
|
+
this.#eventEmitter = eventEmitter;
|
|
581
|
+
this.#baseUrl = baseUrl;
|
|
582
|
+
this.#crypto = crypto;
|
|
583
|
+
this.#appName = appName;
|
|
584
|
+
this.#profileFetcher = profileFetcher;
|
|
585
|
+
this.#signer = new RenownCryptoSigner(crypto, this.#appName, this.user);
|
|
586
|
+
this.on("user", (user) => {
|
|
587
|
+
this.#signer.user = user;
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
get baseUrl() {
|
|
591
|
+
return this.#baseUrl;
|
|
592
|
+
}
|
|
593
|
+
get user() {
|
|
594
|
+
return this.#store.get("user");
|
|
595
|
+
}
|
|
596
|
+
get status() {
|
|
597
|
+
return this.#status;
|
|
598
|
+
}
|
|
599
|
+
get signer() {
|
|
600
|
+
return this.#signer;
|
|
601
|
+
}
|
|
602
|
+
get crypto() {
|
|
603
|
+
return this.#crypto;
|
|
604
|
+
}
|
|
605
|
+
get did() {
|
|
606
|
+
return this.#crypto.did;
|
|
607
|
+
}
|
|
608
|
+
get profileFetcher() {
|
|
609
|
+
return this.#profileFetcher;
|
|
610
|
+
}
|
|
611
|
+
#updateStatus(status) {
|
|
612
|
+
this.#status = status;
|
|
613
|
+
this.#eventEmitter.emit("status", status);
|
|
614
|
+
}
|
|
615
|
+
#updateUser(user) {
|
|
616
|
+
if (user) this.#store.set("user", user);
|
|
617
|
+
else this.#store.delete("user");
|
|
618
|
+
this.#eventEmitter.emit("user", user);
|
|
619
|
+
}
|
|
620
|
+
async login(userDid) {
|
|
621
|
+
this.#updateStatus("checking");
|
|
622
|
+
try {
|
|
623
|
+
const result = parsePkhDid(userDid);
|
|
624
|
+
const credential = await this.#getCredential(result.address, result.chainId, this.#crypto.did);
|
|
625
|
+
if (!credential) {
|
|
626
|
+
this.#updateUser(void 0);
|
|
627
|
+
throw new Error("Credential not found");
|
|
628
|
+
}
|
|
629
|
+
if (!(credential.issuer.id === userDid && credential.credentialSubject.id === this.did)) throw new Error("Invalid credential");
|
|
630
|
+
const user = {
|
|
631
|
+
...result,
|
|
632
|
+
address: credential.issuer.ethereumAddress,
|
|
633
|
+
did: userDid,
|
|
634
|
+
credential
|
|
635
|
+
};
|
|
636
|
+
this.#updateUser(user);
|
|
637
|
+
this.#updateStatus("authorized");
|
|
638
|
+
if (this.#profileFetcher) this.#profileFetcher(user, this.#baseUrl).then((profile) => {
|
|
639
|
+
if (profile && this.user?.address === user.address && this.user.chainId === user.chainId) this.#updateUser({
|
|
640
|
+
...this.user,
|
|
641
|
+
profile,
|
|
642
|
+
ens: {
|
|
643
|
+
name: profile.username ?? void 0,
|
|
644
|
+
avatarUrl: profile.userImage ?? void 0
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}).catch(console.error);
|
|
648
|
+
return user;
|
|
649
|
+
} catch (error) {
|
|
650
|
+
this.#updateUser(void 0);
|
|
651
|
+
this.#updateStatus("not-authorized");
|
|
652
|
+
throw error;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
logout() {
|
|
656
|
+
this.#updateUser(void 0);
|
|
657
|
+
this.#updateStatus("initial");
|
|
658
|
+
return Promise.resolve();
|
|
659
|
+
}
|
|
660
|
+
on(event, listener) {
|
|
661
|
+
return this.#eventEmitter.on(event, listener);
|
|
662
|
+
}
|
|
663
|
+
async #getCredential(address, chainId, appDid) {
|
|
664
|
+
if (!this.#baseUrl) throw new Error("RENOWN_URL is not set");
|
|
665
|
+
const url = new URL(`/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`, this.#baseUrl);
|
|
666
|
+
const response = await fetch(url, { method: "GET" });
|
|
667
|
+
if (response.ok) return (await response.json()).credential;
|
|
668
|
+
else throw new Error(`Failed to get credential: ${response.status}`);
|
|
669
|
+
}
|
|
670
|
+
async verifyBearerToken(token) {
|
|
671
|
+
return verifyAuthBearerToken(token);
|
|
672
|
+
}
|
|
673
|
+
async getBearerToken(options) {
|
|
674
|
+
if (!this.user) throw new Error("User not found");
|
|
675
|
+
return this.#crypto.getBearerToken(this.user.address, options);
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
//#endregion
|
|
679
|
+
//#region src/event/memory.ts
|
|
680
|
+
var MemoryEventEmitter = class {
|
|
681
|
+
#listeners = /* @__PURE__ */ new Map();
|
|
682
|
+
on(event, listener) {
|
|
683
|
+
if (!this.#listeners.has(event)) this.#listeners.set(event, /* @__PURE__ */ new Set());
|
|
684
|
+
this.#listeners.get(event).add(listener);
|
|
685
|
+
return () => {
|
|
686
|
+
this.#listeners.get(event)?.delete(listener);
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
emit(event, data) {
|
|
690
|
+
this.#listeners.get(event)?.forEach((listener) => listener(data));
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
//#endregion
|
|
694
|
+
//#region src/profile.ts
|
|
695
|
+
const fetchRenownProfile = async (user, baseUrl) => {
|
|
696
|
+
try {
|
|
697
|
+
const response = await fetch(`${baseUrl}/api/profile`, {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers: { "Content-Type": "application/json" },
|
|
700
|
+
body: JSON.stringify({ ethAddress: user.address })
|
|
701
|
+
});
|
|
702
|
+
if (!response.ok) return;
|
|
703
|
+
return (await response.json()).profile ?? void 0;
|
|
704
|
+
} catch {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
//#endregion
|
|
709
|
+
//#region src/renown-builder.ts
|
|
710
|
+
/**
|
|
711
|
+
* Base builder for creating Renown instances.
|
|
712
|
+
* Use platform-specific builders (RenownBuilder from init.browser.js or init.node.js)
|
|
713
|
+
* for pre-configured defaults.
|
|
714
|
+
*/
|
|
715
|
+
var BaseRenownBuilder = class BaseRenownBuilder {
|
|
716
|
+
#appName;
|
|
717
|
+
#storage;
|
|
718
|
+
#eventEmitter;
|
|
719
|
+
#crypto;
|
|
720
|
+
#keyPairStorage;
|
|
721
|
+
#baseUrl;
|
|
722
|
+
#profileFetcher;
|
|
723
|
+
/**
|
|
724
|
+
* @param appName - Application name used for signing context
|
|
725
|
+
*/
|
|
726
|
+
constructor(appName) {
|
|
727
|
+
this.#appName = appName;
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Set custom storage for user data persistence.
|
|
731
|
+
* Defaults to in-memory storage if not set.
|
|
732
|
+
*/
|
|
733
|
+
withStorage(storage) {
|
|
734
|
+
this.#storage = storage;
|
|
735
|
+
return this;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Set custom event emitter for user state changes.
|
|
739
|
+
* Defaults to in-memory event emitter if not set.
|
|
740
|
+
*/
|
|
741
|
+
withEventEmitter(eventEmitter) {
|
|
742
|
+
this.#eventEmitter = eventEmitter;
|
|
743
|
+
return this;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Set a pre-built crypto instance.
|
|
747
|
+
* Either crypto or keyPairStorage must be provided.
|
|
748
|
+
*/
|
|
749
|
+
withCrypto(crypto) {
|
|
750
|
+
this.#crypto = crypto;
|
|
751
|
+
return this;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Set key pair storage for cryptographic keys.
|
|
755
|
+
* A crypto instance will be built from this storage.
|
|
756
|
+
* Either crypto or keyPairStorage must be provided.
|
|
757
|
+
*/
|
|
758
|
+
withKeyPairStorage(keyPairStorage) {
|
|
759
|
+
this.#keyPairStorage = keyPairStorage;
|
|
760
|
+
return this;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Set the Renown server URL for credential verification.
|
|
764
|
+
* Defaults to https://www.renown.id
|
|
765
|
+
*/
|
|
766
|
+
withBaseUrl(baseUrl) {
|
|
767
|
+
this.#baseUrl = baseUrl;
|
|
768
|
+
return this;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Set a profile fetcher strategy for enriching user data after login.
|
|
772
|
+
* The fetcher receives the authenticated user and the base URL,
|
|
773
|
+
* and returns a RenownProfile. Called in the background after each login.
|
|
774
|
+
* Defaults to fetchRenownProfile which calls the Renown API.
|
|
775
|
+
*/
|
|
776
|
+
withProfileFetcher(profileFetcher) {
|
|
777
|
+
this.#profileFetcher = profileFetcher;
|
|
778
|
+
return this;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Build and initialize the Renown instance.
|
|
782
|
+
* If a user is stored, attempts to re-authenticate them.
|
|
783
|
+
* @throws Error if neither crypto nor keyPairStorage is provided
|
|
784
|
+
*/
|
|
785
|
+
async build() {
|
|
786
|
+
if (!this.#crypto && !this.#keyPairStorage) throw new Error("Either crypto or keyPairStorage is required. Use withCrypto() or withKeyPairStorage() to set one.");
|
|
787
|
+
const crypto = this.#crypto ?? await new RenownCryptoBuilder().withKeyPairStorage(this.#keyPairStorage).build();
|
|
788
|
+
const storage = this.#storage ?? new RenownMemoryStorage();
|
|
789
|
+
const eventEmitter = this.#eventEmitter ?? new MemoryEventEmitter();
|
|
790
|
+
const baseUrl = this.#baseUrl ?? "https://www.renown.id";
|
|
791
|
+
const renown = new Renown(storage, eventEmitter, crypto, this.#appName, baseUrl, this.#profileFetcher ?? fetchRenownProfile);
|
|
792
|
+
if (renown.user) try {
|
|
793
|
+
await renown.login(renown.user.did);
|
|
794
|
+
} catch (error) {
|
|
795
|
+
console.error("Failed to re-authenticate user:", error);
|
|
796
|
+
}
|
|
797
|
+
return renown;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Create a BaseRenownBuilder from options object for a more concise API
|
|
801
|
+
*/
|
|
802
|
+
static from(options) {
|
|
803
|
+
const builder = new BaseRenownBuilder(options.appName);
|
|
804
|
+
if (options.storage) builder.withStorage(options.storage);
|
|
805
|
+
if (options.eventEmitter) builder.withEventEmitter(options.eventEmitter);
|
|
806
|
+
if (options.crypto) builder.withCrypto(options.crypto);
|
|
807
|
+
if (options.keyPairStorage) builder.withKeyPairStorage(options.keyPairStorage);
|
|
808
|
+
if (options.baseUrl) builder.withBaseUrl(options.baseUrl);
|
|
809
|
+
if (options.profileFetcher) builder.withProfileFetcher(options.profileFetcher);
|
|
810
|
+
return builder;
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
//#endregion
|
|
814
|
+
export { DEFAULT_RENOWN_CHAIN_ID as C, ISSUER_TYPE as D, DOMAIN_TYPE as E, VERIFIABLE_CREDENTIAL_EIP712_TYPE as O, CREDENTIAL_TYPES as S, DEFAULT_RENOWN_URL as T, getResolver$1 as _, BaseStorage as a, CREDENTIAL_SCHEMA_EIP712_TYPE as b, extractResultingHashFromSignature as c, MemoryKeyStorage as d, RenownCryptoBuilder as f, createAuthBearerToken as g, assertIsAuthCredential as h, RenownMemoryStorage as i, parseSignatureHashField as l, RenownCrypto as m, fetchRenownProfile as n, RenownCryptoSigner as o, ConnectCrypto as p, Renown as r, createSignatureVerifier as s, BaseRenownBuilder as t, signatureHasResultingHash as u, parsePkhDid as v, DEFAULT_RENOWN_NETWORK_ID as w, CREDENTIAL_SUBJECT_TYPE as x, verifyAuthBearerToken as y };
|
|
815
|
+
|
|
816
|
+
//# sourceMappingURL=renown-builder-xQpZet3I.js.map
|