@provablehq/veil-aleo-sdk 0.10.0 → 0.11.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/dist/index.js CHANGED
@@ -194,7 +194,6 @@ function mnemonicToHDKey(mnemonic, options = {}) {
194
194
  }
195
195
 
196
196
  // src/provableApi.ts
197
- var DEFAULT_PROVABLE_API_URL = "https://api.provable.com";
198
197
  var EXPIRY_SKEW_MS = 5 * 60 * 1e3;
199
198
  function memoryCredentialStore(initial) {
200
199
  let held = initial;
@@ -206,35 +205,15 @@ function memoryCredentialStore(initial) {
206
205
  };
207
206
  }
208
207
  async function registerProvableApi(params) {
209
- const baseUrl = params.baseUrl ?? DEFAULT_PROVABLE_API_URL;
210
- const transport = params.transport ?? fetch;
211
- const response = await transport(`${baseUrl}/consumers`, {
212
- method: "POST",
213
- headers: { "content-type": "application/json" },
214
- body: JSON.stringify({ username: params.username })
215
- });
216
- if (!response.ok) {
217
- const body2 = await response.text();
218
- if (response.status === 409) {
219
- throw new Error(
220
- `Provable API username '${params.username}' is already registered. Credentials cannot be recovered from a username: supply the existing consumerId and apiKey, or register under a different name. (HTTP 409: ${body2})`
221
- );
222
- }
223
- throw new Error(
224
- `Provable API consumer registration failed (HTTP ${response.status}): ${body2}`
225
- );
226
- }
227
- const body = await response.json();
228
- if (!body.consumer?.id || !body.key) {
229
- throw new Error("Provable API consumer registration response carried no consumer id and key.");
230
- }
231
- return { consumerId: body.consumer.id, apiKey: body.key };
208
+ void params;
209
+ return void 0;
232
210
  }
233
211
  async function mintJwt(credentials, baseUrl, transport) {
234
212
  const response = await transport(`${baseUrl}/jwts/${encodeURIComponent(credentials.consumerId)}`, {
235
213
  method: "POST",
236
214
  headers: { "X-Provable-API-Key": credentials.apiKey }
237
215
  });
216
+ if (response.status === 404) return void 0;
238
217
  if (!response.ok) {
239
218
  throw new Error(
240
219
  `Provable API JWT mint failed (HTTP ${response.status}): ${await response.text()}`
@@ -251,42 +230,20 @@ async function mintJwt(credentials, baseUrl, transport) {
251
230
  return { jwt: header, expiration: body.exp * 1e3 };
252
231
  }
253
232
  function createProvableSession(options = {}) {
254
- const baseUrl = options.baseUrl ?? DEFAULT_PROVABLE_API_URL;
233
+ const baseUrl = options.baseUrl;
255
234
  const transport = options.transport ?? fetch;
256
235
  const consumers = { proving: false, recordScanning: false };
257
236
  let credentials = options.credentials;
258
- let registered = false;
259
237
  let credentialsInFlight;
260
238
  let jwt;
261
239
  let jwtInFlight;
262
- async function resolveCredentials(usernameOverride) {
263
- if (credentials) return credentials;
264
- const stored = await options.store?.load();
265
- if (stored) {
240
+ let noJwtRoute = false;
241
+ function getCredentials() {
242
+ if (credentials) return Promise.resolve(credentials);
243
+ credentialsInFlight ??= Promise.resolve(options.store?.load()).then((stored) => {
266
244
  credentials = stored;
267
- return credentials;
268
- }
269
- const username = usernameOverride ?? (typeof options.username === "function" ? options.username() : options.username);
270
- if (!username) {
271
- throw new Error(
272
- "No Provable API credentials available \u2014 pass credentials, a store holding them, or a username to register with."
273
- );
274
- }
275
- const issued = await registerProvableApi({ username, baseUrl, transport });
276
- credentials = issued;
277
- registered = true;
278
- try {
279
- await options.store?.save(issued);
280
- } catch (cause) {
281
- throw new Error(
282
- `Registered Provable API consumer ${issued.consumerId}, but persisting its credentials failed. They are live for this process \u2014 read them from getCredentials() and store them yourself \u2014 but the API key cannot be reissued, so a restart loses it.`,
283
- { cause }
284
- );
285
- }
286
- return credentials;
287
- }
288
- function getCredentials({ username } = {}) {
289
- credentialsInFlight ??= resolveCredentials(username).finally(() => {
245
+ return stored;
246
+ }).finally(() => {
290
247
  credentialsInFlight = void 0;
291
248
  });
292
249
  return credentialsInFlight;
@@ -295,8 +252,11 @@ function createProvableSession(options = {}) {
295
252
  const stale = !jwt || Date.now() >= jwt.expiration - EXPIRY_SKEW_MS;
296
253
  if (!forceRefresh && !stale) return Promise.resolve(jwt);
297
254
  jwtInFlight ??= (async () => {
255
+ if (!baseUrl || noJwtRoute) return void 0;
298
256
  const resolved = await getCredentials();
257
+ if (!resolved) return void 0;
299
258
  jwt = await mintJwt(resolved, baseUrl, transport);
259
+ if (!jwt) noJwtRoute = true;
300
260
  return jwt;
301
261
  })().finally(() => {
302
262
  jwtInFlight = void 0;
@@ -304,7 +264,7 @@ function createProvableSession(options = {}) {
304
264
  return jwtInFlight;
305
265
  }
306
266
  return {
307
- registeredConsumer: () => registered,
267
+ registeredConsumer: () => false,
308
268
  getCredentials,
309
269
  getJwt,
310
270
  consumers,
@@ -317,23 +277,21 @@ function getProvableSession(client) {
317
277
  return client.proving?.session;
318
278
  }
319
279
  async function authenticateProvableApi(client, params = {}) {
320
- if (client.proving?.keyedAuth) {
321
- throw new Error(
322
- "This client authenticates with a provisioned API key \u2014 every request already carries it, and there is no consumer or JWT to resolve. Remove the authenticateProvableApi call."
323
- );
324
- }
325
280
  const session = getProvableSession(client);
326
281
  if (!session) {
327
- throw new Error(
328
- "No Provable API session on this client \u2014 pass consumerId and apiKey, or a credentialStore, when creating it."
329
- );
282
+ return {
283
+ credentials: void 0,
284
+ expiration: void 0,
285
+ registered: false,
286
+ applied: { proving: false, recordScanning: false }
287
+ };
330
288
  }
331
- const credentials = await session.getCredentials({ username: params.username });
332
- const { expiration } = await session.getJwt({ forceRefresh: params.forceRefresh });
289
+ const credentials = await session.getCredentials();
290
+ const minted = credentials ? await session.getJwt({ forceRefresh: params.forceRefresh }) : void 0;
333
291
  return {
334
292
  credentials,
335
- expiration,
336
- registered: session.registeredConsumer(),
293
+ expiration: minted?.expiration,
294
+ registered: false,
337
295
  applied: { ...session.consumers }
338
296
  };
339
297
  }
@@ -344,8 +302,32 @@ function provableApiActions() {
344
302
  }
345
303
 
346
304
  // src/index.ts
347
- var DEFAULT_PROVER_URL = "https://api.provable.com/prove";
348
- var DEFAULT_SCANNER_URL = "https://api.provable.com/scanner";
305
+ var DEFAULT_PROVER_URL = "https://edge.provable.com/api/prove";
306
+ var DEFAULT_SCANNER_URL = "https://edge.provable.com/api/scanner";
307
+ var DEFAULT_NETWORK_URL = "https://edge.provable.com/api/v2";
308
+ var EDGE_GATEWAY = "https://edge.provable.com/api";
309
+ function legacyMintRoot(...targets) {
310
+ for (const target of targets) {
311
+ if (!target || target.startsWith(EDGE_GATEWAY)) continue;
312
+ try {
313
+ return new URL(target).origin;
314
+ } catch {
315
+ continue;
316
+ }
317
+ }
318
+ return void 0;
319
+ }
320
+ function sessionForCredentials(options, ...targets) {
321
+ if (options.auth) return void 0;
322
+ if (options.session) return options.session;
323
+ if (options.apiKey && options.consumerId) {
324
+ return createProvableSession({
325
+ credentials: { consumerId: options.consumerId, apiKey: options.apiKey },
326
+ baseUrl: legacyMintRoot(...targets)
327
+ });
328
+ }
329
+ return void 0;
330
+ }
349
331
  async function loadNetwork(name) {
350
332
  const sdk = await loadSdk(name);
351
333
  silenceSdkLogs(sdk);
@@ -402,7 +384,8 @@ function buildSdk(initialNetwork, initialSdk) {
402
384
  let networkUrl = options.networkUrl;
403
385
  let keyProvider = new currentSdk.AleoKeyProvider();
404
386
  keyProvider.useCache(true);
405
- options.session?.attach("proving");
387
+ const session = sessionForCredentials(options, options.proverUrl);
388
+ session?.attach("proving");
406
389
  let configNetwork = network;
407
390
  const resolveProverUrl = () => {
408
391
  const configured = options.proverUrl ?? (options.mode === "delegated" ? DEFAULT_PROVER_URL : void 0);
@@ -421,7 +404,7 @@ function buildSdk(initialNetwork, initialSdk) {
421
404
  // Carried for `authenticateProvableApi` to find on a client. Core never
422
405
  // reads binding-specific fields on a proving config — `url` and `apiKey`
423
406
  // already travel the same way.
424
- session: options.session,
407
+ session,
425
408
  keyedAuth: options.auth,
426
409
  buildTransaction: async (txOptions) => {
427
410
  const programManager = new currentSdk.ProgramManager(
@@ -465,7 +448,7 @@ function buildSdk(initialNetwork, initialSdk) {
465
448
  const dpsClient = new AleoNetworkClient(proverUrl);
466
449
  const auth = async (forceRefresh) => {
467
450
  if (options.auth) return { auth: options.auth };
468
- if (options.session) return { jwtData: await options.session.getJwt({ forceRefresh }) };
451
+ if (session) return { jwtData: await session.getJwt({ forceRefresh }) };
469
452
  return { apiKey: options.apiKey, consumerId: options.consumerId };
470
453
  };
471
454
  await txOptions.onProgress?.({ type: "prover-submitted" });
@@ -475,7 +458,7 @@ function buildSdk(initialNetwork, initialSdk) {
475
458
  url: proverUrl,
476
459
  ...credentials
477
460
  });
478
- if (!result.ok && (result.status === 401 || result.status === 403) && options.session) {
461
+ if (!result.ok && (result.status === 401 || result.status === 403) && session) {
479
462
  credentials = await auth(true);
480
463
  result = await dpsClient.submitProvingRequestSafe({
481
464
  provingRequest,
@@ -597,7 +580,7 @@ function buildSdk(initialNetwork, initialSdk) {
597
580
  const dpsClient = new AleoNetworkClient(proverUrl);
598
581
  const auth = async (forceRefresh) => {
599
582
  if (options.auth) return { auth: options.auth };
600
- if (options.session) return { jwtData: await options.session.getJwt({ forceRefresh }) };
583
+ if (session) return { jwtData: await session.getJwt({ forceRefresh }) };
601
584
  return { apiKey: options.apiKey, consumerId: options.consumerId };
602
585
  };
603
586
  let credentials = await auth(false);
@@ -606,7 +589,7 @@ function buildSdk(initialNetwork, initialSdk) {
606
589
  url: proverUrl,
607
590
  ...credentials
608
591
  });
609
- if (!result.ok && (result.status === 401 || result.status === 403) && options.session) {
592
+ if (!result.ok && (result.status === 401 || result.status === 403) && session) {
610
593
  credentials = await auth(true);
611
594
  result = await dpsClient.submitProvingRequestSafe({
612
595
  provingRequest,
@@ -741,11 +724,11 @@ function buildSdk(initialNetwork, initialSdk) {
741
724
  );
742
725
  }
743
726
  }
744
- async function scanOwned(scanner, params, hasCredentials, session) {
727
+ async function scanOwned(scanner, params, session) {
745
728
  const ownedFilter = buildOwnedFilter(params);
746
729
  const ALWAYS_RETRY = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
747
730
  const AUTH_RETRY = /* @__PURE__ */ new Set([401, 403]);
748
- const canReMint = hasCredentials || !!session;
731
+ const canReMint = !!session && !!await session.getJwt();
749
732
  const retryable = (status) => ALWAYS_RETRY.has(status) || canReMint && AUTH_RETRY.has(status);
750
733
  const MAX_ATTEMPTS = 4;
751
734
  let last = "";
@@ -762,9 +745,8 @@ function buildSdk(initialNetwork, initialSdk) {
762
745
  lastStatus = void 0;
763
746
  }
764
747
  if (attempt === MAX_ATTEMPTS - 1) break;
765
- if (lastStatus !== void 0 && AUTH_RETRY.has(lastStatus)) {
766
- if (session) scanner.setJwtData(await session.getJwt({ forceRefresh: true }));
767
- else scanner.setJwtData(void 0);
748
+ if (canReMint && lastStatus !== void 0 && AUTH_RETRY.has(lastStatus)) {
749
+ scanner.setJwtData(await session.getJwt({ forceRefresh: true }));
768
750
  }
769
751
  await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** attempt));
770
752
  }
@@ -778,7 +760,7 @@ function buildSdk(initialNetwork, initialSdk) {
778
760
  });
779
761
  if (!options.session && options.apiKey && !options.consumerId) {
780
762
  throw new ConfigurationError(
781
- "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."
763
+ "Record scanning with an apiKey also needs consumerId. Pass both, use auth: { mode: 'api-key' } for a provisioned key, or omit both for the open gateway."
782
764
  );
783
765
  }
784
766
  let scannerSdk = { RecordScanner, ViewKey };
@@ -786,7 +768,7 @@ function buildSdk(initialNetwork, initialSdk) {
786
768
  let viewKey;
787
769
  let viewKeyString;
788
770
  let registration = makeRegisterOnce(options.startBlock ?? 0);
789
- let credential = options.auth ?? options.session;
771
+ let credential = options.auth ?? sessionForCredentials(options, options.url);
790
772
  const sessionOf = (source) => source && !("mode" in source) ? source : void 0;
791
773
  sessionOf(credential)?.attach("recordScanning");
792
774
  const url = options.url ?? DEFAULT_SCANNER_URL;
@@ -807,6 +789,7 @@ function buildSdk(initialNetwork, initialSdk) {
807
789
  registration = makeRegisterOnce(options.startBlock ?? 0);
808
790
  }
809
791
  return {
792
+ url,
810
793
  setAccount: (account) => {
811
794
  viewKeyString = account.viewKey;
812
795
  buildScanner();
@@ -845,8 +828,7 @@ function buildSdk(initialNetwork, initialSdk) {
845
828
  const activeSession = sessionOf(credential);
846
829
  if (activeSession) activeScanner.setJwtData(await activeSession.getJwt());
847
830
  await activeRegistration.ensure(activeScanner, activeViewKey);
848
- const canReMint = !credential && !!(options.apiKey && options.consumerId);
849
- return scanOwned(activeScanner, params, canReMint, activeSession);
831
+ return scanOwned(activeScanner, params, activeSession);
850
832
  },
851
833
  switchNetwork: async (newNetwork) => {
852
834
  if (newNetwork !== "mainnet" && newNetwork !== "testnet") {
@@ -867,11 +849,11 @@ function buildSdk(initialNetwork, initialSdk) {
867
849
  });
868
850
  if (!options.session && options.apiKey && !options.consumerId) {
869
851
  throw new ConfigurationError(
870
- "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."
852
+ "Record scanning with an apiKey also needs consumerId. Pass both, use auth: { mode: 'api-key' } for a provisioned key, or omit both for the open gateway."
871
853
  );
872
854
  }
873
855
  const viewKey = ViewKey.from_string(options.viewKey);
874
- const session = options.session;
856
+ const session = sessionForCredentials(options, options.url);
875
857
  const credentialProps = options.auth ? { auth: options.auth } : session ? {} : {
876
858
  ...options.consumerId ? { consumerId: options.consumerId } : {},
877
859
  ...options.apiKey ? { apiKey: options.apiKey } : {}
@@ -888,7 +870,7 @@ function buildSdk(initialNetwork, initialSdk) {
888
870
  requestRecords: async (params) => {
889
871
  if (session) scanner.setJwtData(await session.getJwt());
890
872
  await registration.ensure(scanner, viewKey);
891
- return scanOwned(scanner, params, !!(options.apiKey && options.consumerId), session);
873
+ return scanOwned(scanner, params, session);
892
874
  }
893
875
  };
894
876
  }
@@ -900,28 +882,28 @@ function buildSdk(initialNetwork, initialSdk) {
900
882
  credentialStore: options.credentialStore,
901
883
  session: options.session
902
884
  });
903
- if (options.auth && options.records && !options.records.setAuth) {
885
+ const networkUrl = options.networkUrl ?? DEFAULT_NETWORK_URL;
886
+ const records = options.records ?? createRemoteScanner();
887
+ if (options.auth && !records.setAuth) {
904
888
  throw new ConfigurationError(
905
889
  "Provisioned-key auth needs a record provider with setAuth \u2014 pass a scanner from createRemoteScanner, or construct the provider with the key."
906
890
  );
907
891
  }
908
892
  const account = privateKeyToAccount(options.privateKey);
909
- const transport = http(options.networkUrl, { network });
893
+ const transport = http(networkUrl, { network });
910
894
  const credentials = options.consumerId && options.apiKey ? { consumerId: options.consumerId, apiKey: options.apiKey } : void 0;
911
895
  const configured = !!(credentials || options.credentialStore || options.session);
912
896
  const session = options.auth ? void 0 : options.session ?? createProvableSession({
913
897
  credentials,
914
898
  store: options.credentialStore ?? memoryCredentialStore(),
915
- // Resolved lazily: only a registration needs it. The derived default
916
- // carries a random suffix because a username is spent once — an account
917
- // that lost its stored key must still be able to register, and the old
918
- // key is unrecoverable. A caller-supplied name is used verbatim, so a
919
- // collision fails rather than quietly registering something else.
920
- username: options.username ?? (() => `veil-${account.address.slice(5, 13)}-${Math.random().toString(36).slice(2, 8)}`)
899
+ // The prover names the legacy gateway first; a legacy scanner url
900
+ // counts too, so a client on the default prover that scans the
901
+ // legacy service still mints for it.
902
+ baseUrl: legacyMintRoot(options.proverUrl, records.url)
921
903
  });
922
904
  const proving = createProvingConfig({
923
905
  mode: options.provingMode ?? "delegated",
924
- networkUrl: options.networkUrl,
906
+ networkUrl,
925
907
  proverUrl: options.proverUrl,
926
908
  session,
927
909
  auth: options.auth,
@@ -930,20 +912,20 @@ function buildSdk(initialNetwork, initialSdk) {
930
912
  apiKey: options.apiKey,
931
913
  consumerId: options.consumerId,
932
914
  account,
933
- ...options.useFeeMaster !== void 0 ? { useFeeMaster: options.useFeeMaster } : {},
915
+ // The hosted prover pays fees by default, so an account holding no public
916
+ // credits can write; a caller funding its own fees opts out.
917
+ useFeeMaster: options.useFeeMaster ?? true,
934
918
  ...options.confirmationTimeout !== void 0 ? { confirmationTimeout: options.confirmationTimeout } : {}
935
919
  });
936
920
  const publicClient = createPublicClient({ transport });
937
- if (options.records) {
938
- if (options.auth) options.records.setAuth?.(options.auth);
939
- else if (configured && session) options.records.setSession?.(session);
940
- options.records.setAccount({ viewKey: account.viewKey });
941
- }
921
+ if (options.auth) records.setAuth?.(options.auth);
922
+ else if (configured && session) records.setSession?.(session);
923
+ records.setAccount({ viewKey: account.viewKey });
942
924
  const walletClient = createWalletClient({
943
925
  account,
944
926
  transport,
945
927
  proving,
946
- ...options.records ? { recordProvider: options.records } : {}
928
+ recordProvider: records
947
929
  }).extend(provableApiActions());
948
930
  return { publicClient, walletClient, account };
949
931
  }
@@ -1073,6 +1055,7 @@ function createDevnodeClient(options) {
1073
1055
  }
1074
1056
  export {
1075
1057
  BLS12377HDKey,
1058
+ DEFAULT_NETWORK_URL,
1076
1059
  DEFAULT_PROVER_URL,
1077
1060
  DEFAULT_SCANNER_URL,
1078
1061
  DEVNODE_ADDR,