@provablehq/veil-aleo-sdk 0.6.0 → 0.7.1
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 +171 -11
- package/dist/index.d.ts +153 -17
- package/dist/index.js +370 -26
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +34 -0
- package/dist/node.js +42 -0
- package/dist/node.js.map +1 -0
- package/dist/provableApi-C4bT37jI.d.ts +362 -0
- package/package.json +9 -5
package/dist/index.js
CHANGED
|
@@ -23,6 +23,36 @@ import {
|
|
|
23
23
|
extractTransitions
|
|
24
24
|
} from "@provablehq/veil-core";
|
|
25
25
|
|
|
26
|
+
// src/utils/rss.ts
|
|
27
|
+
import {
|
|
28
|
+
assertValidRecordFilter,
|
|
29
|
+
resolveScanPrograms
|
|
30
|
+
} from "@provablehq/veil-core";
|
|
31
|
+
function presentList(values) {
|
|
32
|
+
return values && values.length > 0 ? values : void 0;
|
|
33
|
+
}
|
|
34
|
+
function buildOwnedFilter(params) {
|
|
35
|
+
const filter = params.filter;
|
|
36
|
+
assertValidRecordFilter(filter);
|
|
37
|
+
const wireFilter = Object.fromEntries(
|
|
38
|
+
Object.entries({
|
|
39
|
+
programs: resolveScanPrograms(params),
|
|
40
|
+
records: presentList(filter?.records),
|
|
41
|
+
functions: presentList(filter?.functions),
|
|
42
|
+
commitments: presentList(filter?.commitments),
|
|
43
|
+
start: filter?.start,
|
|
44
|
+
end: filter?.end,
|
|
45
|
+
results_per_page: filter?.resultsPerPage,
|
|
46
|
+
page: filter?.page
|
|
47
|
+
}).filter(([, value]) => value !== void 0)
|
|
48
|
+
);
|
|
49
|
+
const body = {};
|
|
50
|
+
if (params.statusFilter === "unspent") body.unspent = true;
|
|
51
|
+
else if (params.statusFilter === "spent") body.unspent = false;
|
|
52
|
+
if (Object.keys(wireFilter).length > 0) body.filter = wireFilter;
|
|
53
|
+
return body;
|
|
54
|
+
}
|
|
55
|
+
|
|
26
56
|
// src/mnemonic.ts
|
|
27
57
|
import { hmac } from "@noble/hashes/hmac";
|
|
28
58
|
import { sha512 } from "@noble/hashes/sha512";
|
|
@@ -163,11 +193,168 @@ function mnemonicToHDKey(mnemonic, options = {}) {
|
|
|
163
193
|
return BLS12377HDKey.fromMasterSeed(seed).derivePath(DERIVATION_PATHS[derivation]).deriveChild(index);
|
|
164
194
|
}
|
|
165
195
|
|
|
196
|
+
// src/provableApi.ts
|
|
197
|
+
var DEFAULT_PROVABLE_API_URL = "https://api.provable.com";
|
|
198
|
+
var EXPIRY_SKEW_MS = 5 * 60 * 1e3;
|
|
199
|
+
function memoryCredentialStore(initial) {
|
|
200
|
+
let held = initial;
|
|
201
|
+
return {
|
|
202
|
+
load: () => held,
|
|
203
|
+
save: (credentials) => {
|
|
204
|
+
held = credentials;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async function registerProvableApi(params) {
|
|
209
|
+
const baseUrl = params.baseUrl ?? DEFAULT_PROVABLE_API_URL;
|
|
210
|
+
const transport = params.transport ?? fetch;
|
|
211
|
+
const response = await transport(`${baseUrl}/consumers`, {
|
|
212
|
+
method: "POST",
|
|
213
|
+
headers: { "content-type": "application/json" },
|
|
214
|
+
body: JSON.stringify({ username: params.username })
|
|
215
|
+
});
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
const body2 = await response.text();
|
|
218
|
+
if (response.status === 409) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Provable API username '${params.username}' is already registered. Credentials cannot be recovered from a username: supply the existing consumerId and apiKey, or register under a different name. (HTTP 409: ${body2})`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
throw new Error(
|
|
224
|
+
`Provable API consumer registration failed (HTTP ${response.status}): ${body2}`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const body = await response.json();
|
|
228
|
+
if (!body.consumer?.id || !body.key) {
|
|
229
|
+
throw new Error("Provable API consumer registration response carried no consumer id and key.");
|
|
230
|
+
}
|
|
231
|
+
return { consumerId: body.consumer.id, apiKey: body.key };
|
|
232
|
+
}
|
|
233
|
+
async function mintJwt(credentials, baseUrl, transport) {
|
|
234
|
+
const response = await transport(`${baseUrl}/jwts/${encodeURIComponent(credentials.consumerId)}`, {
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers: { "X-Provable-API-Key": credentials.apiKey }
|
|
237
|
+
});
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Provable API JWT mint failed (HTTP ${response.status}): ${await response.text()}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
const header = response.headers.get("authorization");
|
|
244
|
+
if (!header) {
|
|
245
|
+
throw new Error("Provable API JWT mint response carried no authorization header.");
|
|
246
|
+
}
|
|
247
|
+
const body = await response.json();
|
|
248
|
+
if (typeof body.exp !== "number") {
|
|
249
|
+
throw new Error("Provable API JWT mint response carried no exp claim.");
|
|
250
|
+
}
|
|
251
|
+
return { jwt: header, expiration: body.exp * 1e3 };
|
|
252
|
+
}
|
|
253
|
+
function createProvableSession(options = {}) {
|
|
254
|
+
const baseUrl = options.baseUrl ?? DEFAULT_PROVABLE_API_URL;
|
|
255
|
+
const transport = options.transport ?? fetch;
|
|
256
|
+
const consumers = { proving: false, recordScanning: false };
|
|
257
|
+
let credentials = options.credentials;
|
|
258
|
+
let registered = false;
|
|
259
|
+
let credentialsInFlight;
|
|
260
|
+
let jwt;
|
|
261
|
+
let jwtInFlight;
|
|
262
|
+
async function resolveCredentials(usernameOverride) {
|
|
263
|
+
if (credentials) return credentials;
|
|
264
|
+
const stored = await options.store?.load();
|
|
265
|
+
if (stored) {
|
|
266
|
+
credentials = stored;
|
|
267
|
+
return credentials;
|
|
268
|
+
}
|
|
269
|
+
const username = usernameOverride ?? (typeof options.username === "function" ? options.username() : options.username);
|
|
270
|
+
if (!username) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
"No Provable API credentials available \u2014 pass credentials, a store holding them, or a username to register with."
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
const issued = await registerProvableApi({ username, baseUrl, transport });
|
|
276
|
+
credentials = issued;
|
|
277
|
+
registered = true;
|
|
278
|
+
try {
|
|
279
|
+
await options.store?.save(issued);
|
|
280
|
+
} catch (cause) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`Registered Provable API consumer ${issued.consumerId}, but persisting its credentials failed. They are live for this process \u2014 read them from getCredentials() and store them yourself \u2014 but the API key cannot be reissued, so a restart loses it.`,
|
|
283
|
+
{ cause }
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
return credentials;
|
|
287
|
+
}
|
|
288
|
+
function getCredentials({ username } = {}) {
|
|
289
|
+
credentialsInFlight ??= resolveCredentials(username).finally(() => {
|
|
290
|
+
credentialsInFlight = void 0;
|
|
291
|
+
});
|
|
292
|
+
return credentialsInFlight;
|
|
293
|
+
}
|
|
294
|
+
function getJwt({ forceRefresh = false } = {}) {
|
|
295
|
+
const stale = !jwt || Date.now() >= jwt.expiration - EXPIRY_SKEW_MS;
|
|
296
|
+
if (!forceRefresh && !stale) return Promise.resolve(jwt);
|
|
297
|
+
jwtInFlight ??= (async () => {
|
|
298
|
+
const resolved = await getCredentials();
|
|
299
|
+
jwt = await mintJwt(resolved, baseUrl, transport);
|
|
300
|
+
return jwt;
|
|
301
|
+
})().finally(() => {
|
|
302
|
+
jwtInFlight = void 0;
|
|
303
|
+
});
|
|
304
|
+
return jwtInFlight;
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
registeredConsumer: () => registered,
|
|
308
|
+
getCredentials,
|
|
309
|
+
getJwt,
|
|
310
|
+
consumers,
|
|
311
|
+
attach: (consumer) => {
|
|
312
|
+
consumers[consumer] = true;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function getProvableSession(client) {
|
|
317
|
+
return client.proving?.session;
|
|
318
|
+
}
|
|
319
|
+
async function authenticateProvableApi(client, params = {}) {
|
|
320
|
+
if (client.proving?.keyedAuth) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
"This client authenticates with a provisioned API key \u2014 every request already carries it, and there is no consumer or JWT to resolve. Remove the authenticateProvableApi call."
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
const session = getProvableSession(client);
|
|
326
|
+
if (!session) {
|
|
327
|
+
throw new Error(
|
|
328
|
+
"No Provable API session on this client \u2014 pass consumerId and apiKey, or a credentialStore, when creating it."
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
const credentials = await session.getCredentials({ username: params.username });
|
|
332
|
+
const { expiration } = await session.getJwt({ forceRefresh: params.forceRefresh });
|
|
333
|
+
return {
|
|
334
|
+
credentials,
|
|
335
|
+
expiration,
|
|
336
|
+
registered: session.registeredConsumer(),
|
|
337
|
+
applied: { ...session.consumers }
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function provableApiActions() {
|
|
341
|
+
return (client) => ({
|
|
342
|
+
authenticateProvableApi: (params) => authenticateProvableApi(client, params)
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
166
346
|
// src/index.ts
|
|
347
|
+
var DEFAULT_PROVER_URL = "https://api.provable.com/prove";
|
|
348
|
+
var DEFAULT_SCANNER_URL = "https://api.provable.com/scanner";
|
|
167
349
|
async function loadNetwork(name) {
|
|
168
350
|
const sdk = await loadSdk(name);
|
|
351
|
+
silenceSdkLogs(sdk);
|
|
169
352
|
return buildSdk(name, sdk);
|
|
170
353
|
}
|
|
354
|
+
function silenceSdkLogs(sdk) {
|
|
355
|
+
const { setLogLevel } = sdk;
|
|
356
|
+
setLogLevel?.("silent");
|
|
357
|
+
}
|
|
171
358
|
function buildSdk(initialNetwork, initialSdk) {
|
|
172
359
|
let currentSdk = initialSdk;
|
|
173
360
|
const network = initialNetwork;
|
|
@@ -207,12 +394,35 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
207
394
|
return new AleoNetworkClient(url);
|
|
208
395
|
}
|
|
209
396
|
function createProvingConfig(options) {
|
|
397
|
+
assertKeyedAuthAlone(options.auth, {
|
|
398
|
+
session: options.session,
|
|
399
|
+
apiKey: options.apiKey,
|
|
400
|
+
consumerId: options.consumerId
|
|
401
|
+
});
|
|
210
402
|
let networkUrl = options.networkUrl;
|
|
211
403
|
let keyProvider = new currentSdk.AleoKeyProvider();
|
|
212
404
|
keyProvider.useCache(true);
|
|
405
|
+
options.session?.attach("proving");
|
|
406
|
+
let configNetwork = network;
|
|
407
|
+
const resolveProverUrl = () => {
|
|
408
|
+
const configured = options.proverUrl ?? (options.mode === "delegated" ? DEFAULT_PROVER_URL : void 0);
|
|
409
|
+
if (!configured) return void 0;
|
|
410
|
+
const base = configured.replace(/\/+$/, "").replace(/\/(mainnet|testnet)$/, "");
|
|
411
|
+
return `${base}/${configNetwork}`;
|
|
412
|
+
};
|
|
213
413
|
return {
|
|
214
414
|
mode: options.mode,
|
|
215
|
-
|
|
415
|
+
// A getter, not a snapshot: the network segment moves with `switchChain`,
|
|
416
|
+
// and a fixed string here would report the network this config started on
|
|
417
|
+
// long after it left.
|
|
418
|
+
get url() {
|
|
419
|
+
return resolveProverUrl();
|
|
420
|
+
},
|
|
421
|
+
// Carried for `authenticateProvableApi` to find on a client. Core never
|
|
422
|
+
// reads binding-specific fields on a proving config — `url` and `apiKey`
|
|
423
|
+
// already travel the same way.
|
|
424
|
+
session: options.session,
|
|
425
|
+
keyedAuth: options.auth,
|
|
216
426
|
buildTransaction: async (txOptions) => {
|
|
217
427
|
const programManager = new currentSdk.ProgramManager(
|
|
218
428
|
networkUrl,
|
|
@@ -305,9 +515,10 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
305
515
|
const ct = RecordCiphertext.fromString(ciphertext);
|
|
306
516
|
return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : null;
|
|
307
517
|
} : void 0;
|
|
308
|
-
const buildPollingClient = () => createPublicClient({ transport: http(networkUrl, { network }) });
|
|
518
|
+
const buildPollingClient = () => createPublicClient({ transport: http(networkUrl, { network: configNetwork }) });
|
|
309
519
|
if (options.mode === "delegated") {
|
|
310
|
-
|
|
520
|
+
const proverUrl = resolveProverUrl();
|
|
521
|
+
if (!proverUrl) throw new ConfigurationError("Delegated execution requires proverUrl. Pass proverUrl to createProvingConfig or createAleoClient.");
|
|
311
522
|
let response;
|
|
312
523
|
try {
|
|
313
524
|
const provingRequest = await programManager.provingRequest({
|
|
@@ -321,13 +532,33 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
321
532
|
broadcast: true,
|
|
322
533
|
useFeeMaster: options.useFeeMaster ?? true
|
|
323
534
|
});
|
|
324
|
-
const dpsClient = new AleoNetworkClient(
|
|
325
|
-
|
|
535
|
+
const dpsClient = new AleoNetworkClient(proverUrl);
|
|
536
|
+
const auth = async (forceRefresh) => {
|
|
537
|
+
if (options.auth) return { auth: options.auth };
|
|
538
|
+
if (options.session) return { jwtData: await options.session.getJwt({ forceRefresh }) };
|
|
539
|
+
return { apiKey: options.apiKey, consumerId: options.consumerId };
|
|
540
|
+
};
|
|
541
|
+
let credentials = await auth(false);
|
|
542
|
+
let result = await dpsClient.submitProvingRequestSafe({
|
|
326
543
|
provingRequest,
|
|
327
|
-
url:
|
|
328
|
-
|
|
329
|
-
consumerId: options.consumerId
|
|
544
|
+
url: proverUrl,
|
|
545
|
+
...credentials
|
|
330
546
|
});
|
|
547
|
+
if (!result.ok && (result.status === 401 || result.status === 403) && options.session) {
|
|
548
|
+
credentials = await auth(true);
|
|
549
|
+
result = await dpsClient.submitProvingRequestSafe({
|
|
550
|
+
provingRequest,
|
|
551
|
+
url: proverUrl,
|
|
552
|
+
...credentials
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
if (!result.ok) {
|
|
556
|
+
throw new ProvingError({
|
|
557
|
+
message: `Delegated proving failed (HTTP ${result.status}): ${result.error?.message ?? "unknown error"}`,
|
|
558
|
+
statusCode: result.status
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
response = result.data;
|
|
331
562
|
} catch (e) {
|
|
332
563
|
if (e instanceof BaseError) throw e;
|
|
333
564
|
throw classifyProvingError(e);
|
|
@@ -382,8 +613,10 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
382
613
|
);
|
|
383
614
|
}
|
|
384
615
|
currentSdk = await loadSdk(newNetwork);
|
|
616
|
+
silenceSdkLogs(currentSdk);
|
|
385
617
|
keyProvider = new currentSdk.AleoKeyProvider();
|
|
386
618
|
keyProvider.useCache(true);
|
|
619
|
+
configNetwork = newNetwork;
|
|
387
620
|
}
|
|
388
621
|
};
|
|
389
622
|
}
|
|
@@ -428,43 +661,74 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
428
661
|
}
|
|
429
662
|
};
|
|
430
663
|
}
|
|
431
|
-
|
|
664
|
+
function assertKeyedAuthAlone(auth, conflicts) {
|
|
665
|
+
if (!auth) return;
|
|
666
|
+
const named = Object.keys(conflicts).filter((key) => conflicts[key]);
|
|
667
|
+
if (named.length) {
|
|
668
|
+
throw new ConfigurationError(
|
|
669
|
+
`Provisioned-key auth is mutually exclusive with ${named.join(", ")} \u2014 edge API keys are handed out, not registered.`
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async function scanOwned(scanner, params, hasCredentials, session) {
|
|
674
|
+
const ownedFilter = buildOwnedFilter(params);
|
|
432
675
|
const ALWAYS_RETRY = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
433
676
|
const AUTH_RETRY = /* @__PURE__ */ new Set([401, 403]);
|
|
677
|
+
const canReMint = hasCredentials || !!session;
|
|
434
678
|
const retryable = (status) => ALWAYS_RETRY.has(status) || canReMint && AUTH_RETRY.has(status);
|
|
435
679
|
const MAX_ATTEMPTS = 4;
|
|
436
680
|
let last = "";
|
|
681
|
+
let lastStatus;
|
|
437
682
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
438
683
|
try {
|
|
439
|
-
const result = await scanner.owned(
|
|
440
|
-
unspent: statusFilter !== "spent",
|
|
441
|
-
filter: { programs: [program] }
|
|
442
|
-
});
|
|
684
|
+
const result = await scanner.owned(ownedFilter);
|
|
443
685
|
if (result.ok) return (result.data ?? []).map((r) => toOwnedRecord(r));
|
|
444
686
|
last = `HTTP ${result.status}: ${result.error?.message ?? "unknown error"}`;
|
|
687
|
+
lastStatus = result.status;
|
|
445
688
|
if (!retryable(result.status)) break;
|
|
446
689
|
} catch (err) {
|
|
447
690
|
last = err instanceof Error ? err.message : String(err);
|
|
691
|
+
lastStatus = void 0;
|
|
448
692
|
}
|
|
449
693
|
if (attempt === MAX_ATTEMPTS - 1) break;
|
|
450
|
-
|
|
694
|
+
if (lastStatus !== void 0 && AUTH_RETRY.has(lastStatus)) {
|
|
695
|
+
if (session) scanner.setJwtData(await session.getJwt({ forceRefresh: true }));
|
|
696
|
+
else scanner.setJwtData(void 0);
|
|
697
|
+
}
|
|
451
698
|
await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** attempt));
|
|
452
699
|
}
|
|
453
700
|
throw new Error(`Record scan failed (${last})`);
|
|
454
701
|
}
|
|
455
|
-
function createRemoteScanner(options) {
|
|
702
|
+
function createRemoteScanner(options = {}) {
|
|
703
|
+
assertKeyedAuthAlone(options.auth, {
|
|
704
|
+
session: options.session,
|
|
705
|
+
apiKey: options.apiKey,
|
|
706
|
+
consumerId: options.consumerId
|
|
707
|
+
});
|
|
708
|
+
if (!options.session && options.apiKey && !options.consumerId) {
|
|
709
|
+
throw new ConfigurationError(
|
|
710
|
+
"Record scanning with an apiKey also needs consumerId \u2014 a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service."
|
|
711
|
+
);
|
|
712
|
+
}
|
|
456
713
|
let scannerSdk = { RecordScanner, ViewKey };
|
|
457
714
|
let scanner;
|
|
458
715
|
let viewKey;
|
|
459
716
|
let viewKeyString;
|
|
460
717
|
let registration = makeRegisterOnce(options.startBlock ?? 0);
|
|
718
|
+
let credential = options.auth ?? options.session;
|
|
719
|
+
const sessionOf = (source) => source && !("mode" in source) ? source : void 0;
|
|
720
|
+
sessionOf(credential)?.attach("recordScanning");
|
|
721
|
+
const url = options.url ?? DEFAULT_SCANNER_URL;
|
|
461
722
|
function buildScanner() {
|
|
462
723
|
if (!viewKeyString) return;
|
|
463
724
|
viewKey = scannerSdk.ViewKey.from_string(viewKeyString);
|
|
725
|
+
const credentialProps = credential && "mode" in credential ? { auth: credential } : credential ? {} : {
|
|
726
|
+
...options.consumerId ? { consumerId: options.consumerId } : {},
|
|
727
|
+
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
728
|
+
};
|
|
464
729
|
scanner = new scannerSdk.RecordScanner({
|
|
465
|
-
url
|
|
466
|
-
|
|
467
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
730
|
+
url,
|
|
731
|
+
...credentialProps,
|
|
468
732
|
viewKeys: [viewKey],
|
|
469
733
|
decryptEnabled: true,
|
|
470
734
|
autoReRegister: true
|
|
@@ -476,6 +740,30 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
476
740
|
viewKeyString = account.viewKey;
|
|
477
741
|
buildScanner();
|
|
478
742
|
},
|
|
743
|
+
/**
|
|
744
|
+
* Shares a Provable API session with this scanner.
|
|
745
|
+
*
|
|
746
|
+
* Called by {@link createAleoClient} so one session covers proving and
|
|
747
|
+
* scanning. Takes effect on the next scan — the token is applied at the
|
|
748
|
+
* scan boundary, not at construction.
|
|
749
|
+
*/
|
|
750
|
+
setSession: (next) => {
|
|
751
|
+
credential = next;
|
|
752
|
+
next.attach("recordScanning");
|
|
753
|
+
buildScanner();
|
|
754
|
+
},
|
|
755
|
+
/**
|
|
756
|
+
* Shares provisioned-key auth with this scanner.
|
|
757
|
+
*
|
|
758
|
+
* Called by {@link createAleoClient} when the client uses the edge
|
|
759
|
+
* gateway's keyed model. Replaces any session, since the two models are
|
|
760
|
+
* mutually exclusive. Takes effect on the next scan.
|
|
761
|
+
*/
|
|
762
|
+
setAuth: (next) => {
|
|
763
|
+
credential = next;
|
|
764
|
+
if (scanner) scanner.setAuth(next);
|
|
765
|
+
else buildScanner();
|
|
766
|
+
},
|
|
479
767
|
requestRecords: async (params) => {
|
|
480
768
|
if (!scanner) {
|
|
481
769
|
throw new Error("No active account set on record scanner. Call setAccount() first.");
|
|
@@ -483,8 +771,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
483
771
|
const activeScanner = scanner;
|
|
484
772
|
const activeViewKey = viewKey;
|
|
485
773
|
const activeRegistration = registration;
|
|
774
|
+
const activeSession = sessionOf(credential);
|
|
775
|
+
if (activeSession) activeScanner.setJwtData(await activeSession.getJwt());
|
|
486
776
|
await activeRegistration.ensure(activeScanner, activeViewKey);
|
|
487
|
-
|
|
777
|
+
const canReMint = !credential && !!(options.apiKey && options.consumerId);
|
|
778
|
+
return scanOwned(activeScanner, params, canReMint, activeSession);
|
|
488
779
|
},
|
|
489
780
|
switchNetwork: async (newNetwork) => {
|
|
490
781
|
if (newNetwork !== "mainnet" && newNetwork !== "testnet") {
|
|
@@ -498,11 +789,25 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
498
789
|
};
|
|
499
790
|
}
|
|
500
791
|
function createStandaloneScanner(options) {
|
|
792
|
+
assertKeyedAuthAlone(options.auth, {
|
|
793
|
+
session: options.session,
|
|
794
|
+
apiKey: options.apiKey,
|
|
795
|
+
consumerId: options.consumerId
|
|
796
|
+
});
|
|
797
|
+
if (!options.session && options.apiKey && !options.consumerId) {
|
|
798
|
+
throw new ConfigurationError(
|
|
799
|
+
"Record scanning with an apiKey also needs consumerId \u2014 a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service."
|
|
800
|
+
);
|
|
801
|
+
}
|
|
501
802
|
const viewKey = ViewKey.from_string(options.viewKey);
|
|
803
|
+
const session = options.session;
|
|
804
|
+
const credentialProps = options.auth ? { auth: options.auth } : session ? {} : {
|
|
805
|
+
...options.consumerId ? { consumerId: options.consumerId } : {},
|
|
806
|
+
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
807
|
+
};
|
|
502
808
|
const scanner = new RecordScanner({
|
|
503
|
-
url: options.url,
|
|
504
|
-
|
|
505
|
-
...options.apiKey ? { apiKey: options.apiKey } : {},
|
|
809
|
+
url: options.url ?? DEFAULT_SCANNER_URL,
|
|
810
|
+
...credentialProps,
|
|
506
811
|
viewKeys: [viewKey],
|
|
507
812
|
decryptEnabled: true,
|
|
508
813
|
autoReRegister: true
|
|
@@ -510,25 +815,57 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
510
815
|
const registration = makeRegisterOnce(options.startBlock ?? 0);
|
|
511
816
|
return {
|
|
512
817
|
requestRecords: async (params) => {
|
|
818
|
+
if (session) scanner.setJwtData(await session.getJwt());
|
|
513
819
|
await registration.ensure(scanner, viewKey);
|
|
514
|
-
return scanOwned(scanner, params
|
|
820
|
+
return scanOwned(scanner, params, !!(options.apiKey && options.consumerId), session);
|
|
515
821
|
}
|
|
516
822
|
};
|
|
517
823
|
}
|
|
518
824
|
function createAleoClient(options) {
|
|
825
|
+
assertKeyedAuthAlone(options.auth, {
|
|
826
|
+
apiKey: options.apiKey,
|
|
827
|
+
consumerId: options.consumerId,
|
|
828
|
+
username: options.username,
|
|
829
|
+
credentialStore: options.credentialStore,
|
|
830
|
+
session: options.session
|
|
831
|
+
});
|
|
832
|
+
if (options.auth && options.records && !options.records.setAuth) {
|
|
833
|
+
throw new ConfigurationError(
|
|
834
|
+
"Provisioned-key auth needs a record provider with setAuth \u2014 pass a scanner from createRemoteScanner, or construct the provider with the key."
|
|
835
|
+
);
|
|
836
|
+
}
|
|
519
837
|
const account = privateKeyToAccount(options.privateKey);
|
|
520
838
|
const transport = http(options.networkUrl, { network });
|
|
839
|
+
const credentials = options.consumerId && options.apiKey ? { consumerId: options.consumerId, apiKey: options.apiKey } : void 0;
|
|
840
|
+
const configured = !!(credentials || options.credentialStore || options.session);
|
|
841
|
+
const session = options.auth ? void 0 : options.session ?? createProvableSession({
|
|
842
|
+
credentials,
|
|
843
|
+
store: options.credentialStore ?? memoryCredentialStore(),
|
|
844
|
+
// Resolved lazily: only a registration needs it. The derived default
|
|
845
|
+
// carries a random suffix because a username is spent once — an account
|
|
846
|
+
// that lost its stored key must still be able to register, and the old
|
|
847
|
+
// key is unrecoverable. A caller-supplied name is used verbatim, so a
|
|
848
|
+
// collision fails rather than quietly registering something else.
|
|
849
|
+
username: options.username ?? (() => `veil-${account.address.slice(5, 13)}-${Math.random().toString(36).slice(2, 8)}`)
|
|
850
|
+
});
|
|
521
851
|
const proving = createProvingConfig({
|
|
522
852
|
mode: options.provingMode ?? "delegated",
|
|
523
853
|
networkUrl: options.networkUrl,
|
|
524
854
|
proverUrl: options.proverUrl,
|
|
855
|
+
session,
|
|
856
|
+
auth: options.auth,
|
|
857
|
+
// Ignored by the proving config whenever a session is present, which is
|
|
858
|
+
// where the one-minter rule is enforced.
|
|
525
859
|
apiKey: options.apiKey,
|
|
526
860
|
consumerId: options.consumerId,
|
|
527
861
|
account,
|
|
528
|
-
...options.useFeeMaster !== void 0 ? { useFeeMaster: options.useFeeMaster } : {}
|
|
862
|
+
...options.useFeeMaster !== void 0 ? { useFeeMaster: options.useFeeMaster } : {},
|
|
863
|
+
...options.confirmationTimeout !== void 0 ? { confirmationTimeout: options.confirmationTimeout } : {}
|
|
529
864
|
});
|
|
530
865
|
const publicClient = createPublicClient({ transport });
|
|
531
866
|
if (options.records) {
|
|
867
|
+
if (options.auth) options.records.setAuth?.(options.auth);
|
|
868
|
+
else if (configured && session) options.records.setSession?.(session);
|
|
532
869
|
options.records.setAccount({ viewKey: account.viewKey });
|
|
533
870
|
}
|
|
534
871
|
const walletClient = createWalletClient({
|
|
@@ -536,7 +873,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
536
873
|
transport,
|
|
537
874
|
proving,
|
|
538
875
|
...options.records ? { recordProvider: options.records } : {}
|
|
539
|
-
});
|
|
876
|
+
}).extend(provableApiActions());
|
|
540
877
|
return { publicClient, walletClient, account };
|
|
541
878
|
}
|
|
542
879
|
return {
|
|
@@ -554,7 +891,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
554
891
|
createAleoClient
|
|
555
892
|
};
|
|
556
893
|
}
|
|
557
|
-
var DEVNODE_CONSENSUS_HEIGHTS = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16";
|
|
894
|
+
var DEVNODE_CONSENSUS_HEIGHTS = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,4294967295";
|
|
558
895
|
function privateKeyToAccount(privateKey) {
|
|
559
896
|
const sdkAccount = new Account({ privateKey });
|
|
560
897
|
const address = sdkAccount.address().to_string();
|
|
@@ -665,16 +1002,23 @@ function createDevnodeClient(options) {
|
|
|
665
1002
|
}
|
|
666
1003
|
export {
|
|
667
1004
|
BLS12377HDKey,
|
|
1005
|
+
DEFAULT_PROVER_URL,
|
|
1006
|
+
DEFAULT_SCANNER_URL,
|
|
668
1007
|
DEVNODE_ADDR,
|
|
669
1008
|
DEVNODE_PRIVATE_KEY,
|
|
670
1009
|
LEGACY_PATH,
|
|
671
1010
|
STANDARD_PATH,
|
|
1011
|
+
authenticateProvableApi,
|
|
672
1012
|
createDevnodeClient,
|
|
1013
|
+
createProvableSession,
|
|
673
1014
|
generateAccount,
|
|
674
1015
|
generateMnemonic2 as generateMnemonic,
|
|
675
1016
|
loadNetwork,
|
|
1017
|
+
memoryCredentialStore,
|
|
676
1018
|
mnemonicToHDKey,
|
|
677
1019
|
mnemonicToSeed,
|
|
1020
|
+
provableApiActions,
|
|
1021
|
+
registerProvableApi,
|
|
678
1022
|
validateMnemonic2 as validateMnemonic,
|
|
679
1023
|
validateWord
|
|
680
1024
|
};
|