@provablehq/veil-aleo-sdk 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/index.d.ts +32 -5
- package/dist/index.js +123 -31
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +2 -1
- package/dist/{provableApi-DsStWMOJ.d.ts → provableApi-C4bT37jI.d.ts} +41 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -217,6 +217,29 @@ For local iteration without a live chain, `createDevnodeClient()` returns the
|
|
|
217
217
|
same client pair pointed at an Aleo Devnode instance with a pre-funded seeded
|
|
218
218
|
account.
|
|
219
219
|
|
|
220
|
+
## Provisioned API keys (edge gateway)
|
|
221
|
+
|
|
222
|
+
The edge gateway (`edge.provable.com`) runs a different auth model: no consumer
|
|
223
|
+
registration and no JWTs. An operator hands out an API key, and every request
|
|
224
|
+
carries it verbatim in an `X-API-Key` header. Configure it with `auth` instead
|
|
225
|
+
of the consumer options:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
const { walletClient } = aleo.createAleoClient({
|
|
229
|
+
privateKey,
|
|
230
|
+
networkUrl: 'https://edge.provable.com/api/v2',
|
|
231
|
+
proverUrl: 'https://edge.provable.com/api/prove',
|
|
232
|
+
records: aleo.createRemoteScanner({ url: 'https://edge.provable.com/api/scanner' }),
|
|
233
|
+
auth: { mode: 'api-key', value: process.env.PROVABLE_API_KEY! },
|
|
234
|
+
})
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The two models are mutually exclusive: combining `auth` with `apiKey`,
|
|
238
|
+
`consumerId`, `username`, `credentialStore`, or `session` throws at
|
|
239
|
+
construction. There is no session under keyed auth — nothing registers,
|
|
240
|
+
persists, or refreshes — so `authenticateProvableApi()` throws, and a 401
|
|
241
|
+
means the key is invalid or revoked, which only the operator can fix.
|
|
242
|
+
|
|
220
243
|
## WASM dependency
|
|
221
244
|
|
|
222
245
|
`@provablehq/sdk` ships the Aleo cryptography as WebAssembly, and this package
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { loadNetwork as loadNetwork$1 } from '@provablehq/sdk/dynamic.js';
|
|
2
2
|
export { DEVNODE_ADDR, DEVNODE_PRIVATE_KEY } from '@provablehq/veil-aleo-devnode';
|
|
3
3
|
import { LocalAccount, RecordProvider, StandaloneRecordScanner, PublicClient, WalletClient } from '@provablehq/veil-core';
|
|
4
|
-
import { P as ProvableSession, a as
|
|
5
|
-
export { A as AuthenticateProvableApiParameters,
|
|
4
|
+
import { P as ProvableSession, a as ProvableKeyedAuth, b as ProvingConfigWithSession, c as ProvableCredentialStore, d as ProvableWalletClient } from './provableApi-C4bT37jI.js';
|
|
5
|
+
export { A as AuthenticateProvableApiParameters, e as AuthenticateProvableApiReturnType, C as CreateProvableSessionOptions, f as ProvableApiActions, g as ProvableApiCredentials, h as ProvableJwt, i as ProvableSessionConsumers, R as RegisterProvableApiParameters, j as authenticateProvableApi, k as createProvableSession, m as memoryCredentialStore, p as provableApiActions, r as registerProvableApi } from './provableApi-C4bT37jI.js';
|
|
6
|
+
import '@provablehq/sdk';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Names the derivation-path convention used to turn a seed into Aleo keys.
|
|
@@ -253,6 +254,10 @@ interface AleoSdk {
|
|
|
253
254
|
* from the prover client, so one party mints JWTs. The session is attached
|
|
254
255
|
* to the returned configuration, which is what lets
|
|
255
256
|
* `authenticateProvableApi` find it on a client.
|
|
257
|
+
* @param options.auth Optional provisioned-key auth for the edge gateway.
|
|
258
|
+
* Every proving request carries the key verbatim; nothing registers or
|
|
259
|
+
* mints, and a 401 is terminal. Mutually exclusive with `session`,
|
|
260
|
+
* `apiKey`, and `consumerId` — combining them throws.
|
|
256
261
|
*/
|
|
257
262
|
createProvingConfig(options: {
|
|
258
263
|
mode: 'delegated' | 'local';
|
|
@@ -264,6 +269,7 @@ interface AleoSdk {
|
|
|
264
269
|
confirmationTimeout?: number;
|
|
265
270
|
useFeeMaster?: boolean;
|
|
266
271
|
session?: ProvableSession;
|
|
272
|
+
auth?: ProvableKeyedAuth;
|
|
267
273
|
}): ProvingConfigWithSession;
|
|
268
274
|
/**
|
|
269
275
|
* Creates a record scanner backed by Provable's Record Scanner Service.
|
|
@@ -290,8 +296,13 @@ interface AleoSdk {
|
|
|
290
296
|
* passes the scanner to that factory does not need this.
|
|
291
297
|
* @param options.startBlock Optional block height to begin scanning from at
|
|
292
298
|
* registration. Defaults to 0 (full history).
|
|
293
|
-
* @
|
|
294
|
-
*
|
|
299
|
+
* @param options.auth Optional provisioned-key auth for the edge gateway.
|
|
300
|
+
* Every scan carries the key verbatim; nothing registers or mints, and a
|
|
301
|
+
* 401 is terminal. Mutually exclusive with `session`, `apiKey`, and
|
|
302
|
+
* `consumerId` — combining them throws.
|
|
303
|
+
* @returns The provider, plus `setSession` and `setAuth` for a factory to
|
|
304
|
+
* share one credential source across proving and scanning after
|
|
305
|
+
* construction.
|
|
295
306
|
*/
|
|
296
307
|
createRemoteScanner(options?: {
|
|
297
308
|
url?: string;
|
|
@@ -299,8 +310,10 @@ interface AleoSdk {
|
|
|
299
310
|
apiKey?: string;
|
|
300
311
|
session?: ProvableSession;
|
|
301
312
|
startBlock?: number;
|
|
313
|
+
auth?: ProvableKeyedAuth;
|
|
302
314
|
}): RecordProvider & {
|
|
303
315
|
setSession: (session: ProvableSession) => void;
|
|
316
|
+
setAuth: (auth: ProvableKeyedAuth) => void;
|
|
304
317
|
};
|
|
305
318
|
/**
|
|
306
319
|
* Creates a standalone record scanner with an explicit view key.
|
|
@@ -322,6 +335,10 @@ interface AleoSdk {
|
|
|
322
335
|
* into a wallet client, so nothing shares a session with it later.
|
|
323
336
|
* @param options.startBlock Optional block height to begin scanning from at
|
|
324
337
|
* registration. Defaults to 0 (full history).
|
|
338
|
+
* @param options.auth Optional provisioned-key auth for the edge gateway.
|
|
339
|
+
* Every scan carries the key verbatim; nothing registers or mints, and a
|
|
340
|
+
* 401 is terminal. Mutually exclusive with `session`, `apiKey`, and
|
|
341
|
+
* `consumerId` — combining them throws.
|
|
325
342
|
*/
|
|
326
343
|
createStandaloneScanner(options: {
|
|
327
344
|
url?: string;
|
|
@@ -330,6 +347,7 @@ interface AleoSdk {
|
|
|
330
347
|
apiKey?: string;
|
|
331
348
|
session?: ProvableSession;
|
|
332
349
|
startBlock?: number;
|
|
350
|
+
auth?: ProvableKeyedAuth;
|
|
333
351
|
}): StandaloneRecordScanner;
|
|
334
352
|
/**
|
|
335
353
|
* Creates a fully-wired Aleo client from a private key and network URL.
|
|
@@ -372,6 +390,13 @@ interface AleoSdk {
|
|
|
372
390
|
* aimed at an open service keeps needing no credential.
|
|
373
391
|
* @param options.session Optional pre-built session, for a caller that owns
|
|
374
392
|
* one already. Takes precedence over the credential options.
|
|
393
|
+
* @param options.auth Optional provisioned-key auth for the edge gateway.
|
|
394
|
+
* Selects the keyed model for the whole client: proving and scanning carry
|
|
395
|
+
* the key on every request, no session exists, and
|
|
396
|
+
* `authenticateProvableApi` throws since there is nothing to resolve.
|
|
397
|
+
* Mutually exclusive with every consumer option (`apiKey`, `consumerId`,
|
|
398
|
+
* `username`, `credentialStore`, `session`) — edge keys are handed out by
|
|
399
|
+
* an operator, not registered.
|
|
375
400
|
* @returns A public client, a wallet client carrying
|
|
376
401
|
* `authenticateProvableApi`, and the account.
|
|
377
402
|
*
|
|
@@ -395,6 +420,7 @@ interface AleoSdk {
|
|
|
395
420
|
username?: string | (() => string);
|
|
396
421
|
credentialStore?: ProvableCredentialStore;
|
|
397
422
|
session?: ProvableSession;
|
|
423
|
+
auth?: ProvableKeyedAuth;
|
|
398
424
|
/**
|
|
399
425
|
* Record provider for `requestRecords`. Not wired by default — pass
|
|
400
426
|
* `aleo.createRemoteScanner(...)` or any
|
|
@@ -403,6 +429,7 @@ interface AleoSdk {
|
|
|
403
429
|
*/
|
|
404
430
|
records?: RecordProvider & {
|
|
405
431
|
setSession?: (session: ProvableSession) => void;
|
|
432
|
+
setAuth?: (auth: ProvableKeyedAuth) => void;
|
|
406
433
|
};
|
|
407
434
|
}): {
|
|
408
435
|
publicClient: PublicClient;
|
|
@@ -454,4 +481,4 @@ declare function createDevnodeClient(options?: {
|
|
|
454
481
|
account: LocalAccount<'privateKey'>;
|
|
455
482
|
};
|
|
456
483
|
|
|
457
|
-
export { type AleoDerivationId, type AleoSdk, BLS12377HDKey, DEFAULT_PROVER_URL, DEFAULT_SCANNER_URL, LEGACY_PATH, ProvableCredentialStore, ProvableSession, ProvableWalletClient, ProvingConfigWithSession, STANDARD_PATH, type SupportedNetwork, createDevnodeClient, generateAccount, generateMnemonic, loadNetwork, mnemonicToHDKey, mnemonicToSeed, validateMnemonic, validateWord };
|
|
484
|
+
export { type AleoDerivationId, type AleoSdk, BLS12377HDKey, DEFAULT_PROVER_URL, DEFAULT_SCANNER_URL, LEGACY_PATH, ProvableCredentialStore, ProvableKeyedAuth, ProvableSession, ProvableWalletClient, ProvingConfigWithSession, STANDARD_PATH, type SupportedNetwork, createDevnodeClient, generateAccount, generateMnemonic, loadNetwork, mnemonicToHDKey, mnemonicToSeed, validateMnemonic, validateWord };
|
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";
|
|
@@ -177,7 +207,8 @@ function memoryCredentialStore(initial) {
|
|
|
177
207
|
}
|
|
178
208
|
async function registerProvableApi(params) {
|
|
179
209
|
const baseUrl = params.baseUrl ?? DEFAULT_PROVABLE_API_URL;
|
|
180
|
-
const
|
|
210
|
+
const transport = params.transport ?? fetch;
|
|
211
|
+
const response = await transport(`${baseUrl}/consumers`, {
|
|
181
212
|
method: "POST",
|
|
182
213
|
headers: { "content-type": "application/json" },
|
|
183
214
|
body: JSON.stringify({ username: params.username })
|
|
@@ -199,8 +230,8 @@ async function registerProvableApi(params) {
|
|
|
199
230
|
}
|
|
200
231
|
return { consumerId: body.consumer.id, apiKey: body.key };
|
|
201
232
|
}
|
|
202
|
-
async function mintJwt(credentials, baseUrl) {
|
|
203
|
-
const response = await
|
|
233
|
+
async function mintJwt(credentials, baseUrl, transport) {
|
|
234
|
+
const response = await transport(`${baseUrl}/jwts/${encodeURIComponent(credentials.consumerId)}`, {
|
|
204
235
|
method: "POST",
|
|
205
236
|
headers: { "X-Provable-API-Key": credentials.apiKey }
|
|
206
237
|
});
|
|
@@ -221,6 +252,7 @@ async function mintJwt(credentials, baseUrl) {
|
|
|
221
252
|
}
|
|
222
253
|
function createProvableSession(options = {}) {
|
|
223
254
|
const baseUrl = options.baseUrl ?? DEFAULT_PROVABLE_API_URL;
|
|
255
|
+
const transport = options.transport ?? fetch;
|
|
224
256
|
const consumers = { proving: false, recordScanning: false };
|
|
225
257
|
let credentials = options.credentials;
|
|
226
258
|
let registered = false;
|
|
@@ -240,7 +272,7 @@ function createProvableSession(options = {}) {
|
|
|
240
272
|
"No Provable API credentials available \u2014 pass credentials, a store holding them, or a username to register with."
|
|
241
273
|
);
|
|
242
274
|
}
|
|
243
|
-
const issued = await registerProvableApi({ username, baseUrl });
|
|
275
|
+
const issued = await registerProvableApi({ username, baseUrl, transport });
|
|
244
276
|
credentials = issued;
|
|
245
277
|
registered = true;
|
|
246
278
|
try {
|
|
@@ -264,7 +296,7 @@ function createProvableSession(options = {}) {
|
|
|
264
296
|
if (!forceRefresh && !stale) return Promise.resolve(jwt);
|
|
265
297
|
jwtInFlight ??= (async () => {
|
|
266
298
|
const resolved = await getCredentials();
|
|
267
|
-
jwt = await mintJwt(resolved, baseUrl);
|
|
299
|
+
jwt = await mintJwt(resolved, baseUrl, transport);
|
|
268
300
|
return jwt;
|
|
269
301
|
})().finally(() => {
|
|
270
302
|
jwtInFlight = void 0;
|
|
@@ -285,6 +317,11 @@ function getProvableSession(client) {
|
|
|
285
317
|
return client.proving?.session;
|
|
286
318
|
}
|
|
287
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
|
+
}
|
|
288
325
|
const session = getProvableSession(client);
|
|
289
326
|
if (!session) {
|
|
290
327
|
throw new Error(
|
|
@@ -357,6 +394,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
357
394
|
return new AleoNetworkClient(url);
|
|
358
395
|
}
|
|
359
396
|
function createProvingConfig(options) {
|
|
397
|
+
assertKeyedAuthAlone(options.auth, {
|
|
398
|
+
session: options.session,
|
|
399
|
+
apiKey: options.apiKey,
|
|
400
|
+
consumerId: options.consumerId
|
|
401
|
+
});
|
|
360
402
|
let networkUrl = options.networkUrl;
|
|
361
403
|
let keyProvider = new currentSdk.AleoKeyProvider();
|
|
362
404
|
keyProvider.useCache(true);
|
|
@@ -380,6 +422,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
380
422
|
// reads binding-specific fields on a proving config — `url` and `apiKey`
|
|
381
423
|
// already travel the same way.
|
|
382
424
|
session: options.session,
|
|
425
|
+
keyedAuth: options.auth,
|
|
383
426
|
buildTransaction: async (txOptions) => {
|
|
384
427
|
const programManager = new currentSdk.ProgramManager(
|
|
385
428
|
networkUrl,
|
|
@@ -490,7 +533,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
490
533
|
useFeeMaster: options.useFeeMaster ?? true
|
|
491
534
|
});
|
|
492
535
|
const dpsClient = new AleoNetworkClient(proverUrl);
|
|
493
|
-
const auth = async (forceRefresh) =>
|
|
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
|
+
};
|
|
494
541
|
let credentials = await auth(false);
|
|
495
542
|
let result = await dpsClient.submitProvingRequestSafe({
|
|
496
543
|
provingRequest,
|
|
@@ -614,7 +661,17 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
614
661
|
}
|
|
615
662
|
};
|
|
616
663
|
}
|
|
617
|
-
|
|
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);
|
|
618
675
|
const ALWAYS_RETRY = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
619
676
|
const AUTH_RETRY = /* @__PURE__ */ new Set([401, 403]);
|
|
620
677
|
const canReMint = hasCredentials || !!session;
|
|
@@ -624,10 +681,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
624
681
|
let lastStatus;
|
|
625
682
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
626
683
|
try {
|
|
627
|
-
const result = await scanner.owned(
|
|
628
|
-
unspent: statusFilter !== "spent",
|
|
629
|
-
filter: { programs: [program] }
|
|
630
|
-
});
|
|
684
|
+
const result = await scanner.owned(ownedFilter);
|
|
631
685
|
if (result.ok) return (result.data ?? []).map((r) => toOwnedRecord(r));
|
|
632
686
|
last = `HTTP ${result.status}: ${result.error?.message ?? "unknown error"}`;
|
|
633
687
|
lastStatus = result.status;
|
|
@@ -646,6 +700,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
646
700
|
throw new Error(`Record scan failed (${last})`);
|
|
647
701
|
}
|
|
648
702
|
function createRemoteScanner(options = {}) {
|
|
703
|
+
assertKeyedAuthAlone(options.auth, {
|
|
704
|
+
session: options.session,
|
|
705
|
+
apiKey: options.apiKey,
|
|
706
|
+
consumerId: options.consumerId
|
|
707
|
+
});
|
|
649
708
|
if (!options.session && options.apiKey && !options.consumerId) {
|
|
650
709
|
throw new ConfigurationError(
|
|
651
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."
|
|
@@ -656,20 +715,20 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
656
715
|
let viewKey;
|
|
657
716
|
let viewKeyString;
|
|
658
717
|
let registration = makeRegisterOnce(options.startBlock ?? 0);
|
|
659
|
-
let
|
|
660
|
-
|
|
718
|
+
let credential = options.auth ?? options.session;
|
|
719
|
+
const sessionOf = (source) => source && !("mode" in source) ? source : void 0;
|
|
720
|
+
sessionOf(credential)?.attach("recordScanning");
|
|
661
721
|
const url = options.url ?? DEFAULT_SCANNER_URL;
|
|
662
722
|
function buildScanner() {
|
|
663
723
|
if (!viewKeyString) return;
|
|
664
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
|
+
};
|
|
665
729
|
scanner = new scannerSdk.RecordScanner({
|
|
666
730
|
url,
|
|
667
|
-
|
|
668
|
-
// the scanner and only one party mints.
|
|
669
|
-
...session ? {} : {
|
|
670
|
-
...options.consumerId ? { consumerId: options.consumerId } : {},
|
|
671
|
-
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
672
|
-
},
|
|
731
|
+
...credentialProps,
|
|
673
732
|
viewKeys: [viewKey],
|
|
674
733
|
decryptEnabled: true,
|
|
675
734
|
autoReRegister: true
|
|
@@ -689,10 +748,22 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
689
748
|
* scan boundary, not at construction.
|
|
690
749
|
*/
|
|
691
750
|
setSession: (next) => {
|
|
692
|
-
|
|
751
|
+
credential = next;
|
|
693
752
|
next.attach("recordScanning");
|
|
694
753
|
buildScanner();
|
|
695
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
|
+
},
|
|
696
767
|
requestRecords: async (params) => {
|
|
697
768
|
if (!scanner) {
|
|
698
769
|
throw new Error("No active account set on record scanner. Call setAccount() first.");
|
|
@@ -700,9 +771,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
700
771
|
const activeScanner = scanner;
|
|
701
772
|
const activeViewKey = viewKey;
|
|
702
773
|
const activeRegistration = registration;
|
|
703
|
-
|
|
774
|
+
const activeSession = sessionOf(credential);
|
|
775
|
+
if (activeSession) activeScanner.setJwtData(await activeSession.getJwt());
|
|
704
776
|
await activeRegistration.ensure(activeScanner, activeViewKey);
|
|
705
|
-
|
|
777
|
+
const canReMint = !credential && !!(options.apiKey && options.consumerId);
|
|
778
|
+
return scanOwned(activeScanner, params, canReMint, activeSession);
|
|
706
779
|
},
|
|
707
780
|
switchNetwork: async (newNetwork) => {
|
|
708
781
|
if (newNetwork !== "mainnet" && newNetwork !== "testnet") {
|
|
@@ -716,6 +789,11 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
716
789
|
};
|
|
717
790
|
}
|
|
718
791
|
function createStandaloneScanner(options) {
|
|
792
|
+
assertKeyedAuthAlone(options.auth, {
|
|
793
|
+
session: options.session,
|
|
794
|
+
apiKey: options.apiKey,
|
|
795
|
+
consumerId: options.consumerId
|
|
796
|
+
});
|
|
719
797
|
if (!options.session && options.apiKey && !options.consumerId) {
|
|
720
798
|
throw new ConfigurationError(
|
|
721
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."
|
|
@@ -723,13 +801,13 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
723
801
|
}
|
|
724
802
|
const viewKey = ViewKey.from_string(options.viewKey);
|
|
725
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
|
+
};
|
|
726
808
|
const scanner = new RecordScanner({
|
|
727
809
|
url: options.url ?? DEFAULT_SCANNER_URL,
|
|
728
|
-
|
|
729
|
-
...session ? {} : {
|
|
730
|
-
...options.consumerId ? { consumerId: options.consumerId } : {},
|
|
731
|
-
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
732
|
-
},
|
|
810
|
+
...credentialProps,
|
|
733
811
|
viewKeys: [viewKey],
|
|
734
812
|
decryptEnabled: true,
|
|
735
813
|
autoReRegister: true
|
|
@@ -739,16 +817,28 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
739
817
|
requestRecords: async (params) => {
|
|
740
818
|
if (session) scanner.setJwtData(await session.getJwt());
|
|
741
819
|
await registration.ensure(scanner, viewKey);
|
|
742
|
-
return scanOwned(scanner, params
|
|
820
|
+
return scanOwned(scanner, params, !!(options.apiKey && options.consumerId), session);
|
|
743
821
|
}
|
|
744
822
|
};
|
|
745
823
|
}
|
|
746
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
|
+
}
|
|
747
837
|
const account = privateKeyToAccount(options.privateKey);
|
|
748
838
|
const transport = http(options.networkUrl, { network });
|
|
749
839
|
const credentials = options.consumerId && options.apiKey ? { consumerId: options.consumerId, apiKey: options.apiKey } : void 0;
|
|
750
840
|
const configured = !!(credentials || options.credentialStore || options.session);
|
|
751
|
-
const session = options.session ?? createProvableSession({
|
|
841
|
+
const session = options.auth ? void 0 : options.session ?? createProvableSession({
|
|
752
842
|
credentials,
|
|
753
843
|
store: options.credentialStore ?? memoryCredentialStore(),
|
|
754
844
|
// Resolved lazily: only a registration needs it. The derived default
|
|
@@ -763,6 +853,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
763
853
|
networkUrl: options.networkUrl,
|
|
764
854
|
proverUrl: options.proverUrl,
|
|
765
855
|
session,
|
|
856
|
+
auth: options.auth,
|
|
766
857
|
// Ignored by the proving config whenever a session is present, which is
|
|
767
858
|
// where the one-minter rule is enforced.
|
|
768
859
|
apiKey: options.apiKey,
|
|
@@ -773,7 +864,8 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
773
864
|
});
|
|
774
865
|
const publicClient = createPublicClient({ transport });
|
|
775
866
|
if (options.records) {
|
|
776
|
-
if (
|
|
867
|
+
if (options.auth) options.records.setAuth?.(options.auth);
|
|
868
|
+
else if (configured && session) options.records.setSession?.(session);
|
|
777
869
|
options.records.setAccount({ viewKey: account.viewKey });
|
|
778
870
|
}
|
|
779
871
|
const walletClient = createWalletClient({
|
|
@@ -799,7 +891,7 @@ function buildSdk(initialNetwork, initialSdk) {
|
|
|
799
891
|
createAleoClient
|
|
800
892
|
};
|
|
801
893
|
}
|
|
802
|
-
var DEVNODE_CONSENSUS_HEIGHTS = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17";
|
|
894
|
+
var DEVNODE_CONSENSUS_HEIGHTS = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,4294967295";
|
|
803
895
|
function privateKeyToAccount(privateKey) {
|
|
804
896
|
const sdkAccount = new Account({ privateKey });
|
|
805
897
|
const address = sdkAccount.address().to_string();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mnemonic.ts","../src/provableApi.ts"],"sourcesContent":["/**\n * @provablehq/veil-aleo-sdk\n *\n * Loads `@provablehq/sdk` for a specific Aleo network and exposes the SDK's\n * functionality bound to that network's setup parameters.\n *\n * Usage:\n * import { loadNetwork } from '@provablehq/veil-aleo-sdk'\n * import { http } from '@provablehq/veil-core'\n *\n * const aleo = await loadNetwork('mainnet')\n *\n * const account = aleo.privateKeyToAccount('APrivateKey1...')\n * const { publicClient, walletClient } = aleo.createAleoClient({\n * privateKey: 'APrivateKey1...',\n * networkUrl: 'https://api.provable.com/v2',\n * })\n *\n * Switching networks: load a new handle. Existing accounts remain valid —\n * Aleo private keys, view keys, and addresses are network-agnostic.\n */\n\nimport { loadNetwork as loadSdk } from '@provablehq/sdk/dynamic.js'\nimport {\n Account,\n AleoKeyProvider,\n Program,\n ProgramManager,\n RecordCiphertext as StaticRecordCiphertext,\n ViewKey as StaticViewKey,\n getOrInitConsensusVersionTestHeights,\n} from '@provablehq/sdk'\nimport { DEVNODE_PRIVATE_KEY, DEVNODE_ADDR } from '@provablehq/veil-aleo-devnode'\nexport { DEVNODE_PRIVATE_KEY, DEVNODE_ADDR }\nimport type { LocalAccount } from '@provablehq/veil-core'\nimport type { ProvingConfig, BuildTransactionOptions, BuildDeploymentOptions, SimulateOptions, ExecuteOptions, RawSimulateResult, RawExecuteResult } from '@provablehq/veil-core'\nimport type { OwnedRecord, RecordProvider, StandaloneRecordScanner, RequestRecordsParameters } from '@provablehq/veil-core'\nimport type { Network, PublicClient, WalletClient } from '@provablehq/veil-core'\nimport {\n createPublicClient,\n createWalletClient,\n http,\n BaseError,\n ProvingError,\n ConfigurationError,\n classifyBroadcastError,\n classifyProvingError,\n waitForConfirmation,\n extractTransitions,\n} from '@provablehq/veil-core'\nimport type { Decryptor } from '@provablehq/veil-core'\nimport { generateMnemonic, mnemonicToHDKey, type AleoDerivationId } from './mnemonic.js'\nimport {\n createProvableSession,\n memoryCredentialStore,\n provableApiActions,\n type ProvableCredentialStore,\n type ProvableSession,\n type ProvableWalletClient,\n type ProvingConfigWithSession,\n} from './provableApi.js'\n\nexport {\n registerProvableApi,\n createProvableSession,\n memoryCredentialStore,\n authenticateProvableApi,\n provableApiActions,\n type ProvableApiCredentials,\n type ProvableCredentialStore,\n type ProvableJwt,\n type ProvableSession,\n type ProvableSessionConsumers,\n type ProvableWalletClient,\n type ProvingConfigWithSession,\n type RegisterProvableApiParameters,\n type CreateProvableSessionOptions,\n type AuthenticateProvableApiParameters,\n type AuthenticateProvableApiReturnType,\n type ProvableApiActions,\n} from './provableApi.js'\n\nexport {\n BLS12377HDKey,\n generateMnemonic,\n validateMnemonic,\n validateWord,\n mnemonicToSeed,\n mnemonicToHDKey,\n STANDARD_PATH,\n LEGACY_PATH,\n type AleoDerivationId,\n} from './mnemonic.js'\n\n/** Networks supported by `@provablehq/sdk/dynamic.js`. */\nexport type SupportedNetwork = 'mainnet' | 'testnet'\n\n/**\n * Base URL of Provable's hosted delegated proving service.\n *\n * The default `proverUrl` for `mode: 'delegated'`. A base, so the active network\n * is appended — which is what lets `switchChain` re-target proving.\n */\nexport const DEFAULT_PROVER_URL = 'https://api.provable.com/prove'\n\n/**\n * Base URL of Provable's hosted Record Scanner Service.\n *\n * The default `url` for both scanner factories. A base — the SDK appends the\n * network segment, which is what lets a scanner follow `switchChain`.\n */\nexport const DEFAULT_SCANNER_URL = 'https://api.provable.com/scanner'\n\n// `loadSdk('testnet')` and `loadSdk('mainnet')` return modules whose runtime\n// classes have the same shape. The narrowed-to-testnet type is used as the\n// canonical handle to avoid TS's union-of-modules confusion.\ntype SdkModule = Awaited<ReturnType<typeof loadSdk<'testnet'>>>\n\n/**\n * A network-bound SDK handle. All functions on this handle use the binary\n * set loaded for the named network.\n *\n * Most key/account operations (`privateKeyToAccount`, `mnemonicToAccount`,\n * `generateAccount`, `decryptRecord`, `verifySignature`) are mathematically\n * network-agnostic — the same private key (or mnemonic) derives the same\n * address and view key regardless of which network's binary was loaded.\n * Proving and program operations (`createProvingConfig`, `createAleoClient`,\n * scanners) are network-bound.\n */\nexport interface AleoSdk {\n /** The network this handle is bound to. */\n readonly network: SupportedNetwork\n\n /** Creates a `LocalAccount` from an Aleo private key. */\n privateKeyToAccount(privateKey: string): LocalAccount<'privateKey'>\n\n /**\n * Creates a `LocalAccount` from a BIP39 mnemonic phrase using Aleo's\n * BLS12-377 HD derivation (matches Shield wallet derivation).\n *\n * Defaults to the SLIP-0044 Aleo coin type path `m/44'/683'`, account\n * index 0. Pass `derivation: 'legacy'` to use the pre-registration path\n * `m/44'/0'` for compatibility with older wallets.\n */\n mnemonicToAccount(\n mnemonic: string,\n options?: { index?: number; derivation?: AleoDerivationId },\n ): LocalAccount<'mnemonic'>\n\n /**\n * Generates a fresh BIP39 mnemonic and derives its Aleo account in one call.\n * Pure and local — no network access. The caller MUST persist the returned\n * mnemonic; it is the only way to re-derive the account.\n *\n * @param options.strength Entropy bits: 128 (12 words, default) or 256 (24 words).\n * @param options.index Account index on the derivation path. Defaults to 0.\n * @param options.derivation Derivation path id. Defaults to `'standard'`\n * (`m/44'/683'`); pass `'legacy'` for pre-registration `m/44'/0'` wallets.\n * @returns The generated mnemonic and the account derived from it.\n *\n * @example\n * const { mnemonic, account } = aleo.generateMnemonicAccount()\n * // store `mnemonic` safely; `account.address` is ready to use\n */\n generateMnemonicAccount(options?: {\n strength?: 128 | 256\n index?: number\n derivation?: AleoDerivationId\n }): { mnemonic: string; account: LocalAccount<'mnemonic'> }\n\n /** Creates a new random Aleo account. */\n generateAccount(): LocalAccount<'privateKey'>\n\n /** Decrypts a record ciphertext using a view key. */\n decryptRecord(viewKey: string, ciphertext: string): string\n\n /** Verifies a signature against a message and address. */\n verifySignature(address: string, message: Uint8Array, signature: string): boolean\n\n /** Creates an `AleoNetworkClient` for direct SDK access. */\n createNetworkClient(url: string): InstanceType<SdkModule['AleoNetworkClient']>\n\n /**\n * Creates a `ProvingConfig` for `createWalletClient({ proving })`.\n *\n * @param options.proverUrl Base URL of the delegated proving service — the\n * network segment is appended, so do not include it. That is what lets\n * `switchChain` re-target proving instead of leaving it on the network the\n * client started from. A base that already ends in `/mainnet` or `/testnet`\n * is re-targeted rather than doubled. Defaults to\n * {@link DEFAULT_PROVER_URL} under `mode: 'delegated'`; unused under\n * `mode: 'local'`, which reaches no prover.\n * @param options.session Optional Provable API session. When present the\n * configuration authenticates from it and withholds `apiKey`/`consumerId`\n * from the prover client, so one party mints JWTs. The session is attached\n * to the returned configuration, which is what lets\n * `authenticateProvableApi` find it on a client.\n */\n createProvingConfig(options: {\n mode: 'delegated' | 'local'\n networkUrl: string\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n account?: LocalAccount<'privateKey'>\n confirmationTimeout?: number\n useFeeMaster?: boolean\n session?: ProvableSession\n }): ProvingConfigWithSession\n\n /**\n * Creates a record scanner backed by Provable's Record Scanner Service.\n *\n * The first `requestRecords` call registers the account's view key with the\n * service (a network round-trip) to obtain the UUID scanning requires;\n * subsequent calls reuse it. `setAccount` resets the registration.\n *\n * The provider implements `switchNetwork`, so a wallet client carrying it\n * re-targets record scanning when `switchChain` runs — the scanner rebuilds\n * against the new network and re-registers lazily on the next scan.\n *\n * @param options.url Base URL of the service (the SDK appends the network\n * segment — do not include it). Defaults to {@link DEFAULT_SCANNER_URL}.\n * @param options.consumerId Optional consumer id used for JWT refresh.\n * Unnecessary when a `session` supplies the token. Required alongside\n * `apiKey` otherwise — a JWT is minted from the pair, so half of it\n * authenticates nothing and construction throws rather than 401ing later.\n * @param options.apiKey Optional API key for the authenticated service\n * (e.g. the hosted Provable RSS). Omit for an open/unauthenticated service.\n * @param options.session Optional Provable API session to authenticate from,\n * shared with delegated proving. `createAleoClient` supplies its own\n * session through `setSession` on the returned provider, so a caller who\n * passes the scanner to that factory does not need this.\n * @param options.startBlock Optional block height to begin scanning from at\n * registration. Defaults to 0 (full history).\n * @returns The provider, plus `setSession` for a factory to share one session\n * across proving and scanning after construction.\n */\n createRemoteScanner(options?: {\n url?: string\n consumerId?: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n }): RecordProvider & { setSession: (session: ProvableSession) => void }\n\n /**\n * Creates a standalone record scanner with an explicit view key.\n *\n * Like {@link createRemoteScanner}, the first `requestRecords` registers the\n * view key with the service (a network round-trip) to obtain the scanning UUID.\n *\n * @param options.url Base URL of the service (the SDK appends the network\n * segment). Defaults to {@link DEFAULT_SCANNER_URL}.\n * @param options.consumerId Optional consumer id used for JWT refresh.\n * Unnecessary when a `session` supplies the token. Required alongside\n * `apiKey` otherwise — a JWT is minted from the pair, so half of it\n * authenticates nothing and construction throws rather than 401ing later.\n * @param options.viewKey The view key (`AViewKey1…`) to scan and decrypt with.\n * @param options.apiKey Optional API key for the authenticated service. Omit\n * for an open/unauthenticated service.\n * @param options.session Optional Provable API session to authenticate from.\n * Supplied at construction only — a standalone scanner is not pluggable\n * into a wallet client, so nothing shares a session with it later.\n * @param options.startBlock Optional block height to begin scanning from at\n * registration. Defaults to 0 (full history).\n */\n createStandaloneScanner(options: {\n url?: string\n consumerId?: string\n viewKey: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n }): StandaloneRecordScanner\n\n /**\n * Creates a fully-wired Aleo client from a private key and network URL.\n *\n * Builds one Provable API session from the credential options and shares it\n * across delegated proving and record scanning, so a single\n * `walletClient.authenticateProvableApi()` covers both. Omit the credential\n * options for a client that authenticates neither.\n *\n * @param options.apiKey Optional Provable API key. Paired with `consumerId`,\n * it seeds the session directly.\n * @param options.consumerId Optional Provable API consumer id.\n * @param options.proverUrl Base URL of the delegated proving service — the\n * network segment is appended, so do not include it. That is what lets\n * `switchChain` re-target proving. Defaults to {@link DEFAULT_PROVER_URL},\n * since `provingMode` itself defaults to `'delegated'`; pass an override for\n * a self-hosted prover.\n * @param options.confirmationTimeout Milliseconds to wait for a submitted\n * transaction to confirm. Defaults to 60_000 (one minute), which covers a\n * healthy confirmation with room to spare; a transaction still absent after\n * that is more often one the node never included than one about to land.\n * Raise it for a congested network or a multi-transition call that takes\n * longer to include, rather than treating a slow confirmation as a failure.\n * @param options.username Optional handle to register a Provable API consumer\n * under, used only when no credentials and no stored pair are available.\n * A function is called lazily, at the moment registration happens. Defaults\n * to a name derived from the account address plus a random suffix — the\n * suffix matters because a username is spent once, so an account that lost\n * its stored key must still be able to register. Supplying a fixed name\n * makes the consumer identifiable but fails if that name is taken, since\n * credentials cannot be recovered from a username.\n * @param options.credentialStore Optional persistence for Provable API\n * credentials. When neither `consumerId`/`apiKey` nor a stored pair is\n * available, a consumer is registered under a name derived from the account\n * address and saved here. Defaults to `memoryCredentialStore()`, which holds\n * a registered consumer only for the life of the process — pass\n * `fileCredentialStore` from `@provablehq/veil-aleo-sdk/node`, or any\n * {@link ProvableCredentialStore}, for anything longer-lived. A client left\n * fully unconfigured does not share its session with `records`, so a scanner\n * aimed at an open service keeps needing no credential.\n * @param options.session Optional pre-built session, for a caller that owns\n * one already. Takes precedence over the credential options.\n * @returns A public client, a wallet client carrying\n * `authenticateProvableApi`, and the account.\n *\n * @example\n * const scanner = aleo.createRemoteScanner({ url: SCANNER_URL })\n * const { walletClient } = aleo.createAleoClient({\n * privateKey, networkUrl, proverUrl, records: scanner, credentialStore: store,\n * })\n * const { credentials, registered } = await walletClient.authenticateProvableApi()\n * if (registered) console.log('registered consumer', credentials.consumerId)\n */\n createAleoClient(options: {\n privateKey: string\n networkUrl: string\n provingMode?: 'delegated' | 'local'\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n useFeeMaster?: boolean\n confirmationTimeout?: number\n username?: string | (() => string)\n credentialStore?: ProvableCredentialStore\n session?: ProvableSession\n /**\n * Record provider for `requestRecords`. Not wired by default — pass\n * `aleo.createRemoteScanner(...)` or any\n * custom `RecordProvider`. `requestRecords` throws with a setup hint\n * when no provider is configured.\n */\n records?: RecordProvider & { setSession?: (session: ProvableSession) => void }\n }): {\n publicClient: PublicClient\n walletClient: ProvableWalletClient\n account: LocalAccount<'privateKey'>\n }\n}\n\n/**\n * Loads `@provablehq/sdk` for the named network and returns a network-bound\n * handle. The SDK module cache memoizes the load — calling twice for the\n * same network returns the same binary set without re-instantiating.\n */\nexport async function loadNetwork(name: SupportedNetwork): Promise<AleoSdk> {\n const sdk = (await loadSdk(name)) as SdkModule\n silenceSdkLogs(sdk)\n return buildSdk(name, sdk)\n}\n\n/**\n * Silences `@provablehq/sdk`'s own console output on a freshly loaded module.\n *\n * The SDK writes failed requests and retries straight to the console, so a record\n * scan that recovers after a transient 401 still prints one line per attempt.\n * Those lines are not errors — Veil reports failure by throwing, and every retry\n * that mattered is already reflected in what the call returns — but they read as\n * failure to anyone watching a script run, and they cannot be attributed to a\n * caller. Called on every load, including a network switch, because the log level\n * is per-module rather than process-wide.\n *\n * @param sdk A module returned by `@provablehq/sdk/dynamic.js`.\n */\nfunction silenceSdkLogs(sdk: SdkModule): void {\n // Feature-detected rather than called directly: the export is absent from\n // older pins, and a missing logger must not fail the load.\n const { setLogLevel } = sdk as unknown as { setLogLevel?: (level: 'silent') => void }\n setLogLevel?.('silent')\n}\n\nfunction buildSdk(initialNetwork: SupportedNetwork, initialSdk: SdkModule): AleoSdk {\n // Mutable handle so `createProvingConfig().switchNetwork()` can swap the\n // underlying binary set without rebuilding the wallet client.\n let currentSdk: SdkModule = initialSdk\n const network = initialNetwork\n const {\n Account,\n PrivateKey,\n Signature,\n Address,\n ViewKey,\n AleoNetworkClient,\n RecordScanner,\n RecordCiphertext,\n } = initialSdk\n\n\n\n function mnemonicToAccount(\n mnemonic: string,\n options?: { index?: number; derivation?: AleoDerivationId },\n ): LocalAccount<'mnemonic'> {\n const hd = mnemonicToHDKey(mnemonic, options)\n // wasm-bindgen exports the snake_case name; it is not a typo.\n const privateKey = (PrivateKey as unknown as {\n from_seed_unchecked: (seed: Uint8Array) => InstanceType<SdkModule['PrivateKey']>\n }).from_seed_unchecked(hd.key).to_string()\n return { ...privateKeyToAccount(privateKey), source: 'mnemonic' }\n }\n\n function generateMnemonicAccount(options?: {\n strength?: 128 | 256\n index?: number\n derivation?: AleoDerivationId\n }): { mnemonic: string; account: LocalAccount<'mnemonic'> } {\n const mnemonic = generateMnemonic(options?.strength ?? 128)\n const { strength: _strength, ...derivationOptions } = options ?? {}\n return { mnemonic, account: mnemonicToAccount(mnemonic, derivationOptions) }\n }\n\n function generateAccount(): LocalAccount<'privateKey'> {\n const sdkAccount = new Account()\n return privateKeyToAccount(sdkAccount.privateKey().to_string())\n }\n\n function decryptRecord(viewKeyString: string, ciphertext: string): string {\n return ViewKey.from_string(viewKeyString).decrypt(ciphertext)\n }\n\n function verifySignature(\n addressString: string,\n message: Uint8Array,\n signatureString: string,\n ): boolean {\n const sig = Signature.from_string(signatureString)\n const addr = Address.from_string(addressString)\n return sig.verify(addr, message)\n }\n\n function createNetworkClient(url: string): InstanceType<SdkModule['AleoNetworkClient']> {\n return new AleoNetworkClient(url)\n }\n\n function createProvingConfig(options: {\n mode: 'delegated' | 'local'\n networkUrl: string\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n account?: LocalAccount<'privateKey'>\n /** Timeout in ms for waiting for transaction confirmation (default: 60_000 = 1 min) */\n confirmationTimeout?: number\n /**\n * The delegated prover pays the transaction fee from its FeeMaster\n * account instead of the caller's public credits. Only meaningful with\n * `mode: 'delegated'`; requires the prover service to allow it for the\n * consumer. Defaults to true — accounts need no public credits to\n * transact. Set false when the account funds its own fees.\n */\n useFeeMaster?: boolean\n /**\n * Provable API session to authenticate delegated proving with. When\n * present it is the only party minting JWTs — `apiKey` and `consumerId`\n * are withheld from the prover client so the SDK never mints in parallel.\n */\n session?: ProvableSession\n }): ProvingConfigWithSession {\n // Each call reads from currentSdk so switchNetwork can swap the binary set\n // without rebuilding the wallet client.\n let networkUrl = options.networkUrl\n let keyProvider = new currentSdk.AleoKeyProvider()\n keyProvider.useCache(true)\n options.session?.attach('proving')\n\n // Tracked per configuration rather than read from the handle: the handle's\n // `network` names the binaries it loaded, and confirmation polling has to\n // follow this client's current chain instead.\n let configNetwork: SupportedNetwork = network\n\n /**\n * Resolves the prover endpoint for the network in force.\n *\n * `proverUrl` is a base — the network segment is appended here, the same way\n * the record scanner's base URL works — so a client that switches chains\n * reaches the right prover without rebuilding. A base that already ends in a\n * network segment is accepted and re-targeted rather than doubled, so a\n * caller who passes the fully-qualified URL still switches correctly.\n */\n const resolveProverUrl = (): string | undefined => {\n // Delegated proving has one obvious endpoint, so it defaults rather than\n // failing on the first write. Local proving reaches no prover at all.\n const configured =\n options.proverUrl ?? (options.mode === 'delegated' ? DEFAULT_PROVER_URL : undefined)\n if (!configured) return undefined\n const base = configured.replace(/\\/+$/, '').replace(/\\/(mainnet|testnet)$/, '')\n return `${base}/${configNetwork}`\n }\n\n return {\n mode: options.mode,\n // A getter, not a snapshot: the network segment moves with `switchChain`,\n // and a fixed string here would report the network this config started on\n // long after it left.\n get url() {\n return resolveProverUrl()\n },\n // Carried for `authenticateProvableApi` to find on a client. Core never\n // reads binding-specific fields on a proving config — `url` and `apiKey`\n // already travel the same way.\n session: options.session,\n\n buildTransaction: async (txOptions: BuildTransactionOptions) => {\n const programManager = new currentSdk.ProgramManager(\n networkUrl,\n keyProvider,\n undefined,\n )\n\n if (options.account) {\n const sdkAccount = new currentSdk.Account({ privateKey: options.account.privateKey })\n programManager.setAccount(sdkAccount)\n }\n\n // The user-facing API takes dynamic-dispatch import names (`string[]`);\n // the SDK needs a name → source map covering BOTH the program's static\n // imports (declared in the `import` block) and the user's dynamic ones.\n // Auto-discover static imports first, then add the user-provided\n // dynamic ones on top. The SDK's ProgramImports values can be string\n // or Program; its return type is mirrored instead of reconstructed.\n type SdkProgramImports = Awaited<\n ReturnType<InstanceType<SdkModule['AleoNetworkClient']>['getProgramImports']>\n >\n let resolvedImports: SdkProgramImports | undefined\n if (txOptions.imports && txOptions.imports.length > 0) {\n const programSource = await programManager.networkClient.getProgram(txOptions.programName)\n const staticImports = await programManager.networkClient.getProgramImports(programSource)\n const merged: SdkProgramImports = { ...staticImports }\n for (const name of txOptions.imports) {\n merged[name] = await programManager.networkClient.getProgram(name)\n }\n resolvedImports = merged\n }\n\n const tx = await programManager.buildExecutionTransaction({\n programName: txOptions.programName,\n functionName: txOptions.functionName,\n priorityFee: 0,\n privateFee: txOptions.privateFee ?? false,\n inputs: txOptions.inputs,\n ...(resolvedImports ? { imports: resolvedImports } : {}),\n })\n\n return JSON.parse(tx.toString())\n },\n\n buildDeployment: async (deployOptions: BuildDeploymentOptions) => {\n const programManager = new currentSdk.ProgramManager(\n networkUrl,\n keyProvider,\n undefined,\n )\n\n if (options.account) {\n const sdkAccount = new currentSdk.Account({ privateKey: options.account.privateKey })\n programManager.setAccount(sdkAccount)\n }\n\n const tx = await programManager.buildDeploymentTransaction(\n deployOptions.program,\n 0,\n deployOptions.privateFee ?? false,\n )\n\n return JSON.parse(tx.toString())\n },\n\n simulate: async (simOptions: SimulateOptions): Promise<RawSimulateResult> => {\n const programManager = new currentSdk.ProgramManager(networkUrl, keyProvider, undefined)\n if (options.account) {\n programManager.setAccount(new currentSdk.Account({ privateKey: options.account.privateKey }))\n }\n\n // Self-custody decryptor: same view-key-based decryptor as the execute path.\n const accountViewKey = options.account ? ViewKey.from_string(options.account.viewKey) : undefined\n const decryptor: Decryptor | undefined = accountViewKey\n ? (ciphertext: string) => {\n const ct = RecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : null\n }\n : undefined\n\n // `buildAuthorization` runs the function (with cross-program calls) and produces an\n // Authorization whose transitions carry program/function metadata and the actual\n // outputs — same structure a confirmed Transaction has, minus the proof.\n const authorization = await programManager.buildAuthorization({\n programName: simOptions.programName,\n functionName: simOptions.functionName,\n inputs: simOptions.inputs,\n programSource: simOptions.programSource,\n programImports: simOptions.programImports,\n })\n\n // Convert the wasm Transition objects into the wire-shaped tx that extractTransitions\n // consumes. Private outputs come back from an Authorization as TVK-encrypted ciphertexts\n // (Aleo's on-chain privacy model); decrypt with the caller's TVK first so plaintext\n // values are visible. `transition.toString()` emits the same wire-format JSON the chain\n // returns from `/transaction/confirmed/{id}` — Aleo-typed string values like '10u32',\n // 'aleo1...', or 'record1...' under each output's `value`.\n const tx = {\n execution: {\n transitions: authorization.transitions().map((t: any) => {\n let source = t\n if (accountViewKey) {\n try {\n source = t.decryptTransition(t.tvk(accountViewKey))\n } catch {\n // Foreign transition signed by another caller — leave outputs encrypted.\n }\n }\n return JSON.parse(source.toString())\n }),\n },\n }\n\n const { transitions, outputs } = extractTransitions(tx, decryptor)\n return { transitions, outputs }\n },\n\n execute: async (execOptions: ExecuteOptions): Promise<RawExecuteResult> => {\n const programManager = new currentSdk.ProgramManager(networkUrl, keyProvider, undefined)\n if (options.account) {\n programManager.setAccount(new currentSdk.Account({ privateKey: options.account.privateKey }))\n }\n\n /** Convert microcredits (Veil API) to credits (SDK API) for priority fee */\n const priorityFee = Number(execOptions.fee) / 1_000_000\n\n /** Self-custody decryptor: use the local account's view key to decrypt owned record ciphertexts. */\n const accountViewKey = options.account ? ViewKey.from_string(options.account.viewKey) : undefined\n const decryptor: Decryptor | undefined = accountViewKey\n ? (ciphertext: string) => {\n const ct = RecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : null\n }\n : undefined\n\n /** Build a Veil publicClient bound to the current networkUrl for chain polling. */\n const buildPollingClient = () =>\n createPublicClient({ transport: http(networkUrl, { network: configNetwork as Network }) })\n\n if (options.mode === 'delegated') {\n const proverUrl = resolveProverUrl()\n if (!proverUrl) throw new ConfigurationError('Delegated execution requires proverUrl. Pass proverUrl to createProvingConfig or createAleoClient.')\n\n let response: any\n try {\n const provingRequest = await programManager.provingRequest({\n programName: execOptions.programName,\n programSource: execOptions.programSource,\n programImports: execOptions.programImports,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n priorityFee,\n privateFee: execOptions.privateFee ?? false,\n broadcast: true,\n useFeeMaster: options.useFeeMaster ?? true,\n })\n\n const dpsClient = new AleoNetworkClient(proverUrl)\n\n const auth = async (forceRefresh: boolean) =>\n options.session\n ? { jwtData: await options.session.getJwt({ forceRefresh }) }\n : { apiKey: options.apiKey, consumerId: options.consumerId }\n\n // The safe variant reports HTTP status instead of throwing, which is\n // what makes a rejected credential distinguishable from a proving\n // failure. Minting happens outside the submit so a mint failure\n // surfaces as itself rather than as a proving error.\n let credentials = await auth(false)\n let result = await dpsClient.submitProvingRequestSafe({\n provingRequest,\n url: proverUrl,\n ...credentials,\n })\n // A freshly minted JWT can reach a prover that has not yet synced\n // the credential, so one replacement attempt is worth making.\n if (!result.ok && (result.status === 401 || result.status === 403) && options.session) {\n credentials = await auth(true)\n result = await dpsClient.submitProvingRequestSafe({\n provingRequest,\n url: proverUrl,\n ...credentials,\n })\n }\n if (!result.ok) {\n throw new ProvingError({\n message: `Delegated proving failed (HTTP ${result.status}): ${result.error?.message ?? 'unknown error'}`,\n statusCode: result.status,\n })\n }\n response = result.data\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw classifyProvingError(e)\n }\n\n const txId = response.transaction?.id\n if (!txId) throw new ConfigurationError('DPS response did not contain a transaction ID — check prover service configuration.')\n\n const confirmedTx = await waitForConfirmation(buildPollingClient(), txId, options.confirmationTimeout)\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n\n } else {\n let tx: any\n try {\n tx = await programManager.buildExecutionTransaction({\n programName: execOptions.programName,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n priorityFee,\n privateFee: execOptions.privateFee ?? false,\n program: execOptions.programSource,\n imports: execOptions.programImports,\n })\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw new ProvingError({ message: e instanceof Error ? e.message : String(e), cause: e as Error })\n }\n\n let txId: string\n try {\n const submitClient = new AleoNetworkClient(networkUrl)\n submitClient.setVerboseErrors(false)\n txId = await submitClient.submitTransaction(tx)\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw classifyBroadcastError(e)\n }\n\n const confirmedTx = await waitForConfirmation(buildPollingClient(), txId, options.confirmationTimeout)\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n }\n },\n\n decrypt: async (cipherText) => {\n if (!options.account?.viewKey) {\n throw new Error(\n 'decrypt requires an account with a viewKey on the proving config.',\n )\n }\n return currentSdk.ViewKey.from_string(options.account.viewKey).decrypt(cipherText)\n },\n\n switchNetwork: async (newNetwork) => {\n if (newNetwork !== 'mainnet' && newNetwork !== 'testnet') {\n throw new Error(\n `loadNetwork supports 'mainnet' or 'testnet' (received '${newNetwork}').`,\n )\n }\n currentSdk = (await loadSdk(newNetwork as SupportedNetwork)) as SdkModule\n silenceSdkLogs(currentSdk)\n keyProvider = new currentSdk.AleoKeyProvider()\n keyProvider.useCache(true)\n // Confirmation polling and the prover endpoint both read this, so it\n // must move with the switch or a delegated client proves and polls the\n // chain it just left.\n configNetwork = newNetwork as SupportedNetwork\n },\n }\n }\n\n // The RSS returns record fields in snake_case (record_plaintext,\n // program_name, …); the veil OwnedRecord contract is camelCase. Map them —\n // a bare cast silently leaves recordPlaintext undefined, which reads as an\n // unspendable wallet. Fields whose two casings coincide are read directly;\n // the rest accept either case so a future camelCase SDK build keeps working.\n // `uid` and `recordView` are privacy-wallet-adapter concepts the RSS does\n // not supply, so they are intentionally omitted.\n function toOwnedRecord(raw: Record<string, unknown>): OwnedRecord {\n const pick = (snake: string, camel: string): unknown => raw[snake] ?? raw[camel]\n return {\n blockHeight: pick('block_height', 'blockHeight') as number | undefined,\n blockTimestamp: pick('block_timestamp', 'blockTimestamp') as number | undefined,\n commitment: raw.commitment as string | undefined,\n functionName: pick('function_name', 'functionName') as string | undefined,\n outputIndex: pick('output_index', 'outputIndex') as number | undefined,\n owner: raw.owner as string | undefined,\n programName: pick('program_name', 'programName') as string,\n recordCiphertext: pick('record_ciphertext', 'recordCiphertext') as string | undefined,\n recordName: pick('record_name', 'recordName') as string | undefined,\n sender: raw.sender as string | undefined,\n spent: raw.spent as boolean | undefined,\n tag: raw.tag as string,\n transactionId: pick('transaction_id', 'transactionId') as string | undefined,\n transitionId: pick('transition_id', 'transitionId') as string | undefined,\n transactionIndex: pick('transaction_index', 'transactionIndex') as number | undefined,\n transitionIndex: pick('transition_index', 'transitionIndex') as number | undefined,\n recordPlaintext: (pick('record_plaintext', 'recordPlaintext') as string | undefined) ?? '',\n }\n }\n\n // A scanner's UUID is issued at registration; owned() rejects locally\n // without one. Register once, lazily, and memoize the in-flight promise so\n // concurrent scans share a single round-trip. Account or network changes\n // replace the whole object (one registration per scanner build).\n function makeRegisterOnce(startBlock: number) {\n let registration: Promise<void> | undefined\n return {\n ensure(\n scanner: InstanceType<SdkModule['RecordScanner']>,\n viewKey: ReturnType<SdkModule['ViewKey']['from_string']>,\n ): Promise<void> {\n if (!registration) {\n registration = (async () => {\n const result = await scanner.registerEncrypted(viewKey, startBlock)\n if (!result.ok) {\n registration = undefined // allow a later retry after a transient failure\n throw new Error(\n `Record scanner registration failed (HTTP ${result.status}): ${result.error?.message ?? 'unknown error'}`,\n )\n }\n })()\n }\n return registration\n },\n }\n }\n\n // Scans owned records with bounded retry. owned() returns a discriminated\n // result on HTTP error but *throws* on a network failure or an invalidated\n // UUID — both paths are retried here. A freshly-minted JWT can momentarily\n // hit an RSS backend that has not yet synced the credential (HTTP 401), and\n // the SDK caches that JWT for the scanner's lifetime — so between attempts it\n // is dropped (setJwtData(undefined) forces a re-mint), backed off, and retried,\n // giving the backend time to catch up. A non-transient status surfaces at once.\n //\n // 429/5xx are always transient; a 401/403 is only worth retrying when a JWT\n // can actually be re-minted (apiKey configured) — on an unauthenticated\n // scanner those are permanent, so retrying just burns backoff.\n async function scanOwned(\n scanner: InstanceType<SdkModule['RecordScanner']>,\n program: string,\n statusFilter: string | undefined,\n hasCredentials: boolean,\n session?: ProvableSession,\n ): Promise<OwnedRecord[]> {\n const ALWAYS_RETRY = new Set([429, 500, 502, 503, 504])\n const AUTH_RETRY = new Set([401, 403])\n // A JWT can be replaced when the SDK holds a complete pair to re-mint from,\n // or when a session owns minting on the scanner's behalf. `hasCredentials`\n // is the pair, not just the key — half of it mints nothing, so treating a\n // 401 as retryable would only burn backoff.\n const canReMint = hasCredentials || !!session\n const retryable = (status: number) => ALWAYS_RETRY.has(status) || (canReMint && AUTH_RETRY.has(status))\n const MAX_ATTEMPTS = 4\n let last = ''\n let lastStatus: number | undefined\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n try {\n const result = await scanner.owned({\n unspent: statusFilter !== 'spent',\n filter: { programs: [program] },\n })\n if (result.ok) return (result.data ?? []).map((r) => toOwnedRecord(r as Record<string, unknown>))\n last = `HTTP ${result.status}: ${result.error?.message ?? 'unknown error'}`\n lastStatus = result.status\n if (!retryable(result.status)) break\n } catch (err) {\n // owned() throws (rather than returning a result) on a network failure\n // or an invalidated UUID — treat as transient and retry.\n last = err instanceof Error ? err.message : String(err)\n lastStatus = undefined\n }\n if (attempt === MAX_ATTEMPTS - 1) break\n // Replace the token only when it was the thing rejected. A 429 or 5xx says\n // nothing about the credential, and re-minting on those costs a round-trip\n // and swaps the token the proving path shares.\n if (lastStatus !== undefined && AUTH_RETRY.has(lastStatus)) {\n if (session) scanner.setJwtData(await session.getJwt({ forceRefresh: true }))\n else scanner.setJwtData(undefined)\n }\n await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** attempt))\n }\n throw new Error(`Record scan failed (${last})`)\n }\n\n function createRemoteScanner(options: {\n url?: string\n consumerId?: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n } = {}): RecordProvider & { setSession: (session: ProvableSession) => void } {\n // A JWT is minted from the pair, so half of it authenticates nothing: the\n // consumer id is the path segment and the key the header. Without a session\n // to supply tokens instead, an incomplete pair would send unauthenticated\n // requests and 401 — fail here rather than four retries later.\n if (!options.session && options.apiKey && !options.consumerId) {\n throw new ConfigurationError(\n 'Record scanning with an apiKey also needs consumerId — a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service.',\n )\n }\n // The RecordScanner class is network-bound: a scanner built from a given\n // SDK module scans that module's network. Network switching rebuilds the\n // scanner (and the wasm view key) from the target network's module.\n let scannerSdk: Pick<SdkModule, 'RecordScanner' | 'ViewKey'> = { RecordScanner, ViewKey }\n let scanner: InstanceType<SdkModule['RecordScanner']> | undefined\n let viewKey: ReturnType<SdkModule['ViewKey']['from_string']> | undefined\n let viewKeyString: string | undefined\n let registration = makeRegisterOnce(options.startBlock ?? 0)\n let session = options.session\n session?.attach('recordScanning')\n const url = options.url ?? DEFAULT_SCANNER_URL\n\n function buildScanner() {\n if (!viewKeyString) return // no active account yet — nothing to rebuild\n viewKey = scannerSdk.ViewKey.from_string(viewKeyString)\n scanner = new scannerSdk.RecordScanner({\n url,\n // A session supplies the token per scan, so the credentials stay out of\n // the scanner and only one party mints.\n ...(session ? {} : {\n ...(options.consumerId ? { consumerId: options.consumerId } : {}),\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n }),\n viewKeys: [viewKey],\n decryptEnabled: true,\n autoReRegister: true,\n })\n // Each build gets its own registration: view keys register per account\n // AND per network, and the old promise stays bound to the scanner a\n // concurrent scan may still hold.\n registration = makeRegisterOnce(options.startBlock ?? 0)\n }\n\n return {\n setAccount: (account: { viewKey: string }) => {\n viewKeyString = account.viewKey\n buildScanner()\n },\n\n /**\n * Shares a Provable API session with this scanner.\n *\n * Called by {@link createAleoClient} so one session covers proving and\n * scanning. Takes effect on the next scan — the token is applied at the\n * scan boundary, not at construction.\n */\n setSession: (next: ProvableSession) => {\n session = next\n next.attach('recordScanning')\n // Rebuild so the scanner drops any credentials it was constructed with;\n // leaving them in place would let the SDK mint alongside the session.\n buildScanner()\n },\n\n requestRecords: async (params: RequestRecordsParameters): Promise<OwnedRecord[]> => {\n if (!scanner) {\n throw new Error('No active account set on record scanner. Call setAccount() first.')\n }\n\n // Pin this scan to the current build: a concurrent setAccount or\n // switchNetwork swaps the closures, and mixing builds mid-scan would\n // register one scanner and scan another.\n const activeScanner = scanner\n const activeViewKey = viewKey!\n const activeRegistration = registration\n // Apply the token before registration, not just before the scan:\n // registering a view key is itself an authenticated call.\n if (session) activeScanner.setJwtData(await session.getJwt())\n await activeRegistration.ensure(activeScanner, activeViewKey)\n return scanOwned(activeScanner, params.program, params.statusFilter, !!(options.apiKey && options.consumerId), session)\n },\n\n switchNetwork: async (newNetwork: string) => {\n if (newNetwork !== 'mainnet' && newNetwork !== 'testnet') {\n throw new Error(\n `Record scanning supports 'mainnet' or 'testnet' (received '${newNetwork}').`,\n )\n }\n scannerSdk = (await loadSdk(newNetwork as SupportedNetwork)) as SdkModule\n buildScanner()\n },\n }\n }\n\n function createStandaloneScanner(options: {\n url?: string\n consumerId?: string\n viewKey: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n }): StandaloneRecordScanner {\n // A JWT is minted from the pair, so half of it authenticates nothing: the\n // consumer id is the path segment and the key the header. Without a session\n // to supply tokens instead, an incomplete pair would send unauthenticated\n // requests and 401 — fail here rather than four retries later.\n if (!options.session && options.apiKey && !options.consumerId) {\n throw new ConfigurationError(\n 'Record scanning with an apiKey also needs consumerId — a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service.',\n )\n }\n const viewKey = ViewKey.from_string(options.viewKey)\n // Deliberately not attached: a standalone scanner is not pluggable into a\n // wallet client, so no client's `applied` report covers it.\n const session = options.session\n const scanner = new RecordScanner({\n url: options.url ?? DEFAULT_SCANNER_URL,\n // Credentials only when no session mints on this scanner's behalf.\n ...(session ? {} : {\n ...(options.consumerId ? { consumerId: options.consumerId } : {}),\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n }),\n viewKeys: [viewKey],\n decryptEnabled: true,\n autoReRegister: true,\n })\n const registration = makeRegisterOnce(options.startBlock ?? 0)\n\n return {\n requestRecords: async (params: RequestRecordsParameters): Promise<OwnedRecord[]> => {\n // Registration is authenticated too, so the token goes in first.\n if (session) scanner.setJwtData(await session.getJwt())\n await registration.ensure(scanner, viewKey)\n return scanOwned(scanner, params.program, params.statusFilter, !!(options.apiKey && options.consumerId), session)\n },\n }\n }\n\n function createAleoClient(options: {\n privateKey: string\n networkUrl: string\n provingMode?: 'delegated' | 'local'\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n /** Forwarded to `createProvingConfig` — the delegated prover pays fees. Defaults to true. */\n useFeeMaster?: boolean\n confirmationTimeout?: number\n username?: string | (() => string)\n credentialStore?: ProvableCredentialStore\n session?: ProvableSession\n records?: RecordProvider & { setSession?: (session: ProvableSession) => void }\n }): {\n publicClient: PublicClient\n walletClient: ProvableWalletClient\n account: LocalAccount<'privateKey'>\n } {\n const account = privateKeyToAccount(options.privateKey)\n const transport = http(options.networkUrl, { network: network as Network })\n\n // One session for the whole client, so a single authenticateProvableApi()\n // covers proving and scanning.\n const credentials =\n options.consumerId && options.apiKey\n ? { consumerId: options.consumerId, apiKey: options.apiKey }\n : undefined\n // Whether the caller named a credential source. Without one the session\n // still exists — falling back to process-lifetime memory, so delegated\n // proving works out of the box — but it is not shared with the record\n // provider, since a scanner pointed at an open service needs no credential\n // and must not start registering one.\n const configured = !!(credentials || options.credentialStore || options.session)\n const session =\n options.session ??\n createProvableSession({\n credentials,\n store: options.credentialStore ?? memoryCredentialStore(),\n // Resolved lazily: only a registration needs it. The derived default\n // carries a random suffix because a username is spent once — an account\n // that lost its stored key must still be able to register, and the old\n // key is unrecoverable. A caller-supplied name is used verbatim, so a\n // collision fails rather than quietly registering something else.\n username:\n options.username ??\n (() => `veil-${account.address.slice(5, 13)}-${Math.random().toString(36).slice(2, 8)}`),\n })\n\n const proving = createProvingConfig({\n mode: options.provingMode ?? 'delegated',\n networkUrl: options.networkUrl,\n proverUrl: options.proverUrl,\n session,\n // Ignored by the proving config whenever a session is present, which is\n // where the one-minter rule is enforced.\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n account,\n ...(options.useFeeMaster !== undefined ? { useFeeMaster: options.useFeeMaster } : {}),\n ...(options.confirmationTimeout !== undefined\n ? { confirmationTimeout: options.confirmationTimeout }\n : {}),\n })\n\n const publicClient = createPublicClient({ transport })\n\n if (options.records) {\n // Session before account: sharing the session rebuilds the scanner to drop\n // any credentials it was constructed with, and setAccount is what triggers\n // the one build that matters. Only shared when the caller named a\n // credential source — an unconfigured client must leave a scanner aimed at\n // an open service exactly as it was.\n if (configured) options.records.setSession?.(session)\n options.records.setAccount({ viewKey: account.viewKey })\n }\n\n const walletClient = createWalletClient({\n account,\n transport,\n proving,\n ...(options.records ? { recordProvider: options.records } : {}),\n }).extend(provableApiActions())\n\n return { publicClient, walletClient, account }\n }\n\n return {\n network,\n privateKeyToAccount,\n mnemonicToAccount,\n generateMnemonicAccount,\n generateAccount,\n decryptRecord,\n verifySignature,\n createNetworkClient,\n createProvingConfig,\n createRemoteScanner,\n createStandaloneScanner,\n createAleoClient,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Standalone exports — synchronous helpers and devnode client factory.\n// These use the statically-imported SDK (testnet binaries) so they work\n// without an awaited loadNetwork() call.\n// ---------------------------------------------------------------------------\n\n// Consensus version activation heights the WASM layer assumes when building\n// devnode transactions. MUST mirror the CONSENSUS_VERSION_HEIGHTS default that\n// @provablehq/veil-aleo-devnode passes to the aleo-devnode process, so the transaction builder\n// and the node agree on which consensus version is active at each height. The\n// entry count must also equal the WASM SDK's consensus-version count exactly —\n// a shorter list panics with an opaque `unreachable` inside the WASM.\nconst DEVNODE_CONSENSUS_HEIGHTS = '0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17'\n\nfunction privateKeyToAccount(privateKey: string): LocalAccount<'privateKey'> {\n const sdkAccount = new Account({ privateKey })\n const address = sdkAccount.address().to_string()\n const viewKey = sdkAccount.viewKey().to_string()\n\n const signFn = async (message: Uint8Array): Promise<Uint8Array> => {\n const sig = sdkAccount.sign(message)\n return new TextEncoder().encode(sig.to_string())\n }\n\n return {\n type: 'local',\n source: 'privateKey',\n address,\n privateKey,\n viewKey,\n sign: signFn,\n signMessage: signFn,\n }\n}\n\n/** Creates a new random Aleo account (uses static SDK binaries). */\nexport function generateAccount(): LocalAccount<'privateKey'> {\n const sdkAccount = new Account()\n return privateKeyToAccount(sdkAccount.privateKey().to_string())\n}\n\n/**\n * Creates a fully-wired client pair pointing at a local Aleo Devnode instance.\n *\n * Devnode is a lightweight local Aleo node (similar to Foundry's Anvil) that\n * bypasses consensus and skips ZK proof generation, enabling rapid program iteration.\n * The seeded account is pre-funded; both key and socket address can be overridden.\n *\n * The returned wallet client supports `executeContract`. Its confirmation wait\n * resolves once the devnode includes the transaction in a block — automatic\n * after broadcast by default; under `manualBlockCreation` the caller must\n * advance blocks (e.g. a test client's `advanceBlock`) while the call is\n * pending. Record outputs owned by the client's account are decrypted to\n * plaintext in the result; foreign records are dropped.\n *\n * @example\n * ```ts\n * // Zero-config — uses seeded key and localhost:3030\n * const { publicClient, walletClient, account } = createDevnodeClient()\n *\n * // Custom key or socket address\n * const { publicClient, walletClient, account } = createDevnodeClient({\n * privateKey: 'APrivateKey1...',\n * socketAddr: '127.0.0.1:4040',\n * })\n * ```\n */\nexport function createDevnodeClient(options?: {\n privateKey?: string\n /** Socket address of the devnode, e.g. \"127.0.0.1:3030\" */\n socketAddr?: string\n}): { publicClient: PublicClient; walletClient: WalletClient; account: LocalAccount<'privateKey'> } {\n const url = `http://${options?.socketAddr ?? DEVNODE_ADDR}`\n const account = privateKeyToAccount(options?.privateKey ?? DEVNODE_PRIVATE_KEY)\n const sdkAccount = new Account({ privateKey: account.privateKey })\n const transport = http(url, { network: 'testnet' })\n\n const keyProvider = new AleoKeyProvider()\n keyProvider.useCache(true)\n\n // Initialize the wasm consensus heights before any wasm build or parse call\n // this client makes. Idempotent get-or-init: safe to call per client.\n getOrInitConsensusVersionTestHeights(DEVNODE_CONSENSUS_HEIGHTS)\n\n // Created before the proving config so `execute` can broadcast and poll\n // through the same transport-backed client the caller receives.\n const publicClient = createPublicClient({ transport })\n\n /**\n * Builds an unproven devnode execution transaction. `imports` must already\n * map program id → source; resolution of dynamic-dispatch import names\n * happens in `buildTransaction`, not here. Priority fees are always 0 on\n * the devnode path — a caller-supplied fee is ignored.\n */\n const buildExecutionTx = async (opts: {\n programName: string\n functionName: string\n inputs: string[]\n privateFee?: boolean | undefined\n imports?: Record<string, string> | undefined\n }) => {\n const programManager = new ProgramManager(url, keyProvider, undefined)\n programManager.setAccount(sdkAccount)\n return programManager.buildDevnodeExecutionTransaction({\n programName: opts.programName,\n functionName: opts.functionName,\n priorityFee: 0,\n privateFee: opts.privateFee ?? false,\n inputs: opts.inputs,\n ...(opts.imports ? { imports: opts.imports } : {}),\n })\n }\n\n const proving: ProvingConfig = {\n mode: 'devnode',\n buildDeployment: async (deployOptions: BuildDeploymentOptions) => {\n const programManager = new ProgramManager(url, keyProvider, undefined)\n programManager.setAccount(sdkAccount)\n const tx = await programManager.buildDevnodeDeploymentTransaction({\n program: deployOptions.program,\n priorityFee: 0,\n privateFee: deployOptions.privateFee ?? false,\n })\n return JSON.parse(tx.toString())\n },\n buildTransaction: async (txOptions: BuildTransactionOptions) => {\n // Fetch program sources for any call.dynamic targets the caller declared,\n // and recursively include their static imports as well.\n // Use direct REST calls instead of the SDK network client to avoid the\n // /latest_edition endpoint which returns 500 on the devnode.\n let imports: Record<string, string> | undefined\n if (txOptions.imports && txOptions.imports.length > 0) {\n const networkClient = new ProgramManager(url, keyProvider, undefined).networkClient\n imports = {}\n const queue = [...txOptions.imports]\n const seen = new Set<string>()\n while (queue.length > 0) {\n const name = queue.shift()!\n if (seen.has(name)) continue\n seen.add(name)\n const source = await networkClient.getProgram(name); // automatically throws.\n imports[name] = source;\n const importNames = Program.fromString(source).getImports(); // Invoke `wasm` to avoid regex.\n for (const dep of importNames) {\n if (dep && !seen.has(dep)) queue.push(dep)\n }\n }\n }\n\n const tx = await buildExecutionTx({\n programName: txOptions.programName,\n functionName: txOptions.functionName,\n inputs: txOptions.inputs,\n privateFee: txOptions.privateFee,\n imports,\n })\n return JSON.parse(tx.toString())\n },\n execute: async (execOptions: ExecuteOptions): Promise<RawExecuteResult> => {\n const tx = await buildExecutionTx({\n programName: execOptions.programName,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n privateFee: execOptions.privateFee,\n imports: execOptions.programImports,\n })\n\n // Broadcast through the same transport-backed request writeContract uses.\n const txId = (await publicClient.request({\n method: 'sendTransaction',\n params: { transaction: tx.toString() },\n })) as string\n\n // The devnode auto-produces a block after broadcast by default; under\n // manualBlockCreation the caller must advance blocks for this to resolve.\n const confirmedTx = await waitForConfirmation(publicClient, txId)\n\n // Self-custody decryptor: records owned by the devnode account surface\n // as plaintext; records owned by someone else (e.g. a compliance record\n // minted to an authority) pass through as ciphertext rather than being\n // dropped, so the outputs keep their transition positions — positional\n // consumers like the generated contract bindings depend on that.\n const accountViewKey = StaticViewKey.from_string(account.viewKey)\n const decryptor: Decryptor = (ciphertext: string) => {\n const ct = StaticRecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : ciphertext\n }\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n },\n }\n\n const walletClient = createWalletClient({ account, transport, proving })\n\n return { publicClient, walletClient, account }\n}\n","import { hmac } from '@noble/hashes/hmac'\nimport { sha512 } from '@noble/hashes/sha512'\nimport * as bip39 from '@scure/bip39'\nimport { wordlist } from '@scure/bip39/wordlists/english'\n\nconst HARDENED_OFFSET = 0x80000000\n\n// Aleo-specific HMAC key for HD master derivation (parallel to BIP32's\n// \"Bitcoin seed\", but for BLS12-377). Matches shield-core.\nconst BLS12_377_CURVE = 'bls12_377 seed'\n\nconst PATH_REGEX = /^m(\\/[0-9]+')+$/\n\n/**\n * Names the derivation-path convention used to turn a seed into Aleo keys.\n *\n * `'standard'` uses the SLIP-0044-registered Aleo coin type (`m/44'/683'`);\n * `'legacy'` uses the pre-registration path (`m/44'/0'`) some older wallets\n * chose. Pick `'legacy'` only to recover accounts created by such a wallet.\n */\nexport type AleoDerivationId = 'standard' | 'legacy'\n\n/** SLIP-0044 registered Aleo coin type. */\nexport const STANDARD_PATH = \"m/44'/683'\"\n\n/** Pre-SLIP-0044-registration derivation path. Some older wallets used this. */\nexport const LEGACY_PATH = \"m/44'/0'\"\n\n/** Maps each {@link AleoDerivationId} to its account-level derivation path. */\nexport const DERIVATION_PATHS: Record<AleoDerivationId, string> = {\n standard: STANDARD_PATH,\n legacy: LEGACY_PATH,\n}\n\ninterface IKeys {\n key: Uint8Array\n chainCode: Uint8Array\n}\n\nfunction uint32BE(n: number): Uint8Array {\n if (!Number.isInteger(n) || n < 0 || n > 0xffffffff) {\n throw new Error(`uint32BE: value out of range (got ${n})`)\n }\n const out = new Uint8Array(4)\n new DataView(out.buffer).setUint32(0, n, false)\n return out\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0)\n const out = new Uint8Array(total)\n let offset = 0\n for (const p of parts) {\n out.set(p, offset)\n offset += p.length\n }\n return out\n}\n\nfunction ckdPriv({ key, chainCode }: IKeys, index: number): IKeys {\n const data = concatBytes(new Uint8Array([0]), key, uint32BE(index))\n const I = hmac(sha512, chainCode, data)\n return { key: I.slice(0, 32), chainCode: I.slice(32) }\n}\n\nfunction getMasterKeyFromSeed(seed: Uint8Array): IKeys {\n const I = hmac(sha512, BLS12_377_CURVE, seed)\n return { key: I.slice(0, 32), chainCode: I.slice(32) }\n}\n\nfunction isValidPath(path: string): boolean {\n if (!PATH_REGEX.test(path)) return false\n return path\n .split('/')\n .slice(1)\n .map((s) => s.replace(\"'\", ''))\n .every((s) => Number.isFinite(Number(s)))\n}\n\n/**\n * Hierarchical-deterministic key node for the BLS12-377 curve Aleo uses.\n *\n * Follows the SLIP-0010 construction (HMAC-SHA512 chains, hardened-only\n * derivation) with an Aleo-specific master key tag, matching shield-core.\n * All operations are pure and local — nothing touches the network. Start\n * from {@link BLS12377HDKey.fromMasterSeed} (or {@link mnemonicToHDKey})\n * rather than the constructor; the 32-byte `key` of a derived node is the\n * seed for an Aleo private key.\n */\nexport class BLS12377HDKey {\n /**\n * Wraps raw node material. Callers normally use\n * {@link BLS12377HDKey.fromMasterSeed} instead of constructing directly.\n *\n * @param key 32-byte private key material of this node.\n * @param chainCode 32-byte chain code used to derive children.\n */\n constructor(\n public readonly key: Uint8Array,\n public readonly chainCode: Uint8Array,\n ) {}\n\n /**\n * Derives the master node from a BIP-39 seed. Pure and local.\n *\n * @param seed Seed bytes, typically the 64-byte output of\n * {@link mnemonicToSeed}.\n * @returns The root node from which paths are derived.\n */\n static fromMasterSeed(seed: Uint8Array): BLS12377HDKey {\n const master = getMasterKeyFromSeed(seed)\n return new BLS12377HDKey(master.key, master.chainCode)\n }\n\n /**\n * Derives the descendant node at a hardened path. Pure and local.\n *\n * @param path Path of the form `m/44'/683'` — every segment MUST be\n * hardened (trailing `'`) and below 2^31.\n * @returns A new node; this node is unchanged.\n * @throws If the path is malformed, contains a non-hardened segment, or a\n * segment is out of range.\n */\n derive(path: string): BLS12377HDKey {\n if (!isValidPath(path)) {\n throw new Error(\n `Invalid derivation path: ${path} (must match m/N'/N'/... — hardened only)`,\n )\n }\n const segments = path\n .split('/')\n .slice(1)\n .map((s) => parseInt(s.replace(\"'\", ''), 10))\n\n for (const seg of segments) {\n if (seg >= HARDENED_OFFSET) {\n throw new Error(\n `Derivation path segment out of range: ${seg} (must be < 2³¹)`,\n )\n }\n }\n\n const result = segments.reduce(\n (acc, segment) => ckdPriv(acc, segment + HARDENED_OFFSET),\n { key: this.key, chainCode: this.chainCode } as IKeys,\n )\n return new BLS12377HDKey(result.key, result.chainCode)\n }\n\n /** Alias for {@link BLS12377HDKey.derive}, kept for HD-key API parity. */\n derivePath(path: string): BLS12377HDKey {\n return this.derive(path)\n }\n\n /**\n * Derives the account node at `m/{index}'/0'` relative to this node. Pure\n * and local. Applied to a {@link DERIVATION_PATHS} node, this yields the\n * account at that index.\n *\n * @param index Zero-based account index, below 2^31; hardening is applied\n * internally.\n * @returns The account-level node.\n * @throws If the index is negative, fractional, or 2^31 or greater.\n */\n deriveChild(index: number): BLS12377HDKey {\n if (!Number.isInteger(index) || index < 0 || index >= HARDENED_OFFSET) {\n throw new Error(\n `Invalid child index: ${index} (must be integer in [0, 2³¹))`,\n )\n }\n return this.derive(`m/${index}'/0'`)\n }\n}\n\n/**\n * Generates a fresh BIP-39 mnemonic from the English wordlist.\n *\n * Draws entropy from the platform CSPRNG; no network access. The phrase is\n * the root secret for every account derived from it — the caller MUST store\n * it securely and never log it.\n *\n * @param strength Entropy in bits: 128 yields 12 words, 256 yields 24.\n * Defaults to 128.\n * @returns A space-separated mnemonic phrase.\n *\n * @example\n * import { generateMnemonic, mnemonicToHDKey } from '@provablehq/veil-aleo-sdk'\n *\n * const mnemonic = generateMnemonic()\n * const account0 = mnemonicToHDKey(mnemonic)\n */\nexport function generateMnemonic(strength: 128 | 256 = 128): string {\n return bip39.generateMnemonic(wordlist, strength)\n}\n\n/**\n * Checks a full mnemonic phrase against BIP-39: English wordlist membership,\n * word count, and checksum. Pure and local.\n *\n * @param mnemonic Space-separated candidate phrase.\n * @returns True only if the phrase can be used for key derivation; a single\n * wrong or reordered word fails the checksum.\n */\nexport function validateMnemonic(mnemonic: string): boolean {\n return bip39.validateMnemonic(mnemonic, wordlist)\n}\n\n/**\n * Checks whether a single word belongs to the English BIP-39 wordlist. Pure\n * and local. Use for per-word feedback while a phrase is being typed;\n * validating the complete phrase still requires {@link validateMnemonic}.\n *\n * @param word Candidate word, lowercase.\n * @returns True if the word is one of the 2048 list entries.\n */\nexport function validateWord(word: string): boolean {\n return wordlist.includes(word)\n}\n\n/**\n * Converts a mnemonic to its 64-byte BIP-39 seed via PBKDF2-HMAC-SHA512 with\n * an empty passphrase. Pure, local, and deterministic.\n *\n * The mnemonic is not validated here — call {@link validateMnemonic} first;\n * an invalid phrase still produces a seed, only for the wrong accounts.\n *\n * @param mnemonic Space-separated BIP-39 phrase.\n * @returns Seed bytes for {@link BLS12377HDKey.fromMasterSeed}.\n */\nexport function mnemonicToSeed(mnemonic: string): Uint8Array {\n return bip39.mnemonicToSeedSync(mnemonic)\n}\n\n/**\n * Derives the Aleo account key at the given index from a mnemonic in one\n * step: seed, master node, derivation path, account child. Pure and local.\n * This is the usual entry point for turning a stored phrase into key\n * material.\n *\n * @param mnemonic Space-separated BIP-39 phrase.\n * @param options.index Zero-based account index, below 2^31. Defaults to 0.\n * @param options.derivation Path convention. Defaults to `'standard'`\n * (`m/44'/683'`); pass `'legacy'` to recover accounts from wallets that\n * predate the SLIP-0044 registration.\n * @returns The account node; its `key` bytes seed the Aleo private key.\n * @throws If the index is out of range.\n *\n * @example\n * import { mnemonicToHDKey } from '@provablehq/veil-aleo-sdk'\n *\n * const hdKey = mnemonicToHDKey(mnemonic, { index: 1 })\n */\nexport function mnemonicToHDKey(\n mnemonic: string,\n options: { index?: number; derivation?: AleoDerivationId } = {},\n): BLS12377HDKey {\n const { index = 0, derivation = 'standard' } = options\n const seed = mnemonicToSeed(mnemonic)\n return BLS12377HDKey.fromMasterSeed(seed)\n .derivePath(DERIVATION_PATHS[derivation])\n .deriveChild(index)\n}\n","import type {\n Client,\n ProvingConfig,\n RecordProvider,\n WalletActions,\n} from '@provablehq/veil-core'\n\n/** Root of the hosted Provable API. Consumer and JWT endpoints sit here, not under the versioned path. */\nconst DEFAULT_PROVABLE_API_URL = 'https://api.provable.com'\n\n/**\n * Margin treated as expired ahead of a JWT's stated expiry.\n *\n * Matches the margin the Provable SDK applies internally, so both sides agree\n * on when a token is still usable.\n */\nconst EXPIRY_SKEW_MS = 5 * 60 * 1000\n\n/**\n * Credentials issued by the Provable API for a registered consumer.\n *\n * Authenticate delegated proving and the hosted Record Scanner Service. The\n * pair is minted by {@link registerProvableApi} and exchanged for short-lived\n * JWTs.\n *\n * @property consumerId Consumer id. Forms the path segment when minting JWTs.\n * @property apiKey API key. Returned once at registration and unrecoverable\n * afterward, so a caller MUST persist it.\n */\nexport type ProvableApiCredentials = {\n consumerId: string\n apiKey: string\n}\n\n/**\n * Persists Provable API credentials between runs.\n *\n * Implemented by the caller — a file, a keychain, `localStorage`, or a secret\n * manager are all valid, and the choice belongs to the runtime rather than to\n * the SDK. A session reads through `load` on first use and writes through\n * `save` exactly once, immediately after registering a new consumer.\n *\n * @property load Reads stored credentials. Returning `undefined` means no\n * consumer is registered yet and triggers registration.\n * @property save Writes credentials. The API key is unrecoverable if this\n * write is lost, so a failure here should propagate rather than be swallowed.\n *\n * @example\n * const store: ProvableCredentialStore = {\n * load: async () => JSON.parse(await readFile(path, 'utf8')).provableApi,\n * save: async (c) => writeFile(path, JSON.stringify({ provableApi: c }), { mode: 0o600 }),\n * }\n */\nexport type ProvableCredentialStore = {\n load: () => Promise<ProvableApiCredentials | undefined> | ProvableApiCredentials | undefined\n save: (credentials: ProvableApiCredentials) => Promise<void> | void\n}\n\n/**\n * Builds a credential store that keeps credentials for the life of the process.\n *\n * The default when a client is given no credentials and no store, and the right\n * choice for tests and short-lived workers. Suited to any runtime, since it\n * touches no storage.\n *\n * A consumer registered into this store is lost when the process exits, and its\n * API key is issued once — so a process that registers here and runs again\n * registers a second consumer that nobody can reclaim. Anything longer-lived\n * than a single run belongs in a persistent store: `fileCredentialStore` from\n * `@provablehq/veil-aleo-sdk/node`, or a caller-supplied\n * {@link ProvableCredentialStore}.\n *\n * @param initial Optional credentials to start with, so a caller can seed the\n * store from an environment variable and skip registration.\n * @returns A store backed by a closure variable.\n *\n * @example\n * const store = memoryCredentialStore()\n * // or seeded, in which case nothing registers:\n * const seeded = memoryCredentialStore({ consumerId, apiKey })\n */\nexport function memoryCredentialStore(\n initial?: ProvableApiCredentials,\n): ProvableCredentialStore {\n let held = initial\n return {\n load: () => held,\n save: (credentials) => {\n held = credentials\n },\n }\n}\n\n/**\n * A minted Provable API JWT and its expiry.\n *\n * Structurally identical to the Provable SDK's `JWTData` and\n * `RecordScannerJWTData`, so a value of this type passes directly as their\n * `jwtData` option.\n *\n * @property jwt The `Authorization` header value, verbatim as issued by the\n * API (Bearer-prefixed).\n * @property expiration Expiry as milliseconds since the Unix epoch.\n */\nexport type ProvableJwt = {\n jwt: string\n expiration: number\n}\n\n/**\n * The consumers a session has been wired into.\n *\n * Reported by {@link authenticateProvableApi} so a caller can tell which paths\n * one authentication call actually covers.\n *\n * @property proving Whether a proving configuration carries this session.\n * @property recordScanning Whether a record provider carries this session.\n */\nexport type ProvableSessionConsumers = {\n proving: boolean\n recordScanning: boolean\n}\n\n/**\n * A live Provable API session: consumer credentials plus a cached, refreshing JWT.\n *\n * Built by `createProvingConfig`, `createRemoteScanner`, and\n * `createAleoClient` from the credential options they are given — a caller\n * configures credentials and does not construct this directly. Sharing one\n * session across delegated proving and record scanning means a single minted\n * JWT and a single refresh policy for both.\n *\n * @property registeredConsumer Reports whether this session registered a new\n * consumer rather than loading an existing one. Only meaningful after\n * credentials have resolved.\n * @property getCredentials Resolves the credentials, registering on first use\n * when neither direct credentials nor a store supply them.\n * @property getJwt Returns a JWT valid for at least the expiry margin,\n * minting or refreshing as needed.\n * @property consumers Which consumers carry this session. Advisory reporting;\n * nothing reads it to make decisions. `recordScanning` is set where a record\n * provider is wired to a client, so sharing one session across several\n * clients under-reports rather than claiming a path a given client lacks.\n * @property attach Records that a consumer now carries this session. Called by\n * the factories during wiring.\n */\nexport type ProvableSession = {\n registeredConsumer: () => boolean\n getCredentials: (options?: { username?: string }) => Promise<ProvableApiCredentials>\n getJwt: (options?: { forceRefresh?: boolean }) => Promise<ProvableJwt>\n consumers: ProvableSessionConsumers\n attach: (consumer: keyof ProvableSessionConsumers) => void\n}\n\n/**\n * Options for {@link registerProvableApi}.\n *\n * @property username Handle for the consumer. Globally unique across the\n * Provable API, so a taken name fails the call.\n * @property baseUrl Optional Provable API root. Defaults to\n * `https://api.provable.com`. Applies when targeting a non-production\n * deployment.\n */\nexport type RegisterProvableApiParameters = {\n username: string\n baseUrl?: string\n}\n\n/**\n * Options for {@link createProvableSession}.\n *\n * @property credentials Optional credentials to use directly. Take precedence\n * over `store`, so an operator can inject a rotated or CI-provided pair\n * without clearing persisted state first.\n * @property store Optional persistence for credentials across runs. Omit for a\n * consumer that lives only as long as the process.\n * @property username Optional handle to register under when neither\n * `credentials` nor `store` yields a pair. A function is called lazily, so a\n * caller can derive the name from an account address that is not known at\n * configuration time. Required only if registration may happen.\n * @property baseUrl Optional Provable API root. Defaults to\n * `https://api.provable.com`.\n */\nexport type CreateProvableSessionOptions = {\n credentials?: ProvableApiCredentials\n store?: ProvableCredentialStore\n username?: string | (() => string)\n baseUrl?: string\n}\n\n/**\n * Options for {@link authenticateProvableApi}.\n *\n * @property username Optional handle to register under when the client's\n * configuration yields no credentials. Overrides the name configured on the\n * session.\n * @property forceRefresh Mint a fresh JWT even when the cached one is still\n * valid. Defaults to false. Applies when recovering from a rejected token.\n */\nexport type AuthenticateProvableApiParameters = {\n username?: string\n forceRefresh?: boolean\n}\n\n/**\n * Result of {@link authenticateProvableApi}.\n *\n * @property credentials The resolved consumer credentials. Worth persisting\n * when `registered` is true — the API key is unrecoverable afterward.\n * @property expiration Expiry of the minted JWT, as milliseconds since the\n * Unix epoch.\n * @property registered Whether this call registered a new consumer rather than\n * loading an existing one.\n * @property applied Which paths the session reaches. `recordScanning` is false\n * when the client was given a record provider that cannot accept a session —\n * any implementation other than the ones this package builds — in which case\n * that provider keeps using the credentials it was constructed with.\n */\nexport type AuthenticateProvableApiReturnType = {\n credentials: ProvableApiCredentials\n expiration: number\n registered: boolean\n applied: ProvableSessionConsumers\n}\n\n/**\n * The Provable API authentication action, merged into a client by `extend`.\n *\n * @property authenticateProvableApi Resolves the client's Provable API session.\n */\nexport type ProvableApiActions = {\n authenticateProvableApi: (\n params?: AuthenticateProvableApiParameters,\n ) => Promise<AuthenticateProvableApiReturnType>\n}\n\n/**\n * A wallet client carrying the Provable API authentication action.\n *\n * Composed inside the client's action set rather than intersected onto\n * `WalletClient`, so a caller who extends further — adding DEX actions, for\n * example — keeps `authenticateProvableApi` in the resulting type. `extend`\n * carries forward only what sits in the action set, so an outer intersection\n * would be dropped on the next call.\n *\n * The wallet half is restated rather than derived. `Omit<WalletClient, keyof\n * Client>` reads better and was tried first, but `keyof Client` resolves to\n * `never` against core's built declarations — so the Omit keeps every base field,\n * violates the `Extended` constraint, and silently collapses to a type missing\n * every wallet action. It typechecks against core's source and fails only for\n * consumers, which is the worst place to find out.\n *\n * Keep this in step if core changes what a wallet client carries; a\n * `WalletClientActions` export from core would remove the duplication safely.\n */\nexport type ProvableWalletClient = Client<\n WalletActions & { recordProvider: RecordProvider | undefined } & ProvableApiActions\n>\n\n/**\n * A proving configuration carrying the Provable API session.\n *\n * `createProvingConfig` returns this shape. Core types `Client.proving` as the\n * bare {@link ProvingConfig} and never reads binding-specific fields — `url` and\n * `apiKey` already travel the same way — so the session rides along without a\n * core change, and {@link authenticateProvableApi} narrows to read it.\n *\n * @property session The session shared with record scanning, or `undefined`\n * when the client was configured without credentials.\n */\nexport type ProvingConfigWithSession = ProvingConfig & {\n session?: ProvableSession | undefined\n}\n\n/**\n * Registers a Provable API consumer and returns its credentials.\n *\n * Unauthenticated — this is the call that issues the credentials everything\n * else authenticates with. Hits the network.\n *\n * A username is spent once. It is globally unique, the API exposes no endpoint\n * that reads a consumer back, and a duplicate registration answers 409 with\n * nothing usable in it — so a taken name cannot be traded for the credentials it\n * belongs to, and the only remedy is the stored key or a different name.\n *\n * @param params Handle to register under, and optionally a non-default API root.\n * @returns The consumer id and API key. The key is shown only here, so the\n * caller MUST persist it.\n * @throws When the username is already registered, when registration returns any\n * other non-2xx status, or when the response body does not carry a consumer id\n * and key.\n *\n * @example\n * const credentials = await registerProvableApi({ username: 'my-bot-42' })\n * await writeFile('creds.json', JSON.stringify(credentials))\n */\nexport async function registerProvableApi(\n params: RegisterProvableApiParameters,\n): Promise<ProvableApiCredentials> {\n const baseUrl = params.baseUrl ?? DEFAULT_PROVABLE_API_URL\n const response = await fetch(`${baseUrl}/consumers`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ username: params.username }),\n })\n if (!response.ok) {\n const body = await response.text()\n // A 409 is the one failure a caller can act on, and the obvious next move —\n // look the consumer up, or re-register to get the key again — does not\n // exist. Say so here rather than leaving them to discover it.\n if (response.status === 409) {\n throw new Error(\n `Provable API username '${params.username}' is already registered. Credentials cannot be ` +\n 'recovered from a username: supply the existing consumerId and apiKey, or register under ' +\n `a different name. (HTTP 409: ${body})`,\n )\n }\n throw new Error(\n `Provable API consumer registration failed (HTTP ${response.status}): ${body}`,\n )\n }\n const body = (await response.json()) as { consumer?: { id?: string }; key?: string }\n if (!body.consumer?.id || !body.key) {\n throw new Error('Provable API consumer registration response carried no consumer id and key.')\n }\n return { consumerId: body.consumer.id, apiKey: body.key }\n}\n\n/**\n * Mints a JWT for a registered consumer.\n *\n * The token arrives in the `Authorization` response header and its expiry in\n * the response body's `exp` claim, in seconds. Hits the network.\n *\n * @param credentials The consumer id and API key to authenticate the mint with.\n * @param baseUrl Provable API root.\n * @returns The token and its expiry in milliseconds since the Unix epoch.\n * @throws When the mint returns a non-2xx status, or when the response omits\n * the authorization header or the expiry claim.\n */\nasync function mintJwt(credentials: ProvableApiCredentials, baseUrl: string): Promise<ProvableJwt> {\n const response = await fetch(`${baseUrl}/jwts/${encodeURIComponent(credentials.consumerId)}`, {\n method: 'POST',\n headers: { 'X-Provable-API-Key': credentials.apiKey },\n })\n if (!response.ok) {\n throw new Error(\n `Provable API JWT mint failed (HTTP ${response.status}): ${await response.text()}`,\n )\n }\n const header = response.headers.get('authorization')\n if (!header) {\n throw new Error('Provable API JWT mint response carried no authorization header.')\n }\n const body = (await response.json()) as { exp?: number }\n if (typeof body.exp !== 'number') {\n throw new Error('Provable API JWT mint response carried no exp claim.')\n }\n return { jwt: header, expiration: body.exp * 1000 }\n}\n\n/**\n * Builds a Provable API session that resolves credentials and refreshes its JWT.\n *\n * Credentials resolve on first use — supplied directly, else loaded from the\n * store, else registered and saved. Registration and minting are each\n * single-flighted, so a cold client that proves and scans concurrently\n * registers once and mints once. Pure and local until the first\n * `getCredentials` or `getJwt` call.\n *\n * @param options Credential source, optional persistence, and the name to\n * register under.\n * @returns A session for `createProvingConfig`, `createRemoteScanner`, and\n * `createAleoClient` to share.\n *\n * @example\n * const session = createProvableSession({ store, username: 'my-bot-42' })\n * const { jwt } = await session.getJwt()\n */\nexport function createProvableSession(options: CreateProvableSessionOptions = {}): ProvableSession {\n const baseUrl = options.baseUrl ?? DEFAULT_PROVABLE_API_URL\n const consumers: ProvableSessionConsumers = { proving: false, recordScanning: false }\n\n let credentials = options.credentials\n let registered = false\n let credentialsInFlight: Promise<ProvableApiCredentials> | undefined\n let jwt: ProvableJwt | undefined\n let jwtInFlight: Promise<ProvableJwt> | undefined\n\n async function resolveCredentials(usernameOverride?: string): Promise<ProvableApiCredentials> {\n if (credentials) return credentials\n const stored = await options.store?.load()\n if (stored) {\n credentials = stored\n return credentials\n }\n // Resolved only if it will be used: a configured function may be doing real\n // work, and the derived default has a random component.\n const username =\n usernameOverride ?? (typeof options.username === 'function' ? options.username() : options.username)\n if (!username) {\n throw new Error(\n 'No Provable API credentials available — pass credentials, a store holding them, or a username to register with.',\n )\n }\n const issued = await registerProvableApi({ username, baseUrl })\n // Held before persisting, even though persisting is what makes them\n // durable. A username is spent once and the key is issued once, so if the\n // write fails the worst outcome is registering *again* on the next attempt\n // and burning another name. Holding them first makes that impossible, and\n // the throw below still tells the caller the key is not stored.\n credentials = issued\n registered = true\n try {\n await options.store?.save(issued)\n } catch (cause) {\n throw new Error(\n `Registered Provable API consumer ${issued.consumerId}, but persisting its credentials failed. ` +\n 'They are live for this process — read them from getCredentials() and store them yourself — but ' +\n 'the API key cannot be reissued, so a restart loses it.',\n { cause },\n )\n }\n return credentials\n }\n\n function getCredentials({ username }: { username?: string } = {}): Promise<ProvableApiCredentials> {\n // Collapse concurrent resolutions so a cold prove and scan register once.\n credentialsInFlight ??= resolveCredentials(username).finally(() => {\n credentialsInFlight = undefined\n })\n return credentialsInFlight\n }\n\n function getJwt({ forceRefresh = false }: { forceRefresh?: boolean } = {}): Promise<ProvableJwt> {\n const stale = !jwt || Date.now() >= jwt.expiration - EXPIRY_SKEW_MS\n if (!forceRefresh && !stale) return Promise.resolve(jwt!)\n // A forced refresh joins an in-flight mint rather than racing it, so a\n // burst of rejected calls still produces one replacement token.\n jwtInFlight ??= (async () => {\n const resolved = await getCredentials()\n jwt = await mintJwt(resolved, baseUrl)\n return jwt\n })().finally(() => {\n jwtInFlight = undefined\n })\n return jwtInFlight\n }\n\n return {\n registeredConsumer: () => registered,\n getCredentials,\n getJwt,\n consumers,\n attach: (consumer) => {\n consumers[consumer] = true\n },\n }\n}\n\n/**\n * Reads the Provable API session off a client's proving configuration.\n *\n * `createProvingConfig` attaches the session to the configuration it returns.\n * Core types `proving` as the bare interface and never reads binding-specific\n * fields — `url` and `apiKey` are already carried the same way — so the narrow\n * is safe and stays local to this accessor.\n *\n * @param client The client to read from.\n * @returns The session, or `undefined` when the client has no proving\n * configuration or was configured without credentials.\n */\nfunction getProvableSession(client: Client): ProvableSession | undefined {\n return (client.proving as ProvingConfigWithSession | undefined)?.session\n}\n\n/**\n * Resolves the Provable API session backing delegated proving and record scanning.\n *\n * Registers a consumer when the client's configuration yields none, mints a\n * JWT, and leaves both on the session the client's proving configuration and\n * record provider already hold — so proving and scanning authenticate from then\n * on without further setup. Optional: the first prove or scan resolves the same\n * session lazily. Calling it explicitly front-loads registration, surfaces\n * credential failures before a transaction is built, and returns a newly issued\n * API key at the one moment it is recoverable.\n *\n * Hits the network: registration on first run, plus one JWT mint.\n *\n * @param client A client whose proving configuration carries Provable API\n * credentials or a credential store.\n * @param params Optional registration name and forced refresh.\n * @returns The credentials, the JWT expiry, whether a consumer was registered,\n * and which paths the session reaches.\n * @throws When the client has no Provable API session configured, or when\n * registration or minting fails.\n *\n * @example\n * const { credentials, registered } = await client.authenticateProvableApi()\n * if (registered) await store.save(credentials)\n */\nexport async function authenticateProvableApi(\n client: Client,\n params: AuthenticateProvableApiParameters = {},\n): Promise<AuthenticateProvableApiReturnType> {\n const session = getProvableSession(client)\n if (!session) {\n throw new Error(\n 'No Provable API session on this client — pass consumerId and apiKey, or a credentialStore, when creating it.',\n )\n }\n const credentials = await session.getCredentials({ username: params.username })\n const { expiration } = await session.getJwt({ forceRefresh: params.forceRefresh })\n return {\n credentials,\n expiration,\n registered: session.registeredConsumer(),\n applied: { ...session.consumers },\n }\n}\n\n/**\n * Builds the Provable API auth decorator for `client.extend()`.\n *\n * `createAleoClient` applies this already. Applies directly when composing a\n * client by hand from `createWalletClient` and a proving configuration built\n * with credentials.\n *\n * @returns A decorator: pass it to `client.extend(...)`.\n *\n * @example\n * const client = createWalletClient({ account, transport, proving })\n * .extend(provableApiActions())\n * await client.authenticateProvableApi()\n */\nexport function provableApiActions() {\n return (client: Client): ProvableApiActions => ({\n authenticateProvableApi: (params) => authenticateProvableApi(client, params),\n })\n}\n"],"mappings":"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","names":["generateMnemonic","validateMnemonic","body","Account","generateMnemonic","generateAccount"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/rss.ts","../src/mnemonic.ts","../src/provableApi.ts"],"sourcesContent":["/**\n * @provablehq/veil-aleo-sdk\n *\n * Loads `@provablehq/sdk` for a specific Aleo network and exposes the SDK's\n * functionality bound to that network's setup parameters.\n *\n * Usage:\n * import { loadNetwork } from '@provablehq/veil-aleo-sdk'\n * import { http } from '@provablehq/veil-core'\n *\n * const aleo = await loadNetwork('mainnet')\n *\n * const account = aleo.privateKeyToAccount('APrivateKey1...')\n * const { publicClient, walletClient } = aleo.createAleoClient({\n * privateKey: 'APrivateKey1...',\n * networkUrl: 'https://api.provable.com/v2',\n * })\n *\n * Switching networks: load a new handle. Existing accounts remain valid —\n * Aleo private keys, view keys, and addresses are network-agnostic.\n */\n\nimport { loadNetwork as loadSdk } from '@provablehq/sdk/dynamic.js'\nimport {\n Account,\n AleoKeyProvider,\n Program,\n ProgramManager,\n RecordCiphertext as StaticRecordCiphertext,\n ViewKey as StaticViewKey,\n getOrInitConsensusVersionTestHeights,\n} from '@provablehq/sdk'\nimport { DEVNODE_PRIVATE_KEY, DEVNODE_ADDR } from '@provablehq/veil-aleo-devnode'\nexport { DEVNODE_PRIVATE_KEY, DEVNODE_ADDR }\nimport type { LocalAccount } from '@provablehq/veil-core'\nimport type { ProvingConfig, BuildTransactionOptions, BuildDeploymentOptions, SimulateOptions, ExecuteOptions, RawSimulateResult, RawExecuteResult } from '@provablehq/veil-core'\nimport type { OwnedRecord, RecordProvider, StandaloneRecordScanner, RequestRecordsParameters } from '@provablehq/veil-core'\nimport type { Network, PublicClient, WalletClient } from '@provablehq/veil-core'\nimport {\n createPublicClient,\n createWalletClient,\n http,\n BaseError,\n ProvingError,\n ConfigurationError,\n classifyBroadcastError,\n classifyProvingError,\n waitForConfirmation,\n extractTransitions,\n} from '@provablehq/veil-core'\nimport type { Decryptor } from '@provablehq/veil-core'\nimport { buildOwnedFilter } from './utils/rss.js'\nimport { generateMnemonic, mnemonicToHDKey, type AleoDerivationId } from './mnemonic.js'\nimport {\n createProvableSession,\n memoryCredentialStore,\n provableApiActions,\n type ProvableCredentialStore,\n type ProvableKeyedAuth,\n type ProvableSession,\n type ProvableWalletClient,\n type ProvingConfigWithSession,\n} from './provableApi.js'\n\nexport {\n registerProvableApi,\n createProvableSession,\n memoryCredentialStore,\n authenticateProvableApi,\n provableApiActions,\n type ProvableApiCredentials,\n type ProvableKeyedAuth,\n type ProvableCredentialStore,\n type ProvableJwt,\n type ProvableSession,\n type ProvableSessionConsumers,\n type ProvableWalletClient,\n type ProvingConfigWithSession,\n type RegisterProvableApiParameters,\n type CreateProvableSessionOptions,\n type AuthenticateProvableApiParameters,\n type AuthenticateProvableApiReturnType,\n type ProvableApiActions,\n} from './provableApi.js'\n\nexport {\n BLS12377HDKey,\n generateMnemonic,\n validateMnemonic,\n validateWord,\n mnemonicToSeed,\n mnemonicToHDKey,\n STANDARD_PATH,\n LEGACY_PATH,\n type AleoDerivationId,\n} from './mnemonic.js'\n\n/** Networks supported by `@provablehq/sdk/dynamic.js`. */\nexport type SupportedNetwork = 'mainnet' | 'testnet'\n\n/**\n * Base URL of Provable's hosted delegated proving service.\n *\n * The default `proverUrl` for `mode: 'delegated'`. A base, so the active network\n * is appended — which is what lets `switchChain` re-target proving.\n */\nexport const DEFAULT_PROVER_URL = 'https://api.provable.com/prove'\n\n/**\n * Base URL of Provable's hosted Record Scanner Service.\n *\n * The default `url` for both scanner factories. A base — the SDK appends the\n * network segment, which is what lets a scanner follow `switchChain`.\n */\nexport const DEFAULT_SCANNER_URL = 'https://api.provable.com/scanner'\n\n// `loadSdk('testnet')` and `loadSdk('mainnet')` return modules whose runtime\n// classes have the same shape. The narrowed-to-testnet type is used as the\n// canonical handle to avoid TS's union-of-modules confusion.\ntype SdkModule = Awaited<ReturnType<typeof loadSdk<'testnet'>>>\n\n/**\n * A network-bound SDK handle. All functions on this handle use the binary\n * set loaded for the named network.\n *\n * Most key/account operations (`privateKeyToAccount`, `mnemonicToAccount`,\n * `generateAccount`, `decryptRecord`, `verifySignature`) are mathematically\n * network-agnostic — the same private key (or mnemonic) derives the same\n * address and view key regardless of which network's binary was loaded.\n * Proving and program operations (`createProvingConfig`, `createAleoClient`,\n * scanners) are network-bound.\n */\nexport interface AleoSdk {\n /** The network this handle is bound to. */\n readonly network: SupportedNetwork\n\n /** Creates a `LocalAccount` from an Aleo private key. */\n privateKeyToAccount(privateKey: string): LocalAccount<'privateKey'>\n\n /**\n * Creates a `LocalAccount` from a BIP39 mnemonic phrase using Aleo's\n * BLS12-377 HD derivation (matches Shield wallet derivation).\n *\n * Defaults to the SLIP-0044 Aleo coin type path `m/44'/683'`, account\n * index 0. Pass `derivation: 'legacy'` to use the pre-registration path\n * `m/44'/0'` for compatibility with older wallets.\n */\n mnemonicToAccount(\n mnemonic: string,\n options?: { index?: number; derivation?: AleoDerivationId },\n ): LocalAccount<'mnemonic'>\n\n /**\n * Generates a fresh BIP39 mnemonic and derives its Aleo account in one call.\n * Pure and local — no network access. The caller MUST persist the returned\n * mnemonic; it is the only way to re-derive the account.\n *\n * @param options.strength Entropy bits: 128 (12 words, default) or 256 (24 words).\n * @param options.index Account index on the derivation path. Defaults to 0.\n * @param options.derivation Derivation path id. Defaults to `'standard'`\n * (`m/44'/683'`); pass `'legacy'` for pre-registration `m/44'/0'` wallets.\n * @returns The generated mnemonic and the account derived from it.\n *\n * @example\n * const { mnemonic, account } = aleo.generateMnemonicAccount()\n * // store `mnemonic` safely; `account.address` is ready to use\n */\n generateMnemonicAccount(options?: {\n strength?: 128 | 256\n index?: number\n derivation?: AleoDerivationId\n }): { mnemonic: string; account: LocalAccount<'mnemonic'> }\n\n /** Creates a new random Aleo account. */\n generateAccount(): LocalAccount<'privateKey'>\n\n /** Decrypts a record ciphertext using a view key. */\n decryptRecord(viewKey: string, ciphertext: string): string\n\n /** Verifies a signature against a message and address. */\n verifySignature(address: string, message: Uint8Array, signature: string): boolean\n\n /** Creates an `AleoNetworkClient` for direct SDK access. */\n createNetworkClient(url: string): InstanceType<SdkModule['AleoNetworkClient']>\n\n /**\n * Creates a `ProvingConfig` for `createWalletClient({ proving })`.\n *\n * @param options.proverUrl Base URL of the delegated proving service — the\n * network segment is appended, so do not include it. That is what lets\n * `switchChain` re-target proving instead of leaving it on the network the\n * client started from. A base that already ends in `/mainnet` or `/testnet`\n * is re-targeted rather than doubled. Defaults to\n * {@link DEFAULT_PROVER_URL} under `mode: 'delegated'`; unused under\n * `mode: 'local'`, which reaches no prover.\n * @param options.session Optional Provable API session. When present the\n * configuration authenticates from it and withholds `apiKey`/`consumerId`\n * from the prover client, so one party mints JWTs. The session is attached\n * to the returned configuration, which is what lets\n * `authenticateProvableApi` find it on a client.\n * @param options.auth Optional provisioned-key auth for the edge gateway.\n * Every proving request carries the key verbatim; nothing registers or\n * mints, and a 401 is terminal. Mutually exclusive with `session`,\n * `apiKey`, and `consumerId` — combining them throws.\n */\n createProvingConfig(options: {\n mode: 'delegated' | 'local'\n networkUrl: string\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n account?: LocalAccount<'privateKey'>\n confirmationTimeout?: number\n useFeeMaster?: boolean\n session?: ProvableSession\n auth?: ProvableKeyedAuth\n }): ProvingConfigWithSession\n\n /**\n * Creates a record scanner backed by Provable's Record Scanner Service.\n *\n * The first `requestRecords` call registers the account's view key with the\n * service (a network round-trip) to obtain the UUID scanning requires;\n * subsequent calls reuse it. `setAccount` resets the registration.\n *\n * The provider implements `switchNetwork`, so a wallet client carrying it\n * re-targets record scanning when `switchChain` runs — the scanner rebuilds\n * against the new network and re-registers lazily on the next scan.\n *\n * @param options.url Base URL of the service (the SDK appends the network\n * segment — do not include it). Defaults to {@link DEFAULT_SCANNER_URL}.\n * @param options.consumerId Optional consumer id used for JWT refresh.\n * Unnecessary when a `session` supplies the token. Required alongside\n * `apiKey` otherwise — a JWT is minted from the pair, so half of it\n * authenticates nothing and construction throws rather than 401ing later.\n * @param options.apiKey Optional API key for the authenticated service\n * (e.g. the hosted Provable RSS). Omit for an open/unauthenticated service.\n * @param options.session Optional Provable API session to authenticate from,\n * shared with delegated proving. `createAleoClient` supplies its own\n * session through `setSession` on the returned provider, so a caller who\n * passes the scanner to that factory does not need this.\n * @param options.startBlock Optional block height to begin scanning from at\n * registration. Defaults to 0 (full history).\n * @param options.auth Optional provisioned-key auth for the edge gateway.\n * Every scan carries the key verbatim; nothing registers or mints, and a\n * 401 is terminal. Mutually exclusive with `session`, `apiKey`, and\n * `consumerId` — combining them throws.\n * @returns The provider, plus `setSession` and `setAuth` for a factory to\n * share one credential source across proving and scanning after\n * construction.\n */\n createRemoteScanner(options?: {\n url?: string\n consumerId?: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n auth?: ProvableKeyedAuth\n }): RecordProvider & {\n setSession: (session: ProvableSession) => void\n setAuth: (auth: ProvableKeyedAuth) => void\n }\n\n /**\n * Creates a standalone record scanner with an explicit view key.\n *\n * Like {@link createRemoteScanner}, the first `requestRecords` registers the\n * view key with the service (a network round-trip) to obtain the scanning UUID.\n *\n * @param options.url Base URL of the service (the SDK appends the network\n * segment). Defaults to {@link DEFAULT_SCANNER_URL}.\n * @param options.consumerId Optional consumer id used for JWT refresh.\n * Unnecessary when a `session` supplies the token. Required alongside\n * `apiKey` otherwise — a JWT is minted from the pair, so half of it\n * authenticates nothing and construction throws rather than 401ing later.\n * @param options.viewKey The view key (`AViewKey1…`) to scan and decrypt with.\n * @param options.apiKey Optional API key for the authenticated service. Omit\n * for an open/unauthenticated service.\n * @param options.session Optional Provable API session to authenticate from.\n * Supplied at construction only — a standalone scanner is not pluggable\n * into a wallet client, so nothing shares a session with it later.\n * @param options.startBlock Optional block height to begin scanning from at\n * registration. Defaults to 0 (full history).\n * @param options.auth Optional provisioned-key auth for the edge gateway.\n * Every scan carries the key verbatim; nothing registers or mints, and a\n * 401 is terminal. Mutually exclusive with `session`, `apiKey`, and\n * `consumerId` — combining them throws.\n */\n createStandaloneScanner(options: {\n url?: string\n consumerId?: string\n viewKey: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n auth?: ProvableKeyedAuth\n }): StandaloneRecordScanner\n\n /**\n * Creates a fully-wired Aleo client from a private key and network URL.\n *\n * Builds one Provable API session from the credential options and shares it\n * across delegated proving and record scanning, so a single\n * `walletClient.authenticateProvableApi()` covers both. Omit the credential\n * options for a client that authenticates neither.\n *\n * @param options.apiKey Optional Provable API key. Paired with `consumerId`,\n * it seeds the session directly.\n * @param options.consumerId Optional Provable API consumer id.\n * @param options.proverUrl Base URL of the delegated proving service — the\n * network segment is appended, so do not include it. That is what lets\n * `switchChain` re-target proving. Defaults to {@link DEFAULT_PROVER_URL},\n * since `provingMode` itself defaults to `'delegated'`; pass an override for\n * a self-hosted prover.\n * @param options.confirmationTimeout Milliseconds to wait for a submitted\n * transaction to confirm. Defaults to 60_000 (one minute), which covers a\n * healthy confirmation with room to spare; a transaction still absent after\n * that is more often one the node never included than one about to land.\n * Raise it for a congested network or a multi-transition call that takes\n * longer to include, rather than treating a slow confirmation as a failure.\n * @param options.username Optional handle to register a Provable API consumer\n * under, used only when no credentials and no stored pair are available.\n * A function is called lazily, at the moment registration happens. Defaults\n * to a name derived from the account address plus a random suffix — the\n * suffix matters because a username is spent once, so an account that lost\n * its stored key must still be able to register. Supplying a fixed name\n * makes the consumer identifiable but fails if that name is taken, since\n * credentials cannot be recovered from a username.\n * @param options.credentialStore Optional persistence for Provable API\n * credentials. When neither `consumerId`/`apiKey` nor a stored pair is\n * available, a consumer is registered under a name derived from the account\n * address and saved here. Defaults to `memoryCredentialStore()`, which holds\n * a registered consumer only for the life of the process — pass\n * `fileCredentialStore` from `@provablehq/veil-aleo-sdk/node`, or any\n * {@link ProvableCredentialStore}, for anything longer-lived. A client left\n * fully unconfigured does not share its session with `records`, so a scanner\n * aimed at an open service keeps needing no credential.\n * @param options.session Optional pre-built session, for a caller that owns\n * one already. Takes precedence over the credential options.\n * @param options.auth Optional provisioned-key auth for the edge gateway.\n * Selects the keyed model for the whole client: proving and scanning carry\n * the key on every request, no session exists, and\n * `authenticateProvableApi` throws since there is nothing to resolve.\n * Mutually exclusive with every consumer option (`apiKey`, `consumerId`,\n * `username`, `credentialStore`, `session`) — edge keys are handed out by\n * an operator, not registered.\n * @returns A public client, a wallet client carrying\n * `authenticateProvableApi`, and the account.\n *\n * @example\n * const scanner = aleo.createRemoteScanner({ url: SCANNER_URL })\n * const { walletClient } = aleo.createAleoClient({\n * privateKey, networkUrl, proverUrl, records: scanner, credentialStore: store,\n * })\n * const { credentials, registered } = await walletClient.authenticateProvableApi()\n * if (registered) console.log('registered consumer', credentials.consumerId)\n */\n createAleoClient(options: {\n privateKey: string\n networkUrl: string\n provingMode?: 'delegated' | 'local'\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n useFeeMaster?: boolean\n confirmationTimeout?: number\n username?: string | (() => string)\n credentialStore?: ProvableCredentialStore\n session?: ProvableSession\n auth?: ProvableKeyedAuth\n /**\n * Record provider for `requestRecords`. Not wired by default — pass\n * `aleo.createRemoteScanner(...)` or any\n * custom `RecordProvider`. `requestRecords` throws with a setup hint\n * when no provider is configured.\n */\n records?: RecordProvider & {\n setSession?: (session: ProvableSession) => void\n setAuth?: (auth: ProvableKeyedAuth) => void\n }\n }): {\n publicClient: PublicClient\n walletClient: ProvableWalletClient\n account: LocalAccount<'privateKey'>\n }\n}\n\n/**\n * Loads `@provablehq/sdk` for the named network and returns a network-bound\n * handle. The SDK module cache memoizes the load — calling twice for the\n * same network returns the same binary set without re-instantiating.\n */\nexport async function loadNetwork(name: SupportedNetwork): Promise<AleoSdk> {\n const sdk = (await loadSdk(name)) as SdkModule\n silenceSdkLogs(sdk)\n return buildSdk(name, sdk)\n}\n\n/**\n * Silences `@provablehq/sdk`'s own console output on a freshly loaded module.\n *\n * The SDK writes failed requests and retries straight to the console, so a record\n * scan that recovers after a transient 401 still prints one line per attempt.\n * Those lines are not errors — Veil reports failure by throwing, and every retry\n * that mattered is already reflected in what the call returns — but they read as\n * failure to anyone watching a script run, and they cannot be attributed to a\n * caller. Called on every load, including a network switch, because the log level\n * is per-module rather than process-wide.\n *\n * @param sdk A module returned by `@provablehq/sdk/dynamic.js`.\n */\nfunction silenceSdkLogs(sdk: SdkModule): void {\n // Feature-detected rather than called directly: the export is absent from\n // older pins, and a missing logger must not fail the load.\n const { setLogLevel } = sdk as unknown as { setLogLevel?: (level: 'silent') => void }\n setLogLevel?.('silent')\n}\n\nfunction buildSdk(initialNetwork: SupportedNetwork, initialSdk: SdkModule): AleoSdk {\n // Mutable handle so `createProvingConfig().switchNetwork()` can swap the\n // underlying binary set without rebuilding the wallet client.\n let currentSdk: SdkModule = initialSdk\n const network = initialNetwork\n const {\n Account,\n PrivateKey,\n Signature,\n Address,\n ViewKey,\n AleoNetworkClient,\n RecordScanner,\n RecordCiphertext,\n } = initialSdk\n\n\n\n function mnemonicToAccount(\n mnemonic: string,\n options?: { index?: number; derivation?: AleoDerivationId },\n ): LocalAccount<'mnemonic'> {\n const hd = mnemonicToHDKey(mnemonic, options)\n // wasm-bindgen exports the snake_case name; it is not a typo.\n const privateKey = (PrivateKey as unknown as {\n from_seed_unchecked: (seed: Uint8Array) => InstanceType<SdkModule['PrivateKey']>\n }).from_seed_unchecked(hd.key).to_string()\n return { ...privateKeyToAccount(privateKey), source: 'mnemonic' }\n }\n\n function generateMnemonicAccount(options?: {\n strength?: 128 | 256\n index?: number\n derivation?: AleoDerivationId\n }): { mnemonic: string; account: LocalAccount<'mnemonic'> } {\n const mnemonic = generateMnemonic(options?.strength ?? 128)\n const { strength: _strength, ...derivationOptions } = options ?? {}\n return { mnemonic, account: mnemonicToAccount(mnemonic, derivationOptions) }\n }\n\n function generateAccount(): LocalAccount<'privateKey'> {\n const sdkAccount = new Account()\n return privateKeyToAccount(sdkAccount.privateKey().to_string())\n }\n\n function decryptRecord(viewKeyString: string, ciphertext: string): string {\n return ViewKey.from_string(viewKeyString).decrypt(ciphertext)\n }\n\n function verifySignature(\n addressString: string,\n message: Uint8Array,\n signatureString: string,\n ): boolean {\n const sig = Signature.from_string(signatureString)\n const addr = Address.from_string(addressString)\n return sig.verify(addr, message)\n }\n\n function createNetworkClient(url: string): InstanceType<SdkModule['AleoNetworkClient']> {\n return new AleoNetworkClient(url)\n }\n\n function createProvingConfig(options: {\n mode: 'delegated' | 'local'\n networkUrl: string\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n account?: LocalAccount<'privateKey'>\n /** Timeout in ms for waiting for transaction confirmation (default: 60_000 = 1 min) */\n confirmationTimeout?: number\n /**\n * The delegated prover pays the transaction fee from its FeeMaster\n * account instead of the caller's public credits. Only meaningful with\n * `mode: 'delegated'`; requires the prover service to allow it for the\n * consumer. Defaults to true — accounts need no public credits to\n * transact. Set false when the account funds its own fees.\n */\n useFeeMaster?: boolean\n /**\n * Provable API session to authenticate delegated proving with. When\n * present it is the only party minting JWTs — `apiKey` and `consumerId`\n * are withheld from the prover client so the SDK never mints in parallel.\n */\n session?: ProvableSession\n auth?: ProvableKeyedAuth\n }): ProvingConfigWithSession {\n assertKeyedAuthAlone(options.auth, {\n session: options.session,\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n })\n // Each call reads from currentSdk so switchNetwork can swap the binary set\n // without rebuilding the wallet client.\n let networkUrl = options.networkUrl\n let keyProvider = new currentSdk.AleoKeyProvider()\n keyProvider.useCache(true)\n options.session?.attach('proving')\n\n // Tracked per configuration rather than read from the handle: the handle's\n // `network` names the binaries it loaded, and confirmation polling has to\n // follow this client's current chain instead.\n let configNetwork: SupportedNetwork = network\n\n /**\n * Resolves the prover endpoint for the network in force.\n *\n * `proverUrl` is a base — the network segment is appended here, the same way\n * the record scanner's base URL works — so a client that switches chains\n * reaches the right prover without rebuilding. A base that already ends in a\n * network segment is accepted and re-targeted rather than doubled, so a\n * caller who passes the fully-qualified URL still switches correctly.\n */\n const resolveProverUrl = (): string | undefined => {\n // Delegated proving has one obvious endpoint, so it defaults rather than\n // failing on the first write. Local proving reaches no prover at all.\n const configured =\n options.proverUrl ?? (options.mode === 'delegated' ? DEFAULT_PROVER_URL : undefined)\n if (!configured) return undefined\n const base = configured.replace(/\\/+$/, '').replace(/\\/(mainnet|testnet)$/, '')\n return `${base}/${configNetwork}`\n }\n\n return {\n mode: options.mode,\n // A getter, not a snapshot: the network segment moves with `switchChain`,\n // and a fixed string here would report the network this config started on\n // long after it left.\n get url() {\n return resolveProverUrl()\n },\n // Carried for `authenticateProvableApi` to find on a client. Core never\n // reads binding-specific fields on a proving config — `url` and `apiKey`\n // already travel the same way.\n session: options.session,\n keyedAuth: options.auth,\n\n buildTransaction: async (txOptions: BuildTransactionOptions) => {\n const programManager = new currentSdk.ProgramManager(\n networkUrl,\n keyProvider,\n undefined,\n )\n\n if (options.account) {\n const sdkAccount = new currentSdk.Account({ privateKey: options.account.privateKey })\n programManager.setAccount(sdkAccount)\n }\n\n // The user-facing API takes dynamic-dispatch import names (`string[]`);\n // the SDK needs a name → source map covering BOTH the program's static\n // imports (declared in the `import` block) and the user's dynamic ones.\n // Auto-discover static imports first, then add the user-provided\n // dynamic ones on top. The SDK's ProgramImports values can be string\n // or Program; its return type is mirrored instead of reconstructed.\n type SdkProgramImports = Awaited<\n ReturnType<InstanceType<SdkModule['AleoNetworkClient']>['getProgramImports']>\n >\n let resolvedImports: SdkProgramImports | undefined\n if (txOptions.imports && txOptions.imports.length > 0) {\n const programSource = await programManager.networkClient.getProgram(txOptions.programName)\n const staticImports = await programManager.networkClient.getProgramImports(programSource)\n const merged: SdkProgramImports = { ...staticImports }\n for (const name of txOptions.imports) {\n merged[name] = await programManager.networkClient.getProgram(name)\n }\n resolvedImports = merged\n }\n\n const tx = await programManager.buildExecutionTransaction({\n programName: txOptions.programName,\n functionName: txOptions.functionName,\n priorityFee: 0,\n privateFee: txOptions.privateFee ?? false,\n inputs: txOptions.inputs,\n ...(resolvedImports ? { imports: resolvedImports } : {}),\n })\n\n return JSON.parse(tx.toString())\n },\n\n buildDeployment: async (deployOptions: BuildDeploymentOptions) => {\n const programManager = new currentSdk.ProgramManager(\n networkUrl,\n keyProvider,\n undefined,\n )\n\n if (options.account) {\n const sdkAccount = new currentSdk.Account({ privateKey: options.account.privateKey })\n programManager.setAccount(sdkAccount)\n }\n\n const tx = await programManager.buildDeploymentTransaction(\n deployOptions.program,\n 0,\n deployOptions.privateFee ?? false,\n )\n\n return JSON.parse(tx.toString())\n },\n\n simulate: async (simOptions: SimulateOptions): Promise<RawSimulateResult> => {\n const programManager = new currentSdk.ProgramManager(networkUrl, keyProvider, undefined)\n if (options.account) {\n programManager.setAccount(new currentSdk.Account({ privateKey: options.account.privateKey }))\n }\n\n // Self-custody decryptor: same view-key-based decryptor as the execute path.\n const accountViewKey = options.account ? ViewKey.from_string(options.account.viewKey) : undefined\n const decryptor: Decryptor | undefined = accountViewKey\n ? (ciphertext: string) => {\n const ct = RecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : null\n }\n : undefined\n\n // `buildAuthorization` runs the function (with cross-program calls) and produces an\n // Authorization whose transitions carry program/function metadata and the actual\n // outputs — same structure a confirmed Transaction has, minus the proof.\n const authorization = await programManager.buildAuthorization({\n programName: simOptions.programName,\n functionName: simOptions.functionName,\n inputs: simOptions.inputs,\n programSource: simOptions.programSource,\n programImports: simOptions.programImports,\n })\n\n // Convert the wasm Transition objects into the wire-shaped tx that extractTransitions\n // consumes. Private outputs come back from an Authorization as TVK-encrypted ciphertexts\n // (Aleo's on-chain privacy model); decrypt with the caller's TVK first so plaintext\n // values are visible. `transition.toString()` emits the same wire-format JSON the chain\n // returns from `/transaction/confirmed/{id}` — Aleo-typed string values like '10u32',\n // 'aleo1...', or 'record1...' under each output's `value`.\n const tx = {\n execution: {\n transitions: authorization.transitions().map((t: any) => {\n let source = t\n if (accountViewKey) {\n try {\n source = t.decryptTransition(t.tvk(accountViewKey))\n } catch {\n // Foreign transition signed by another caller — leave outputs encrypted.\n }\n }\n return JSON.parse(source.toString())\n }),\n },\n }\n\n const { transitions, outputs } = extractTransitions(tx, decryptor)\n return { transitions, outputs }\n },\n\n execute: async (execOptions: ExecuteOptions): Promise<RawExecuteResult> => {\n const programManager = new currentSdk.ProgramManager(networkUrl, keyProvider, undefined)\n if (options.account) {\n programManager.setAccount(new currentSdk.Account({ privateKey: options.account.privateKey }))\n }\n\n /** Convert microcredits (Veil API) to credits (SDK API) for priority fee */\n const priorityFee = Number(execOptions.fee) / 1_000_000\n\n /** Self-custody decryptor: use the local account's view key to decrypt owned record ciphertexts. */\n const accountViewKey = options.account ? ViewKey.from_string(options.account.viewKey) : undefined\n const decryptor: Decryptor | undefined = accountViewKey\n ? (ciphertext: string) => {\n const ct = RecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : null\n }\n : undefined\n\n /** Build a Veil publicClient bound to the current networkUrl for chain polling. */\n const buildPollingClient = () =>\n createPublicClient({ transport: http(networkUrl, { network: configNetwork as Network }) })\n\n if (options.mode === 'delegated') {\n const proverUrl = resolveProverUrl()\n if (!proverUrl) throw new ConfigurationError('Delegated execution requires proverUrl. Pass proverUrl to createProvingConfig or createAleoClient.')\n\n let response: any\n try {\n const provingRequest = await programManager.provingRequest({\n programName: execOptions.programName,\n programSource: execOptions.programSource,\n programImports: execOptions.programImports,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n priorityFee,\n privateFee: execOptions.privateFee ?? false,\n broadcast: true,\n useFeeMaster: options.useFeeMaster ?? true,\n })\n\n const dpsClient = new AleoNetworkClient(proverUrl)\n\n const auth = async (forceRefresh: boolean) => {\n if (options.auth) return { auth: options.auth }\n if (options.session) return { jwtData: await options.session.getJwt({ forceRefresh }) }\n return { apiKey: options.apiKey, consumerId: options.consumerId }\n }\n\n // The safe variant reports HTTP status instead of throwing, which is\n // what makes a rejected credential distinguishable from a proving\n // failure. Minting happens outside the submit so a mint failure\n // surfaces as itself rather than as a proving error.\n let credentials = await auth(false)\n let result = await dpsClient.submitProvingRequestSafe({\n provingRequest,\n url: proverUrl,\n ...credentials,\n })\n // A freshly minted JWT can reach a prover that has not yet synced\n // the credential, so one replacement attempt is worth making.\n if (!result.ok && (result.status === 401 || result.status === 403) && options.session) {\n credentials = await auth(true)\n result = await dpsClient.submitProvingRequestSafe({\n provingRequest,\n url: proverUrl,\n ...credentials,\n })\n }\n if (!result.ok) {\n throw new ProvingError({\n message: `Delegated proving failed (HTTP ${result.status}): ${result.error?.message ?? 'unknown error'}`,\n statusCode: result.status,\n })\n }\n response = result.data\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw classifyProvingError(e)\n }\n\n const txId = response.transaction?.id\n if (!txId) throw new ConfigurationError('DPS response did not contain a transaction ID — check prover service configuration.')\n\n const confirmedTx = await waitForConfirmation(buildPollingClient(), txId, options.confirmationTimeout)\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n\n } else {\n let tx: any\n try {\n tx = await programManager.buildExecutionTransaction({\n programName: execOptions.programName,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n priorityFee,\n privateFee: execOptions.privateFee ?? false,\n program: execOptions.programSource,\n imports: execOptions.programImports,\n })\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw new ProvingError({ message: e instanceof Error ? e.message : String(e), cause: e as Error })\n }\n\n let txId: string\n try {\n const submitClient = new AleoNetworkClient(networkUrl)\n submitClient.setVerboseErrors(false)\n txId = await submitClient.submitTransaction(tx)\n } catch (e) {\n if (e instanceof BaseError) throw e\n throw classifyBroadcastError(e)\n }\n\n const confirmedTx = await waitForConfirmation(buildPollingClient(), txId, options.confirmationTimeout)\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n }\n },\n\n decrypt: async (cipherText) => {\n if (!options.account?.viewKey) {\n throw new Error(\n 'decrypt requires an account with a viewKey on the proving config.',\n )\n }\n return currentSdk.ViewKey.from_string(options.account.viewKey).decrypt(cipherText)\n },\n\n switchNetwork: async (newNetwork) => {\n if (newNetwork !== 'mainnet' && newNetwork !== 'testnet') {\n throw new Error(\n `loadNetwork supports 'mainnet' or 'testnet' (received '${newNetwork}').`,\n )\n }\n currentSdk = (await loadSdk(newNetwork as SupportedNetwork)) as SdkModule\n silenceSdkLogs(currentSdk)\n keyProvider = new currentSdk.AleoKeyProvider()\n keyProvider.useCache(true)\n // Confirmation polling and the prover endpoint both read this, so it\n // must move with the switch or a delegated client proves and polls the\n // chain it just left.\n configNetwork = newNetwork as SupportedNetwork\n },\n }\n }\n\n // The RSS returns record fields in snake_case (record_plaintext,\n // program_name, …); the veil OwnedRecord contract is camelCase. Map them —\n // a bare cast silently leaves recordPlaintext undefined, which reads as an\n // unspendable wallet. Fields whose two casings coincide are read directly;\n // the rest accept either case so a future camelCase SDK build keeps working.\n // `uid` and `recordView` are privacy-wallet-adapter concepts the RSS does\n // not supply, so they are intentionally omitted.\n function toOwnedRecord(raw: Record<string, unknown>): OwnedRecord {\n const pick = (snake: string, camel: string): unknown => raw[snake] ?? raw[camel]\n return {\n blockHeight: pick('block_height', 'blockHeight') as number | undefined,\n blockTimestamp: pick('block_timestamp', 'blockTimestamp') as number | undefined,\n commitment: raw.commitment as string | undefined,\n functionName: pick('function_name', 'functionName') as string | undefined,\n outputIndex: pick('output_index', 'outputIndex') as number | undefined,\n owner: raw.owner as string | undefined,\n programName: pick('program_name', 'programName') as string,\n recordCiphertext: pick('record_ciphertext', 'recordCiphertext') as string | undefined,\n recordName: pick('record_name', 'recordName') as string | undefined,\n sender: raw.sender as string | undefined,\n spent: raw.spent as boolean | undefined,\n tag: raw.tag as string,\n transactionId: pick('transaction_id', 'transactionId') as string | undefined,\n transitionId: pick('transition_id', 'transitionId') as string | undefined,\n transactionIndex: pick('transaction_index', 'transactionIndex') as number | undefined,\n transitionIndex: pick('transition_index', 'transitionIndex') as number | undefined,\n recordPlaintext: (pick('record_plaintext', 'recordPlaintext') as string | undefined) ?? '',\n }\n }\n\n // A scanner's UUID is issued at registration; owned() rejects locally\n // without one. Register once, lazily, and memoize the in-flight promise so\n // concurrent scans share a single round-trip. Account or network changes\n // replace the whole object (one registration per scanner build).\n function makeRegisterOnce(startBlock: number) {\n let registration: Promise<void> | undefined\n return {\n ensure(\n scanner: InstanceType<SdkModule['RecordScanner']>,\n viewKey: ReturnType<SdkModule['ViewKey']['from_string']>,\n ): Promise<void> {\n if (!registration) {\n registration = (async () => {\n const result = await scanner.registerEncrypted(viewKey, startBlock)\n if (!result.ok) {\n registration = undefined // allow a later retry after a transient failure\n throw new Error(\n `Record scanner registration failed (HTTP ${result.status}): ${result.error?.message ?? 'unknown error'}`,\n )\n }\n })()\n }\n return registration\n },\n }\n }\n\n // Scans owned records with bounded retry. owned() returns a discriminated\n // result on HTTP error but *throws* on a network failure or an invalidated\n // UUID — both paths are retried here. A freshly-minted JWT can momentarily\n // hit an RSS backend that has not yet synced the credential (HTTP 401), and\n // the SDK caches that JWT for the scanner's lifetime — so between attempts it\n // is dropped (setJwtData(undefined) forces a re-mint), backed off, and retried,\n // giving the backend time to catch up. A non-transient status surfaces at once.\n //\n // 429/5xx are always transient; a 401/403 is only worth retrying when a JWT\n // can actually be re-minted (apiKey configured) — on an unauthenticated\n // scanner those are permanent, so retrying just burns backoff.\n /**\n * Rejects provisioned-key auth combined with any consumer-lifecycle option.\n *\n * The two models are disjoint: a handed-out key registers nothing, persists\n * nothing, and mints nothing, so a consumer option beside it means the\n * caller misunderstands which gateway they target. Names the options\n * actually passed, and throws before any work is done.\n *\n * @param auth The keyed auth option, when given.\n * @param conflicts Consumer-lifecycle options by name; truthy values conflict.\n * @throws ConfigurationError when `auth` is combined with any truthy conflict.\n */\n function assertKeyedAuthAlone(\n auth: ProvableKeyedAuth | undefined,\n conflicts: Record<string, unknown>,\n ): void {\n if (!auth) return\n const named = Object.keys(conflicts).filter((key) => conflicts[key])\n if (named.length) {\n throw new ConfigurationError(\n `Provisioned-key auth is mutually exclusive with ${named.join(', ')} — edge API keys are handed out, not registered.`,\n )\n }\n }\n\n async function scanOwned(\n scanner: InstanceType<SdkModule['RecordScanner']>,\n params: RequestRecordsParameters,\n hasCredentials: boolean,\n session?: ProvableSession,\n ): Promise<OwnedRecord[]> {\n // Built once: the body is identical across retries, and rebuilding it per\n // attempt would let a mutation by owned() (which stamps `uuid` onto the\n // object it is given) go unnoticed.\n const ownedFilter = buildOwnedFilter(params)\n const ALWAYS_RETRY = new Set([429, 500, 502, 503, 504])\n const AUTH_RETRY = new Set([401, 403])\n // A JWT can be replaced when the SDK holds a complete pair to re-mint from,\n // or when a session owns minting on the scanner's behalf. `hasCredentials`\n // is the pair, not just the key — half of it mints nothing, so treating a\n // 401 as retryable would only burn backoff.\n const canReMint = hasCredentials || !!session\n const retryable = (status: number) => ALWAYS_RETRY.has(status) || (canReMint && AUTH_RETRY.has(status))\n const MAX_ATTEMPTS = 4\n let last = ''\n let lastStatus: number | undefined\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n try {\n const result = await scanner.owned(ownedFilter)\n if (result.ok) return (result.data ?? []).map((r) => toOwnedRecord(r as Record<string, unknown>))\n last = `HTTP ${result.status}: ${result.error?.message ?? 'unknown error'}`\n lastStatus = result.status\n if (!retryable(result.status)) break\n } catch (err) {\n // owned() throws (rather than returning a result) on a network failure\n // or an invalidated UUID — treat as transient and retry.\n last = err instanceof Error ? err.message : String(err)\n lastStatus = undefined\n }\n if (attempt === MAX_ATTEMPTS - 1) break\n // Replace the token only when it was the thing rejected. A 429 or 5xx says\n // nothing about the credential, and re-minting on those costs a round-trip\n // and swaps the token the proving path shares.\n if (lastStatus !== undefined && AUTH_RETRY.has(lastStatus)) {\n if (session) scanner.setJwtData(await session.getJwt({ forceRefresh: true }))\n else scanner.setJwtData(undefined)\n }\n await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** attempt))\n }\n throw new Error(`Record scan failed (${last})`)\n }\n\n function createRemoteScanner(options: {\n url?: string\n consumerId?: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n auth?: ProvableKeyedAuth\n } = {}): RecordProvider & {\n setSession: (session: ProvableSession) => void\n setAuth: (auth: ProvableKeyedAuth) => void\n } {\n assertKeyedAuthAlone(options.auth, {\n session: options.session,\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n })\n // A JWT is minted from the pair, so half of it authenticates nothing: the\n // consumer id is the path segment and the key the header. Without a session\n // to supply tokens instead, an incomplete pair would send unauthenticated\n // requests and 401 — fail here rather than four retries later.\n if (!options.session && options.apiKey && !options.consumerId) {\n throw new ConfigurationError(\n 'Record scanning with an apiKey also needs consumerId — a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service.',\n )\n }\n // The RecordScanner class is network-bound: a scanner built from a given\n // SDK module scans that module's network. Network switching rebuilds the\n // scanner (and the wasm view key) from the target network's module.\n let scannerSdk: Pick<SdkModule, 'RecordScanner' | 'ViewKey'> = { RecordScanner, ViewKey }\n let scanner: InstanceType<SdkModule['RecordScanner']> | undefined\n let viewKey: ReturnType<SdkModule['ViewKey']['from_string']> | undefined\n let viewKeyString: string | undefined\n let registration = makeRegisterOnce(options.startBlock ?? 0)\n // One slot for the credential source: a JWT session or a provisioned key,\n // never both. The discriminant is the keyed variant's `mode` field.\n let credential: ProvableSession | ProvableKeyedAuth | undefined = options.auth ?? options.session\n const sessionOf = (source: typeof credential): ProvableSession | undefined =>\n source && !('mode' in source) ? source : undefined\n sessionOf(credential)?.attach('recordScanning')\n const url = options.url ?? DEFAULT_SCANNER_URL\n\n function buildScanner() {\n if (!viewKeyString) return // no active account yet — nothing to rebuild\n viewKey = scannerSdk.ViewKey.from_string(viewKeyString)\n // Keyed auth rides in the scanner itself — there is no token to supply\n // per scan. Under a session the credentials stay out of the scanner so\n // only one party mints.\n const credentialProps =\n credential && 'mode' in credential\n ? { auth: credential }\n : credential\n ? {}\n : {\n ...(options.consumerId ? { consumerId: options.consumerId } : {}),\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n }\n scanner = new scannerSdk.RecordScanner({\n url,\n ...credentialProps,\n viewKeys: [viewKey],\n decryptEnabled: true,\n autoReRegister: true,\n })\n // Each build gets its own registration: view keys register per account\n // AND per network, and the old promise stays bound to the scanner a\n // concurrent scan may still hold.\n registration = makeRegisterOnce(options.startBlock ?? 0)\n }\n\n return {\n setAccount: (account: { viewKey: string }) => {\n viewKeyString = account.viewKey\n buildScanner()\n },\n\n /**\n * Shares a Provable API session with this scanner.\n *\n * Called by {@link createAleoClient} so one session covers proving and\n * scanning. Takes effect on the next scan — the token is applied at the\n * scan boundary, not at construction.\n */\n setSession: (next: ProvableSession) => {\n credential = next\n next.attach('recordScanning')\n // Rebuild so the scanner drops any credentials it was constructed with;\n // leaving them in place would let the SDK mint alongside the session.\n buildScanner()\n },\n\n /**\n * Shares provisioned-key auth with this scanner.\n *\n * Called by {@link createAleoClient} when the client uses the edge\n * gateway's keyed model. Replaces any session, since the two models are\n * mutually exclusive. Takes effect on the next scan.\n */\n setAuth: (next: ProvableKeyedAuth) => {\n credential = next\n // A live scanner swaps its auth in place, keeping the registration and\n // the parsed view key; a rebuild would force both to be redone.\n if (scanner) scanner.setAuth(next)\n else buildScanner()\n },\n\n requestRecords: async (params: RequestRecordsParameters): Promise<OwnedRecord[]> => {\n if (!scanner) {\n throw new Error('No active account set on record scanner. Call setAccount() first.')\n }\n\n // Pin this scan to the current build: a concurrent setAccount or\n // switchNetwork swaps the closures, and mixing builds mid-scan would\n // register one scanner and scan another.\n const activeScanner = scanner\n const activeViewKey = viewKey!\n const activeRegistration = registration\n // Pin the credential with the build: a concurrent setAuth or\n // setSession must not swap models mid-scan.\n const activeSession = sessionOf(credential)\n\n // Apply the token before registration, not just before the scan:\n // registering a view key is itself an authenticated call. Keyed auth\n // rides in the scanner, so there is no token to apply.\n if (activeSession) activeScanner.setJwtData(await activeSession.getJwt())\n await activeRegistration.ensure(activeScanner, activeViewKey)\n // Re-mint material reflects the live credential: a 401 on a\n // provisioned key is terminal, and retrying it would only burn backoff.\n const canReMint = !credential && !!(options.apiKey && options.consumerId)\n return scanOwned(activeScanner, params, canReMint, activeSession)\n },\n\n switchNetwork: async (newNetwork: string) => {\n if (newNetwork !== 'mainnet' && newNetwork !== 'testnet') {\n throw new Error(\n `Record scanning supports 'mainnet' or 'testnet' (received '${newNetwork}').`,\n )\n }\n scannerSdk = (await loadSdk(newNetwork as SupportedNetwork)) as SdkModule\n buildScanner()\n },\n }\n }\n\n function createStandaloneScanner(options: {\n url?: string\n consumerId?: string\n viewKey: string\n apiKey?: string\n session?: ProvableSession\n startBlock?: number\n auth?: ProvableKeyedAuth\n }): StandaloneRecordScanner {\n assertKeyedAuthAlone(options.auth, {\n session: options.session,\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n })\n // A JWT is minted from the pair, so half of it authenticates nothing: the\n // consumer id is the path segment and the key the header. Without a session\n // to supply tokens instead, an incomplete pair would send unauthenticated\n // requests and 401 — fail here rather than four retries later.\n if (!options.session && options.apiKey && !options.consumerId) {\n throw new ConfigurationError(\n 'Record scanning with an apiKey also needs consumerId — a JWT is minted from the pair. Pass both, pass a session, or omit both for an unauthenticated service.',\n )\n }\n const viewKey = ViewKey.from_string(options.viewKey)\n // Deliberately not attached: a standalone scanner is not pluggable into a\n // wallet client, so no client's `applied` report covers it.\n const session = options.session\n // Keyed auth rides in the scanner itself. Credentials only when no\n // session mints on this scanner's behalf.\n const credentialProps = options.auth\n ? { auth: options.auth }\n : session\n ? {}\n : {\n ...(options.consumerId ? { consumerId: options.consumerId } : {}),\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n }\n const scanner = new RecordScanner({\n url: options.url ?? DEFAULT_SCANNER_URL,\n ...credentialProps,\n viewKeys: [viewKey],\n decryptEnabled: true,\n autoReRegister: true,\n })\n const registration = makeRegisterOnce(options.startBlock ?? 0)\n\n return {\n requestRecords: async (params: RequestRecordsParameters): Promise<OwnedRecord[]> => {\n // Registration is authenticated too, so the token goes in first.\n if (session) scanner.setJwtData(await session.getJwt())\n await registration.ensure(scanner, viewKey)\n return scanOwned(scanner, params, !!(options.apiKey && options.consumerId), session)\n },\n }\n }\n\n function createAleoClient(options: {\n privateKey: string\n networkUrl: string\n provingMode?: 'delegated' | 'local'\n proverUrl?: string\n apiKey?: string\n consumerId?: string\n /** Forwarded to `createProvingConfig` — the delegated prover pays fees. Defaults to true. */\n useFeeMaster?: boolean\n confirmationTimeout?: number\n username?: string | (() => string)\n credentialStore?: ProvableCredentialStore\n session?: ProvableSession\n auth?: ProvableKeyedAuth\n records?: RecordProvider & {\n setSession?: (session: ProvableSession) => void\n setAuth?: (auth: ProvableKeyedAuth) => void\n }\n }): {\n publicClient: PublicClient\n walletClient: ProvableWalletClient\n account: LocalAccount<'privateKey'>\n } {\n assertKeyedAuthAlone(options.auth, {\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n username: options.username,\n credentialStore: options.credentialStore,\n session: options.session,\n })\n // A keyed client must be able to hand its key to the record provider; a\n // provider without setAuth would scan unauthenticated and 401 at runtime.\n if (options.auth && options.records && !options.records.setAuth) {\n throw new ConfigurationError(\n 'Provisioned-key auth needs a record provider with setAuth — pass a scanner from createRemoteScanner, or construct the provider with the key.',\n )\n }\n\n const account = privateKeyToAccount(options.privateKey)\n const transport = http(options.networkUrl, { network: network as Network })\n\n // One session for the whole client, so a single authenticateProvableApi()\n // covers proving and scanning. Keyed auth builds none: there is nothing to\n // register, persist, or mint.\n const credentials =\n options.consumerId && options.apiKey\n ? { consumerId: options.consumerId, apiKey: options.apiKey }\n : undefined\n // Whether the caller named a credential source. Without one the session\n // still exists — falling back to process-lifetime memory, so delegated\n // proving works out of the box — but it is not shared with the record\n // provider, since a scanner pointed at an open service needs no credential\n // and must not start registering one.\n const configured = !!(credentials || options.credentialStore || options.session)\n const session = options.auth\n ? undefined\n : options.session ??\n createProvableSession({\n credentials,\n store: options.credentialStore ?? memoryCredentialStore(),\n // Resolved lazily: only a registration needs it. The derived default\n // carries a random suffix because a username is spent once — an account\n // that lost its stored key must still be able to register, and the old\n // key is unrecoverable. A caller-supplied name is used verbatim, so a\n // collision fails rather than quietly registering something else.\n username:\n options.username ??\n (() => `veil-${account.address.slice(5, 13)}-${Math.random().toString(36).slice(2, 8)}`),\n })\n\n const proving = createProvingConfig({\n mode: options.provingMode ?? 'delegated',\n networkUrl: options.networkUrl,\n proverUrl: options.proverUrl,\n session,\n auth: options.auth,\n // Ignored by the proving config whenever a session is present, which is\n // where the one-minter rule is enforced.\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n account,\n ...(options.useFeeMaster !== undefined ? { useFeeMaster: options.useFeeMaster } : {}),\n ...(options.confirmationTimeout !== undefined\n ? { confirmationTimeout: options.confirmationTimeout }\n : {}),\n })\n\n const publicClient = createPublicClient({ transport })\n\n if (options.records) {\n // Credentials before account: sharing them rebuilds the scanner to drop\n // any credentials it was constructed with, and setAccount is what triggers\n // the one build that matters. Only shared when the caller named a\n // credential source — an unconfigured client must leave a scanner aimed at\n // an open service exactly as it was.\n if (options.auth) options.records.setAuth?.(options.auth)\n else if (configured && session) options.records.setSession?.(session)\n options.records.setAccount({ viewKey: account.viewKey })\n }\n\n const walletClient = createWalletClient({\n account,\n transport,\n proving,\n ...(options.records ? { recordProvider: options.records } : {}),\n }).extend(provableApiActions())\n\n return { publicClient, walletClient, account }\n }\n\n return {\n network,\n privateKeyToAccount,\n mnemonicToAccount,\n generateMnemonicAccount,\n generateAccount,\n decryptRecord,\n verifySignature,\n createNetworkClient,\n createProvingConfig,\n createRemoteScanner,\n createStandaloneScanner,\n createAleoClient,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Standalone exports — synchronous helpers and devnode client factory.\n// These use the statically-imported SDK (testnet binaries) so they work\n// without an awaited loadNetwork() call.\n// ---------------------------------------------------------------------------\n\n// Consensus version activation heights the WASM layer assumes when building\n// devnode transactions. MUST mirror the CONSENSUS_VERSION_HEIGHTS default that\n// @provablehq/veil-aleo-devnode passes to the aleo-devnode process, so the transaction builder\n// and the node agree on which consensus version is active at each height. The\n// entry count must also equal the WASM SDK's consensus-version count exactly —\n// a shorter list panics with an opaque `unreachable` inside the WASM. The WASM\n// (snarkVM 4.9.1) carries one more consensus version than aleo-devnode 0.2.4,\n// so the nineteenth entry activates at u32::MAX — a height no devnode reaches —\n// keeping both sides on identical rules everywhere they can actually run.\nconst DEVNODE_CONSENSUS_HEIGHTS = '0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,4294967295'\n\nfunction privateKeyToAccount(privateKey: string): LocalAccount<'privateKey'> {\n const sdkAccount = new Account({ privateKey })\n const address = sdkAccount.address().to_string()\n const viewKey = sdkAccount.viewKey().to_string()\n\n const signFn = async (message: Uint8Array): Promise<Uint8Array> => {\n const sig = sdkAccount.sign(message)\n return new TextEncoder().encode(sig.to_string())\n }\n\n return {\n type: 'local',\n source: 'privateKey',\n address,\n privateKey,\n viewKey,\n sign: signFn,\n signMessage: signFn,\n }\n}\n\n/** Creates a new random Aleo account (uses static SDK binaries). */\nexport function generateAccount(): LocalAccount<'privateKey'> {\n const sdkAccount = new Account()\n return privateKeyToAccount(sdkAccount.privateKey().to_string())\n}\n\n/**\n * Creates a fully-wired client pair pointing at a local Aleo Devnode instance.\n *\n * Devnode is a lightweight local Aleo node (similar to Foundry's Anvil) that\n * bypasses consensus and skips ZK proof generation, enabling rapid program iteration.\n * The seeded account is pre-funded; both key and socket address can be overridden.\n *\n * The returned wallet client supports `executeContract`. Its confirmation wait\n * resolves once the devnode includes the transaction in a block — automatic\n * after broadcast by default; under `manualBlockCreation` the caller must\n * advance blocks (e.g. a test client's `advanceBlock`) while the call is\n * pending. Record outputs owned by the client's account are decrypted to\n * plaintext in the result; foreign records are dropped.\n *\n * @example\n * ```ts\n * // Zero-config — uses seeded key and localhost:3030\n * const { publicClient, walletClient, account } = createDevnodeClient()\n *\n * // Custom key or socket address\n * const { publicClient, walletClient, account } = createDevnodeClient({\n * privateKey: 'APrivateKey1...',\n * socketAddr: '127.0.0.1:4040',\n * })\n * ```\n */\nexport function createDevnodeClient(options?: {\n privateKey?: string\n /** Socket address of the devnode, e.g. \"127.0.0.1:3030\" */\n socketAddr?: string\n}): { publicClient: PublicClient; walletClient: WalletClient; account: LocalAccount<'privateKey'> } {\n const url = `http://${options?.socketAddr ?? DEVNODE_ADDR}`\n const account = privateKeyToAccount(options?.privateKey ?? DEVNODE_PRIVATE_KEY)\n const sdkAccount = new Account({ privateKey: account.privateKey })\n const transport = http(url, { network: 'testnet' })\n\n const keyProvider = new AleoKeyProvider()\n keyProvider.useCache(true)\n\n // Initialize the wasm consensus heights before any wasm build or parse call\n // this client makes. Idempotent get-or-init: safe to call per client.\n getOrInitConsensusVersionTestHeights(DEVNODE_CONSENSUS_HEIGHTS)\n\n // Created before the proving config so `execute` can broadcast and poll\n // through the same transport-backed client the caller receives.\n const publicClient = createPublicClient({ transport })\n\n /**\n * Builds an unproven devnode execution transaction. `imports` must already\n * map program id → source; resolution of dynamic-dispatch import names\n * happens in `buildTransaction`, not here. Priority fees are always 0 on\n * the devnode path — a caller-supplied fee is ignored.\n */\n const buildExecutionTx = async (opts: {\n programName: string\n functionName: string\n inputs: string[]\n privateFee?: boolean | undefined\n imports?: Record<string, string> | undefined\n }) => {\n const programManager = new ProgramManager(url, keyProvider, undefined)\n programManager.setAccount(sdkAccount)\n return programManager.buildDevnodeExecutionTransaction({\n programName: opts.programName,\n functionName: opts.functionName,\n priorityFee: 0,\n privateFee: opts.privateFee ?? false,\n inputs: opts.inputs,\n ...(opts.imports ? { imports: opts.imports } : {}),\n })\n }\n\n const proving: ProvingConfig = {\n mode: 'devnode',\n buildDeployment: async (deployOptions: BuildDeploymentOptions) => {\n const programManager = new ProgramManager(url, keyProvider, undefined)\n programManager.setAccount(sdkAccount)\n const tx = await programManager.buildDevnodeDeploymentTransaction({\n program: deployOptions.program,\n priorityFee: 0,\n privateFee: deployOptions.privateFee ?? false,\n })\n return JSON.parse(tx.toString())\n },\n buildTransaction: async (txOptions: BuildTransactionOptions) => {\n // Fetch program sources for any call.dynamic targets the caller declared,\n // and recursively include their static imports as well.\n // Use direct REST calls instead of the SDK network client to avoid the\n // /latest_edition endpoint which returns 500 on the devnode.\n let imports: Record<string, string> | undefined\n if (txOptions.imports && txOptions.imports.length > 0) {\n const networkClient = new ProgramManager(url, keyProvider, undefined).networkClient\n imports = {}\n const queue = [...txOptions.imports]\n const seen = new Set<string>()\n while (queue.length > 0) {\n const name = queue.shift()!\n if (seen.has(name)) continue\n seen.add(name)\n const source = await networkClient.getProgram(name); // automatically throws.\n imports[name] = source;\n const importNames = Program.fromString(source).getImports(); // Invoke `wasm` to avoid regex.\n for (const dep of importNames) {\n if (dep && !seen.has(dep)) queue.push(dep)\n }\n }\n }\n\n const tx = await buildExecutionTx({\n programName: txOptions.programName,\n functionName: txOptions.functionName,\n inputs: txOptions.inputs,\n privateFee: txOptions.privateFee,\n imports,\n })\n return JSON.parse(tx.toString())\n },\n execute: async (execOptions: ExecuteOptions): Promise<RawExecuteResult> => {\n const tx = await buildExecutionTx({\n programName: execOptions.programName,\n functionName: execOptions.functionName,\n inputs: execOptions.inputs,\n privateFee: execOptions.privateFee,\n imports: execOptions.programImports,\n })\n\n // Broadcast through the same transport-backed request writeContract uses.\n const txId = (await publicClient.request({\n method: 'sendTransaction',\n params: { transaction: tx.toString() },\n })) as string\n\n // The devnode auto-produces a block after broadcast by default; under\n // manualBlockCreation the caller must advance blocks for this to resolve.\n const confirmedTx = await waitForConfirmation(publicClient, txId)\n\n // Self-custody decryptor: records owned by the devnode account surface\n // as plaintext; records owned by someone else (e.g. a compliance record\n // minted to an authority) pass through as ciphertext rather than being\n // dropped, so the outputs keep their transition positions — positional\n // consumers like the generated contract bindings depend on that.\n const accountViewKey = StaticViewKey.from_string(account.viewKey)\n const decryptor: Decryptor = (ciphertext: string) => {\n const ct = StaticRecordCiphertext.fromString(ciphertext)\n return ct.isOwner(accountViewKey) ? ct.decrypt(accountViewKey).toString() : ciphertext\n }\n const { transitions, outputs } = extractTransitions(confirmedTx, decryptor)\n return { transactionId: txId, transitions, outputs }\n },\n }\n\n const walletClient = createWalletClient({ account, transport, proving })\n\n return { publicClient, walletClient, account }\n}\n","// Record Scanning Service wire encoding.\n//\n// Internal to this package — deliberately absent from package.json `exports`, so\n// the request body shape stays an implementation detail rather than semver-bound\n// public API. Tests import it by path.\n\nimport type { OwnedFilter } from '@provablehq/sdk'\nimport {\n assertValidRecordFilter,\n resolveScanPrograms,\n type RequestRecordsParameters,\n} from '@provablehq/veil-core'\n\n// An empty list is no constraint. The service renders a present list as\n// `column = ANY($1)`, so sending `[]` would match nothing — the opposite of what\n// a caller narrowing by a list that came back empty means. Dropping it here\n// keeps the wire body in step with how the local path reads the same filter.\nfunction presentList(values?: string[]): string[] | undefined {\n return values && values.length > 0 ? values : undefined\n}\n\n/**\n * Builds the `/records/owned` request body for a record scan.\n *\n * Translates Veil's camelCase {@link RequestRecordsParameters} into the field\n * names the Record Scanning Service deserializes — `resultsPerPage` becomes\n * `results_per_page`, which is why this cannot be a pass-through. The SDK's\n * `owned()` JSON-stringifies the object verbatim, so what is built here is what\n * the service receives. Pure and local.\n *\n * `unspent` is tri-state by presence rather than by value: the service turns\n * `unspent: true` into `spent = false` and `unspent: false` into `spent = true`,\n * so `'all'` MUST omit the key entirely. Sending `true` for it would return\n * unspent records only.\n *\n * The column mask the service reads (a top-level `response_filter`) is\n * deliberately absent. `filter.response` is ignored by the owned endpoint, and a\n * mask omitting `record_ciphertext` would leave every record undecryptable — see\n * `RecordFilter`'s docs on `response`.\n *\n * The service clamps `results_per_page` to 1000 and defaults `page` to 0, so a\n * scan matching more records than one page holds returns a page rather than\n * failing. This is the backend limit that Veil's `DEFAULT_RECORD_PAGE_SIZE`\n * matches.\n *\n * @param params Program, spent-status filter, and row filter for the scan.\n * @returns The request body, carrying only the keys the parameters set.\n *\n * @example\n * buildOwnedFilter({ program: 'credits.aleo', statusFilter: 'unspent' })\n * // { unspent: true, filter: { programs: ['credits.aleo'] } }\n */\nexport function buildOwnedFilter(params: RequestRecordsParameters): OwnedFilter {\n const filter = params.filter\n assertValidRecordFilter(filter)\n\n // One entry per wire field, one omission rule. Naming each field once keeps a\n // copy-paste from silently pairing the wrong source and target.\n const wireFilter = Object.fromEntries(\n Object.entries({\n programs: resolveScanPrograms(params),\n records: presentList(filter?.records),\n functions: presentList(filter?.functions),\n commitments: presentList(filter?.commitments),\n start: filter?.start,\n end: filter?.end,\n results_per_page: filter?.resultsPerPage,\n page: filter?.page,\n }).filter(([, value]) => value !== undefined),\n )\n\n const body: OwnedFilter = {}\n // Omitted for 'all' and for an unset status, which both mean no spent clause.\n if (params.statusFilter === 'unspent') body.unspent = true\n else if (params.statusFilter === 'spent') body.unspent = false\n // An empty filter object narrows nothing; leave it off so the body stays the\n // minimal expression of the request.\n if (Object.keys(wireFilter).length > 0) body.filter = wireFilter\n return body\n}\n","import { hmac } from '@noble/hashes/hmac'\nimport { sha512 } from '@noble/hashes/sha512'\nimport * as bip39 from '@scure/bip39'\nimport { wordlist } from '@scure/bip39/wordlists/english'\n\nconst HARDENED_OFFSET = 0x80000000\n\n// Aleo-specific HMAC key for HD master derivation (parallel to BIP32's\n// \"Bitcoin seed\", but for BLS12-377). Matches shield-core.\nconst BLS12_377_CURVE = 'bls12_377 seed'\n\nconst PATH_REGEX = /^m(\\/[0-9]+')+$/\n\n/**\n * Names the derivation-path convention used to turn a seed into Aleo keys.\n *\n * `'standard'` uses the SLIP-0044-registered Aleo coin type (`m/44'/683'`);\n * `'legacy'` uses the pre-registration path (`m/44'/0'`) some older wallets\n * chose. Pick `'legacy'` only to recover accounts created by such a wallet.\n */\nexport type AleoDerivationId = 'standard' | 'legacy'\n\n/** SLIP-0044 registered Aleo coin type. */\nexport const STANDARD_PATH = \"m/44'/683'\"\n\n/** Pre-SLIP-0044-registration derivation path. Some older wallets used this. */\nexport const LEGACY_PATH = \"m/44'/0'\"\n\n/** Maps each {@link AleoDerivationId} to its account-level derivation path. */\nexport const DERIVATION_PATHS: Record<AleoDerivationId, string> = {\n standard: STANDARD_PATH,\n legacy: LEGACY_PATH,\n}\n\ninterface IKeys {\n key: Uint8Array\n chainCode: Uint8Array\n}\n\nfunction uint32BE(n: number): Uint8Array {\n if (!Number.isInteger(n) || n < 0 || n > 0xffffffff) {\n throw new Error(`uint32BE: value out of range (got ${n})`)\n }\n const out = new Uint8Array(4)\n new DataView(out.buffer).setUint32(0, n, false)\n return out\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0)\n const out = new Uint8Array(total)\n let offset = 0\n for (const p of parts) {\n out.set(p, offset)\n offset += p.length\n }\n return out\n}\n\nfunction ckdPriv({ key, chainCode }: IKeys, index: number): IKeys {\n const data = concatBytes(new Uint8Array([0]), key, uint32BE(index))\n const I = hmac(sha512, chainCode, data)\n return { key: I.slice(0, 32), chainCode: I.slice(32) }\n}\n\nfunction getMasterKeyFromSeed(seed: Uint8Array): IKeys {\n const I = hmac(sha512, BLS12_377_CURVE, seed)\n return { key: I.slice(0, 32), chainCode: I.slice(32) }\n}\n\nfunction isValidPath(path: string): boolean {\n if (!PATH_REGEX.test(path)) return false\n return path\n .split('/')\n .slice(1)\n .map((s) => s.replace(\"'\", ''))\n .every((s) => Number.isFinite(Number(s)))\n}\n\n/**\n * Hierarchical-deterministic key node for the BLS12-377 curve Aleo uses.\n *\n * Follows the SLIP-0010 construction (HMAC-SHA512 chains, hardened-only\n * derivation) with an Aleo-specific master key tag, matching shield-core.\n * All operations are pure and local — nothing touches the network. Start\n * from {@link BLS12377HDKey.fromMasterSeed} (or {@link mnemonicToHDKey})\n * rather than the constructor; the 32-byte `key` of a derived node is the\n * seed for an Aleo private key.\n */\nexport class BLS12377HDKey {\n /**\n * Wraps raw node material. Callers normally use\n * {@link BLS12377HDKey.fromMasterSeed} instead of constructing directly.\n *\n * @param key 32-byte private key material of this node.\n * @param chainCode 32-byte chain code used to derive children.\n */\n constructor(\n public readonly key: Uint8Array,\n public readonly chainCode: Uint8Array,\n ) {}\n\n /**\n * Derives the master node from a BIP-39 seed. Pure and local.\n *\n * @param seed Seed bytes, typically the 64-byte output of\n * {@link mnemonicToSeed}.\n * @returns The root node from which paths are derived.\n */\n static fromMasterSeed(seed: Uint8Array): BLS12377HDKey {\n const master = getMasterKeyFromSeed(seed)\n return new BLS12377HDKey(master.key, master.chainCode)\n }\n\n /**\n * Derives the descendant node at a hardened path. Pure and local.\n *\n * @param path Path of the form `m/44'/683'` — every segment MUST be\n * hardened (trailing `'`) and below 2^31.\n * @returns A new node; this node is unchanged.\n * @throws If the path is malformed, contains a non-hardened segment, or a\n * segment is out of range.\n */\n derive(path: string): BLS12377HDKey {\n if (!isValidPath(path)) {\n throw new Error(\n `Invalid derivation path: ${path} (must match m/N'/N'/... — hardened only)`,\n )\n }\n const segments = path\n .split('/')\n .slice(1)\n .map((s) => parseInt(s.replace(\"'\", ''), 10))\n\n for (const seg of segments) {\n if (seg >= HARDENED_OFFSET) {\n throw new Error(\n `Derivation path segment out of range: ${seg} (must be < 2³¹)`,\n )\n }\n }\n\n const result = segments.reduce(\n (acc, segment) => ckdPriv(acc, segment + HARDENED_OFFSET),\n { key: this.key, chainCode: this.chainCode } as IKeys,\n )\n return new BLS12377HDKey(result.key, result.chainCode)\n }\n\n /** Alias for {@link BLS12377HDKey.derive}, kept for HD-key API parity. */\n derivePath(path: string): BLS12377HDKey {\n return this.derive(path)\n }\n\n /**\n * Derives the account node at `m/{index}'/0'` relative to this node. Pure\n * and local. Applied to a {@link DERIVATION_PATHS} node, this yields the\n * account at that index.\n *\n * @param index Zero-based account index, below 2^31; hardening is applied\n * internally.\n * @returns The account-level node.\n * @throws If the index is negative, fractional, or 2^31 or greater.\n */\n deriveChild(index: number): BLS12377HDKey {\n if (!Number.isInteger(index) || index < 0 || index >= HARDENED_OFFSET) {\n throw new Error(\n `Invalid child index: ${index} (must be integer in [0, 2³¹))`,\n )\n }\n return this.derive(`m/${index}'/0'`)\n }\n}\n\n/**\n * Generates a fresh BIP-39 mnemonic from the English wordlist.\n *\n * Draws entropy from the platform CSPRNG; no network access. The phrase is\n * the root secret for every account derived from it — the caller MUST store\n * it securely and never log it.\n *\n * @param strength Entropy in bits: 128 yields 12 words, 256 yields 24.\n * Defaults to 128.\n * @returns A space-separated mnemonic phrase.\n *\n * @example\n * import { generateMnemonic, mnemonicToHDKey } from '@provablehq/veil-aleo-sdk'\n *\n * const mnemonic = generateMnemonic()\n * const account0 = mnemonicToHDKey(mnemonic)\n */\nexport function generateMnemonic(strength: 128 | 256 = 128): string {\n return bip39.generateMnemonic(wordlist, strength)\n}\n\n/**\n * Checks a full mnemonic phrase against BIP-39: English wordlist membership,\n * word count, and checksum. Pure and local.\n *\n * @param mnemonic Space-separated candidate phrase.\n * @returns True only if the phrase can be used for key derivation; a single\n * wrong or reordered word fails the checksum.\n */\nexport function validateMnemonic(mnemonic: string): boolean {\n return bip39.validateMnemonic(mnemonic, wordlist)\n}\n\n/**\n * Checks whether a single word belongs to the English BIP-39 wordlist. Pure\n * and local. Use for per-word feedback while a phrase is being typed;\n * validating the complete phrase still requires {@link validateMnemonic}.\n *\n * @param word Candidate word, lowercase.\n * @returns True if the word is one of the 2048 list entries.\n */\nexport function validateWord(word: string): boolean {\n return wordlist.includes(word)\n}\n\n/**\n * Converts a mnemonic to its 64-byte BIP-39 seed via PBKDF2-HMAC-SHA512 with\n * an empty passphrase. Pure, local, and deterministic.\n *\n * The mnemonic is not validated here — call {@link validateMnemonic} first;\n * an invalid phrase still produces a seed, only for the wrong accounts.\n *\n * @param mnemonic Space-separated BIP-39 phrase.\n * @returns Seed bytes for {@link BLS12377HDKey.fromMasterSeed}.\n */\nexport function mnemonicToSeed(mnemonic: string): Uint8Array {\n return bip39.mnemonicToSeedSync(mnemonic)\n}\n\n/**\n * Derives the Aleo account key at the given index from a mnemonic in one\n * step: seed, master node, derivation path, account child. Pure and local.\n * This is the usual entry point for turning a stored phrase into key\n * material.\n *\n * @param mnemonic Space-separated BIP-39 phrase.\n * @param options.index Zero-based account index, below 2^31. Defaults to 0.\n * @param options.derivation Path convention. Defaults to `'standard'`\n * (`m/44'/683'`); pass `'legacy'` to recover accounts from wallets that\n * predate the SLIP-0044 registration.\n * @returns The account node; its `key` bytes seed the Aleo private key.\n * @throws If the index is out of range.\n *\n * @example\n * import { mnemonicToHDKey } from '@provablehq/veil-aleo-sdk'\n *\n * const hdKey = mnemonicToHDKey(mnemonic, { index: 1 })\n */\nexport function mnemonicToHDKey(\n mnemonic: string,\n options: { index?: number; derivation?: AleoDerivationId } = {},\n): BLS12377HDKey {\n const { index = 0, derivation = 'standard' } = options\n const seed = mnemonicToSeed(mnemonic)\n return BLS12377HDKey.fromMasterSeed(seed)\n .derivePath(DERIVATION_PATHS[derivation])\n .deriveChild(index)\n}\n","import type {\n Client,\n ProvingConfig,\n RecordProvider,\n WalletActions,\n} from '@provablehq/veil-core'\nimport type { ApiAuthConfig } from '@provablehq/sdk'\n\n/** Root of the hosted Provable API. Consumer and JWT endpoints sit here, not under the versioned path. */\nconst DEFAULT_PROVABLE_API_URL = 'https://api.provable.com'\n\n/**\n * Margin treated as expired ahead of a JWT's stated expiry.\n *\n * Matches the margin the Provable SDK applies internally, so both sides agree\n * on when a token is still usable.\n */\nconst EXPIRY_SKEW_MS = 5 * 60 * 1000\n\n/**\n * Credentials issued by the Provable API for a registered consumer.\n *\n * Authenticate delegated proving and the hosted Record Scanner Service. The\n * pair is minted by {@link registerProvableApi} and exchanged for short-lived\n * JWTs.\n *\n * @property consumerId Consumer id. Forms the path segment when minting JWTs.\n * @property apiKey API key. Returned once at registration and unrecoverable\n * afterward, so a caller MUST persist it.\n */\nexport type ProvableApiCredentials = {\n consumerId: string\n apiKey: string\n}\n\n/**\n * Persists Provable API credentials between runs.\n *\n * Implemented by the caller — a file, a keychain, `localStorage`, or a secret\n * manager are all valid, and the choice belongs to the runtime rather than to\n * the SDK. A session reads through `load` on first use and writes through\n * `save` exactly once, immediately after registering a new consumer.\n *\n * @property load Reads stored credentials. Returning `undefined` means no\n * consumer is registered yet and triggers registration.\n * @property save Writes credentials. The API key is unrecoverable if this\n * write is lost, so a failure here should propagate rather than be swallowed.\n *\n * @example\n * const store: ProvableCredentialStore = {\n * load: async () => JSON.parse(await readFile(path, 'utf8')).provableApi,\n * save: async (c) => writeFile(path, JSON.stringify({ provableApi: c }), { mode: 0o600 }),\n * }\n */\nexport type ProvableCredentialStore = {\n load: () => Promise<ProvableApiCredentials | undefined> | ProvableApiCredentials | undefined\n save: (credentials: ProvableApiCredentials) => Promise<void> | void\n}\n\n/**\n * Builds a credential store that keeps credentials for the life of the process.\n *\n * The default when a client is given no credentials and no store, and the right\n * choice for tests and short-lived workers. Suited to any runtime, since it\n * touches no storage.\n *\n * A consumer registered into this store is lost when the process exits, and its\n * API key is issued once — so a process that registers here and runs again\n * registers a second consumer that nobody can reclaim. Anything longer-lived\n * than a single run belongs in a persistent store: `fileCredentialStore` from\n * `@provablehq/veil-aleo-sdk/node`, or a caller-supplied\n * {@link ProvableCredentialStore}.\n *\n * @param initial Optional credentials to start with, so a caller can seed the\n * store from an environment variable and skip registration.\n * @returns A store backed by a closure variable.\n *\n * @example\n * const store = memoryCredentialStore()\n * // or seeded, in which case nothing registers:\n * const seeded = memoryCredentialStore({ consumerId, apiKey })\n */\nexport function memoryCredentialStore(\n initial?: ProvableApiCredentials,\n): ProvableCredentialStore {\n let held = initial\n return {\n load: () => held,\n save: (credentials) => {\n held = credentials\n },\n }\n}\n\n/**\n * Provisioned-key authentication for the edge Provable API gateway.\n *\n * The keyed variant of the Provable SDK's `ApiAuthConfig`, derived rather\n * than restated so the two cannot drift — values of this type pass straight\n * into the SDK's `RecordScanner` and delegated proving as their `auth`\n * option, where the SDK applies the header default (`DEFAULT_API_KEY_HEADER`).\n *\n * The edge gateway (`edge.provable.com`) runs a different auth model from\n * `api.provable.com`: there is no consumer registration and no JWT minting.\n * An operator hands out API keys, and every request carries the key verbatim\n * in a header. Nothing registers, persists, or refreshes, and a rejected\n * request (401) means the key is invalid or revoked — retrying cannot help,\n * and only the operator can issue a replacement.\n *\n * Mutually exclusive with the session options (`credentials`, `store`,\n * `username`, `session`): those describe the registered-consumer lifecycle,\n * which a provisioned key does not have. Combining them throws at\n * construction.\n *\n * @example\n * const auth: ProvableKeyedAuth = { mode: 'api-key', value: process.env.PROVABLE_API_KEY! }\n */\nexport type ProvableKeyedAuth = Extract<ApiAuthConfig, { mode: 'api-key' }>\n\n/**\n * A minted Provable API JWT and its expiry.\n *\n * Structurally identical to the Provable SDK's `JWTData` and\n * `RecordScannerJWTData`, so a value of this type passes directly as their\n * `jwtData` option.\n *\n * @property jwt The `Authorization` header value, verbatim as issued by the\n * API (Bearer-prefixed).\n * @property expiration Expiry as milliseconds since the Unix epoch.\n */\nexport type ProvableJwt = {\n jwt: string\n expiration: number\n}\n\n/**\n * The consumers a session has been wired into.\n *\n * Reported by {@link authenticateProvableApi} so a caller can tell which paths\n * one authentication call actually covers.\n *\n * @property proving Whether a proving configuration carries this session.\n * @property recordScanning Whether a record provider carries this session.\n */\nexport type ProvableSessionConsumers = {\n proving: boolean\n recordScanning: boolean\n}\n\n/**\n * A live Provable API session: consumer credentials plus a cached, refreshing JWT.\n *\n * Built by `createProvingConfig`, `createRemoteScanner`, and\n * `createAleoClient` from the credential options they are given — a caller\n * configures credentials and does not construct this directly. Sharing one\n * session across delegated proving and record scanning means a single minted\n * JWT and a single refresh policy for both.\n *\n * @property registeredConsumer Reports whether this session registered a new\n * consumer rather than loading an existing one. Only meaningful after\n * credentials have resolved.\n * @property getCredentials Resolves the credentials, registering on first use\n * when neither direct credentials nor a store supply them.\n * @property getJwt Returns a JWT valid for at least the expiry margin,\n * minting or refreshing as needed.\n * @property consumers Which consumers carry this session. Advisory reporting;\n * nothing reads it to make decisions. `recordScanning` is set where a record\n * provider is wired to a client, so sharing one session across several\n * clients under-reports rather than claiming a path a given client lacks.\n * @property attach Records that a consumer now carries this session. Called by\n * the factories during wiring.\n */\nexport type ProvableSession = {\n registeredConsumer: () => boolean\n getCredentials: (options?: { username?: string }) => Promise<ProvableApiCredentials>\n getJwt: (options?: { forceRefresh?: boolean }) => Promise<ProvableJwt>\n consumers: ProvableSessionConsumers\n attach: (consumer: keyof ProvableSessionConsumers) => void\n}\n\n/**\n * Options for {@link registerProvableApi}.\n *\n * @property username Handle for the consumer. Globally unique across the\n * Provable API, so a taken name fails the call.\n * @property baseUrl Optional Provable API root. Defaults to\n * `https://api.provable.com`. Applies when targeting a non-production\n * deployment.\n * @property transport Optional fetch-compatible transport for the request.\n * Defaults to the global `fetch`. Applies when a caller intercepts or\n * instruments HTTP — a proxy, a recorder, a test stub.\n */\nexport type RegisterProvableApiParameters = {\n username: string\n baseUrl?: string\n transport?: typeof fetch\n}\n\n/**\n * Options for {@link createProvableSession}.\n *\n * @property credentials Optional credentials to use directly. Take precedence\n * over `store`, so an operator can inject a rotated or CI-provided pair\n * without clearing persisted state first.\n * @property store Optional persistence for credentials across runs. Omit for a\n * consumer that lives only as long as the process.\n * @property username Optional handle to register under when neither\n * `credentials` nor `store` yields a pair. A function is called lazily, so a\n * caller can derive the name from an account address that is not known at\n * configuration time. Required only if registration may happen.\n * @property baseUrl Optional Provable API root. Defaults to\n * `https://api.provable.com`.\n * @property transport Optional fetch-compatible transport used for\n * registration and JWT minting. Defaults to the global `fetch`. Applies\n * when a caller intercepts or instruments HTTP — a proxy, a recorder, a\n * test stub.\n */\nexport type CreateProvableSessionOptions = {\n credentials?: ProvableApiCredentials\n store?: ProvableCredentialStore\n username?: string | (() => string)\n baseUrl?: string\n transport?: typeof fetch\n}\n\n/**\n * Options for {@link authenticateProvableApi}.\n *\n * @property username Optional handle to register under when the client's\n * configuration yields no credentials. Overrides the name configured on the\n * session.\n * @property forceRefresh Mint a fresh JWT even when the cached one is still\n * valid. Defaults to false. Applies when recovering from a rejected token.\n */\nexport type AuthenticateProvableApiParameters = {\n username?: string\n forceRefresh?: boolean\n}\n\n/**\n * Result of {@link authenticateProvableApi}.\n *\n * @property credentials The resolved consumer credentials. Worth persisting\n * when `registered` is true — the API key is unrecoverable afterward.\n * @property expiration Expiry of the minted JWT, as milliseconds since the\n * Unix epoch.\n * @property registered Whether this call registered a new consumer rather than\n * loading an existing one.\n * @property applied Which paths the session reaches. `recordScanning` is false\n * when the client was given a record provider that cannot accept a session —\n * any implementation other than the ones this package builds — in which case\n * that provider keeps using the credentials it was constructed with.\n */\nexport type AuthenticateProvableApiReturnType = {\n credentials: ProvableApiCredentials\n expiration: number\n registered: boolean\n applied: ProvableSessionConsumers\n}\n\n/**\n * The Provable API authentication action, merged into a client by `extend`.\n *\n * @property authenticateProvableApi Resolves the client's Provable API session.\n */\nexport type ProvableApiActions = {\n authenticateProvableApi: (\n params?: AuthenticateProvableApiParameters,\n ) => Promise<AuthenticateProvableApiReturnType>\n}\n\n/**\n * A wallet client carrying the Provable API authentication action.\n *\n * Composed inside the client's action set rather than intersected onto\n * `WalletClient`, so a caller who extends further — adding DEX actions, for\n * example — keeps `authenticateProvableApi` in the resulting type. `extend`\n * carries forward only what sits in the action set, so an outer intersection\n * would be dropped on the next call.\n *\n * The wallet half is restated rather than derived. `Omit<WalletClient, keyof\n * Client>` reads better and was tried first, but `keyof Client` resolves to\n * `never` against core's built declarations — so the Omit keeps every base field,\n * violates the `Extended` constraint, and silently collapses to a type missing\n * every wallet action. It typechecks against core's source and fails only for\n * consumers, which is the worst place to find out.\n *\n * Keep this in step if core changes what a wallet client carries; a\n * `WalletClientActions` export from core would remove the duplication safely.\n */\nexport type ProvableWalletClient = Client<\n WalletActions & { recordProvider: RecordProvider | undefined } & ProvableApiActions\n>\n\n/**\n * A proving configuration carrying the Provable API session.\n *\n * `createProvingConfig` returns this shape. Core types `Client.proving` as the\n * bare {@link ProvingConfig} and never reads binding-specific fields — `url` and\n * `apiKey` already travel the same way — so the session rides along without a\n * core change, and {@link authenticateProvableApi} narrows to read it.\n *\n * @property session The session shared with record scanning, or `undefined`\n * when the client was configured without credentials.\n * @property keyedAuth The provisioned-key auth the client was configured\n * with, or `undefined` under the session model. Mutually exclusive with\n * `session`.\n */\nexport type ProvingConfigWithSession = ProvingConfig & {\n session?: ProvableSession | undefined\n keyedAuth?: ProvableKeyedAuth | undefined\n}\n\n/**\n * Registers a Provable API consumer and returns its credentials.\n *\n * Unauthenticated — this is the call that issues the credentials everything\n * else authenticates with. Hits the network.\n *\n * A username is spent once. It is globally unique, the API exposes no endpoint\n * that reads a consumer back, and a duplicate registration answers 409 with\n * nothing usable in it — so a taken name cannot be traded for the credentials it\n * belongs to, and the only remedy is the stored key or a different name.\n *\n * @param params Handle to register under, and optionally a non-default API root.\n * @returns The consumer id and API key. The key is shown only here, so the\n * caller MUST persist it.\n * @throws When the username is already registered, when registration returns any\n * other non-2xx status, or when the response body does not carry a consumer id\n * and key.\n *\n * @example\n * const credentials = await registerProvableApi({ username: 'my-bot-42' })\n * await writeFile('creds.json', JSON.stringify(credentials))\n */\nexport async function registerProvableApi(\n params: RegisterProvableApiParameters,\n): Promise<ProvableApiCredentials> {\n const baseUrl = params.baseUrl ?? DEFAULT_PROVABLE_API_URL\n const transport = params.transport ?? fetch\n const response = await transport(`${baseUrl}/consumers`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ username: params.username }),\n })\n if (!response.ok) {\n const body = await response.text()\n // A 409 is the one failure a caller can act on, and the obvious next move —\n // look the consumer up, or re-register to get the key again — does not\n // exist. Say so here rather than leaving them to discover it.\n if (response.status === 409) {\n throw new Error(\n `Provable API username '${params.username}' is already registered. Credentials cannot be ` +\n 'recovered from a username: supply the existing consumerId and apiKey, or register under ' +\n `a different name. (HTTP 409: ${body})`,\n )\n }\n throw new Error(\n `Provable API consumer registration failed (HTTP ${response.status}): ${body}`,\n )\n }\n const body = (await response.json()) as { consumer?: { id?: string }; key?: string }\n if (!body.consumer?.id || !body.key) {\n throw new Error('Provable API consumer registration response carried no consumer id and key.')\n }\n return { consumerId: body.consumer.id, apiKey: body.key }\n}\n\n/**\n * Mints a JWT for a registered consumer.\n *\n * The token arrives in the `Authorization` response header and its expiry in\n * the response body's `exp` claim, in seconds. Hits the network.\n *\n * @param credentials The consumer id and API key to authenticate the mint with.\n * @param baseUrl Provable API root.\n * @param transport Fetch-compatible transport for the request.\n * @returns The token and its expiry in milliseconds since the Unix epoch.\n * @throws When the mint returns a non-2xx status, or when the response omits\n * the authorization header or the expiry claim.\n */\nasync function mintJwt(\n credentials: ProvableApiCredentials,\n baseUrl: string,\n transport: typeof fetch,\n): Promise<ProvableJwt> {\n const response = await transport(`${baseUrl}/jwts/${encodeURIComponent(credentials.consumerId)}`, {\n method: 'POST',\n headers: { 'X-Provable-API-Key': credentials.apiKey },\n })\n if (!response.ok) {\n throw new Error(\n `Provable API JWT mint failed (HTTP ${response.status}): ${await response.text()}`,\n )\n }\n const header = response.headers.get('authorization')\n if (!header) {\n throw new Error('Provable API JWT mint response carried no authorization header.')\n }\n const body = (await response.json()) as { exp?: number }\n if (typeof body.exp !== 'number') {\n throw new Error('Provable API JWT mint response carried no exp claim.')\n }\n return { jwt: header, expiration: body.exp * 1000 }\n}\n\n/**\n * Builds a Provable API session that resolves credentials and refreshes its JWT.\n *\n * Credentials resolve on first use — supplied directly, else loaded from the\n * store, else registered and saved. Registration and minting are each\n * single-flighted, so a cold client that proves and scans concurrently\n * registers once and mints once. Pure and local until the first\n * `getCredentials` or `getJwt` call.\n *\n * @param options Credential source, optional persistence, and the name to\n * register under.\n * @returns A session for `createProvingConfig`, `createRemoteScanner`, and\n * `createAleoClient` to share.\n *\n * @example\n * const session = createProvableSession({ store, username: 'my-bot-42' })\n * const { jwt } = await session.getJwt()\n */\nexport function createProvableSession(options: CreateProvableSessionOptions = {}): ProvableSession {\n const baseUrl = options.baseUrl ?? DEFAULT_PROVABLE_API_URL\n const transport = options.transport ?? fetch\n const consumers: ProvableSessionConsumers = { proving: false, recordScanning: false }\n\n let credentials = options.credentials\n let registered = false\n let credentialsInFlight: Promise<ProvableApiCredentials> | undefined\n let jwt: ProvableJwt | undefined\n let jwtInFlight: Promise<ProvableJwt> | undefined\n\n async function resolveCredentials(usernameOverride?: string): Promise<ProvableApiCredentials> {\n if (credentials) return credentials\n const stored = await options.store?.load()\n if (stored) {\n credentials = stored\n return credentials\n }\n // Resolved only if it will be used: a configured function may be doing real\n // work, and the derived default has a random component.\n const username =\n usernameOverride ?? (typeof options.username === 'function' ? options.username() : options.username)\n if (!username) {\n throw new Error(\n 'No Provable API credentials available — pass credentials, a store holding them, or a username to register with.',\n )\n }\n const issued = await registerProvableApi({ username, baseUrl, transport })\n // Held before persisting, even though persisting is what makes them\n // durable. A username is spent once and the key is issued once, so if the\n // write fails the worst outcome is registering *again* on the next attempt\n // and burning another name. Holding them first makes that impossible, and\n // the throw below still tells the caller the key is not stored.\n credentials = issued\n registered = true\n try {\n await options.store?.save(issued)\n } catch (cause) {\n throw new Error(\n `Registered Provable API consumer ${issued.consumerId}, but persisting its credentials failed. ` +\n 'They are live for this process — read them from getCredentials() and store them yourself — but ' +\n 'the API key cannot be reissued, so a restart loses it.',\n { cause },\n )\n }\n return credentials\n }\n\n function getCredentials({ username }: { username?: string } = {}): Promise<ProvableApiCredentials> {\n // Collapse concurrent resolutions so a cold prove and scan register once.\n credentialsInFlight ??= resolveCredentials(username).finally(() => {\n credentialsInFlight = undefined\n })\n return credentialsInFlight\n }\n\n function getJwt({ forceRefresh = false }: { forceRefresh?: boolean } = {}): Promise<ProvableJwt> {\n const stale = !jwt || Date.now() >= jwt.expiration - EXPIRY_SKEW_MS\n if (!forceRefresh && !stale) return Promise.resolve(jwt!)\n // A forced refresh joins an in-flight mint rather than racing it, so a\n // burst of rejected calls still produces one replacement token.\n jwtInFlight ??= (async () => {\n const resolved = await getCredentials()\n jwt = await mintJwt(resolved, baseUrl, transport)\n return jwt\n })().finally(() => {\n jwtInFlight = undefined\n })\n return jwtInFlight\n }\n\n return {\n registeredConsumer: () => registered,\n getCredentials,\n getJwt,\n consumers,\n attach: (consumer) => {\n consumers[consumer] = true\n },\n }\n}\n\n/**\n * Reads the Provable API session off a client's proving configuration.\n *\n * `createProvingConfig` attaches the session to the configuration it returns.\n * Core types `proving` as the bare interface and never reads binding-specific\n * fields — `url` and `apiKey` are already carried the same way — so the narrow\n * is safe and stays local to this accessor.\n *\n * @param client The client to read from.\n * @returns The session, or `undefined` when the client has no proving\n * configuration or was configured without credentials.\n */\nfunction getProvableSession(client: Client): ProvableSession | undefined {\n return (client.proving as ProvingConfigWithSession | undefined)?.session\n}\n\n/**\n * Resolves the Provable API session backing delegated proving and record scanning.\n *\n * Registers a consumer when the client's configuration yields none, mints a\n * JWT, and leaves both on the session the client's proving configuration and\n * record provider already hold — so proving and scanning authenticate from then\n * on without further setup. Optional: the first prove or scan resolves the same\n * session lazily. Calling it explicitly front-loads registration, surfaces\n * credential failures before a transaction is built, and returns a newly issued\n * API key at the one moment it is recoverable.\n *\n * Hits the network: registration on first run, plus one JWT mint.\n *\n * @param client A client whose proving configuration carries Provable API\n * credentials or a credential store.\n * @param params Optional registration name and forced refresh.\n * @returns The credentials, the JWT expiry, whether a consumer was registered,\n * and which paths the session reaches.\n * @throws When the client has no Provable API session configured, or when\n * registration or minting fails.\n *\n * @example\n * const { credentials, registered } = await client.authenticateProvableApi()\n * if (registered) await store.save(credentials)\n */\nexport async function authenticateProvableApi(\n client: Client,\n params: AuthenticateProvableApiParameters = {},\n): Promise<AuthenticateProvableApiReturnType> {\n // Keyed auth has no lifecycle to resolve: no consumer to register, no JWT\n // to mint. Answering with fabricated credentials would hide that, so the\n // call refuses instead of pretending.\n if ((client.proving as ProvingConfigWithSession | undefined)?.keyedAuth) {\n throw new Error(\n 'This client authenticates with a provisioned API key — every request already carries it, and ' +\n 'there is no consumer or JWT to resolve. Remove the authenticateProvableApi call.',\n )\n }\n const session = getProvableSession(client)\n if (!session) {\n throw new Error(\n 'No Provable API session on this client — pass consumerId and apiKey, or a credentialStore, when creating it.',\n )\n }\n const credentials = await session.getCredentials({ username: params.username })\n const { expiration } = await session.getJwt({ forceRefresh: params.forceRefresh })\n return {\n credentials,\n expiration,\n registered: session.registeredConsumer(),\n applied: { ...session.consumers },\n }\n}\n\n/**\n * Builds the Provable API auth decorator for `client.extend()`.\n *\n * `createAleoClient` applies this already. Applies directly when composing a\n * client by hand from `createWalletClient` and a proving configuration built\n * with credentials.\n *\n * @returns A decorator: pass it to `client.extend(...)`.\n *\n * @example\n * const client = createWalletClient({ account, transport, proving })\n * .extend(provableApiActions())\n * await client.authenticateProvableApi()\n */\nexport function provableApiActions() {\n return (client: Client): ProvableApiActions => ({\n authenticateProvableApi: (params) => authenticateProvableApi(client, params),\n })\n}\n"],"mappings":"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","names":["generateMnemonic","validateMnemonic","body","Account","generateMnemonic","generateAccount"]}
|
package/dist/node.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as ProvableCredentialStore } from './provableApi-C4bT37jI.js';
|
|
2
2
|
import '@provablehq/veil-core';
|
|
3
|
+
import '@provablehq/sdk';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Builds a credential store backed by a JSON file.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ProvingConfig, Client, WalletActions, RecordProvider } from '@provablehq/veil-core';
|
|
2
|
+
import { ApiAuthConfig } from '@provablehq/sdk';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Credentials issued by the Provable API for a registered consumer.
|
|
@@ -62,6 +63,32 @@ type ProvableCredentialStore = {
|
|
|
62
63
|
* const seeded = memoryCredentialStore({ consumerId, apiKey })
|
|
63
64
|
*/
|
|
64
65
|
declare function memoryCredentialStore(initial?: ProvableApiCredentials): ProvableCredentialStore;
|
|
66
|
+
/**
|
|
67
|
+
* Provisioned-key authentication for the edge Provable API gateway.
|
|
68
|
+
*
|
|
69
|
+
* The keyed variant of the Provable SDK's `ApiAuthConfig`, derived rather
|
|
70
|
+
* than restated so the two cannot drift — values of this type pass straight
|
|
71
|
+
* into the SDK's `RecordScanner` and delegated proving as their `auth`
|
|
72
|
+
* option, where the SDK applies the header default (`DEFAULT_API_KEY_HEADER`).
|
|
73
|
+
*
|
|
74
|
+
* The edge gateway (`edge.provable.com`) runs a different auth model from
|
|
75
|
+
* `api.provable.com`: there is no consumer registration and no JWT minting.
|
|
76
|
+
* An operator hands out API keys, and every request carries the key verbatim
|
|
77
|
+
* in a header. Nothing registers, persists, or refreshes, and a rejected
|
|
78
|
+
* request (401) means the key is invalid or revoked — retrying cannot help,
|
|
79
|
+
* and only the operator can issue a replacement.
|
|
80
|
+
*
|
|
81
|
+
* Mutually exclusive with the session options (`credentials`, `store`,
|
|
82
|
+
* `username`, `session`): those describe the registered-consumer lifecycle,
|
|
83
|
+
* which a provisioned key does not have. Combining them throws at
|
|
84
|
+
* construction.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const auth: ProvableKeyedAuth = { mode: 'api-key', value: process.env.PROVABLE_API_KEY! }
|
|
88
|
+
*/
|
|
89
|
+
type ProvableKeyedAuth = Extract<ApiAuthConfig, {
|
|
90
|
+
mode: 'api-key';
|
|
91
|
+
}>;
|
|
65
92
|
/**
|
|
66
93
|
* A minted Provable API JWT and its expiry.
|
|
67
94
|
*
|
|
@@ -132,10 +159,14 @@ type ProvableSession = {
|
|
|
132
159
|
* @property baseUrl Optional Provable API root. Defaults to
|
|
133
160
|
* `https://api.provable.com`. Applies when targeting a non-production
|
|
134
161
|
* deployment.
|
|
162
|
+
* @property transport Optional fetch-compatible transport for the request.
|
|
163
|
+
* Defaults to the global `fetch`. Applies when a caller intercepts or
|
|
164
|
+
* instruments HTTP — a proxy, a recorder, a test stub.
|
|
135
165
|
*/
|
|
136
166
|
type RegisterProvableApiParameters = {
|
|
137
167
|
username: string;
|
|
138
168
|
baseUrl?: string;
|
|
169
|
+
transport?: typeof fetch;
|
|
139
170
|
};
|
|
140
171
|
/**
|
|
141
172
|
* Options for {@link createProvableSession}.
|
|
@@ -151,12 +182,17 @@ type RegisterProvableApiParameters = {
|
|
|
151
182
|
* configuration time. Required only if registration may happen.
|
|
152
183
|
* @property baseUrl Optional Provable API root. Defaults to
|
|
153
184
|
* `https://api.provable.com`.
|
|
185
|
+
* @property transport Optional fetch-compatible transport used for
|
|
186
|
+
* registration and JWT minting. Defaults to the global `fetch`. Applies
|
|
187
|
+
* when a caller intercepts or instruments HTTP — a proxy, a recorder, a
|
|
188
|
+
* test stub.
|
|
154
189
|
*/
|
|
155
190
|
type CreateProvableSessionOptions = {
|
|
156
191
|
credentials?: ProvableApiCredentials;
|
|
157
192
|
store?: ProvableCredentialStore;
|
|
158
193
|
username?: string | (() => string);
|
|
159
194
|
baseUrl?: string;
|
|
195
|
+
transport?: typeof fetch;
|
|
160
196
|
};
|
|
161
197
|
/**
|
|
162
198
|
* Options for {@link authenticateProvableApi}.
|
|
@@ -231,9 +267,13 @@ type ProvableWalletClient = Client<WalletActions & {
|
|
|
231
267
|
*
|
|
232
268
|
* @property session The session shared with record scanning, or `undefined`
|
|
233
269
|
* when the client was configured without credentials.
|
|
270
|
+
* @property keyedAuth The provisioned-key auth the client was configured
|
|
271
|
+
* with, or `undefined` under the session model. Mutually exclusive with
|
|
272
|
+
* `session`.
|
|
234
273
|
*/
|
|
235
274
|
type ProvingConfigWithSession = ProvingConfig & {
|
|
236
275
|
session?: ProvableSession | undefined;
|
|
276
|
+
keyedAuth?: ProvableKeyedAuth | undefined;
|
|
237
277
|
};
|
|
238
278
|
/**
|
|
239
279
|
* Registers a Provable API consumer and returns its credentials.
|
|
@@ -319,4 +359,4 @@ declare function authenticateProvableApi(client: Client, params?: AuthenticatePr
|
|
|
319
359
|
*/
|
|
320
360
|
declare function provableApiActions(): (client: Client) => ProvableApiActions;
|
|
321
361
|
|
|
322
|
-
export { type AuthenticateProvableApiParameters as A, type CreateProvableSessionOptions as C, type ProvableSession as P, type RegisterProvableApiParameters as R, type
|
|
362
|
+
export { type AuthenticateProvableApiParameters as A, type CreateProvableSessionOptions as C, type ProvableSession as P, type RegisterProvableApiParameters as R, type ProvableKeyedAuth as a, type ProvingConfigWithSession as b, type ProvableCredentialStore as c, type ProvableWalletClient as d, type AuthenticateProvableApiReturnType as e, type ProvableApiActions as f, type ProvableApiCredentials as g, type ProvableJwt as h, type ProvableSessionConsumers as i, authenticateProvableApi as j, createProvableSession as k, memoryCredentialStore as m, provableApiActions as p, registerProvableApi as r };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@provablehq/veil-aleo-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Local signing and proving for the Veil Aleo SDK, backed by the Provable SDK.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@noble/hashes": "^1.7.2",
|
|
41
|
-
"@provablehq/sdk": "^0.11.
|
|
41
|
+
"@provablehq/sdk": "^0.11.9",
|
|
42
42
|
"@scure/bip39": "^1.4.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@provablehq/veil-leo": "0.
|
|
45
|
+
"@provablehq/veil-leo": "0.8.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsup",
|