@veil-cash/sdk 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -406,6 +406,23 @@ interface SubaccountBalances {
406
406
  eth: SubaccountAssetBalance;
407
407
  usdc: SubaccountAssetBalance;
408
408
  }
409
+ /**
410
+ * Private pool balance summary for a specific asset
411
+ */
412
+ interface SubaccountPrivateBalanceStatus {
413
+ privateBalance: string;
414
+ privateBalanceWei: string;
415
+ utxoCount: number;
416
+ spentCount: number;
417
+ unspentCount: number;
418
+ }
419
+ /**
420
+ * Private pool balances for both supported assets
421
+ */
422
+ interface SubaccountPrivateBalances {
423
+ eth: SubaccountPrivateBalanceStatus;
424
+ usdc: SubaccountPrivateBalanceStatus;
425
+ }
409
426
  /**
410
427
  * Queue status for a specific asset
411
428
  */
@@ -423,6 +440,7 @@ interface SubaccountStatusResult {
423
440
  slot: SubaccountSlot;
424
441
  deployed: boolean;
425
442
  balances: SubaccountBalances;
443
+ privateBalances: SubaccountPrivateBalances;
426
444
  queues: {
427
445
  eth: SubaccountQueueStatus;
428
446
  usdc: SubaccountQueueStatus;
@@ -453,6 +471,40 @@ interface SubaccountWithdrawTypedData {
453
471
  deadline: bigint;
454
472
  };
455
473
  }
474
+ /**
475
+ * Options for merging a subaccount's private balance back to the main wallet
476
+ */
477
+ interface SubaccountMergeOptions {
478
+ /** Root private key (VEIL_KEY) */
479
+ rootPrivateKey: `0x${string}`;
480
+ /** Subaccount slot (0-2) */
481
+ slot: number;
482
+ /** Pool to merge in (default: 'eth') */
483
+ pool?: RelayPool;
484
+ /** Optional RPC URL */
485
+ rpcUrl?: string;
486
+ /** Optional relay URL */
487
+ relayUrl?: string;
488
+ /** Progress callback */
489
+ onProgress?: (stage: string, detail?: string) => void;
490
+ }
491
+ /**
492
+ * Result from merging a subaccount's balance to the main wallet
493
+ */
494
+ interface SubaccountMergeResult {
495
+ /** Whether the merge was successful */
496
+ success: boolean;
497
+ /** Transaction hash */
498
+ transactionHash: string;
499
+ /** Block number of the transaction */
500
+ blockNumber: string;
501
+ /** Amount merged (human-readable) */
502
+ amount: string;
503
+ /** Subaccount slot that was merged */
504
+ slot: number;
505
+ /** Pool the merge was executed in */
506
+ pool: RelayPool;
507
+ }
456
508
  /**
457
509
  * Built recovery transaction and signing metadata
458
510
  */
@@ -766,6 +818,31 @@ declare function getQueueBalance(options: {
766
818
  rpcUrl?: string;
767
819
  onProgress?: ProgressCallback;
768
820
  }): Promise<QueueBalanceResult>;
821
+ /**
822
+ * Get remaining daily free deposits for an address.
823
+ * Returns 0 if the queue contract has not been upgraded to V3 yet
824
+ * or if the daily free feature is disabled.
825
+ *
826
+ * @param options - Query options
827
+ * @param options.address - Depositor address to check
828
+ * @param options.pool - Pool identifier ('eth' or 'usdc', default: 'eth')
829
+ * @param options.rpcUrl - Optional RPC URL
830
+ * @returns Number of free deposits remaining today
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * const remaining = await getDailyFreeRemaining({
835
+ * address: '0x...',
836
+ * pool: 'eth',
837
+ * });
838
+ * console.log(`Free deposits left today: ${remaining}`);
839
+ * ```
840
+ */
841
+ declare function getDailyFreeRemaining(options: {
842
+ address: `0x${string}`;
843
+ pool?: RelayPool;
844
+ rpcUrl?: string;
845
+ }): Promise<number>;
769
846
  /**
770
847
  * Get private balance from the Pool contract
771
848
  * Decrypts all encrypted outputs, calculates nullifiers, and checks spent status
@@ -1596,6 +1673,18 @@ declare const QUEUE_ABI: readonly [{
1596
1673
  }];
1597
1674
  readonly stateMutability: "view";
1598
1675
  readonly type: "function";
1676
+ }, {
1677
+ readonly inputs: readonly [{
1678
+ readonly name: "_depositor";
1679
+ readonly type: "address";
1680
+ }];
1681
+ readonly name: "getDailyFreeRemaining";
1682
+ readonly outputs: readonly [{
1683
+ readonly name: "remaining";
1684
+ readonly type: "uint256";
1685
+ }];
1686
+ readonly stateMutability: "view";
1687
+ readonly type: "function";
1599
1688
  }];
1600
1689
  /**
1601
1690
  * ETH Pool Contract ABI
@@ -2587,8 +2676,17 @@ declare function isSubaccountForwarderDeployed(options: {
2587
2676
  forwarderAddress: `0x${string}`;
2588
2677
  rpcUrl?: string;
2589
2678
  }): Promise<boolean>;
2590
- declare function deploySubaccountForwarder(options: SubaccountDeployRequest): Promise<SubaccountRelayResult>;
2679
+ declare function deploySubaccountForwarder(options: SubaccountDeployRequest): Promise<SubaccountRelayResult & {
2680
+ slot: SubaccountSlot;
2681
+ }>;
2591
2682
  declare function sweepSubaccountForwarder(options: SubaccountSweepRequest): Promise<SubaccountRelayResult>;
2683
+ declare function getSubaccountPrivateBalance(options: {
2684
+ rootPrivateKey: `0x${string}`;
2685
+ slot: number;
2686
+ pool?: 'eth' | 'usdc';
2687
+ rpcUrl?: string;
2688
+ onProgress?: (stage: string, detail?: string) => void;
2689
+ }): Promise<PrivateBalanceResult>;
2592
2690
  declare function getSubaccountStatus(options: {
2593
2691
  rootPrivateKey: `0x${string}`;
2594
2692
  slot: number;
@@ -2627,6 +2725,27 @@ declare function buildSubaccountRecoveryTx(options: {
2627
2725
  deadline?: bigint | number;
2628
2726
  rpcUrl?: string;
2629
2727
  }): Promise<SubaccountRecoveryResult>;
2728
+ /**
2729
+ * Merge a subaccount's entire private balance back to the main wallet.
2730
+ *
2731
+ * Builds a ZK transfer proof that moves every unspent UTXO belonging to the
2732
+ * child keypair into a new UTXO encrypted to the parent (root) keypair,
2733
+ * then submits it via the relay.
2734
+ *
2735
+ * @param options - Merge options
2736
+ * @returns Merge result with transaction hash and amount
2737
+ *
2738
+ * @example
2739
+ * ```typescript
2740
+ * const result = await mergeSubaccount({
2741
+ * rootPrivateKey: process.env.VEIL_KEY as `0x${string}`,
2742
+ * slot: 0,
2743
+ * pool: 'eth',
2744
+ * });
2745
+ * console.log(`Merged ${result.amount} — tx: ${result.transactionHash}`);
2746
+ * ```
2747
+ */
2748
+ declare function mergeSubaccount(options: SubaccountMergeOptions): Promise<SubaccountMergeResult>;
2630
2749
 
2631
2750
  /**
2632
2751
  * Crypto utilities for Veil SDK
@@ -2697,4 +2816,4 @@ declare function getExtDataHash(extData: ExtDataInput): bigint;
2697
2816
  */
2698
2817
  declare function shuffle<T>(array: T[]): T[];
2699
2818
 
2700
- export { ADDRESSES, type BuildTransferProofOptions, type BuildWithdrawProofOptions, CIRCUIT_CONFIG, type DepositTxOptions, ENTRY_ABI, ERC20_ABI, type EncryptedMessage, type ExtData, type ExtDataInput, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, type MessageSigner, type NetworkAddresses, POOL_ABI, POOL_CONFIG, type PendingDeposit, type PoolConfig, type PrepareTransactionParams, type PrivateBalanceResult, type ProgressCallback, type ProofArgs, type ProofBuildResult, type ProofInput, QUEUE_ABI, type QueueBalanceResult, type RegisterTxOptions, RelayError, type RelayErrorResponse, type RelayExtData, type RelayMetadata, type RelayPool, type RelayProofArgs, type RelayRequest, type RelayResponse, type RelayType, type SubaccountAsset, type SubaccountAssetBalance, type SubaccountBalances, type SubaccountDeployRequest, type SubaccountQueueStatus, type SubaccountRecoveryResult, type SubaccountRelayResult, type SubaccountSlot, type SubaccountStatusResult, type SubaccountSweepRequest, type SubaccountWithdrawTypedData, type SubmitRelayOptions, type Token, type TransactionData, type TransactionResult, type TransferResult, Utxo, type UtxoInfo, type UtxoParams, type UtxoSelectionResult, VEIL_SIGNED_MESSAGE, type WithdrawResult, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2819
+ export { ADDRESSES, type BuildTransferProofOptions, type BuildWithdrawProofOptions, CIRCUIT_CONFIG, type DepositTxOptions, ENTRY_ABI, ERC20_ABI, type EncryptedMessage, type ExtData, type ExtDataInput, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, type MessageSigner, type NetworkAddresses, POOL_ABI, POOL_CONFIG, type PendingDeposit, type PoolConfig, type PrepareTransactionParams, type PrivateBalanceResult, type ProgressCallback, type ProofArgs, type ProofBuildResult, type ProofInput, QUEUE_ABI, type QueueBalanceResult, type RegisterTxOptions, RelayError, type RelayErrorResponse, type RelayExtData, type RelayMetadata, type RelayPool, type RelayProofArgs, type RelayRequest, type RelayResponse, type RelayType, type SubaccountAsset, type SubaccountAssetBalance, type SubaccountBalances, type SubaccountDeployRequest, type SubaccountMergeOptions, type SubaccountMergeResult, type SubaccountPrivateBalanceStatus, type SubaccountPrivateBalances, type SubaccountQueueStatus, type SubaccountRecoveryResult, type SubaccountRelayResult, type SubaccountSlot, type SubaccountStatusResult, type SubaccountSweepRequest, type SubaccountWithdrawTypedData, type SubmitRelayOptions, type Token, type TransactionData, type TransactionResult, type TransferResult, Utxo, type UtxoInfo, type UtxoParams, type UtxoSelectionResult, VEIL_SIGNED_MESSAGE, type WithdrawResult, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getDailyFreeRemaining, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountPrivateBalance, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeSubaccount, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
package/dist/index.d.ts CHANGED
@@ -406,6 +406,23 @@ interface SubaccountBalances {
406
406
  eth: SubaccountAssetBalance;
407
407
  usdc: SubaccountAssetBalance;
408
408
  }
409
+ /**
410
+ * Private pool balance summary for a specific asset
411
+ */
412
+ interface SubaccountPrivateBalanceStatus {
413
+ privateBalance: string;
414
+ privateBalanceWei: string;
415
+ utxoCount: number;
416
+ spentCount: number;
417
+ unspentCount: number;
418
+ }
419
+ /**
420
+ * Private pool balances for both supported assets
421
+ */
422
+ interface SubaccountPrivateBalances {
423
+ eth: SubaccountPrivateBalanceStatus;
424
+ usdc: SubaccountPrivateBalanceStatus;
425
+ }
409
426
  /**
410
427
  * Queue status for a specific asset
411
428
  */
@@ -423,6 +440,7 @@ interface SubaccountStatusResult {
423
440
  slot: SubaccountSlot;
424
441
  deployed: boolean;
425
442
  balances: SubaccountBalances;
443
+ privateBalances: SubaccountPrivateBalances;
426
444
  queues: {
427
445
  eth: SubaccountQueueStatus;
428
446
  usdc: SubaccountQueueStatus;
@@ -453,6 +471,40 @@ interface SubaccountWithdrawTypedData {
453
471
  deadline: bigint;
454
472
  };
455
473
  }
474
+ /**
475
+ * Options for merging a subaccount's private balance back to the main wallet
476
+ */
477
+ interface SubaccountMergeOptions {
478
+ /** Root private key (VEIL_KEY) */
479
+ rootPrivateKey: `0x${string}`;
480
+ /** Subaccount slot (0-2) */
481
+ slot: number;
482
+ /** Pool to merge in (default: 'eth') */
483
+ pool?: RelayPool;
484
+ /** Optional RPC URL */
485
+ rpcUrl?: string;
486
+ /** Optional relay URL */
487
+ relayUrl?: string;
488
+ /** Progress callback */
489
+ onProgress?: (stage: string, detail?: string) => void;
490
+ }
491
+ /**
492
+ * Result from merging a subaccount's balance to the main wallet
493
+ */
494
+ interface SubaccountMergeResult {
495
+ /** Whether the merge was successful */
496
+ success: boolean;
497
+ /** Transaction hash */
498
+ transactionHash: string;
499
+ /** Block number of the transaction */
500
+ blockNumber: string;
501
+ /** Amount merged (human-readable) */
502
+ amount: string;
503
+ /** Subaccount slot that was merged */
504
+ slot: number;
505
+ /** Pool the merge was executed in */
506
+ pool: RelayPool;
507
+ }
456
508
  /**
457
509
  * Built recovery transaction and signing metadata
458
510
  */
@@ -766,6 +818,31 @@ declare function getQueueBalance(options: {
766
818
  rpcUrl?: string;
767
819
  onProgress?: ProgressCallback;
768
820
  }): Promise<QueueBalanceResult>;
821
+ /**
822
+ * Get remaining daily free deposits for an address.
823
+ * Returns 0 if the queue contract has not been upgraded to V3 yet
824
+ * or if the daily free feature is disabled.
825
+ *
826
+ * @param options - Query options
827
+ * @param options.address - Depositor address to check
828
+ * @param options.pool - Pool identifier ('eth' or 'usdc', default: 'eth')
829
+ * @param options.rpcUrl - Optional RPC URL
830
+ * @returns Number of free deposits remaining today
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * const remaining = await getDailyFreeRemaining({
835
+ * address: '0x...',
836
+ * pool: 'eth',
837
+ * });
838
+ * console.log(`Free deposits left today: ${remaining}`);
839
+ * ```
840
+ */
841
+ declare function getDailyFreeRemaining(options: {
842
+ address: `0x${string}`;
843
+ pool?: RelayPool;
844
+ rpcUrl?: string;
845
+ }): Promise<number>;
769
846
  /**
770
847
  * Get private balance from the Pool contract
771
848
  * Decrypts all encrypted outputs, calculates nullifiers, and checks spent status
@@ -1596,6 +1673,18 @@ declare const QUEUE_ABI: readonly [{
1596
1673
  }];
1597
1674
  readonly stateMutability: "view";
1598
1675
  readonly type: "function";
1676
+ }, {
1677
+ readonly inputs: readonly [{
1678
+ readonly name: "_depositor";
1679
+ readonly type: "address";
1680
+ }];
1681
+ readonly name: "getDailyFreeRemaining";
1682
+ readonly outputs: readonly [{
1683
+ readonly name: "remaining";
1684
+ readonly type: "uint256";
1685
+ }];
1686
+ readonly stateMutability: "view";
1687
+ readonly type: "function";
1599
1688
  }];
1600
1689
  /**
1601
1690
  * ETH Pool Contract ABI
@@ -2587,8 +2676,17 @@ declare function isSubaccountForwarderDeployed(options: {
2587
2676
  forwarderAddress: `0x${string}`;
2588
2677
  rpcUrl?: string;
2589
2678
  }): Promise<boolean>;
2590
- declare function deploySubaccountForwarder(options: SubaccountDeployRequest): Promise<SubaccountRelayResult>;
2679
+ declare function deploySubaccountForwarder(options: SubaccountDeployRequest): Promise<SubaccountRelayResult & {
2680
+ slot: SubaccountSlot;
2681
+ }>;
2591
2682
  declare function sweepSubaccountForwarder(options: SubaccountSweepRequest): Promise<SubaccountRelayResult>;
2683
+ declare function getSubaccountPrivateBalance(options: {
2684
+ rootPrivateKey: `0x${string}`;
2685
+ slot: number;
2686
+ pool?: 'eth' | 'usdc';
2687
+ rpcUrl?: string;
2688
+ onProgress?: (stage: string, detail?: string) => void;
2689
+ }): Promise<PrivateBalanceResult>;
2592
2690
  declare function getSubaccountStatus(options: {
2593
2691
  rootPrivateKey: `0x${string}`;
2594
2692
  slot: number;
@@ -2627,6 +2725,27 @@ declare function buildSubaccountRecoveryTx(options: {
2627
2725
  deadline?: bigint | number;
2628
2726
  rpcUrl?: string;
2629
2727
  }): Promise<SubaccountRecoveryResult>;
2728
+ /**
2729
+ * Merge a subaccount's entire private balance back to the main wallet.
2730
+ *
2731
+ * Builds a ZK transfer proof that moves every unspent UTXO belonging to the
2732
+ * child keypair into a new UTXO encrypted to the parent (root) keypair,
2733
+ * then submits it via the relay.
2734
+ *
2735
+ * @param options - Merge options
2736
+ * @returns Merge result with transaction hash and amount
2737
+ *
2738
+ * @example
2739
+ * ```typescript
2740
+ * const result = await mergeSubaccount({
2741
+ * rootPrivateKey: process.env.VEIL_KEY as `0x${string}`,
2742
+ * slot: 0,
2743
+ * pool: 'eth',
2744
+ * });
2745
+ * console.log(`Merged ${result.amount} — tx: ${result.transactionHash}`);
2746
+ * ```
2747
+ */
2748
+ declare function mergeSubaccount(options: SubaccountMergeOptions): Promise<SubaccountMergeResult>;
2630
2749
 
2631
2750
  /**
2632
2751
  * Crypto utilities for Veil SDK
@@ -2697,4 +2816,4 @@ declare function getExtDataHash(extData: ExtDataInput): bigint;
2697
2816
  */
2698
2817
  declare function shuffle<T>(array: T[]): T[];
2699
2818
 
2700
- export { ADDRESSES, type BuildTransferProofOptions, type BuildWithdrawProofOptions, CIRCUIT_CONFIG, type DepositTxOptions, ENTRY_ABI, ERC20_ABI, type EncryptedMessage, type ExtData, type ExtDataInput, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, type MessageSigner, type NetworkAddresses, POOL_ABI, POOL_CONFIG, type PendingDeposit, type PoolConfig, type PrepareTransactionParams, type PrivateBalanceResult, type ProgressCallback, type ProofArgs, type ProofBuildResult, type ProofInput, QUEUE_ABI, type QueueBalanceResult, type RegisterTxOptions, RelayError, type RelayErrorResponse, type RelayExtData, type RelayMetadata, type RelayPool, type RelayProofArgs, type RelayRequest, type RelayResponse, type RelayType, type SubaccountAsset, type SubaccountAssetBalance, type SubaccountBalances, type SubaccountDeployRequest, type SubaccountQueueStatus, type SubaccountRecoveryResult, type SubaccountRelayResult, type SubaccountSlot, type SubaccountStatusResult, type SubaccountSweepRequest, type SubaccountWithdrawTypedData, type SubmitRelayOptions, type Token, type TransactionData, type TransactionResult, type TransferResult, Utxo, type UtxoInfo, type UtxoParams, type UtxoSelectionResult, VEIL_SIGNED_MESSAGE, type WithdrawResult, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2819
+ export { ADDRESSES, type BuildTransferProofOptions, type BuildWithdrawProofOptions, CIRCUIT_CONFIG, type DepositTxOptions, ENTRY_ABI, ERC20_ABI, type EncryptedMessage, type ExtData, type ExtDataInput, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, type MessageSigner, type NetworkAddresses, POOL_ABI, POOL_CONFIG, type PendingDeposit, type PoolConfig, type PrepareTransactionParams, type PrivateBalanceResult, type ProgressCallback, type ProofArgs, type ProofBuildResult, type ProofInput, QUEUE_ABI, type QueueBalanceResult, type RegisterTxOptions, RelayError, type RelayErrorResponse, type RelayExtData, type RelayMetadata, type RelayPool, type RelayProofArgs, type RelayRequest, type RelayResponse, type RelayType, type SubaccountAsset, type SubaccountAssetBalance, type SubaccountBalances, type SubaccountDeployRequest, type SubaccountMergeOptions, type SubaccountMergeResult, type SubaccountPrivateBalanceStatus, type SubaccountPrivateBalances, type SubaccountQueueStatus, type SubaccountRecoveryResult, type SubaccountRelayResult, type SubaccountSlot, type SubaccountStatusResult, type SubaccountSweepRequest, type SubaccountWithdrawTypedData, type SubmitRelayOptions, type Token, type TransactionData, type TransactionResult, type TransferResult, Utxo, type UtxoInfo, type UtxoParams, type UtxoSelectionResult, VEIL_SIGNED_MESSAGE, type WithdrawResult, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getDailyFreeRemaining, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountPrivateBalance, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeSubaccount, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
package/dist/index.js CHANGED
@@ -597,6 +597,14 @@ var QUEUE_ABI = [
597
597
  outputs: [{ name: "count", type: "uint256" }],
598
598
  stateMutability: "view",
599
599
  type: "function"
600
+ },
601
+ // Get remaining daily free deposits for an address (V3+)
602
+ {
603
+ inputs: [{ name: "_depositor", type: "address" }],
604
+ name: "getDailyFreeRemaining",
605
+ outputs: [{ name: "remaining", type: "uint256" }],
606
+ stateMutability: "view",
607
+ type: "function"
600
608
  }
601
609
  ];
602
610
  var POOL_ABI = [
@@ -1314,6 +1322,25 @@ async function getQueueBalance(options) {
1314
1322
  pendingCount: pendingDeposits.length
1315
1323
  };
1316
1324
  }
1325
+ async function getDailyFreeRemaining(options) {
1326
+ const { address, pool = "eth", rpcUrl } = options;
1327
+ const queueAddress = getQueueAddress(pool);
1328
+ const publicClient = createPublicClient({
1329
+ chain: base,
1330
+ transport: http(rpcUrl)
1331
+ });
1332
+ try {
1333
+ const remaining = await publicClient.readContract({
1334
+ address: queueAddress,
1335
+ abi: QUEUE_ABI,
1336
+ functionName: "getDailyFreeRemaining",
1337
+ args: [address]
1338
+ });
1339
+ return Number(remaining);
1340
+ } catch {
1341
+ return 0;
1342
+ }
1343
+ }
1317
1344
  async function getPrivateBalance(options) {
1318
1345
  const { keypair, pool = "eth", rpcUrl, onProgress } = options;
1319
1346
  const poolAddress = getPoolAddress(pool);
@@ -1641,7 +1668,16 @@ async function postRelayJson(endpoint, body, relayUrl) {
1641
1668
  },
1642
1669
  body: JSON.stringify(body)
1643
1670
  });
1644
- const data = await response.json();
1671
+ const text = await response.text();
1672
+ let data;
1673
+ try {
1674
+ data = JSON.parse(text);
1675
+ } catch {
1676
+ throw new RelayError(
1677
+ `Relay returned non-JSON response (HTTP ${response.status})`,
1678
+ response.status
1679
+ );
1680
+ }
1645
1681
  if (!response.ok) {
1646
1682
  const errorData = data;
1647
1683
  throw new RelayError(
@@ -2213,11 +2249,12 @@ function deriveSubaccountChildDepositKey(childPrivateKey) {
2213
2249
  }
2214
2250
  async function predictSubaccountForwarder(options) {
2215
2251
  const publicClient = createBaseClient(options.rpcUrl);
2252
+ const depositKeyBytes = options.childDepositKey.startsWith("0x") ? options.childDepositKey : `0x${options.childDepositKey}`;
2216
2253
  return publicClient.readContract({
2217
2254
  abi: FORWARDER_FACTORY_ABI,
2218
2255
  address: getForwarderFactoryAddress(),
2219
2256
  functionName: "computeAddress",
2220
- args: [options.salt, options.childDepositKey, options.childOwner]
2257
+ args: [options.salt, depositKeyBytes, options.childOwner]
2221
2258
  });
2222
2259
  }
2223
2260
  async function deriveSubaccountSlot(options) {
@@ -2254,7 +2291,7 @@ async function deploySubaccountForwarder(options) {
2254
2291
  slot: options.slot,
2255
2292
  rpcUrl: options.rpcUrl
2256
2293
  });
2257
- return postRelayJson(
2294
+ const result = await postRelayJson(
2258
2295
  "/stealth/deploy",
2259
2296
  {
2260
2297
  salt: slot.salt,
@@ -2264,6 +2301,7 @@ async function deploySubaccountForwarder(options) {
2264
2301
  },
2265
2302
  options.relayUrl
2266
2303
  );
2304
+ return { ...result, slot };
2267
2305
  }
2268
2306
  async function sweepSubaccountForwarder(options) {
2269
2307
  const asset = normalizeAsset(options.asset);
@@ -2288,11 +2326,32 @@ function toQueueStatus(asset, result) {
2288
2326
  pendingDeposits: result.pendingDeposits
2289
2327
  };
2290
2328
  }
2329
+ function toPrivateBalanceStatus(result) {
2330
+ return {
2331
+ privateBalance: result.privateBalance,
2332
+ privateBalanceWei: result.privateBalanceWei,
2333
+ utxoCount: result.utxoCount,
2334
+ spentCount: result.spentCount,
2335
+ unspentCount: result.unspentCount
2336
+ };
2337
+ }
2338
+ async function getSubaccountPrivateBalance(options) {
2339
+ const normalizedSlot = normalizeSlot(options.slot);
2340
+ assertPrivateKey(options.rootPrivateKey, "rootPrivateKey");
2341
+ const childPrivateKey = deriveSubaccountChildPrivateKey(options.rootPrivateKey, normalizedSlot);
2342
+ const childKeypair = new Keypair(childPrivateKey);
2343
+ return getPrivateBalance({
2344
+ keypair: childKeypair,
2345
+ pool: options.pool,
2346
+ rpcUrl: options.rpcUrl,
2347
+ onProgress: options.onProgress
2348
+ });
2349
+ }
2291
2350
  async function getSubaccountStatus(options) {
2292
2351
  const slot = await deriveSubaccountSlot(options);
2293
2352
  const publicClient = createBaseClient(options.rpcUrl);
2294
2353
  const addresses = getAddresses();
2295
- const [deployed, ethWei, usdcWei, ethQueue, usdcQueue] = await Promise.all([
2354
+ const [deployed, ethWei, usdcWei, ethQueue, usdcQueue, ethPrivate, usdcPrivate] = await Promise.all([
2296
2355
  isSubaccountForwarderDeployed({
2297
2356
  forwarderAddress: slot.forwarderAddress,
2298
2357
  rpcUrl: options.rpcUrl
@@ -2313,6 +2372,18 @@ async function getSubaccountStatus(options) {
2313
2372
  address: slot.forwarderAddress,
2314
2373
  pool: "usdc",
2315
2374
  rpcUrl: options.rpcUrl
2375
+ }),
2376
+ getSubaccountPrivateBalance({
2377
+ rootPrivateKey: options.rootPrivateKey,
2378
+ slot: options.slot,
2379
+ pool: "eth",
2380
+ rpcUrl: options.rpcUrl
2381
+ }),
2382
+ getSubaccountPrivateBalance({
2383
+ rootPrivateKey: options.rootPrivateKey,
2384
+ slot: options.slot,
2385
+ pool: "usdc",
2386
+ rpcUrl: options.rpcUrl
2316
2387
  })
2317
2388
  ]);
2318
2389
  return {
@@ -2328,6 +2399,10 @@ async function getSubaccountStatus(options) {
2328
2399
  balanceWei: usdcWei.toString()
2329
2400
  }
2330
2401
  },
2402
+ privateBalances: {
2403
+ eth: toPrivateBalanceStatus(ethPrivate),
2404
+ usdc: toPrivateBalanceStatus(usdcPrivate)
2405
+ },
2331
2406
  queues: {
2332
2407
  eth: toQueueStatus("eth", ethQueue),
2333
2408
  usdc: toQueueStatus("usdc", usdcQueue)
@@ -2474,7 +2549,138 @@ async function buildSubaccountRecoveryTx(options) {
2474
2549
  signature
2475
2550
  };
2476
2551
  }
2552
+ async function mergeSubaccount(options) {
2553
+ const {
2554
+ rootPrivateKey,
2555
+ slot,
2556
+ pool = "eth",
2557
+ rpcUrl,
2558
+ relayUrl,
2559
+ onProgress
2560
+ } = options;
2561
+ const normalizedSlot = normalizeSlot(slot);
2562
+ assertPrivateKey(rootPrivateKey, "rootPrivateKey");
2563
+ const poolConfig = POOL_CONFIG[pool];
2564
+ const poolAddress = getPoolAddress(pool);
2565
+ const childPrivateKey = deriveSubaccountChildPrivateKey(rootPrivateKey, normalizedSlot);
2566
+ const childKeypair = new Keypair(childPrivateKey);
2567
+ const parentKeypair = new Keypair(rootPrivateKey);
2568
+ onProgress?.("Fetching subaccount balance...");
2569
+ const balanceResult = await getPrivateBalance({
2570
+ keypair: childKeypair,
2571
+ pool,
2572
+ rpcUrl,
2573
+ onProgress
2574
+ });
2575
+ const unspentUtxoInfos = balanceResult.utxos.filter((u) => !u.isSpent);
2576
+ if (unspentUtxoInfos.length === 0) {
2577
+ throw new Error("Subaccount has no unspent UTXOs to merge");
2578
+ }
2579
+ if (unspentUtxoInfos.length > 16) {
2580
+ throw new Error(
2581
+ `Subaccount has ${unspentUtxoInfos.length} unspent UTXOs which exceeds the 16-input circuit limit. Consolidate UTXOs on the subaccount first before merging.`
2582
+ );
2583
+ }
2584
+ onProgress?.("Preparing UTXOs...");
2585
+ const publicClient = createPublicClient({
2586
+ chain: base,
2587
+ transport: http(rpcUrl)
2588
+ });
2589
+ const utxos = [];
2590
+ for (const utxoInfo of unspentUtxoInfos) {
2591
+ const encryptedOutputs = await publicClient.readContract({
2592
+ address: poolAddress,
2593
+ abi: POOL_ABI,
2594
+ functionName: "getEncryptedOutputs",
2595
+ args: [BigInt(utxoInfo.index), BigInt(utxoInfo.index + 1)]
2596
+ });
2597
+ if (encryptedOutputs.length > 0) {
2598
+ try {
2599
+ const utxo = Utxo.decrypt(encryptedOutputs[0], childKeypair);
2600
+ utxo.index = utxoInfo.index;
2601
+ utxos.push(utxo);
2602
+ } catch {
2603
+ }
2604
+ }
2605
+ }
2606
+ if (utxos.length === 0) {
2607
+ throw new Error("Failed to decrypt subaccount UTXOs");
2608
+ }
2609
+ onProgress?.("Selecting UTXOs...");
2610
+ const amount = balanceResult.privateBalance;
2611
+ const { selectedUtxos, changeAmount } = selectUtxosForWithdraw(
2612
+ utxos,
2613
+ amount,
2614
+ poolConfig.decimals
2615
+ );
2616
+ const outputs = [];
2617
+ const mergeWei = parseUnits(amount, poolConfig.decimals);
2618
+ outputs.push(new Utxo({ amount: mergeWei, keypair: parentKeypair }));
2619
+ if (changeAmount > 0n) {
2620
+ outputs.push(new Utxo({ amount: changeAmount, keypair: parentKeypair }));
2621
+ }
2622
+ onProgress?.("Fetching commitments...");
2623
+ const nextIndex = await publicClient.readContract({
2624
+ address: poolAddress,
2625
+ abi: POOL_ABI,
2626
+ functionName: "nextIndex"
2627
+ });
2628
+ const BATCH_SIZE = 5e3;
2629
+ const commitments = [];
2630
+ const totalBatches = Math.ceil(nextIndex / BATCH_SIZE);
2631
+ for (let start = 0; start < nextIndex; start += BATCH_SIZE) {
2632
+ const end = Math.min(start + BATCH_SIZE, nextIndex);
2633
+ const batchNum = Math.floor(start / BATCH_SIZE) + 1;
2634
+ onProgress?.("Fetching commitments", `batch ${batchNum}/${totalBatches}`);
2635
+ const batch = await publicClient.readContract({
2636
+ address: poolAddress,
2637
+ abi: POOL_ABI,
2638
+ functionName: "getCommitments",
2639
+ args: [BigInt(start), BigInt(end)]
2640
+ });
2641
+ commitments.push(...batch.map((c) => c.toString()));
2642
+ }
2643
+ onProgress?.("Building ZK proof...");
2644
+ const result = await prepareTransaction({
2645
+ commitments,
2646
+ inputs: selectedUtxos,
2647
+ outputs,
2648
+ fee: 0,
2649
+ recipient: "0x0000000000000000000000000000000000000000",
2650
+ relayer: "0x0000000000000000000000000000000000000000",
2651
+ onProgress
2652
+ });
2653
+ onProgress?.("Submitting to relay...");
2654
+ const relayResult = await submitRelay({
2655
+ type: "transfer",
2656
+ pool,
2657
+ relayUrl,
2658
+ proofArgs: {
2659
+ proof: result.args.proof,
2660
+ root: result.args.root,
2661
+ inputNullifiers: result.args.inputNullifiers,
2662
+ outputCommitments: result.args.outputCommitments,
2663
+ publicAmount: result.args.publicAmount,
2664
+ extDataHash: result.args.extDataHash
2665
+ },
2666
+ extData: result.extData,
2667
+ metadata: {
2668
+ amount,
2669
+ recipient: "self",
2670
+ inputUtxoCount: selectedUtxos.length,
2671
+ outputUtxoCount: outputs.length
2672
+ }
2673
+ });
2674
+ return {
2675
+ success: relayResult.success,
2676
+ transactionHash: relayResult.transactionHash,
2677
+ blockNumber: relayResult.blockNumber,
2678
+ amount,
2679
+ slot: normalizedSlot,
2680
+ pool
2681
+ };
2682
+ }
2477
2683
 
2478
- export { ADDRESSES, CIRCUIT_CONFIG, ENTRY_ABI, ERC20_ABI, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, POOL_ABI, POOL_CONFIG, QUEUE_ABI, RelayError, Utxo, VEIL_SIGNED_MESSAGE, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2684
+ export { ADDRESSES, CIRCUIT_CONFIG, ENTRY_ABI, ERC20_ABI, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, POOL_ABI, POOL_CONFIG, QUEUE_ABI, RelayError, Utxo, VEIL_SIGNED_MESSAGE, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getDailyFreeRemaining, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountPrivateBalance, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeSubaccount, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2479
2685
  //# sourceMappingURL=index.js.map
2480
2686
  //# sourceMappingURL=index.js.map