@provablehq/veil-aleo-sdk 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -11
- package/dist/index.d.ts +153 -17
- package/dist/index.js +370 -26
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +34 -0
- package/dist/node.js +42 -0
- package/dist/node.js.map +1 -0
- package/dist/provableApi-C4bT37jI.d.ts +362 -0
- package/package.json +9 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mnemonic.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'\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// `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 /** Creates a `ProvingConfig` for `createWalletClient({ proving })`. */\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 }): ProvingConfig\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).\n * @param options.consumerId Consumer id used for JWT refresh.\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.startBlock Optional block height to begin scanning from at\n * registration. Defaults to 0 (full history).\n */\n createRemoteScanner(options: {\n url: string\n consumerId: string\n apiKey?: string\n startBlock?: number\n }): RecordProvider\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 segment).\n * @param options.consumerId Consumer id used for JWT refresh.\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.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 startBlock?: number\n }): StandaloneRecordScanner\n\n /** Creates a fully-wired Aleo client from a private key and network URL. */\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 /**\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 }): { publicClient: PublicClient; walletClient: WalletClient; account: LocalAccount<'privateKey'> }\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 return buildSdk(name, sdk)\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: 300_000 = 5 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 }): ProvingConfig {\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\n return {\n mode: options.mode,\n url: options.proverUrl,\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: network as Network }) })\n\n if (options.mode === 'delegated') {\n if (!options.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(options.proverUrl)\n response = await dpsClient.submitProvingRequest({\n provingRequest,\n url: options.proverUrl,\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n })\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 keyProvider = new currentSdk.AleoKeyProvider()\n keyProvider.useCache(true)\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 canReMint: boolean,\n ): Promise<OwnedRecord[]> {\n const ALWAYS_RETRY = new Set([429, 500, 502, 503, 504])\n const AUTH_RETRY = new Set([401, 403])\n const retryable = (status: number) => ALWAYS_RETRY.has(status) || (canReMint && AUTH_RETRY.has(status))\n const MAX_ATTEMPTS = 4\n let last = ''\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 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 }\n if (attempt === MAX_ATTEMPTS - 1) break\n scanner.setJwtData(undefined) // drop the cached (rejected) JWT so the next call re-mints\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 startBlock?: number\n }): RecordProvider {\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\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: options.url,\n consumerId: options.consumerId,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\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 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 await activeRegistration.ensure(activeScanner, activeViewKey)\n return scanOwned(activeScanner, params.program, params.statusFilter, !!options.apiKey)\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 startBlock?: number\n }): StandaloneRecordScanner {\n const viewKey = ViewKey.from_string(options.viewKey)\n const scanner = new RecordScanner({\n url: options.url,\n consumerId: options.consumerId,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\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 await registration.ensure(scanner, viewKey)\n return scanOwned(scanner, params.program, params.statusFilter, !!options.apiKey)\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 records?: RecordProvider\n }): { publicClient: PublicClient; walletClient: WalletClient; account: LocalAccount<'privateKey'> } {\n const account = privateKeyToAccount(options.privateKey)\n const transport = http(options.networkUrl, { network: network as Network })\n\n const proving = createProvingConfig({\n mode: options.provingMode ?? 'delegated',\n networkUrl: options.networkUrl,\n proverUrl: options.proverUrl,\n apiKey: options.apiKey,\n consumerId: options.consumerId,\n account,\n ...(options.useFeeMaster !== undefined ? { useFeeMaster: options.useFeeMaster } : {}),\n })\n\n const publicClient = createPublicClient({ transport })\n\n if (options.records) {\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 })\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'\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"],"mappings":";AAsBA,SAAS,eAAe,eAAe;AACvC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX;AAAA,OACK;AACP,SAAS,qBAAqB,oBAAoB;AAMlD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACjDP,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,YAAY,WAAW;AACvB,SAAS,gBAAgB;AAEzB,IAAM,kBAAkB;AAIxB,IAAM,kBAAkB;AAExB,IAAM,aAAa;AAYZ,IAAM,gBAAgB;AAGtB,IAAM,cAAc;AAGpB,IAAM,mBAAqD;AAAA,EAChE,UAAU;AAAA,EACV,QAAQ;AACV;AAOA,SAAS,SAAS,GAAuB;AACvC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,YAAY;AACnD,UAAM,IAAI,MAAM,qCAAqC,CAAC,GAAG;AAAA,EAC3D;AACA,QAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,MAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,GAAG,KAAK;AAC9C,SAAO;AACT;AAEA,SAAS,eAAe,OAAiC;AACvD,QAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACxD,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,KAAK,OAAO;AACrB,QAAI,IAAI,GAAG,MAAM;AACjB,cAAU,EAAE;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,EAAE,KAAK,UAAU,GAAU,OAAsB;AAChE,QAAM,OAAO,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC;AAClE,QAAM,IAAI,KAAK,QAAQ,WAAW,IAAI;AACtC,SAAO,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,EAAE;AACvD;AAEA,SAAS,qBAAqB,MAAyB;AACrD,QAAM,IAAI,KAAK,QAAQ,iBAAiB,IAAI;AAC5C,SAAO,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,EAAE;AACvD;AAEA,SAAS,YAAY,MAAuB;AAC1C,MAAI,CAAC,WAAW,KAAK,IAAI,EAAG,QAAO;AACnC,SAAO,KACJ,MAAM,GAAG,EACT,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,EAAE,QAAQ,KAAK,EAAE,CAAC,EAC7B,MAAM,CAAC,MAAM,OAAO,SAAS,OAAO,CAAC,CAAC,CAAC;AAC5C;AAYO,IAAM,gBAAN,MAAM,eAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB,YACkB,KACA,WAChB;AAFgB;AACA;AAAA,EACf;AAAA,EAFe;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlB,OAAO,eAAe,MAAiC;AACrD,UAAM,SAAS,qBAAqB,IAAI;AACxC,WAAO,IAAI,eAAc,OAAO,KAAK,OAAO,SAAS;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,MAA6B;AAClC,QAAI,CAAC,YAAY,IAAI,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,4BAA4B,IAAI;AAAA,MAClC;AAAA,IACF;AACA,UAAM,WAAW,KACd,MAAM,GAAG,EACT,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,SAAS,EAAE,QAAQ,KAAK,EAAE,GAAG,EAAE,CAAC;AAE9C,eAAW,OAAO,UAAU;AAC1B,UAAI,OAAO,iBAAiB;AAC1B,cAAM,IAAI;AAAA,UACR,yCAAyC,GAAG;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,SAAS;AAAA,MACtB,CAAC,KAAK,YAAY,QAAQ,KAAK,UAAU,eAAe;AAAA,MACxD,EAAE,KAAK,KAAK,KAAK,WAAW,KAAK,UAAU;AAAA,IAC7C;AACA,WAAO,IAAI,eAAc,OAAO,KAAK,OAAO,SAAS;AAAA,EACvD;AAAA;AAAA,EAGA,WAAW,MAA6B;AACtC,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,YAAY,OAA8B;AACxC,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,SAAS,iBAAiB;AACrE,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK;AAAA,MAC/B;AAAA,IACF;AACA,WAAO,KAAK,OAAO,KAAK,KAAK,MAAM;AAAA,EACrC;AACF;AAmBO,SAASA,kBAAiB,WAAsB,KAAa;AAClE,SAAa,uBAAiB,UAAU,QAAQ;AAClD;AAUO,SAASC,kBAAiB,UAA2B;AAC1D,SAAa,uBAAiB,UAAU,QAAQ;AAClD;AAUO,SAAS,aAAa,MAAuB;AAClD,SAAO,SAAS,SAAS,IAAI;AAC/B;AAYO,SAAS,eAAe,UAA8B;AAC3D,SAAa,yBAAmB,QAAQ;AAC1C;AAqBO,SAAS,gBACd,UACA,UAA6D,CAAC,GAC/C;AACf,QAAM,EAAE,QAAQ,GAAG,aAAa,WAAW,IAAI;AAC/C,QAAM,OAAO,eAAe,QAAQ;AACpC,SAAO,cAAc,eAAe,IAAI,EACrC,WAAW,iBAAiB,UAAU,CAAC,EACvC,YAAY,KAAK;AACtB;;;ADxCA,eAAsB,YAAY,MAA0C;AAC1E,QAAM,MAAO,MAAM,QAAQ,IAAI;AAC/B,SAAO,SAAS,MAAM,GAAG;AAC3B;AAEA,SAAS,SAAS,gBAAkC,YAAgC;AAGlF,MAAI,aAAwB;AAC5B,QAAM,UAAU;AAChB,QAAM;AAAA,IACJ,SAAAC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAIJ,WAAS,kBACP,UACA,SAC0B;AAC1B,UAAM,KAAK,gBAAgB,UAAU,OAAO;AAE5C,UAAM,aAAc,WAEjB,oBAAoB,GAAG,GAAG,EAAE,UAAU;AACzC,WAAO,EAAE,GAAG,oBAAoB,UAAU,GAAG,QAAQ,WAAW;AAAA,EAClE;AAEA,WAAS,wBAAwB,SAI2B;AAC1D,UAAM,WAAWC,kBAAiB,SAAS,YAAY,GAAG;AAC1D,UAAM,EAAE,UAAU,WAAW,GAAG,kBAAkB,IAAI,WAAW,CAAC;AAClE,WAAO,EAAE,UAAU,SAAS,kBAAkB,UAAU,iBAAiB,EAAE;AAAA,EAC7E;AAEA,WAASC,mBAA8C;AACrD,UAAM,aAAa,IAAIF,SAAQ;AAC/B,WAAO,oBAAoB,WAAW,WAAW,EAAE,UAAU,CAAC;AAAA,EAChE;AAEA,WAAS,cAAc,eAAuB,YAA4B;AACxE,WAAO,QAAQ,YAAY,aAAa,EAAE,QAAQ,UAAU;AAAA,EAC9D;AAEA,WAAS,gBACP,eACA,SACA,iBACS;AACT,UAAM,MAAM,UAAU,YAAY,eAAe;AACjD,UAAM,OAAO,QAAQ,YAAY,aAAa;AAC9C,WAAO,IAAI,OAAO,MAAM,OAAO;AAAA,EACjC;AAEA,WAAS,oBAAoB,KAA2D;AACtF,WAAO,IAAI,kBAAkB,GAAG;AAAA,EAClC;AAEA,WAAS,oBAAoB,SAiBX;AAGhB,QAAI,aAAa,QAAQ;AACzB,QAAI,cAAc,IAAI,WAAW,gBAAgB;AACjD,gBAAY,SAAS,IAAI;AAEzB,WAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,KAAK,QAAQ;AAAA,MAEb,kBAAkB,OAAO,cAAuC;AAC9D,cAAM,iBAAiB,IAAI,WAAW;AAAA,UACpC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YAAI,QAAQ,SAAS;AACnB,gBAAM,aAAa,IAAI,WAAW,QAAQ,EAAE,YAAY,QAAQ,QAAQ,WAAW,CAAC;AACpF,yBAAe,WAAW,UAAU;AAAA,QACtC;AAWA,YAAI;AACJ,YAAI,UAAU,WAAW,UAAU,QAAQ,SAAS,GAAG;AACrD,gBAAM,gBAAgB,MAAM,eAAe,cAAc,WAAW,UAAU,WAAW;AACzF,gBAAM,gBAAgB,MAAM,eAAe,cAAc,kBAAkB,aAAa;AACxF,gBAAM,SAA4B,EAAE,GAAG,cAAc;AACrD,qBAAW,QAAQ,UAAU,SAAS;AACpC,mBAAO,IAAI,IAAI,MAAM,eAAe,cAAc,WAAW,IAAI;AAAA,UACnE;AACA,4BAAkB;AAAA,QACpB;AAEA,cAAM,KAAK,MAAM,eAAe,0BAA0B;AAAA,UACxD,aAAa,UAAU;AAAA,UACvB,cAAc,UAAU;AAAA,UACxB,aAAa;AAAA,UACb,YAAY,UAAU,cAAc;AAAA,UACpC,QAAQ,UAAU;AAAA,UAClB,GAAI,kBAAkB,EAAE,SAAS,gBAAgB,IAAI,CAAC;AAAA,QACxD,CAAC;AAED,eAAO,KAAK,MAAM,GAAG,SAAS,CAAC;AAAA,MACjC;AAAA,MAEA,iBAAiB,OAAO,kBAA0C;AAChE,cAAM,iBAAiB,IAAI,WAAW;AAAA,UACpC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YAAI,QAAQ,SAAS;AACnB,gBAAM,aAAa,IAAI,WAAW,QAAQ,EAAE,YAAY,QAAQ,QAAQ,WAAW,CAAC;AACpF,yBAAe,WAAW,UAAU;AAAA,QACtC;AAEA,cAAM,KAAK,MAAM,eAAe;AAAA,UAC9B,cAAc;AAAA,UACd;AAAA,UACA,cAAc,cAAc;AAAA,QAC9B;AAEA,eAAO,KAAK,MAAM,GAAG,SAAS,CAAC;AAAA,MACjC;AAAA,MAEA,UAAU,OAAO,eAA4D;AAC3E,cAAM,iBAAiB,IAAI,WAAW,eAAe,YAAY,aAAa,MAAS;AACvF,YAAI,QAAQ,SAAS;AACnB,yBAAe,WAAW,IAAI,WAAW,QAAQ,EAAE,YAAY,QAAQ,QAAQ,WAAW,CAAC,CAAC;AAAA,QAC9F;AAGA,cAAM,iBAAiB,QAAQ,UAAU,QAAQ,YAAY,QAAQ,QAAQ,OAAO,IAAI;AACxF,cAAM,YAAmC,iBACrC,CAAC,eAAuB;AACtB,gBAAM,KAAK,iBAAiB,WAAW,UAAU;AACjD,iBAAO,GAAG,QAAQ,cAAc,IAAI,GAAG,QAAQ,cAAc,EAAE,SAAS,IAAI;AAAA,QAC9E,IACA;AAKJ,cAAM,gBAAgB,MAAM,eAAe,mBAAmB;AAAA,UAC5D,aAAa,WAAW;AAAA,UACxB,cAAc,WAAW;AAAA,UACzB,QAAQ,WAAW;AAAA,UACnB,eAAe,WAAW;AAAA,UAC1B,gBAAgB,WAAW;AAAA,QAC7B,CAAC;AAQD,cAAM,KAAK;AAAA,UACT,WAAW;AAAA,YACT,aAAa,cAAc,YAAY,EAAE,IAAI,CAAC,MAAW;AACvD,kBAAI,SAAS;AACb,kBAAI,gBAAgB;AAClB,oBAAI;AACF,2BAAS,EAAE,kBAAkB,EAAE,IAAI,cAAc,CAAC;AAAA,gBACpD,QAAQ;AAAA,gBAER;AAAA,cACF;AACA,qBAAO,KAAK,MAAM,OAAO,SAAS,CAAC;AAAA,YACrC,CAAC;AAAA,UACH;AAAA,QACF;AAEA,cAAM,EAAE,aAAa,QAAQ,IAAI,mBAAmB,IAAI,SAAS;AACjE,eAAO,EAAE,aAAa,QAAQ;AAAA,MAChC;AAAA,MAEA,SAAS,OAAO,gBAA2D;AACzE,cAAM,iBAAiB,IAAI,WAAW,eAAe,YAAY,aAAa,MAAS;AACvF,YAAI,QAAQ,SAAS;AACnB,yBAAe,WAAW,IAAI,WAAW,QAAQ,EAAE,YAAY,QAAQ,QAAQ,WAAW,CAAC,CAAC;AAAA,QAC9F;AAGA,cAAM,cAAc,OAAO,YAAY,GAAG,IAAI;AAG9C,cAAM,iBAAiB,QAAQ,UAAU,QAAQ,YAAY,QAAQ,QAAQ,OAAO,IAAI;AACxF,cAAM,YAAmC,iBACrC,CAAC,eAAuB;AACtB,gBAAM,KAAK,iBAAiB,WAAW,UAAU;AACjD,iBAAO,GAAG,QAAQ,cAAc,IAAI,GAAG,QAAQ,cAAc,EAAE,SAAS,IAAI;AAAA,QAC9E,IACA;AAGJ,cAAM,qBAAqB,MACzB,mBAAmB,EAAE,WAAW,KAAK,YAAY,EAAE,QAA4B,CAAC,EAAE,CAAC;AAErF,YAAI,QAAQ,SAAS,aAAa;AAChC,cAAI,CAAC,QAAQ,UAAW,OAAM,IAAI,mBAAmB,oGAAoG;AAEzJ,cAAI;AACJ,cAAI;AACF,kBAAM,iBAAiB,MAAM,eAAe,eAAe;AAAA,cACzD,aAAa,YAAY;AAAA,cACzB,eAAe,YAAY;AAAA,cAC3B,gBAAgB,YAAY;AAAA,cAC5B,cAAc,YAAY;AAAA,cAC1B,QAAQ,YAAY;AAAA,cACpB;AAAA,cACA,YAAY,YAAY,cAAc;AAAA,cACtC,WAAW;AAAA,cACX,cAAc,QAAQ,gBAAgB;AAAA,YACxC,CAAC;AAED,kBAAM,YAAY,IAAI,kBAAkB,QAAQ,SAAS;AACzD,uBAAW,MAAM,UAAU,qBAAqB;AAAA,cAC9C;AAAA,cACA,KAAK,QAAQ;AAAA,cACb,QAAQ,QAAQ;AAAA,cAChB,YAAY,QAAQ;AAAA,YACtB,CAAC;AAAA,UACH,SAAS,GAAG;AACV,gBAAI,aAAa,UAAW,OAAM;AAClC,kBAAM,qBAAqB,CAAC;AAAA,UAC9B;AAEA,gBAAM,OAAO,SAAS,aAAa;AACnC,cAAI,CAAC,KAAM,OAAM,IAAI,mBAAmB,0FAAqF;AAE7H,gBAAM,cAAc,MAAM,oBAAoB,mBAAmB,GAAG,MAAM,QAAQ,mBAAmB;AACrG,gBAAM,EAAE,aAAa,QAAQ,IAAI,mBAAmB,aAAa,SAAS;AAC1E,iBAAO,EAAE,eAAe,MAAM,aAAa,QAAQ;AAAA,QAErD,OAAO;AACL,cAAI;AACJ,cAAI;AACF,iBAAK,MAAM,eAAe,0BAA0B;AAAA,cAClD,aAAa,YAAY;AAAA,cACzB,cAAc,YAAY;AAAA,cAC1B,QAAQ,YAAY;AAAA,cACpB;AAAA,cACA,YAAY,YAAY,cAAc;AAAA,cACtC,SAAS,YAAY;AAAA,cACrB,SAAS,YAAY;AAAA,YACvB,CAAC;AAAA,UACH,SAAS,GAAG;AACV,gBAAI,aAAa,UAAW,OAAM;AAClC,kBAAM,IAAI,aAAa,EAAE,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG,OAAO,EAAW,CAAC;AAAA,UACnG;AAEA,cAAI;AACJ,cAAI;AACF,kBAAM,eAAe,IAAI,kBAAkB,UAAU;AACrD,yBAAa,iBAAiB,KAAK;AACnC,mBAAO,MAAM,aAAa,kBAAkB,EAAE;AAAA,UAChD,SAAS,GAAG;AACV,gBAAI,aAAa,UAAW,OAAM;AAClC,kBAAM,uBAAuB,CAAC;AAAA,UAChC;AAEA,gBAAM,cAAc,MAAM,oBAAoB,mBAAmB,GAAG,MAAM,QAAQ,mBAAmB;AACrG,gBAAM,EAAE,aAAa,QAAQ,IAAI,mBAAmB,aAAa,SAAS;AAC1E,iBAAO,EAAE,eAAe,MAAM,aAAa,QAAQ;AAAA,QACrD;AAAA,MACF;AAAA,MAEA,SAAS,OAAO,eAAe;AAC7B,YAAI,CAAC,QAAQ,SAAS,SAAS;AAC7B,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AACA,eAAO,WAAW,QAAQ,YAAY,QAAQ,QAAQ,OAAO,EAAE,QAAQ,UAAU;AAAA,MACnF;AAAA,MAEA,eAAe,OAAO,eAAe;AACnC,YAAI,eAAe,aAAa,eAAe,WAAW;AACxD,gBAAM,IAAI;AAAA,YACR,0DAA0D,UAAU;AAAA,UACtE;AAAA,QACF;AACA,qBAAc,MAAM,QAAQ,UAA8B;AAC1D,sBAAc,IAAI,WAAW,gBAAgB;AAC7C,oBAAY,SAAS,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AASA,WAAS,cAAc,KAA2C;AAChE,UAAM,OAAO,CAAC,OAAe,UAA2B,IAAI,KAAK,KAAK,IAAI,KAAK;AAC/E,WAAO;AAAA,MACL,aAAa,KAAK,gBAAgB,aAAa;AAAA,MAC/C,gBAAgB,KAAK,mBAAmB,gBAAgB;AAAA,MACxD,YAAY,IAAI;AAAA,MAChB,cAAc,KAAK,iBAAiB,cAAc;AAAA,MAClD,aAAa,KAAK,gBAAgB,aAAa;AAAA,MAC/C,OAAO,IAAI;AAAA,MACX,aAAa,KAAK,gBAAgB,aAAa;AAAA,MAC/C,kBAAkB,KAAK,qBAAqB,kBAAkB;AAAA,MAC9D,YAAY,KAAK,eAAe,YAAY;AAAA,MAC5C,QAAQ,IAAI;AAAA,MACZ,OAAO,IAAI;AAAA,MACX,KAAK,IAAI;AAAA,MACT,eAAe,KAAK,kBAAkB,eAAe;AAAA,MACrD,cAAc,KAAK,iBAAiB,cAAc;AAAA,MAClD,kBAAkB,KAAK,qBAAqB,kBAAkB;AAAA,MAC9D,iBAAiB,KAAK,oBAAoB,iBAAiB;AAAA,MAC3D,iBAAkB,KAAK,oBAAoB,iBAAiB,KAA4B;AAAA,IAC1F;AAAA,EACF;AAMA,WAAS,iBAAiB,YAAoB;AAC5C,QAAI;AACJ,WAAO;AAAA,MACL,OACE,SACA,SACe;AACf,YAAI,CAAC,cAAc;AACjB,0BAAgB,YAAY;AAC1B,kBAAM,SAAS,MAAM,QAAQ,kBAAkB,SAAS,UAAU;AAClE,gBAAI,CAAC,OAAO,IAAI;AACd,6BAAe;AACf,oBAAM,IAAI;AAAA,gBACR,4CAA4C,OAAO,MAAM,MAAM,OAAO,OAAO,WAAW,eAAe;AAAA,cACzG;AAAA,YACF;AAAA,UACF,GAAG;AAAA,QACL;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAaA,iBAAe,UACb,SACA,SACA,cACA,WACwB;AACxB,UAAM,eAAe,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,CAAC;AACtD,UAAM,aAAa,oBAAI,IAAI,CAAC,KAAK,GAAG,CAAC;AACrC,UAAM,YAAY,CAAC,WAAmB,aAAa,IAAI,MAAM,KAAM,aAAa,WAAW,IAAI,MAAM;AACrG,UAAM,eAAe;AACrB,QAAI,OAAO;AACX,aAAS,UAAU,GAAG,UAAU,cAAc,WAAW;AACvD,UAAI;AACF,cAAM,SAAS,MAAM,QAAQ,MAAM;AAAA,UACjC,SAAS,iBAAiB;AAAA,UAC1B,QAAQ,EAAE,UAAU,CAAC,OAAO,EAAE;AAAA,QAChC,CAAC;AACD,YAAI,OAAO,GAAI,SAAQ,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,cAAc,CAA4B,CAAC;AAChG,eAAO,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,WAAW,eAAe;AACzE,YAAI,CAAC,UAAU,OAAO,MAAM,EAAG;AAAA,MACjC,SAAS,KAAK;AAGZ,eAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AACA,UAAI,YAAY,eAAe,EAAG;AAClC,cAAQ,WAAW,MAAS;AAC5B,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,MAAM,KAAK,OAAO,CAAC;AAAA,IACxE;AACA,UAAM,IAAI,MAAM,uBAAuB,IAAI,GAAG;AAAA,EAChD;AAEA,WAAS,oBAAoB,SAKV;AAIjB,QAAI,aAA2D,EAAE,eAAe,QAAQ;AACxF,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI,eAAe,iBAAiB,QAAQ,cAAc,CAAC;AAE3D,aAAS,eAAe;AACtB,UAAI,CAAC,cAAe;AACpB,gBAAU,WAAW,QAAQ,YAAY,aAAa;AACtD,gBAAU,IAAI,WAAW,cAAc;AAAA,QACrC,KAAK,QAAQ;AAAA,QACb,YAAY,QAAQ;AAAA,QACpB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,UAAU,CAAC,OAAO;AAAA,QAClB,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,MAClB,CAAC;AAID,qBAAe,iBAAiB,QAAQ,cAAc,CAAC;AAAA,IACzD;AAEA,WAAO;AAAA,MACL,YAAY,CAAC,YAAiC;AAC5C,wBAAgB,QAAQ;AACxB,qBAAa;AAAA,MACf;AAAA,MAEA,gBAAgB,OAAO,WAA6D;AAClF,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,mEAAmE;AAAA,QACrF;AAKA,cAAM,gBAAgB;AACtB,cAAM,gBAAgB;AACtB,cAAM,qBAAqB;AAC3B,cAAM,mBAAmB,OAAO,eAAe,aAAa;AAC5D,eAAO,UAAU,eAAe,OAAO,SAAS,OAAO,cAAc,CAAC,CAAC,QAAQ,MAAM;AAAA,MACvF;AAAA,MAEA,eAAe,OAAO,eAAuB;AAC3C,YAAI,eAAe,aAAa,eAAe,WAAW;AACxD,gBAAM,IAAI;AAAA,YACR,8DAA8D,UAAU;AAAA,UAC1E;AAAA,QACF;AACA,qBAAc,MAAM,QAAQ,UAA8B;AAC1D,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,WAAS,wBAAwB,SAML;AAC1B,UAAM,UAAU,QAAQ,YAAY,QAAQ,OAAO;AACnD,UAAM,UAAU,IAAI,cAAc;AAAA,MAChC,KAAK,QAAQ;AAAA,MACb,YAAY,QAAQ;AAAA,MACpB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,MACnD,UAAU,CAAC,OAAO;AAAA,MAClB,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB,CAAC;AACD,UAAM,eAAe,iBAAiB,QAAQ,cAAc,CAAC;AAE7D,WAAO;AAAA,MACL,gBAAgB,OAAO,WAA6D;AAClF,cAAM,aAAa,OAAO,SAAS,OAAO;AAC1C,eAAO,UAAU,SAAS,OAAO,SAAS,OAAO,cAAc,CAAC,CAAC,QAAQ,MAAM;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAEA,WAAS,iBAAiB,SAU0E;AAClG,UAAM,UAAU,oBAAoB,QAAQ,UAAU;AACtD,UAAM,YAAY,KAAK,QAAQ,YAAY,EAAE,QAA4B,CAAC;AAE1E,UAAM,UAAU,oBAAoB;AAAA,MAClC,MAAM,QAAQ,eAAe;AAAA,MAC7B,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,MACpB;AAAA,MACA,GAAI,QAAQ,iBAAiB,SAAY,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;AAAA,IACrF,CAAC;AAED,UAAM,eAAe,mBAAmB,EAAE,UAAU,CAAC;AAErD,QAAI,QAAQ,SAAS;AACnB,cAAQ,QAAQ,WAAW,EAAE,SAAS,QAAQ,QAAQ,CAAC;AAAA,IACzD;AAEA,UAAM,eAAe,mBAAmB;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,QAAQ,UAAU,EAAE,gBAAgB,QAAQ,QAAQ,IAAI,CAAC;AAAA,IAC/D,CAAC;AAED,WAAO,EAAE,cAAc,cAAc,QAAQ;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAcA,IAAM,4BAA4B;AAElC,SAAS,oBAAoB,YAAgD;AAC3E,QAAM,aAAa,IAAI,QAAQ,EAAE,WAAW,CAAC;AAC7C,QAAM,UAAU,WAAW,QAAQ,EAAE,UAAU;AAC/C,QAAM,UAAU,WAAW,QAAQ,EAAE,UAAU;AAE/C,QAAM,SAAS,OAAO,YAA6C;AACjE,UAAM,MAAM,WAAW,KAAK,OAAO;AACnC,WAAO,IAAI,YAAY,EAAE,OAAO,IAAI,UAAU,CAAC;AAAA,EACjD;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAGO,SAAS,kBAA8C;AAC5D,QAAM,aAAa,IAAI,QAAQ;AAC/B,SAAO,oBAAoB,WAAW,WAAW,EAAE,UAAU,CAAC;AAChE;AA4BO,SAAS,oBAAoB,SAIgE;AAClG,QAAM,MAAM,UAAU,SAAS,cAAc,YAAY;AACzD,QAAM,UAAU,oBAAoB,SAAS,cAAc,mBAAmB;AAC9E,QAAM,aAAa,IAAI,QAAQ,EAAE,YAAY,QAAQ,WAAW,CAAC;AACjE,QAAM,YAAY,KAAK,KAAK,EAAE,SAAS,UAAU,CAAC;AAElD,QAAM,cAAc,IAAI,gBAAgB;AACxC,cAAY,SAAS,IAAI;AAIzB,uCAAqC,yBAAyB;AAI9D,QAAM,eAAe,mBAAmB,EAAE,UAAU,CAAC;AAQrD,QAAM,mBAAmB,OAAO,SAM1B;AACJ,UAAM,iBAAiB,IAAI,eAAe,KAAK,aAAa,MAAS;AACrE,mBAAe,WAAW,UAAU;AACpC,WAAO,eAAe,iCAAiC;AAAA,MACrD,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB,aAAa;AAAA,MACb,YAAY,KAAK,cAAc;AAAA,MAC/B,QAAQ,KAAK;AAAA,MACb,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,QAAM,UAAyB;AAAA,IAC7B,MAAM;AAAA,IACN,iBAAiB,OAAO,kBAA0C;AAChE,YAAM,iBAAiB,IAAI,eAAe,KAAK,aAAa,MAAS;AACrE,qBAAe,WAAW,UAAU;AACpC,YAAM,KAAK,MAAM,eAAe,kCAAkC;AAAA,QAChE,SAAS,cAAc;AAAA,QACvB,aAAa;AAAA,QACb,YAAY,cAAc,cAAc;AAAA,MAC1C,CAAC;AACD,aAAO,KAAK,MAAM,GAAG,SAAS,CAAC;AAAA,IACjC;AAAA,IACA,kBAAkB,OAAO,cAAuC;AAK9D,UAAI;AACJ,UAAI,UAAU,WAAW,UAAU,QAAQ,SAAS,GAAG;AACrD,cAAM,gBAAgB,IAAI,eAAe,KAAK,aAAa,MAAS,EAAE;AACtE,kBAAU,CAAC;AACX,cAAM,QAAQ,CAAC,GAAG,UAAU,OAAO;AACnC,cAAM,OAAO,oBAAI,IAAY;AAC7B,eAAO,MAAM,SAAS,GAAG;AACvB,gBAAM,OAAO,MAAM,MAAM;AACzB,cAAI,KAAK,IAAI,IAAI,EAAG;AACpB,eAAK,IAAI,IAAI;AACb,gBAAM,SAAS,MAAM,cAAc,WAAW,IAAI;AAClD,kBAAQ,IAAI,IAAI;AAChB,gBAAM,cAAc,QAAQ,WAAW,MAAM,EAAE,WAAW;AAC1D,qBAAW,OAAO,aAAa;AAC7B,gBAAI,OAAO,CAAC,KAAK,IAAI,GAAG,EAAG,OAAM,KAAK,GAAG;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,iBAAiB;AAAA,QAChC,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,QACxB,QAAQ,UAAU;AAAA,QAClB,YAAY,UAAU;AAAA,QACtB;AAAA,MACF,CAAC;AACD,aAAO,KAAK,MAAM,GAAG,SAAS,CAAC;AAAA,IACjC;AAAA,IACA,SAAS,OAAO,gBAA2D;AACzE,YAAM,KAAK,MAAM,iBAAiB;AAAA,QAChC,aAAa,YAAY;AAAA,QACzB,cAAc,YAAY;AAAA,QAC1B,QAAQ,YAAY;AAAA,QACpB,YAAY,YAAY;AAAA,QACxB,SAAS,YAAY;AAAA,MACvB,CAAC;AAGD,YAAM,OAAQ,MAAM,aAAa,QAAQ;AAAA,QACvC,QAAQ;AAAA,QACR,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE;AAAA,MACvC,CAAC;AAID,YAAM,cAAc,MAAM,oBAAoB,cAAc,IAAI;AAOhE,YAAM,iBAAiB,cAAc,YAAY,QAAQ,OAAO;AAChE,YAAM,YAAuB,CAAC,eAAuB;AACnD,cAAM,KAAK,uBAAuB,WAAW,UAAU;AACvD,eAAO,GAAG,QAAQ,cAAc,IAAI,GAAG,QAAQ,cAAc,EAAE,SAAS,IAAI;AAAA,MAC9E;AACA,YAAM,EAAE,aAAa,QAAQ,IAAI,mBAAmB,aAAa,SAAS;AAC1E,aAAO,EAAE,eAAe,MAAM,aAAa,QAAQ;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,eAAe,mBAAmB,EAAE,SAAS,WAAW,QAAQ,CAAC;AAEvE,SAAO,EAAE,cAAc,cAAc,QAAQ;AAC/C;","names":["generateMnemonic","validateMnemonic","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
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { c as ProvableCredentialStore } from './provableApi-C4bT37jI.js';
|
|
2
|
+
import '@provablehq/veil-core';
|
|
3
|
+
import '@provablehq/sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Builds a credential store backed by a JSON file.
|
|
7
|
+
*
|
|
8
|
+
* Applies to bots, scripts, servers, and CI — anything holding a private key
|
|
9
|
+
* directly and able to write to disk. The file is written with mode `0600`
|
|
10
|
+
* because it holds an API key the Provable API issues exactly once and cannot
|
|
11
|
+
* reissue. A missing file reads as "not registered yet", so the first run
|
|
12
|
+
* registers a consumer and writes it, and later runs reuse it.
|
|
13
|
+
*
|
|
14
|
+
* @param path Path to the JSON file. Parent directories are created on write.
|
|
15
|
+
* @returns A store reading and writing that file.
|
|
16
|
+
* @throws From `load` when the file exists but cannot be read or parsed. Only an
|
|
17
|
+
* absent file counts as "not registered": any other failure could otherwise
|
|
18
|
+
* register a replacement consumer and abandon the unreissuable key in that
|
|
19
|
+
* file.
|
|
20
|
+
* @throws From `save` when the write fails — a swallowed failure would orphan a
|
|
21
|
+
* consumer whose key is unrecoverable, so it propagates and fails the call
|
|
22
|
+
* that triggered registration.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { fileCredentialStore } from '@provablehq/veil-aleo-sdk/node'
|
|
26
|
+
*
|
|
27
|
+
* const { walletClient } = aleo.createAleoClient({
|
|
28
|
+
* privateKey, networkUrl, proverUrl, records: scanner,
|
|
29
|
+
* credentialStore: fileCredentialStore('./.provable-credentials.json'),
|
|
30
|
+
* })
|
|
31
|
+
*/
|
|
32
|
+
declare function fileCredentialStore(path: string): ProvableCredentialStore;
|
|
33
|
+
|
|
34
|
+
export { fileCredentialStore };
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/node.ts
|
|
2
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
function fileCredentialStore(path) {
|
|
5
|
+
return {
|
|
6
|
+
load: async () => {
|
|
7
|
+
let raw;
|
|
8
|
+
try {
|
|
9
|
+
raw = await readFile(path, "utf8");
|
|
10
|
+
} catch (cause) {
|
|
11
|
+
const code = cause?.code;
|
|
12
|
+
if (code === "ENOENT") return void 0;
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Provable API credential file ${path} could not be read (${code ?? "unknown error"}). Refusing to register a replacement consumer, which would abandon any key stored there.`,
|
|
15
|
+
{ cause }
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
let parsed;
|
|
19
|
+
try {
|
|
20
|
+
parsed = JSON.parse(raw);
|
|
21
|
+
} catch (cause) {
|
|
22
|
+
throw new Error(`Provable API credential file ${path} is not valid JSON.`, { cause });
|
|
23
|
+
}
|
|
24
|
+
const { consumerId, apiKey } = parsed ?? {};
|
|
25
|
+
if (typeof consumerId !== "string" || typeof apiKey !== "string") {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`Provable API credential file ${path} is missing consumerId or apiKey. Delete it to register a new consumer.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return { consumerId, apiKey };
|
|
31
|
+
},
|
|
32
|
+
save: async (credentials) => {
|
|
33
|
+
await mkdir(dirname(path), { recursive: true });
|
|
34
|
+
await writeFile(path, `${JSON.stringify(credentials, null, 2)}
|
|
35
|
+
`, { mode: 384 });
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
fileCredentialStore
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/node.ts"],"sourcesContent":["/**\n * Node-only helpers for `@provablehq/veil-aleo-sdk`.\n *\n * Imported from `@provablehq/veil-aleo-sdk/node` rather than the package root,\n * so the `node:fs` dependency never reaches a browser bundle.\n */\nimport { readFile, writeFile, mkdir } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport type { ProvableApiCredentials, ProvableCredentialStore } from './provableApi.js'\n\n/**\n * Builds a credential store backed by a JSON file.\n *\n * Applies to bots, scripts, servers, and CI — anything holding a private key\n * directly and able to write to disk. The file is written with mode `0600`\n * because it holds an API key the Provable API issues exactly once and cannot\n * reissue. A missing file reads as \"not registered yet\", so the first run\n * registers a consumer and writes it, and later runs reuse it.\n *\n * @param path Path to the JSON file. Parent directories are created on write.\n * @returns A store reading and writing that file.\n * @throws From `load` when the file exists but cannot be read or parsed. Only an\n * absent file counts as \"not registered\": any other failure could otherwise\n * register a replacement consumer and abandon the unreissuable key in that\n * file.\n * @throws From `save` when the write fails — a swallowed failure would orphan a\n * consumer whose key is unrecoverable, so it propagates and fails the call\n * that triggered registration.\n *\n * @example\n * import { fileCredentialStore } from '@provablehq/veil-aleo-sdk/node'\n *\n * const { walletClient } = aleo.createAleoClient({\n * privateKey, networkUrl, proverUrl, records: scanner,\n * credentialStore: fileCredentialStore('./.provable-credentials.json'),\n * })\n */\nexport function fileCredentialStore(path: string): ProvableCredentialStore {\n return {\n load: async () => {\n let raw: string\n try {\n raw = await readFile(path, 'utf8')\n } catch (cause) {\n // Only a genuinely absent file reads as \"no consumer yet\". Any other\n // read failure — a permissions change, a busy or unreadable device — is\n // reported, because treating it as absent would register a replacement\n // consumer and abandon the key sitting in that file, which cannot be\n // reissued. Same reasoning as the malformed-file case below.\n const code = (cause as { code?: string } | undefined)?.code\n // ENOENT only. ENOTDIR means a path component is not a directory — a\n // malformed path rather than a missing file — and reading that as\n // \"no consumer yet\" would register a replacement and abandon the key.\n if (code === 'ENOENT') return undefined\n throw new Error(\n `Provable API credential file ${path} could not be read (${code ?? 'unknown error'}). ` +\n 'Refusing to register a replacement consumer, which would abandon any key stored there.',\n { cause },\n )\n }\n // A malformed or half-written file is reported rather than treated as\n // absent: registering over it would overwrite credentials that may still\n // be recoverable by hand, and the key cannot be reissued.\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (cause) {\n throw new Error(`Provable API credential file ${path} is not valid JSON.`, { cause })\n }\n const { consumerId, apiKey } = (parsed ?? {}) as Partial<ProvableApiCredentials>\n if (typeof consumerId !== 'string' || typeof apiKey !== 'string') {\n throw new Error(\n `Provable API credential file ${path} is missing consumerId or apiKey. Delete it to register a new consumer.`,\n )\n }\n return { consumerId, apiKey }\n },\n save: async (credentials) => {\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, `${JSON.stringify(credentials, null, 2)}\\n`, { mode: 0o600 })\n },\n }\n}\n"],"mappings":";AAMA,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,eAAe;AA8BjB,SAAS,oBAAoB,MAAuC;AACzE,SAAO;AAAA,IACL,MAAM,YAAY;AAChB,UAAI;AACJ,UAAI;AACF,cAAM,MAAM,SAAS,MAAM,MAAM;AAAA,MACnC,SAAS,OAAO;AAMd,cAAM,OAAQ,OAAyC;AAIvD,YAAI,SAAS,SAAU,QAAO;AAC9B,cAAM,IAAI;AAAA,UACR,gCAAgC,IAAI,uBAAuB,QAAQ,eAAe;AAAA,UAElF,EAAE,MAAM;AAAA,QACV;AAAA,MACF;AAIA,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,MAAM,GAAG;AAAA,MACzB,SAAS,OAAO;AACd,cAAM,IAAI,MAAM,gCAAgC,IAAI,uBAAuB,EAAE,MAAM,CAAC;AAAA,MACtF;AACA,YAAM,EAAE,YAAY,OAAO,IAAK,UAAU,CAAC;AAC3C,UAAI,OAAO,eAAe,YAAY,OAAO,WAAW,UAAU;AAChE,cAAM,IAAI;AAAA,UACR,gCAAgC,IAAI;AAAA,QACtC;AAAA,MACF;AACA,aAAO,EAAE,YAAY,OAAO;AAAA,IAC9B;AAAA,IACA,MAAM,OAAO,gBAAgB;AAC3B,YAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAM,UAAU,MAAM,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAAA,IACpF;AAAA,EACF;AACF;","names":[]}
|