@umbra-privacy/sdk 1.0.0 → 2.0.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.
Files changed (181) hide show
  1. package/README.md +104 -25
  2. package/dist/{addresses-Brzgurv_.d.ts → addresses-B7HybtbJ.d.ts} +2 -1
  3. package/dist/{addresses-D_0YAS6B.d.cts → addresses-CTVY1oi7.d.cts} +2 -1
  4. package/dist/arcium-BXXlryfe.d.cts +20 -0
  5. package/dist/arcium-BXXlryfe.d.ts +20 -0
  6. package/dist/chunk-3LS5P32X.cjs +10892 -0
  7. package/dist/chunk-3LS5P32X.cjs.map +1 -0
  8. package/dist/chunk-4RHXVBNI.js +203 -0
  9. package/dist/chunk-4RHXVBNI.js.map +1 -0
  10. package/dist/chunk-4TZVXB5G.js +324 -0
  11. package/dist/chunk-4TZVXB5G.js.map +1 -0
  12. package/dist/chunk-5GUSMQ74.cjs +549 -0
  13. package/dist/chunk-5GUSMQ74.cjs.map +1 -0
  14. package/dist/chunk-5KPQXPQM.js +36 -0
  15. package/dist/chunk-5KPQXPQM.js.map +1 -0
  16. package/dist/chunk-AXD7LXYY.cjs +405 -0
  17. package/dist/chunk-AXD7LXYY.cjs.map +1 -0
  18. package/dist/{chunk-HOEXDXRC.cjs → chunk-BL6WXLPV.cjs} +32 -360
  19. package/dist/chunk-BL6WXLPV.cjs.map +1 -0
  20. package/dist/chunk-CFFLOE7D.cjs +598 -0
  21. package/dist/chunk-CFFLOE7D.cjs.map +1 -0
  22. package/dist/{chunk-BM7N6N7E.js → chunk-CFTW5WNG.js} +3 -325
  23. package/dist/chunk-CFTW5WNG.js.map +1 -0
  24. package/dist/chunk-DD2WCK4C.js +327 -0
  25. package/dist/chunk-DD2WCK4C.js.map +1 -0
  26. package/dist/chunk-DMPMQ74B.cjs +246 -0
  27. package/dist/chunk-DMPMQ74B.cjs.map +1 -0
  28. package/dist/{chunk-2Q75CQQJ.js → chunk-EEKF4553.js} +2 -2
  29. package/dist/chunk-EEKF4553.js.map +1 -0
  30. package/dist/chunk-ENVYYEM4.cjs +113 -0
  31. package/dist/chunk-ENVYYEM4.cjs.map +1 -0
  32. package/dist/chunk-FQX6ZYGJ.js +500 -0
  33. package/dist/chunk-FQX6ZYGJ.js.map +1 -0
  34. package/dist/chunk-FSK2ICMB.cjs +39 -0
  35. package/dist/chunk-FSK2ICMB.cjs.map +1 -0
  36. package/dist/chunk-FZYWLQAF.cjs +355 -0
  37. package/dist/chunk-FZYWLQAF.cjs.map +1 -0
  38. package/dist/chunk-GP26R377.js +436 -0
  39. package/dist/chunk-GP26R377.js.map +1 -0
  40. package/dist/chunk-HA5FLM63.js +393 -0
  41. package/dist/chunk-HA5FLM63.js.map +1 -0
  42. package/dist/chunk-INJ73LXQ.js +1107 -0
  43. package/dist/chunk-INJ73LXQ.js.map +1 -0
  44. package/dist/chunk-KMRROOME.js +10750 -0
  45. package/dist/chunk-KMRROOME.js.map +1 -0
  46. package/dist/{chunk-MDFSBU5W.cjs → chunk-LTCKPTZC.cjs} +2 -351
  47. package/dist/chunk-LTCKPTZC.cjs.map +1 -0
  48. package/dist/chunk-MKNCBUFA.js +564 -0
  49. package/dist/chunk-MKNCBUFA.js.map +1 -0
  50. package/dist/chunk-NKVMSABR.cjs +207 -0
  51. package/dist/chunk-NKVMSABR.cjs.map +1 -0
  52. package/dist/chunk-OFDWNWCL.js +70 -0
  53. package/dist/chunk-OFDWNWCL.js.map +1 -0
  54. package/dist/chunk-QJAUUYZU.cjs +331 -0
  55. package/dist/chunk-QJAUUYZU.cjs.map +1 -0
  56. package/dist/chunk-TLR7A64G.js +103 -0
  57. package/dist/chunk-TLR7A64G.js.map +1 -0
  58. package/dist/{chunk-MVKTV3FT.cjs → chunk-TQQZGNOI.cjs} +2 -2
  59. package/dist/chunk-TQQZGNOI.cjs.map +1 -0
  60. package/dist/chunk-UOFYS6M3.js +219 -0
  61. package/dist/chunk-UOFYS6M3.js.map +1 -0
  62. package/dist/chunk-UXMQI6B7.js +2406 -0
  63. package/dist/chunk-UXMQI6B7.js.map +1 -0
  64. package/dist/chunk-WN75ORDT.js +571 -0
  65. package/dist/chunk-WN75ORDT.js.map +1 -0
  66. package/dist/chunk-Y55PYKXH.cjs +595 -0
  67. package/dist/chunk-Y55PYKXH.cjs.map +1 -0
  68. package/dist/chunk-YEZBTYCP.cjs +77 -0
  69. package/dist/chunk-YEZBTYCP.cjs.map +1 -0
  70. package/dist/chunk-ZQOIYCGA.cjs +1126 -0
  71. package/dist/chunk-ZQOIYCGA.cjs.map +1 -0
  72. package/dist/chunk-ZY3TSHMJ.cjs +2665 -0
  73. package/dist/chunk-ZY3TSHMJ.cjs.map +1 -0
  74. package/dist/client-DkVBHMWb.d.cts +2613 -0
  75. package/dist/client-V4AF6Bz9.d.ts +2613 -0
  76. package/dist/common/pda/index.cjs +145 -0
  77. package/dist/common/pda/index.cjs.map +1 -0
  78. package/dist/common/pda/index.d.cts +1250 -0
  79. package/dist/common/pda/index.d.ts +1250 -0
  80. package/dist/common/pda/index.js +8 -0
  81. package/dist/common/pda/index.js.map +1 -0
  82. package/dist/constants/index.cjs +38 -164
  83. package/dist/constants/index.cjs.map +1 -1
  84. package/dist/constants/index.d.cts +8 -425
  85. package/dist/constants/index.d.ts +8 -425
  86. package/dist/constants/index.js +15 -124
  87. package/dist/constants/index.js.map +1 -1
  88. package/dist/crypto/index.cjs +583 -0
  89. package/dist/crypto/index.cjs.map +1 -0
  90. package/dist/crypto/index.d.cts +6731 -0
  91. package/dist/crypto/index.d.ts +6731 -0
  92. package/dist/crypto/index.js +14 -0
  93. package/dist/crypto/index.js.map +1 -0
  94. package/dist/{cryptography-BTGC72u-.d.ts → cryptography-BFSJcvi6.d.ts} +3 -2465
  95. package/dist/{cryptography-BTGC72u-.d.cts → cryptography-D6tPDh-Y.d.cts} +3 -2465
  96. package/dist/errors/index.cjs +64 -54
  97. package/dist/errors/index.d.cts +7 -797
  98. package/dist/errors/index.d.ts +7 -797
  99. package/dist/errors/index.js +3 -1
  100. package/dist/errors-B9EoPeWV.d.cts +593 -0
  101. package/dist/errors-B9EoPeWV.d.ts +593 -0
  102. package/dist/errors-DAIrstEL.d.cts +300 -0
  103. package/dist/errors-DPNMfyh0.d.ts +300 -0
  104. package/dist/index-BG0yjL7C.d.cts +6006 -0
  105. package/dist/index-ByynoyBO.d.ts +6006 -0
  106. package/dist/index.cjs +5133 -16116
  107. package/dist/index.cjs.map +1 -1
  108. package/dist/index.d.cts +1031 -7685
  109. package/dist/index.d.ts +1031 -7685
  110. package/dist/index.js +3228 -14905
  111. package/dist/index.js.map +1 -1
  112. package/dist/interfaces/index.d.cts +14 -6
  113. package/dist/interfaces/index.d.ts +14 -6
  114. package/dist/interfaces-43cReBcS.d.cts +3346 -0
  115. package/dist/interfaces-B8xKNl_6.d.ts +997 -0
  116. package/dist/interfaces-D2NO6kDD.d.cts +997 -0
  117. package/dist/interfaces-z_xYJlgV.d.ts +3346 -0
  118. package/dist/math/index.cjs +115 -0
  119. package/dist/math/index.cjs.map +1 -0
  120. package/dist/math/index.d.cts +1327 -0
  121. package/dist/math/index.d.ts +1327 -0
  122. package/dist/math/index.js +10 -0
  123. package/dist/math/index.js.map +1 -0
  124. package/dist/networks-RMd3abPE.d.ts +44 -0
  125. package/dist/networks-yAoO8peQ.d.cts +44 -0
  126. package/dist/relayer-NRRMSMNB.js +4 -0
  127. package/dist/relayer-NRRMSMNB.js.map +1 -0
  128. package/dist/relayer-RJHEIXJG.cjs +21 -0
  129. package/dist/relayer-RJHEIXJG.cjs.map +1 -0
  130. package/dist/solana/index.cjs +56 -0
  131. package/dist/solana/index.cjs.map +1 -0
  132. package/dist/solana/index.d.cts +105 -0
  133. package/dist/solana/index.d.ts +105 -0
  134. package/dist/solana/index.js +7 -0
  135. package/dist/solana/index.js.map +1 -0
  136. package/dist/{index-CLj_zWSD.d.ts → temporal-BbRaEPoO.d.ts} +1 -1
  137. package/dist/{index-CX6_pIRS.d.cts → temporal-oUj7iCaq.d.cts} +1 -1
  138. package/dist/transaction-forwarder-5mAMTjw6.d.ts +1155 -0
  139. package/dist/transaction-forwarder-C6gMUG7a.d.cts +1155 -0
  140. package/dist/types/index.cjs +232 -231
  141. package/dist/types/index.d.cts +15 -1485
  142. package/dist/types/index.d.ts +15 -1485
  143. package/dist/types/index.js +2 -1
  144. package/dist/types-BohhvPth.d.cts +87 -0
  145. package/dist/types-CW0oTT0j.d.ts +87 -0
  146. package/dist/types-C_V_CaKK.d.cts +2468 -0
  147. package/dist/types-C_V_CaKK.d.ts +2468 -0
  148. package/dist/types-Ca7frykr.d.ts +793 -0
  149. package/dist/types-CuKeoI19.d.cts +1296 -0
  150. package/dist/types-CxfTIpN9.d.ts +1052 -0
  151. package/dist/{types-n-sHFcgr.d.ts → types-D1jDUjfN.d.ts} +2 -2
  152. package/dist/types-DKEDUlH9.d.ts +1296 -0
  153. package/dist/types-EKuIfxTz.d.cts +1052 -0
  154. package/dist/{types-BBuELtY8.d.cts → types-IMGYmlv-.d.cts} +2 -2
  155. package/dist/types-PwNLi_2k.d.cts +793 -0
  156. package/dist/utils/index.cjs +823 -525
  157. package/dist/utils/index.d.cts +1711 -4021
  158. package/dist/utils/index.d.ts +1711 -4021
  159. package/dist/utils/index.js +9 -3
  160. package/dist/{versions-D9PqsEvj.d.cts → versions-BRlR36EA.d.cts} +1 -0
  161. package/dist/{versions-D9PqsEvj.d.ts → versions-BRlR36EA.d.ts} +1 -0
  162. package/package.json +79 -18
  163. package/dist/chunk-2Q75CQQJ.js.map +0 -1
  164. package/dist/chunk-BM7N6N7E.js.map +0 -1
  165. package/dist/chunk-GXKSUB2U.cjs +0 -4416
  166. package/dist/chunk-GXKSUB2U.cjs.map +0 -1
  167. package/dist/chunk-HOEXDXRC.cjs.map +0 -1
  168. package/dist/chunk-MDFSBU5W.cjs.map +0 -1
  169. package/dist/chunk-MQY7HDIA.js +0 -600
  170. package/dist/chunk-MQY7HDIA.js.map +0 -1
  171. package/dist/chunk-MVKTV3FT.cjs.map +0 -1
  172. package/dist/chunk-PG2J6V6Y.js +0 -4094
  173. package/dist/chunk-PG2J6V6Y.js.map +0 -1
  174. package/dist/chunk-VEGLTTYQ.cjs +0 -621
  175. package/dist/chunk-VEGLTTYQ.cjs.map +0 -1
  176. package/dist/chunk-WVHQ46DD.js +0 -758
  177. package/dist/chunk-WVHQ46DD.js.map +0 -1
  178. package/dist/index-B9pDY73x.d.ts +0 -12933
  179. package/dist/index-D33yo0qB.d.cts +0 -12933
  180. package/dist/networks-C-orpSFW.d.ts +0 -65
  181. package/dist/networks-FxYERGD1.d.cts +0 -65
@@ -0,0 +1,2613 @@
1
+ import { Address, Commitment, MaybeEncodedAccount, Blockhash, createSolanaRpc, createSolanaRpcSubscriptions, sendAndConfirmTransactionFactory, Transaction, TransactionWithBlockhashLifetime, SignatureBytes } from '@solana/kit';
2
+ import { j as U32, e as U256LeBytes, k as U64, U as U128, l as U128LeBytes, h as U512 } from './types-C_V_CaKK.js';
3
+ import { A as AesKey, a as AesCiphertextWithMetadata, b as AesPlaintext, X as X25519PublicKey, c as X25519PrivateKey, M as MasterSeed, d as MasterViewingKey, P as PoseidonKey, Y as YearlyViewingKey, e as MonthlyViewingKey, D as DailyViewingKey, f as MintViewingKey, B as Bn254FieldElement, C as Curve25519FieldElement } from './cryptography-BFSJcvi6.js';
4
+ import { S as SignedTransaction, T as TransactionSignature, M as MasterSeedLoaderFunction, a as MasterSeedStorerFunction, b as MasterSeedGeneratorFunction, L as LoaderFunction, c as StorerFunction, G as GeneratorFunction, P as ParameterizedLoaderFunction, d as ParameterizedStorerFunction, e as ParameterizedGeneratorFunction } from './types-CxfTIpN9.js';
5
+ import { Y as Year, M as Month, D as Day, H as Hour, a as Minute, S as Second } from './types-D1jDUjfN.js';
6
+ import { N as Network, f as ProtocolVersionSpecifierFunction, a as AlgorithmVersionSpecifierFunction, g as SchemeVersionSpecifierFunction, e as NetworkSpecifierFunction } from './versions-BRlR36EA.js';
7
+ import { N as NetworkConfig } from './networks-RMd3abPE.js';
8
+
9
+ /**
10
+ * AES Encryption Interfaces
11
+ *
12
+ * This module defines function type interfaces for AES-256-GCM encryption
13
+ * and decryption operations used in UTXO recovery data encryption.
14
+ *
15
+ * ## Overview
16
+ *
17
+ * AES-256-GCM is used in Umbra to encrypt UTXO recovery data, enabling either
18
+ * the sender (ephemeral unlocker) or the receiver (receiver unlocker) to
19
+ * recover the information required to claim a UTXO at a later time. It is
20
+ * distinct from the Rescue cipher used for confidential token account balances.
21
+ *
22
+ * ## Key Derivation
23
+ *
24
+ * - **Ephemeral Unlocker Key**: Derived from `KDF(masterSeed, generationIndex)`.
25
+ * Allows the sender to recover UTXOs they created, even without knowing the
26
+ * recipient's key material.
27
+ * - **Receiver Unlocker Key**: Derived from the X25519 Diffie-Hellman shared
28
+ * secret between the sender's ephemeral private key and the recipient's
29
+ * X25519 public key. Allows the recipient to independently recover the UTXO.
30
+ *
31
+ * ## Ciphertext Format
32
+ *
33
+ * Both functions operate on the following byte layout:
34
+ * ```
35
+ * [IV (12 bytes) | AuthTag (16 bytes) | Ciphertext (N bytes)]
36
+ * ```
37
+ * This format is self-contained: all information needed for decryption (except
38
+ * the key) is present in the byte array.
39
+ *
40
+ * @packageDocumentation
41
+ * @module interfaces/cryptography/aes
42
+ * @public
43
+ */
44
+
45
+ /**
46
+ * Function type for AES-256-GCM encryption.
47
+ *
48
+ * Encrypts plaintext data using AES-256-GCM with the provided key.
49
+ * The function generates a random IV internally and returns a combined
50
+ * ciphertext format: `[IV (12) | AuthTag (16) | Ciphertext (N)]`.
51
+ *
52
+ * @param key - The AES-256 encryption key. Must be exactly 32 bytes.
53
+ * Keys should be derived using a secure KDF (e.g. HKDF, Rescue-Prime).
54
+ * @param plaintext - The data to encrypt. May be any length including zero bytes.
55
+ * For UTXO recovery the plaintext is 68 bytes: amount (8) + modified
56
+ * generation index (16) + destination address (32) + domain separator (12).
57
+ * @returns A promise that resolves to the combined ciphertext byte array with
58
+ * layout `[IV (12) | AuthTag (16) | EncryptedData (N)]`.
59
+ *
60
+ * @remarks
61
+ * ## Implementation Contract
62
+ *
63
+ * Implementations of this type **must** guarantee:
64
+ * 1. A **fresh cryptographically random 12-byte IV** is generated for each call.
65
+ * Reusing an IV with the same key is catastrophic for GCM security.
66
+ * 2. The authentication tag is **128 bits** (16 bytes) as recommended by NIST SP 800-38D.
67
+ * 3. The output is returned in the canonical format `[IV | AuthTag | Ciphertext]`
68
+ * (note: NOT the @noble/ciphers internal order of `[Ciphertext | AuthTag]`).
69
+ * 4. The function is **referentially transparent** given the same key and plaintext
70
+ * except for the random IV (which makes each ciphertext unique).
71
+ *
72
+ * ## Security Considerations
73
+ *
74
+ * - **Never reuse** an IV with the same key. With a 12-byte IV and a CSPRNG, the
75
+ * probability of accidental collision over 2^32 invocations is approximately 2^-32,
76
+ * which is acceptable for practical use.
77
+ * - The 128-bit authentication tag provides strong integrity and authenticity.
78
+ * - AES-GCM is an AEAD scheme: an attacker who modifies any byte of the ciphertext
79
+ * will cause decryption to throw (tag verification failure), protecting against
80
+ * tampering.
81
+ * - The ciphertext is computationally indistinguishable from random bytes.
82
+ *
83
+ * @public
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const encryptor: AesEncryptorFunction = getAesEncryptor();
88
+ *
89
+ * // Derive key from seed + generation index
90
+ * const key = deriveEphemeralUnlockerKey(masterSeed, generationIndex);
91
+ *
92
+ * // Build the UTXO recovery plaintext
93
+ * const plaintext = buildRecoveryPlaintext(amount, genIndex, destination);
94
+ *
95
+ * const ciphertext = await encryptor(key, plaintext);
96
+ * // layout: [IV (12) | AuthTag (16) | EncryptedData (68)] = 96 bytes total
97
+ * ```
98
+ *
99
+ * @see {@link AesDecryptorFunction} — the paired decryption function type
100
+ * @see {@link getAesEncryptor} — factory that returns the default implementation
101
+ * @see {@link defaultAesEncryptor} — pre-instantiated convenience singleton
102
+ */
103
+ type AesEncryptorFunction = (key: AesKey, plaintext: AesPlaintext) => Promise<AesCiphertextWithMetadata>;
104
+ /**
105
+ * Function type for AES-256-GCM decryption.
106
+ *
107
+ * Decrypts ciphertext data using AES-256-GCM with the provided key.
108
+ * The function expects the combined ciphertext format and extracts the
109
+ * IV and authentication tag from the input before decryption.
110
+ *
111
+ * @param key - The AES-256 decryption key. Must be exactly 32 bytes.
112
+ * Must be the same key that was used during encryption.
113
+ * @param ciphertext - The combined ciphertext byte array in the format
114
+ * `[IV (12) | AuthTag (16) | EncryptedData (N)]`. Minimum 28 bytes.
115
+ * @returns A promise that resolves to the decrypted plaintext as an
116
+ * {@link AesPlaintext} byte array.
117
+ *
118
+ * @throws {Error} If the 128-bit authentication tag fails verification. This
119
+ * occurs when the wrong key is provided or when any byte of the ciphertext
120
+ * has been modified. The error message is intentionally generic to avoid
121
+ * leaking information about which byte caused the failure.
122
+ * @throws {Error} If `key` is not a valid 32-byte {@link AesKey}.
123
+ * @throws {Error} If `ciphertext` is not a valid {@link AesCiphertextWithMetadata}
124
+ * (less than 28 bytes = IV + AuthTag minimum).
125
+ *
126
+ * @remarks
127
+ * ## Implementation Contract
128
+ *
129
+ * Implementations of this type **must** guarantee:
130
+ * 1. **IV extraction**: bytes 0–11 of `ciphertext` are used as the GCM IV.
131
+ * 2. **AuthTag extraction**: bytes 12–27 are used as the 128-bit authentication tag.
132
+ * 3. **Ciphertext body**: bytes 28+ are the encrypted data.
133
+ * 4. **Authentication before decryption**: The authentication tag is verified in
134
+ * constant time **before** any plaintext is returned. Partial plaintext
135
+ * must not be exposed on authentication failure.
136
+ * 5. On success, the returned plaintext is a fresh {@link AesPlaintext} byte array.
137
+ *
138
+ * ## Security Considerations
139
+ *
140
+ * - Authentication failure indicates either the wrong key or tampered bytes.
141
+ * The caller **must not** use any partially decrypted output on failure.
142
+ * - Catch authentication errors and treat them as hard failures; do not retry
143
+ * with a modified ciphertext (this would constitute an oracle attack surface).
144
+ * - Clear sensitive decrypted plaintext from memory as soon as it is processed.
145
+ *
146
+ * @public
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * const decryptor: AesDecryptorFunction = getAesDecryptor();
151
+ *
152
+ * const key = deriveEphemeralUnlockerKey(masterSeed, generationIndex);
153
+ *
154
+ * try {
155
+ * const plaintext = await decryptor(key, ciphertext);
156
+ * const { amount, genIndex, destination } = parseRecoveryPlaintext(plaintext);
157
+ * } catch (error) {
158
+ * // Authentication failed — wrong key or corrupted data.
159
+ * // Do NOT attempt to parse or use any output from this call.
160
+ * console.error("Decryption failed:", error);
161
+ * }
162
+ * ```
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * // Attempting decryption with a different key throws:
167
+ * const wrongKey = deriveEphemeralUnlockerKey(wrongSeed, generationIndex);
168
+ * await decryptor(wrongKey, ciphertext); // throws — authentication tag mismatch
169
+ * ```
170
+ *
171
+ * @see {@link AesEncryptorFunction} — the paired encryption function type
172
+ * @see {@link getAesDecryptor} — factory that returns the default implementation
173
+ * @see {@link defaultAesDecryptor} — pre-instantiated convenience singleton
174
+ */
175
+ type AesDecryptorFunction = (key: AesKey, ciphertext: AesCiphertextWithMetadata) => Promise<AesPlaintext>;
176
+
177
+ /**
178
+ * Solana Provider and Forwarder Interfaces.
179
+ *
180
+ * This module defines the TypeScript contracts for all Solana RPC abstraction
181
+ * layers used by the Umbra SDK. By depending on these interfaces rather than
182
+ * concrete implementations, SDK components remain testable (mock providers can
183
+ * be injected) and portable (different RPC backends can be substituted without
184
+ * changing call sites).
185
+ *
186
+ * @remarks
187
+ * The interfaces are organized into four groups:
188
+ *
189
+ * - **Account Info Provider** — {@link AccountInfoProviderFunction} for
190
+ * fetching raw encoded account data as a `Map`.
191
+ *
192
+ * - **Blockhash Provider** — {@link LatestBlockhashResult} and
193
+ * {@link GetLatestBlockhash} for fetching the latest blockhash and its
194
+ * validity window.
195
+ *
196
+ * - **Epoch Info Provider** — {@link EpochInfoResult} and {@link GetEpochInfo}
197
+ * for fetching current epoch and slot data (used for Token-2022 fee
198
+ * calculation).
199
+ *
200
+ * - **Transaction Forwarder** — {@link ForwardSequentially},
201
+ * {@link ForwardInParallel}, and {@link TransactionForwarder} for submitting
202
+ * signed transactions to the network.
203
+ *
204
+ * Factory types for `@solana/kit` dependencies are also exported
205
+ * ({@link CreateSolanaRpcFunction}, {@link CreateSolanaRpcSubscriptionsFunction},
206
+ * {@link SendAndConfirmTransactionFactoryFunction}) to allow dependency injection
207
+ * of the underlying `@solana/kit` primitives in tests.
208
+ *
209
+ * @packageDocumentation
210
+ */
211
+
212
+ /**
213
+ * Object interface for fetching Solana account information from the network.
214
+ *
215
+ * Provides two methods — `fetchAccount` for single-account lookups and
216
+ * `fetchAccounts` for batch lookups — backed by `@solana/kit`'s
217
+ * `fetchEncodedAccount` and `fetchEncodedAccounts` helpers respectively.
218
+ *
219
+ * @remarks
220
+ * Both methods return `MaybeEncodedAccount` values. Callers must check
221
+ * `account.exists` before accessing `account.data` to handle the case where
222
+ * an account has not been initialized on-chain.
223
+ *
224
+ * The returned encoded data is compatible with Codama-generated decoders. Pass
225
+ * the `MaybeEncodedAccount` directly to a decoder such as
226
+ * `decodeEncryptedUserAccount` to obtain a typed program account struct.
227
+ *
228
+ * @example
229
+ * Injecting a mock `AccountInfoProvider` in tests:
230
+ * ```typescript
231
+ * import type { AccountInfoProvider } from "./interfaces";
232
+ * import { address } from "@solana/kit";
233
+ *
234
+ * const mockProvider: AccountInfoProvider = {
235
+ * fetchAccount: async (addr) => ({
236
+ * exists: true,
237
+ * address: addr,
238
+ * data: new Uint8Array([1, 2, 3, 4]),
239
+ * executable: false,
240
+ * lamports: 1_000_000n,
241
+ * programAddress: address("11111111111111111111111111111111"),
242
+ * }),
243
+ * fetchAccounts: async (addrs) =>
244
+ * addrs.map((addr) => ({
245
+ * exists: false,
246
+ * address: addr,
247
+ * })),
248
+ * };
249
+ * ```
250
+ *
251
+ * @see {@link getRpcAccountInfoProvider} for the default RPC-backed implementation
252
+ * @public
253
+ */
254
+ /**
255
+ * Function type for batch-fetching Solana account information as a `Map`.
256
+ *
257
+ * This is the primary account-fetching interface used throughout the Umbra SDK.
258
+ * It accepts a readonly array of addresses and resolves to a `Map` keyed by
259
+ * address. This functional interface supports the SDK's dependency injection
260
+ * pattern and makes mocking trivial.
261
+ *
262
+ * @remarks
263
+ * **Deduplication** — Implementations should deduplicate input addresses before
264
+ * issuing RPC calls to avoid wasting slots in a `getMultipleAccounts` request.
265
+ *
266
+ * **Non-existent accounts** — The `Map` must contain an entry for every input
267
+ * address (after deduplication), even if the account does not exist on-chain.
268
+ * Non-existent accounts are represented by a `MaybeEncodedAccount` with
269
+ * `exists: false`.
270
+ *
271
+ * **Empty input** — Passing an empty array should return an empty `Map`
272
+ * immediately without making an RPC call.
273
+ *
274
+ * **Performance** — For large address arrays, implementations may need to chunk
275
+ * requests because `getMultipleAccounts` has a per-call limit (typically 100
276
+ * accounts on public RPC nodes). Consider rate-limit constraints as well.
277
+ *
278
+ * @param addresses - A `ReadonlyArray` of Solana `Address` values to fetch.
279
+ * @param options - Optional configuration. Pass `{ commitment }` to override the
280
+ * default `"confirmed"` commitment level for this fetch.
281
+ * @returns A `Promise` resolving to a `Map<Address, MaybeEncodedAccount>` where
282
+ * each key is an input address and each value is the corresponding account data
283
+ * (or a `{ exists: false }` sentinel for missing accounts).
284
+ *
285
+ * @example
286
+ * Using the provider to batch-fetch accounts:
287
+ * ```typescript
288
+ * import type { AccountInfoProviderFunction } from "./interfaces";
289
+ * import { address } from "@solana/kit";
290
+ *
291
+ * const fetchAccounts: AccountInfoProviderFunction = getRpcAccountInfoProvider({
292
+ * rpcUrl: "https://api.mainnet-beta.solana.com",
293
+ * });
294
+ *
295
+ * const addresses = [
296
+ * address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
297
+ * address("11111111111111111111111111111111"),
298
+ * ];
299
+ *
300
+ * const accountMap = await fetchAccounts(addresses);
301
+ *
302
+ * for (const [addr, account] of accountMap) {
303
+ * if (account.exists) {
304
+ * console.log(`${addr}: ${account.data.length} bytes`);
305
+ * } else {
306
+ * console.log(`${addr}: does not exist`);
307
+ * }
308
+ * }
309
+ * ```
310
+ *
311
+ * @example
312
+ * Mock implementation for unit testing:
313
+ * ```typescript
314
+ * const mockProvider: AccountInfoProviderFunction = async (addresses) => {
315
+ * const result = new Map<Address, MaybeEncodedAccount>();
316
+ * for (const addr of addresses) {
317
+ * result.set(addr, {
318
+ * exists: true,
319
+ * address: addr,
320
+ * data: new Uint8Array([0, 1, 2, 3]),
321
+ * executable: false,
322
+ * lamports: 1_000_000n,
323
+ * programAddress: address("11111111111111111111111111111111"),
324
+ * });
325
+ * }
326
+ * return result;
327
+ * };
328
+ * ```
329
+ *
330
+ * @see {@link AccountInfoProvider} for the object-oriented alternative
331
+ * @see {@link getRpcAccountInfoProvider} for the default RPC-backed implementation
332
+ * @public
333
+ */
334
+ type AccountInfoProviderFunction = (addresses: readonly Address[], options?: {
335
+ readonly commitment?: Commitment;
336
+ }) => Promise<Map<Address, MaybeEncodedAccount>>;
337
+ /**
338
+ * The result of fetching the latest blockhash from the Solana network.
339
+ *
340
+ * Contains both the blockhash value and the `lastValidBlockHeight`, which
341
+ * together define the lifetime window for a transaction. The two fields must
342
+ * be passed together to `setTransactionMessageLifetimeUsingBlockhash` from
343
+ * `@solana/kit`.
344
+ *
345
+ * @remarks
346
+ * Transactions using this blockhash must be confirmed before the network
347
+ * reaches `lastValidBlockHeight`, otherwise they will be rejected as expired.
348
+ * On mainnet, the validity window is typically around 150 blocks (~60–90
349
+ * seconds), but this can shrink during periods of high slot skip rates.
350
+ *
351
+ * @see {@link GetLatestBlockhash} for the function that returns this type
352
+ * @public
353
+ */
354
+ interface LatestBlockhashResult {
355
+ /**
356
+ * A recent blockhash observed from the cluster at the `"confirmed"`
357
+ * commitment level.
358
+ *
359
+ * @remarks
360
+ * This hash serves three purposes:
361
+ * - It sets the transaction's lifetime constraint (expires at `lastValidBlockHeight`).
362
+ * - It prevents replay attacks — once expired, the same blockhash cannot be
363
+ * reused to submit a duplicate.
364
+ * - It anchors the transaction to a specific fork of the chain.
365
+ */
366
+ readonly blockhash: Blockhash;
367
+ /**
368
+ * The last block height at which this blockhash is considered valid.
369
+ *
370
+ * @remarks
371
+ * After the network surpasses this block height, any transaction referencing
372
+ * `blockhash` will be rejected with `BlockhashNotFound`. Callers must ensure
373
+ * they submit and confirm the transaction before this height is reached.
374
+ *
375
+ * Typical validity window: ~150 blocks (~60–90 seconds on mainnet).
376
+ */
377
+ readonly lastValidBlockHeight: bigint;
378
+ }
379
+ /**
380
+ * Function type that fetches the latest blockhash and validity window from
381
+ * the Solana network.
382
+ *
383
+ * Every invocation of this function should return a fresh blockhash. Caching
384
+ * is the caller's responsibility; the lifetime window should be factored into
385
+ * any caching strategy.
386
+ *
387
+ * @remarks
388
+ * **Underlying RPC call** — Implementations typically call `getLatestBlockhash`
389
+ * (commitment: `"confirmed"`) on the Solana JSON-RPC API.
390
+ *
391
+ * **Blockhash validity** — Blockhashes are valid for approximately 150 blocks
392
+ * (~1–2 minutes). A transaction must be confirmed before `lastValidBlockHeight`
393
+ * is surpassed; otherwise it will be rejected with `BlockhashNotFound`.
394
+ *
395
+ * **Caching considerations** — Blockhashes can be safely cached for a few
396
+ * seconds to reduce RPC load in high-throughput scenarios, but the cache TTL
397
+ * must be short enough relative to the validity window to avoid expiry.
398
+ *
399
+ * **Integration with `@solana/kit`** — The returned `LatestBlockhashResult` is
400
+ * designed to be passed directly to `setTransactionMessageLifetimeUsingBlockhash`
401
+ * without any transformation:
402
+ *
403
+ * @param options - Optional configuration. Pass `{ commitment }` to override the
404
+ * default `"confirmed"` commitment level for this RPC call.
405
+ * @returns A `Promise` resolving to a {@link LatestBlockhashResult} containing
406
+ * the current blockhash and its last valid block height.
407
+ *
408
+ * @throws May reject if the RPC endpoint is unreachable or returns a malformed
409
+ * response.
410
+ *
411
+ * @example
412
+ * Using in a transaction-building pipeline with `pipe`:
413
+ * ```typescript
414
+ * import type { GetLatestBlockhash } from "./interfaces";
415
+ * import {
416
+ * createTransactionMessage,
417
+ * setTransactionMessageLifetimeUsingBlockhash,
418
+ * pipe,
419
+ * } from "@solana/kit";
420
+ *
421
+ * async function buildTx(getLatestBlockhash: GetLatestBlockhash) {
422
+ * const blockhashResult = await getLatestBlockhash();
423
+ * return pipe(
424
+ * createTransactionMessage({ version: 0 }),
425
+ * (m) => setTransactionMessageLifetimeUsingBlockhash(blockhashResult, m),
426
+ * );
427
+ * }
428
+ * ```
429
+ *
430
+ * @example
431
+ * Simple RPC-backed implementation:
432
+ * ```typescript
433
+ * const getLatestBlockhash: GetLatestBlockhash = async () => {
434
+ * const { value } = await rpc.getLatestBlockhash().send();
435
+ * return value;
436
+ * };
437
+ * ```
438
+ *
439
+ * @example
440
+ * Implementation with short-lived caching:
441
+ * ```typescript
442
+ * const createCachedBlockhashProvider = (rpc: Rpc): GetLatestBlockhash => {
443
+ * let cached: { result: LatestBlockhashResult; fetchedAt: number } | null = null;
444
+ * const CACHE_TTL_MS = 10_000; // 10 seconds
445
+ *
446
+ * return async () => {
447
+ * const now = Date.now();
448
+ * if (cached && now - cached.fetchedAt < CACHE_TTL_MS) {
449
+ * return cached.result;
450
+ * }
451
+ * const { value } = await rpc.getLatestBlockhash().send();
452
+ * cached = { result: value, fetchedAt: now };
453
+ * return value;
454
+ * };
455
+ * };
456
+ * ```
457
+ *
458
+ * @see {@link LatestBlockhashResult} for the returned data shape
459
+ * @see {@link getRpcBlockhashProvider} for the default RPC-backed factory
460
+ * @public
461
+ */
462
+ type GetLatestBlockhash = (options?: {
463
+ readonly commitment?: Commitment;
464
+ }) => Promise<LatestBlockhashResult>;
465
+ /**
466
+ * The result of fetching epoch information from the Solana network.
467
+ *
468
+ * Contains the current epoch number, slot progress within the epoch, absolute
469
+ * slot and block height, and optionally the transaction count for the epoch.
470
+ * The epoch number is particularly important for Token-2022 transfer fee
471
+ * schedule resolution.
472
+ *
473
+ * @remarks
474
+ * Solana mainnet epochs span approximately 432,000 slots (~2–3 days). Epoch
475
+ * boundaries trigger several protocol events: stake reward distribution, leader
476
+ * schedule rotation, and Token-2022 fee schedule transitions.
477
+ *
478
+ * @see {@link GetEpochInfo} for the function that returns this type
479
+ * @public
480
+ */
481
+ interface EpochInfoResult {
482
+ /**
483
+ * The current epoch number.
484
+ *
485
+ * @remarks
486
+ * Epochs are sequential, starting from 0 at genesis. Used by Token-2022
487
+ * transfer fee logic to determine which fee schedule (older or newer) is
488
+ * active for a given mint. If `currentEpoch >= newerTransferFee.epoch`,
489
+ * the newer schedule is in effect.
490
+ */
491
+ readonly epoch: bigint;
492
+ /**
493
+ * The current slot index within the epoch (0-based).
494
+ *
495
+ * @remarks
496
+ * Progress through the current epoch: `slotIndex / slotsInEpoch` gives a
497
+ * value in [0, 1). Each slot is approximately 400ms on mainnet.
498
+ */
499
+ readonly slotIndex: bigint;
500
+ /**
501
+ * Total number of slots in the current epoch.
502
+ *
503
+ * @remarks
504
+ * On mainnet, this is typically 432,000. Divide `slotIndex` by this value
505
+ * to get epoch completion percentage.
506
+ */
507
+ readonly slotsInEpoch: bigint;
508
+ /**
509
+ * The absolute slot number since genesis.
510
+ *
511
+ * @remarks
512
+ * Unlike `slotIndex`, this counter never resets. It represents the total
513
+ * number of slots that have elapsed since the cluster's genesis block.
514
+ */
515
+ readonly absoluteSlot: bigint;
516
+ /**
517
+ * The current confirmed block height.
518
+ *
519
+ * @remarks
520
+ * Block height may differ from slot number because some slots are skipped
521
+ * (no block is produced). Block height strictly increases but may have gaps.
522
+ */
523
+ readonly blockHeight: bigint;
524
+ /**
525
+ * The total number of transactions processed in the current epoch, if reported.
526
+ *
527
+ * @remarks
528
+ * Not all RPC nodes expose this field. When the node returns `null` for
529
+ * `transactionCount`, this field is omitted (set to `undefined`) in the
530
+ * result rather than being present with a null value.
531
+ */
532
+ readonly transactionCount?: bigint;
533
+ }
534
+ /**
535
+ * Function type that fetches current epoch information from the Solana network.
536
+ *
537
+ * The primary use case for this function in the Umbra SDK is determining which
538
+ * Token-2022 transfer fee schedule is active before computing deposit or
539
+ * transfer amounts.
540
+ *
541
+ * @remarks
542
+ * **Underlying RPC call** — Implementations call `getEpochInfo` (commitment:
543
+ * `"confirmed"`) on the Solana JSON-RPC API.
544
+ *
545
+ * **Token-2022 fee schedule selection** — Token-2022 mints with the Transfer
546
+ * Fee extension may define two consecutive schedules: an "older" schedule and a
547
+ * "newer" schedule that takes effect at a future epoch. The active schedule is:
548
+ * - `newerTransferFee` if `currentEpoch >= newerTransferFee.epoch`
549
+ * - `olderTransferFee` otherwise
550
+ *
551
+ * **Caching** — Epochs on mainnet are ~2–3 days long, so caching the result for
552
+ * minutes is safe in most scenarios. Near an epoch boundary, a stale cache could
553
+ * cause the SDK to use the wrong fee schedule; use a conservative TTL (e.g.,
554
+ * 60 seconds) if precision near boundaries matters.
555
+ *
556
+ * @param options - Optional configuration. Pass `{ commitment }` to override the
557
+ * default `"confirmed"` commitment level for this RPC call.
558
+ * @returns A `Promise` resolving to an {@link EpochInfoResult}.
559
+ *
560
+ * @throws May reject if the RPC endpoint is unreachable or returns a malformed
561
+ * response.
562
+ *
563
+ * @example
564
+ * Simple RPC-backed implementation:
565
+ * ```typescript
566
+ * const getEpochInfo: GetEpochInfo = async () => {
567
+ * const result = await rpc.getEpochInfo().send();
568
+ * return {
569
+ * epoch: result.epoch,
570
+ * slotIndex: result.slotIndex,
571
+ * slotsInEpoch: result.slotsInEpoch,
572
+ * absoluteSlot: result.absoluteSlot,
573
+ * blockHeight: result.blockHeight,
574
+ * ...(result.transactionCount !== null && {
575
+ * transactionCount: result.transactionCount,
576
+ * }),
577
+ * };
578
+ * };
579
+ * ```
580
+ *
581
+ * @example
582
+ * Using epoch info for Token-2022 fee calculation:
583
+ * ```typescript
584
+ * const epochInfo = await getEpochInfo();
585
+ * const feeConfig = extractTransferFeeConfig(mintAccountData);
586
+ * if (feeConfig) {
587
+ * const fee = calculateTransferFee(feeConfig, epochInfo.epoch, depositAmount);
588
+ * const grossAmount = depositAmount + fee;
589
+ * }
590
+ * ```
591
+ *
592
+ * @see {@link EpochInfoResult} for the returned data shape
593
+ * @see {@link getRpcEpochInfoProvider} for the default RPC-backed factory
594
+ * @public
595
+ */
596
+ type GetEpochInfo = (options?: {
597
+ readonly commitment?: Commitment;
598
+ }) => Promise<EpochInfoResult>;
599
+ /**
600
+ * Factory function type for creating a Solana JSON-RPC client.
601
+ *
602
+ * Mirrors the signature of `createSolanaRpc` from `@solana/kit`. Expressed as
603
+ * a type alias so that factory functions in the SDK can accept either the real
604
+ * `createSolanaRpc` or a test double without importing the concrete function.
605
+ *
606
+ * @typeParam TUrl - The literal string type of the RPC URL, preserved through
607
+ * the return type for nominal URL typing in `@solana/kit`.
608
+ *
609
+ * @param rpcUrl - The HTTP or HTTPS URL of the Solana JSON-RPC endpoint.
610
+ * @returns A Solana RPC client instance with typed method wrappers.
611
+ *
612
+ * @remarks
613
+ * The default implementation is `createSolanaRpc` from `@solana/kit`. Override
614
+ * this in tests to inject a mock client that returns controlled responses.
615
+ *
616
+ * @example
617
+ * ```typescript
618
+ * import { createSolanaRpc } from "@solana/kit";
619
+ * import type { CreateSolanaRpcFunction } from "./interfaces";
620
+ *
621
+ * const myFactory: CreateSolanaRpcFunction = (url) => createSolanaRpc(url);
622
+ * ```
623
+ *
624
+ * @public
625
+ */
626
+ type CreateSolanaRpcFunction = <TUrl extends string>(rpcUrl: TUrl) => ReturnType<typeof createSolanaRpc<TUrl>>;
627
+ /**
628
+ * Factory function type for creating a Solana RPC subscriptions client.
629
+ *
630
+ * Mirrors the signature of `createSolanaRpcSubscriptions` from `@solana/kit`.
631
+ * Used by the websocket-based transaction forwarder to establish a WebSocket
632
+ * connection for real-time transaction confirmation notifications.
633
+ *
634
+ * @typeParam TUrl - The literal string type of the WebSocket URL.
635
+ *
636
+ * @param rpcSubscriptionsUrl - The WebSocket URL of the Solana RPC endpoint
637
+ * (typically starts with `wss://`).
638
+ * @returns A Solana RPC subscriptions client instance.
639
+ *
640
+ * @remarks
641
+ * The default implementation is `createSolanaRpcSubscriptions` from
642
+ * `@solana/kit`. Override in tests to inject a mock subscriptions client.
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * import { createSolanaRpcSubscriptions } from "@solana/kit";
647
+ * import type { CreateSolanaRpcSubscriptionsFunction } from "./interfaces";
648
+ *
649
+ * const myFactory: CreateSolanaRpcSubscriptionsFunction = (url) =>
650
+ * createSolanaRpcSubscriptions(url);
651
+ * ```
652
+ *
653
+ * @see {@link getWebsocketTransactionForwarder} for the factory that uses this
654
+ * @public
655
+ */
656
+ type CreateSolanaRpcSubscriptionsFunction = <TUrl extends string>(rpcSubscriptionsUrl: TUrl) => ReturnType<typeof createSolanaRpcSubscriptions<TUrl>>;
657
+ /**
658
+ * Factory function type for `sendAndConfirmTransactionFactory` from `@solana/kit`.
659
+ *
660
+ * Expressed as a type alias to enable dependency injection in the websocket-based
661
+ * transaction forwarder. The factory takes an `{ rpc, rpcSubscriptions }` options
662
+ * object and returns a `sendAndConfirmTransaction` function that submits a signed
663
+ * transaction and waits for confirmation via a WebSocket subscription.
664
+ *
665
+ * @remarks
666
+ * The default implementation is `sendAndConfirmTransactionFactory` from
667
+ * `@solana/kit`. Override in tests to inject a mock that avoids real network
668
+ * I/O.
669
+ *
670
+ * @example
671
+ * ```typescript
672
+ * import { sendAndConfirmTransactionFactory } from "@solana/kit";
673
+ * import type { SendAndConfirmTransactionFactoryFunction } from "./interfaces";
674
+ *
675
+ * const myFactory: SendAndConfirmTransactionFactoryFunction = (opts) =>
676
+ * sendAndConfirmTransactionFactory(opts);
677
+ * ```
678
+ *
679
+ * @see {@link getWebsocketTransactionForwarder} for the factory that uses this
680
+ * @public
681
+ */
682
+ type SendAndConfirmTransactionFactoryFunction = typeof sendAndConfirmTransactionFactory;
683
+ /**
684
+ * Function type that forwards signed transactions to the Solana network
685
+ * sequentially, waiting for each to be confirmed before sending the next.
686
+ *
687
+ * Use sequential forwarding when transactions have dependencies — for example,
688
+ * when transaction N creates an account that transaction N+1 writes to. If any
689
+ * transaction fails, subsequent transactions are not attempted.
690
+ *
691
+ * @param transactions - An ordered, readonly array of fully signed transactions.
692
+ * Index 0 is submitted first.
693
+ * @returns A `Promise` resolving to an array of {@link TransactionSignature}
694
+ * values in the same order as the input transactions.
695
+ *
696
+ * @throws Rejects if any transaction in the sequence fails to confirm. The error
697
+ * should identify which transaction failed and may carry the signatures of any
698
+ * previously confirmed transactions in its context.
699
+ *
700
+ * @remarks
701
+ * **Execution semantics:**
702
+ * - Transactions are submitted in array order (index 0 first).
703
+ * - Each transaction is awaited before the next is submitted.
704
+ * - A failure aborts the remaining transactions — they are not retried.
705
+ *
706
+ * **Use cases:**
707
+ * - Creating an account then performing operations on it.
708
+ * - Initializing a program then calling its instructions.
709
+ * - Any scenario where the correctness of transaction N depends on N-1 landing.
710
+ *
711
+ * @example
712
+ * ```typescript
713
+ * const signatures = await forwarder.forwardSequentially([
714
+ * createAccountTx,
715
+ * depositTx,
716
+ * ]);
717
+ * console.log(`Account created: ${signatures[0]}`);
718
+ * console.log(`Deposit landed: ${signatures[1]}`);
719
+ * ```
720
+ *
721
+ * @see {@link ForwardInParallel} for the parallel alternative
722
+ * @see {@link TransactionForwarder} for the interface that contains both methods
723
+ * @public
724
+ */
725
+ type ForwardSequentially = (transactions: readonly SignedTransaction[]) => Promise<readonly TransactionSignature[]>;
726
+ /**
727
+ * Function type that forwards signed transactions to the Solana network in
728
+ * parallel, submitting all without waiting for individual confirmations.
729
+ *
730
+ * Use parallel forwarding when transactions are fully independent — they do not
731
+ * share writable accounts and their outcomes do not affect each other. Parallel
732
+ * forwarding is significantly faster than sequential forwarding for large batches.
733
+ *
734
+ * @param transactions - A readonly array of fully signed transactions to submit
735
+ * simultaneously.
736
+ * @returns A `Promise` resolving to an array of {@link TransactionSignature}
737
+ * values in the same order as the input transactions (not confirmation order).
738
+ *
739
+ * @throws Rejects if any transaction fails. Because all transactions are
740
+ * submitted simultaneously, some may succeed while others fail. The error
741
+ * should indicate which transactions failed.
742
+ *
743
+ * @remarks
744
+ * **Execution semantics:**
745
+ * - All transactions are submitted at approximately the same time.
746
+ * - Confirmations may arrive in any order; results are always returned in input order.
747
+ * - Partial failure is possible: some transactions may confirm while others fail.
748
+ *
749
+ * **Performance considerations:**
750
+ * - Ideal for batch transfers to independent recipients.
751
+ * - May hit per-second rate limits on public RPC nodes with large batches.
752
+ * - The `onTransactionConfirmed` callback is not invoked during parallel forwarding.
753
+ *
754
+ * @example
755
+ * ```typescript
756
+ * const transferTxs = recipients.map((r) => buildTransfer(sender, r, amount));
757
+ * const signatures = await forwarder.forwardInParallel(transferTxs);
758
+ * signatures.forEach((sig, i) => {
759
+ * console.log(`Transfer to ${recipients[i]}: ${sig}`);
760
+ * });
761
+ * ```
762
+ *
763
+ * @see {@link ForwardSequentially} for the sequential alternative
764
+ * @see {@link TransactionForwarder} for the interface that contains both methods
765
+ * @public
766
+ */
767
+ type ForwardInParallel = (transactions: readonly SignedTransaction[]) => Promise<readonly TransactionSignature[]>;
768
+ /**
769
+ * Interface for forwarding fully signed transactions to the Solana network.
770
+ *
771
+ * This interface provides two complementary strategies for transaction
772
+ * submission. Choosing the right strategy affects both correctness and
773
+ * performance:
774
+ *
775
+ * - Use `forwardSequentially` when transactions have dependencies (state
776
+ * produced by one transaction is consumed by the next).
777
+ * - Use `forwardInParallel` when transactions are independent (no shared
778
+ * writable accounts, no ordering requirement).
779
+ *
780
+ * @remarks
781
+ * **Compile-time safety** — Both methods accept only `SignedTransaction`, a
782
+ * branded type that indicates the transaction has at least one signature and
783
+ * carries a blockhash lifetime constraint. Unsigned or partially unsigned
784
+ * transactions produce a compile-time error, preventing accidental submission
785
+ * of incomplete transactions.
786
+ *
787
+ * **Implementation requirements** — Concrete implementations should handle:
788
+ * - RPC endpoint selection, failover, and connection management.
789
+ * - Retry logic for transient send failures.
790
+ * - Blockhash expiry detection (the transaction window closes at
791
+ * `lastValidBlockHeight`).
792
+ * - Structured error propagation with diagnostic context.
793
+ *
794
+ * **Available implementations:**
795
+ * - {@link getWebsocketTransactionForwarder} — uses WebSocket subscriptions
796
+ * for efficient confirmation (lower latency, requires WebSocket access).
797
+ * - {@link getPollingTransactionForwarder} — polls `getSignatureStatuses`
798
+ * (works in environments that block WebSocket; configurable timeouts and
799
+ * per-transaction callbacks).
800
+ *
801
+ * @example
802
+ * Using the interface polymorphically:
803
+ * ```typescript
804
+ * import type { TransactionForwarder } from "./interfaces";
805
+ *
806
+ * async function submitOperations(
807
+ * forwarder: TransactionForwarder,
808
+ * initTx: SignedTransaction,
809
+ * operationTxs: readonly SignedTransaction[],
810
+ * ) {
811
+ * // Init must land before operations can reference the new account
812
+ * await forwarder.forwardSequentially([initTx]);
813
+ *
814
+ * // Operations are independent of each other
815
+ * const sigs = await forwarder.forwardInParallel(operationTxs);
816
+ * return sigs;
817
+ * }
818
+ * ```
819
+ *
820
+ * @see {@link ForwardSequentially} for the sequential method type
821
+ * @see {@link ForwardInParallel} for the parallel method type
822
+ * @see {@link getWebsocketTransactionForwarder} for the WebSocket implementation
823
+ * @see {@link getPollingTransactionForwarder} for the polling implementation
824
+ * @public
825
+ */
826
+ interface TransactionForwarder {
827
+ /**
828
+ * Forwards transactions sequentially.
829
+ *
830
+ * Each transaction is submitted and confirmed before the next transaction
831
+ * is sent. Aborts on the first failure.
832
+ *
833
+ * @see {@link ForwardSequentially}
834
+ */
835
+ forwardSequentially: ForwardSequentially;
836
+ /**
837
+ * Forwards transactions in parallel.
838
+ *
839
+ * All transactions are submitted simultaneously. Confirmations are awaited
840
+ * concurrently. Results are returned in input order regardless of confirmation
841
+ * order.
842
+ *
843
+ * @see {@link ForwardInParallel}
844
+ */
845
+ forwardInParallel: ForwardInParallel;
846
+ /**
847
+ * Sends a transaction without waiting for confirmation.
848
+ *
849
+ * Use for best-effort operations like rent reclamation where blocking
850
+ * on confirmation is unnecessary.
851
+ */
852
+ fireAndForget: FireAndForget;
853
+ }
854
+ /**
855
+ * Sends a single signed transaction to the network without awaiting confirmation.
856
+ * Returns the signature immediately after submission.
857
+ */
858
+ type FireAndForget = (transaction: SignedTransaction) => Promise<TransactionSignature>;
859
+
860
+ /**
861
+ * Arcium Computation Monitor Implementations.
862
+ *
863
+ * Monitors an Arcium `ComputationAccount` for finalization or pruning after
864
+ * a `queue_computation` transaction has been sent. The monitor uses **slot-based
865
+ * timeout**: it reads the `slot` field from the on-chain `ComputationAccount`
866
+ * (the slot when the computation was queued) and compares against the current
867
+ * slot to determine if the computation has been pruned.
868
+ *
869
+ * Two factory functions produce {@link ComputationMonitor} implementations:
870
+ *
871
+ * - **{@link getWebsocketComputationMonitor}** — Subscribes to account change
872
+ * notifications via WebSocket for low-latency finalization detection.
873
+ *
874
+ * - **{@link getPollingComputationMonitor}** — Periodically fetches the
875
+ * ComputationAccount via HTTP. Suitable for environments without WebSocket.
876
+ *
877
+ * ## Outcomes
878
+ *
879
+ * - **Finalized** — The MPC callback landed successfully. The `ComputationAccount.status`
880
+ * transitioned to `Finalized` within the slot window.
881
+ * - **Pruned** — The slot window elapsed without finalization. The MPC nodes either
882
+ * failed to complete or all callback attempts failed. The computation will not
883
+ * finalize and should be considered abandoned.
884
+ *
885
+ * ## Slot-Based Timeout
886
+ *
887
+ * Arcium MPC callbacks typically arrive within ~180 slots (~72 seconds) of queueing.
888
+ * The monitor uses a configurable slot window ({@link DEFAULT_MAX_SLOT_WINDOW} = 200)
889
+ * measured from the `ComputationAccount.slot` field. A wall-clock safety timeout
890
+ * ({@link DEFAULT_SAFETY_TIMEOUT_MS} = 300s) provides a fallback if RPC is unresponsive.
891
+ *
892
+ * @packageDocumentation
893
+ * @module arcium/computation-monitor
894
+ * @since 2.0.0
895
+ */
896
+
897
+ /**
898
+ * Default maximum slot window. If `currentSlot - queuedSlot` exceeds this
899
+ * value, the computation is considered pruned.
900
+ *
901
+ * @remarks
902
+ * Arcium callbacks typically arrive within ~180 slots (~72 seconds).
903
+ * The default of 200 provides a ~20-slot buffer.
904
+ *
905
+ * @since 2.0.0
906
+ * @public
907
+ */
908
+ declare const DEFAULT_MAX_SLOT_WINDOW = 200;
909
+ /**
910
+ * Default wall-clock safety timeout in milliseconds. This is a fallback
911
+ * for cases where the RPC is unresponsive and slot progression cannot be
912
+ * tracked. Under normal conditions, the slot-based window resolves first.
913
+ *
914
+ * @since 2.0.0
915
+ * @public
916
+ */
917
+ declare const DEFAULT_SAFETY_TIMEOUT_MS = 300000;
918
+ /**
919
+ * Default interval in milliseconds between successive poll attempts.
920
+ *
921
+ * @since 2.0.0
922
+ * @public
923
+ */
924
+ declare const DEFAULT_POLLING_INTERVAL_MS = 2000;
925
+ /**
926
+ * Default limit for the `getSignaturesForAddress` RPC call when retrieving
927
+ * the callback transaction signature after finalization.
928
+ *
929
+ * @since 2.0.0
930
+ * @public
931
+ */
932
+ declare const DEFAULT_SIGNATURE_RETRIEVAL_LIMIT = 20;
933
+ /**
934
+ * Result when the MPC computation finalizes successfully.
935
+ *
936
+ * @since 2.0.0
937
+ * @public
938
+ */
939
+ interface ComputationFinalizedResult {
940
+ /** The computation completed and the callback landed on-chain. */
941
+ readonly status: "finalized";
942
+ /** Wall-clock milliseconds from monitor start to finalization detection. */
943
+ readonly elapsedMs: number;
944
+ /** The slot at which the computation was originally queued. */
945
+ readonly queuedSlot: bigint;
946
+ /**
947
+ * The callback transaction signature, if `retrieveCallbackSignature` was `true`.
948
+ * `undefined` otherwise.
949
+ */
950
+ readonly callbackSignature?: TransactionSignature;
951
+ }
952
+ /**
953
+ * Result when the computation is pruned (no successful callback within the slot window).
954
+ *
955
+ * @since 2.0.0
956
+ * @public
957
+ */
958
+ interface ComputationPrunedResult {
959
+ /** The slot window elapsed without a successful callback. */
960
+ readonly status: "pruned";
961
+ /** Wall-clock milliseconds from monitor start to pruning detection. */
962
+ readonly elapsedMs: number;
963
+ /** The slot at which the computation was originally queued. */
964
+ readonly queuedSlot: bigint;
965
+ /** The current slot at the time pruning was detected. */
966
+ readonly currentSlot: bigint;
967
+ }
968
+ /**
969
+ * Discriminated union of all computation monitoring outcomes.
970
+ *
971
+ * @remarks
972
+ * Callers must check `result.status` to determine the outcome:
973
+ *
974
+ * ```typescript
975
+ * const result = await monitor.awaitComputation(address);
976
+ * if (result.status === "finalized") {
977
+ * // MPC succeeded — continue with the encrypted result
978
+ * } else {
979
+ * // Pruned — the computation will never finalize
980
+ * console.log(`Pruned: ${result.currentSlot - result.queuedSlot} slots elapsed`);
981
+ * }
982
+ * ```
983
+ *
984
+ * @since 2.0.0
985
+ * @public
986
+ */
987
+ type ComputationMonitorResult = ComputationFinalizedResult | ComputationPrunedResult;
988
+ /**
989
+ * Extended finalized result with a guaranteed callback signature.
990
+ * Returned when `retrieveCallbackSignature` is `true` and the computation finalized.
991
+ *
992
+ * @since 2.0.0
993
+ * @public
994
+ */
995
+ interface ComputationFinalizedResultWithSignature extends Omit<ComputationFinalizedResult, "callbackSignature"> {
996
+ /** The base58-encoded transaction signature of the successful Arcium callback. */
997
+ readonly callbackSignature: TransactionSignature;
998
+ }
999
+ /**
1000
+ * Result type when `retrieveCallbackSignature` is `true`.
1001
+ * If finalized, the callback signature is guaranteed present.
1002
+ * If pruned, no signature is available.
1003
+ *
1004
+ * @since 2.0.0
1005
+ * @public
1006
+ */
1007
+ type ComputationMonitorResultWithSignature = ComputationFinalizedResultWithSignature | ComputationPrunedResult;
1008
+ /**
1009
+ * Progress event types fired via the `onProgress` callback.
1010
+ *
1011
+ * @remarks
1012
+ * - `queued` — the ComputationAccount was found with status `Queued`
1013
+ * - `finalized` — the computation status transitioned to `Finalized`
1014
+ * - `pruned` — the slot window elapsed without finalization
1015
+ *
1016
+ * @since 2.0.0
1017
+ * @public
1018
+ */
1019
+ type ComputationMonitorProgressEvent = {
1020
+ readonly type: "queued";
1021
+ readonly queuedSlot: bigint;
1022
+ } | {
1023
+ readonly type: "finalized";
1024
+ readonly callbackSignature?: TransactionSignature;
1025
+ } | {
1026
+ readonly type: "pruned";
1027
+ readonly queuedSlot: bigint;
1028
+ readonly currentSlot: bigint;
1029
+ };
1030
+ /**
1031
+ * Options for a computation monitoring invocation.
1032
+ *
1033
+ * @since 2.0.0
1034
+ * @public
1035
+ */
1036
+ interface ComputationMonitorOptions {
1037
+ /**
1038
+ * Maximum number of slots after the queued slot before the computation
1039
+ * is considered pruned. The monitor reads the `slot` field from the
1040
+ * `ComputationAccount` and compares against the current on-chain slot.
1041
+ *
1042
+ * @defaultValue {@link DEFAULT_MAX_SLOT_WINDOW} (200 slots ≈ 80 seconds)
1043
+ */
1044
+ readonly maxSlotWindow?: number;
1045
+ /**
1046
+ * Wall-clock safety timeout in milliseconds. This is a fallback that fires
1047
+ * only if slot progression cannot be tracked (e.g. RPC is unresponsive).
1048
+ * Under normal conditions, the slot-based window resolves first.
1049
+ *
1050
+ * @remarks
1051
+ * When this fires, a {@link ComputationMonitorError} with stage `"timeout"`
1052
+ * is thrown. This indicates an infrastructure problem, not a pruned computation.
1053
+ *
1054
+ * @defaultValue {@link DEFAULT_SAFETY_TIMEOUT_MS} (300,000 ms / 5 minutes)
1055
+ */
1056
+ readonly safetyTimeoutMs?: number;
1057
+ /**
1058
+ * If `true`, perform a `getSignaturesForAddress` call after finalization
1059
+ * to retrieve the successful callback transaction signature.
1060
+ * Has no effect if the computation is pruned.
1061
+ *
1062
+ * @defaultValue `false`
1063
+ */
1064
+ readonly retrieveCallbackSignature?: boolean;
1065
+ /**
1066
+ * Progress callback fired as status changes occur.
1067
+ *
1068
+ * @remarks
1069
+ * This callback is synchronous and should not perform blocking operations.
1070
+ * It is informational and does not affect the monitoring loop.
1071
+ */
1072
+ readonly onProgress?: (event: ComputationMonitorProgressEvent) => void;
1073
+ /**
1074
+ * Commitment level for account fetches and subscriptions.
1075
+ *
1076
+ * @defaultValue `"confirmed"`
1077
+ */
1078
+ readonly commitment?: Commitment;
1079
+ /**
1080
+ * An `AbortSignal` for external cancellation of the monitoring operation.
1081
+ *
1082
+ * @remarks
1083
+ * When aborted, the monitor throws a {@link ComputationMonitorError} with
1084
+ * stage `"timeout"`. This enables callers to cancel from external code
1085
+ * (user navigation, component unmount).
1086
+ */
1087
+ readonly signal?: AbortSignal;
1088
+ }
1089
+ /**
1090
+ * Polling-specific options extending the base monitor options.
1091
+ *
1092
+ * @since 2.0.0
1093
+ * @public
1094
+ */
1095
+ interface PollingComputationMonitorOptions extends ComputationMonitorOptions {
1096
+ /**
1097
+ * Time in milliseconds between successive account fetch attempts.
1098
+ *
1099
+ * @defaultValue {@link DEFAULT_POLLING_INTERVAL_MS} (2,000 ms)
1100
+ */
1101
+ readonly pollingIntervalMs?: number;
1102
+ }
1103
+ /**
1104
+ * Monitors an Arcium `ComputationAccount` for finalization or pruning.
1105
+ *
1106
+ * @since 2.0.0
1107
+ * @public
1108
+ */
1109
+ interface ComputationMonitor {
1110
+ /**
1111
+ * Monitors a ComputationAccount until it finalizes or is pruned.
1112
+ *
1113
+ * @param computationAddress - The on-chain address of the ComputationAccount PDA.
1114
+ * @param options - Monitor options.
1115
+ * @returns A promise resolving to a finalized or pruned result.
1116
+ *
1117
+ * @throws {ComputationMonitorError} With stage `"timeout"` if the safety wall-clock
1118
+ * timeout fires (indicates RPC issues, not normal pruning).
1119
+ * @throws {ComputationMonitorError} With stage `"subscription"` if WebSocket fails.
1120
+ * @throws {ComputationMonitorError} With stage `"signature-retrieval"` if callback
1121
+ * signature lookup fails after finalization.
1122
+ */
1123
+ awaitComputation: {
1124
+ (computationAddress: Address, options?: ComputationMonitorOptions & {
1125
+ retrieveCallbackSignature?: false;
1126
+ }): Promise<ComputationMonitorResult>;
1127
+ (computationAddress: Address, options: ComputationMonitorOptions & {
1128
+ retrieveCallbackSignature: true;
1129
+ }): Promise<ComputationMonitorResultWithSignature>;
1130
+ };
1131
+ }
1132
+ /**
1133
+ * Configuration for the WebSocket-based computation monitor.
1134
+ *
1135
+ * @since 2.0.0
1136
+ * @public
1137
+ */
1138
+ interface WebsocketBasedComputationMonitorConfig {
1139
+ /** HTTP/HTTPS URL of the Solana JSON-RPC endpoint. */
1140
+ readonly rpcUrl: string;
1141
+ /** WebSocket URL of the Solana RPC subscriptions endpoint. */
1142
+ readonly rpcSubscriptionsUrl: string;
1143
+ }
1144
+ /**
1145
+ * Optional dependencies for the WebSocket-based computation monitor.
1146
+ *
1147
+ * @since 2.0.0
1148
+ * @public
1149
+ */
1150
+ interface WebsocketBasedComputationMonitorDeps {
1151
+ /** Override `createSolanaRpc` from `@solana/kit`. */
1152
+ readonly createRpc?: CreateSolanaRpcFunction;
1153
+ /** Override `createSolanaRpcSubscriptions` from `@solana/kit`. */
1154
+ readonly createRpcSubscriptions?: CreateSolanaRpcSubscriptionsFunction;
1155
+ }
1156
+ /**
1157
+ * Configuration for the polling-based computation monitor.
1158
+ *
1159
+ * @since 2.0.0
1160
+ * @public
1161
+ */
1162
+ interface PollingBasedComputationMonitorConfig {
1163
+ /** HTTP/HTTPS URL of the Solana JSON-RPC endpoint. */
1164
+ readonly rpcUrl: string;
1165
+ }
1166
+ /**
1167
+ * Optional dependencies for the polling-based computation monitor.
1168
+ *
1169
+ * @since 2.0.0
1170
+ * @public
1171
+ */
1172
+ interface PollingBasedComputationMonitorDeps {
1173
+ /** Override `createSolanaRpc` from `@solana/kit`. */
1174
+ readonly createRpc?: CreateSolanaRpcFunction;
1175
+ }
1176
+ /**
1177
+ * Creates a {@link ComputationMonitor} that uses WebSocket account change
1178
+ * subscriptions for real-time detection of computation finalization or pruning.
1179
+ *
1180
+ * @remarks
1181
+ * **Detection strategy:** Subscribes to `accountNotifications` for the
1182
+ * computation account. On each notification, decodes the account and checks
1183
+ * the `status` field. Periodically fetches the current slot to detect pruning
1184
+ * when the slot window is exceeded.
1185
+ *
1186
+ * **Initial state check:** Before subscribing, performs an HTTP fetch to handle
1187
+ * the case where the computation already finalized before the monitor started.
1188
+ *
1189
+ * @param config - HTTP RPC URL and WebSocket URL.
1190
+ * @param deps - Optional dependency overrides for testing.
1191
+ * @returns A {@link ComputationMonitor} instance.
1192
+ *
1193
+ * @throws {ComputationMonitorError} Stage `"timeout"` if safety timeout fires.
1194
+ * @throws {ComputationMonitorError} Stage `"subscription"` if WebSocket fails.
1195
+ * @throws {ComputationMonitorError} Stage `"signature-retrieval"` if lookup fails.
1196
+ *
1197
+ * @example
1198
+ * ```typescript
1199
+ * const monitor = getWebsocketComputationMonitor({
1200
+ * rpcUrl: "https://api.mainnet-beta.solana.com",
1201
+ * rpcSubscriptionsUrl: "wss://api.mainnet-beta.solana.com",
1202
+ * });
1203
+ *
1204
+ * const result = await monitor.awaitComputation(computationAddress);
1205
+ * if (result.status === "finalized") {
1206
+ * console.log(`Done in ${result.elapsedMs}ms`);
1207
+ * } else {
1208
+ * console.log(`Pruned after ${result.currentSlot - result.queuedSlot} slots`);
1209
+ * }
1210
+ * ```
1211
+ *
1212
+ * @see {@link getPollingComputationMonitor} for the polling alternative
1213
+ * @since 2.0.0
1214
+ * @public
1215
+ */
1216
+ declare function getWebsocketComputationMonitor(config: WebsocketBasedComputationMonitorConfig, deps?: WebsocketBasedComputationMonitorDeps): ComputationMonitor;
1217
+ /**
1218
+ * Creates a {@link ComputationMonitor} that uses periodic HTTP account fetching
1219
+ * for detection of computation finalization or pruning.
1220
+ *
1221
+ * @remarks
1222
+ * Each poll iteration fetches the `ComputationAccount` and the current slot
1223
+ * in parallel. If the account is finalized, the monitor resolves. If the slot
1224
+ * window is exceeded, the monitor resolves with a pruned result.
1225
+ *
1226
+ * **Transient error handling** — RPC fetch errors during polling are silently
1227
+ * swallowed and the poll loop continues.
1228
+ *
1229
+ * @param config - HTTP RPC endpoint URL.
1230
+ * @param deps - Optional dependency overrides for testing.
1231
+ * @returns A {@link ComputationMonitor} instance.
1232
+ *
1233
+ * @throws {ComputationMonitorError} Stage `"timeout"` if safety timeout fires.
1234
+ * @throws {ComputationMonitorError} Stage `"signature-retrieval"` if lookup fails.
1235
+ *
1236
+ * @example
1237
+ * ```typescript
1238
+ * const monitor = getPollingComputationMonitor({
1239
+ * rpcUrl: "https://api.mainnet-beta.solana.com",
1240
+ * });
1241
+ *
1242
+ * const result = await monitor.awaitComputation(computationAddress, {
1243
+ * maxSlotWindow: 250,
1244
+ * pollingIntervalMs: 3_000,
1245
+ * retrieveCallbackSignature: true,
1246
+ * });
1247
+ *
1248
+ * if (result.status === "finalized") {
1249
+ * console.log(`Callback: ${result.callbackSignature}`);
1250
+ * }
1251
+ * ```
1252
+ *
1253
+ * @see {@link getWebsocketComputationMonitor} for the WebSocket alternative
1254
+ * @since 2.0.0
1255
+ * @public
1256
+ */
1257
+ declare function getPollingComputationMonitor(config: PollingBasedComputationMonitorConfig, deps?: PollingBasedComputationMonitorDeps): ComputationMonitor;
1258
+
1259
+ /**
1260
+ * Umbra Interfaces — UTXO indexer interfaces for Merkle proofs and UTXO scanning.
1261
+ *
1262
+ * @module umbra/interfaces/indexer
1263
+ * @since 2.0.0
1264
+ */
1265
+
1266
+ /**
1267
+ * Base interface for Umbra Indexer configuration.
1268
+ *
1269
+ * @remarks
1270
+ * Contains the essential configuration needed to connect to an Umbra indexer service.
1271
+ * The indexer maintains an off-chain database of protocol state for efficient querying.
1272
+ *
1273
+ * **Indexer Selection:**
1274
+ * Multiple indexer providers may exist. Choose one based on:
1275
+ * - Geographic proximity (lower latency)
1276
+ * - Uptime and reliability
1277
+ * - Query performance
1278
+ *
1279
+ * @example
1280
+ * ```typescript
1281
+ * const indexer: IUmbraIndexer = {
1282
+ * apiEndpoint: 'https://indexer.umbra.finance'
1283
+ * };
1284
+ * ```
1285
+ *
1286
+ * @public
1287
+ */
1288
+ interface IUmbraIndexer {
1289
+ /**
1290
+ * The HTTP endpoint of the indexer service.
1291
+ *
1292
+ * @remarks
1293
+ * This should be a fully qualified URL including the protocol.
1294
+ * The endpoint must support CORS for browser-based clients.
1295
+ *
1296
+ * @example "https://indexer.umbra.finance"
1297
+ */
1298
+ apiEndpoint: string;
1299
+ }
1300
+ /**
1301
+ * Timestamp components returned by the indexer.
1302
+ *
1303
+ * @remarks
1304
+ * Represents the decomposed timestamp of when the UTXO was created.
1305
+ * Used for transaction viewing key derivation.
1306
+ *
1307
+ * @see {@link H1Components}
1308
+ * @public
1309
+ */
1310
+ interface TimestampComponents {
1311
+ /** Year (e.g., 2024) */
1312
+ year: Year;
1313
+ /** Month (1-12) */
1314
+ month: Month;
1315
+ /** Day (1-31) */
1316
+ day: Day;
1317
+ /** Hour (0-23) */
1318
+ hour: Hour;
1319
+ /** Minute (0-59) */
1320
+ minute: Minute;
1321
+ /** Second (0-59) */
1322
+ second: Second;
1323
+ }
1324
+ /**
1325
+ * H1 components returned by the indexer for UTXO data reconstruction.
1326
+ *
1327
+ * @remarks
1328
+ * These are the public components needed to reconstruct the H1 hash
1329
+ * during claim operations. H1 contains metadata about the deposit
1330
+ * that is public knowledge.
1331
+ *
1332
+ * @see {@link UtxoDataItem}
1333
+ * @public
1334
+ */
1335
+ interface H1Components {
1336
+ /** Protocol version identifier */
1337
+ version: U64;
1338
+ /** Index of the commitment in the Merkle tree */
1339
+ commitmentIndex: U128;
1340
+ /** Lower 128 bits of the sender's address */
1341
+ senderAddressLow: U128;
1342
+ /** Upper 128 bits of the sender's address */
1343
+ senderAddressHigh: U128;
1344
+ /** Fixed SOL fees paid to relayer (in lamports) */
1345
+ relayerFixedSolFees: U64;
1346
+ /** Lower 128 bits of the mint address */
1347
+ mintAddressLow: U128;
1348
+ /** Upper 128 bits of the mint address */
1349
+ mintAddressHigh: U128;
1350
+ /** Timestamp components for TVK derivation */
1351
+ timestamp: TimestampComponents;
1352
+ /** Cumulative SPL token volume in the pool at insertion time (base units) */
1353
+ poolVolumeSpl: U64;
1354
+ /** Cumulative SOL volume in the pool at insertion time (lamports) */
1355
+ poolVolumeSol: U64;
1356
+ }
1357
+ /**
1358
+ * Data returned from the Merkle proof endpoint.
1359
+ *
1360
+ * @remarks
1361
+ * Contains the Merkle root, proof path (sibling hashes), and the leaf value
1362
+ * for a specific insertion in the Merkle tree.
1363
+ *
1364
+ * **Hash Encoding:**
1365
+ * All hashes are little-endian byte arrays (U256LeBytes).
1366
+ * The API returns hex strings with `0x` prefix which are converted.
1367
+ *
1368
+ * @see {@link MerkleProofFetcherFunction}
1369
+ * @public
1370
+ */
1371
+ interface MerkleProofData {
1372
+ /** The Merkle root at the time of the query */
1373
+ merkleRoot: U256LeBytes;
1374
+ /** The tree index containing this leaf */
1375
+ treeIndex: U32;
1376
+ /** The insertion index within the tree */
1377
+ insertionIndex: U32;
1378
+ /** Array of sibling hashes from leaf to root */
1379
+ merklePath: U256LeBytes[];
1380
+ /** The leaf node value (commitment) */
1381
+ leaf: U256LeBytes;
1382
+ }
1383
+ /**
1384
+ * Function type for fetching Merkle proofs from the indexer.
1385
+ *
1386
+ * @remarks
1387
+ * Fetches Merkle proofs for one or more leaves in a specific tree.
1388
+ * The returned Map is keyed by insertion index for easy lookup.
1389
+ *
1390
+ * @param treeIndex - The Merkle tree index to query
1391
+ * @param insertionIndices - Array of insertion indices to fetch proofs for
1392
+ * @returns A Map from insertion index to its Merkle proof data
1393
+ *
1394
+ * @example
1395
+ * ```typescript
1396
+ * const proofs = await fetchMerkleProof(0, [42, 43, 44]);
1397
+ * const proof = proofs.get(42);
1398
+ * if (proof) {
1399
+ * console.log('Root:', proof.merkleRoot);
1400
+ * console.log('Path length:', proof.merklePath.length);
1401
+ * }
1402
+ * ```
1403
+ *
1404
+ * @see {@link MerkleProofData}
1405
+ * @public
1406
+ */
1407
+ type MerkleProofFetcherFunction = (treeIndex: U32, insertionIndices: readonly U32[]) => Promise<Map<U32, MerkleProofData>>;
1408
+ /**
1409
+ * Arguments for creating a Merkle proof fetcher function.
1410
+ *
1411
+ * @example
1412
+ * ```typescript
1413
+ * const args: GetMerkleProofFetcherArgs = {
1414
+ * apiEndpoint: 'https://indexer.umbra.finance'
1415
+ * };
1416
+ * ```
1417
+ *
1418
+ * @see {@link MerkleProofFetcherFunction}
1419
+ * @public
1420
+ */
1421
+ interface GetMerkleProofFetcherArgs {
1422
+ /** The HTTP endpoint of the indexer service */
1423
+ apiEndpoint: string;
1424
+ }
1425
+ /**
1426
+ * Optional dependencies for the Merkle proof fetcher factory.
1427
+ *
1428
+ * @remarks
1429
+ * Allows injection of a custom fetch implementation for testing
1430
+ * or environments without global fetch.
1431
+ *
1432
+ * @see {@link MerkleProofFetcherFunction}
1433
+ * @public
1434
+ */
1435
+ interface GetMerkleProofFetcherDeps {
1436
+ /**
1437
+ * Custom fetch implementation.
1438
+ * @default globalThis.fetch
1439
+ */
1440
+ fetch?: typeof globalThis.fetch;
1441
+ }
1442
+ /**
1443
+ * Individual UTXO data item from the indexer API.
1444
+ *
1445
+ * @remarks
1446
+ * Contains all the data needed to reconstruct and claim a UTXO,
1447
+ * including H1/H2 hashes, encrypted data, and metadata.
1448
+ *
1449
+ * **Absolute Index Calculation:**
1450
+ * ```
1451
+ * absoluteIndex = treeIndex * 1,048,576 + insertionIndex
1452
+ * ```
1453
+ *
1454
+ * @see {@link UtxoDataFetcherFunction}
1455
+ * @see {@link H1Components}
1456
+ * @public
1457
+ */
1458
+ interface UtxoDataItem {
1459
+ /** Absolute index in the global UTXO sequence */
1460
+ absoluteIndex: bigint;
1461
+ /** Tree index containing this UTXO */
1462
+ treeIndex: U32;
1463
+ /** Insertion index within the tree */
1464
+ insertionIndex: U32;
1465
+ /** Final commitment h(h1_hash, h2_hash) */
1466
+ finalCommitment: U256LeBytes;
1467
+ /** H1 components for claim proof generation */
1468
+ h1Components: H1Components;
1469
+ /** H1 hash value */
1470
+ h1Hash: U256LeBytes;
1471
+ /** H2 hash value */
1472
+ h2Hash: U256LeBytes;
1473
+ /** AES encrypted UTXO data (amount, destination, gen index, domain separator) */
1474
+ aesEncryptedData: AesCiphertextWithMetadata;
1475
+ /** Depositor's X25519 public key for decryption */
1476
+ depositorX25519PublicKey: X25519PublicKey;
1477
+ /** Block timestamp (Unix epoch seconds) */
1478
+ timestamp: U64;
1479
+ /** Solana slot number */
1480
+ slot: U64;
1481
+ /** Event type: 'deposit' or 'callback' */
1482
+ eventType: "deposit" | "callback";
1483
+ }
1484
+ /**
1485
+ * Paginated result from the UTXO data endpoint.
1486
+ *
1487
+ * @remarks
1488
+ * Contains the fetched UTXO items along with pagination metadata
1489
+ * for iterating through large result sets.
1490
+ *
1491
+ * @see {@link UtxoDataFetcherFunction}
1492
+ * @see {@link UtxoDataItem}
1493
+ * @public
1494
+ */
1495
+ interface UtxoFetchResult {
1496
+ /** Map of insertion index to UTXO data */
1497
+ items: Map<U32, UtxoDataItem>;
1498
+ /** Whether there are more results available */
1499
+ hasMore: boolean;
1500
+ /** Next cursor to continue pagination (use as startIndex for next request) */
1501
+ nextCursor: bigint | undefined;
1502
+ /** Total count of records in the requested range */
1503
+ totalCount: U64;
1504
+ }
1505
+ /**
1506
+ * Function type for fetching UTXO data from the indexer.
1507
+ *
1508
+ * @remarks
1509
+ * Fetches UTXO data by absolute index range with pagination support.
1510
+ *
1511
+ * **Pagination:**
1512
+ * - Use `startIndex` and optional `endIndex` to define the range
1513
+ * - Use `limit` to control page size (default: 1000, max: 5000)
1514
+ * - Use `nextCursor` from result as `startIndex` for next page
1515
+ *
1516
+ * @param startIndex - Starting absolute index (inclusive)
1517
+ * @param endIndex - Optional ending absolute index (inclusive)
1518
+ * @param limit - Maximum number of records to return (default: 1000, max: 5000)
1519
+ * @returns Paginated result with UTXO items and metadata
1520
+ *
1521
+ * @example
1522
+ * ```typescript
1523
+ * // Fetch first page
1524
+ * let result = await fetchUtxoData(0n, undefined, 1000);
1525
+ * console.log(`Fetched ${result.items.size} UTXOs`);
1526
+ *
1527
+ * // Continue pagination
1528
+ * while (result.hasMore && result.nextCursor !== undefined) {
1529
+ * result = await fetchUtxoData(result.nextCursor, undefined, 1000);
1530
+ * console.log(`Fetched ${result.items.size} more UTXOs`);
1531
+ * }
1532
+ * ```
1533
+ *
1534
+ * @see {@link UtxoFetchResult}
1535
+ * @public
1536
+ */
1537
+ type UtxoDataFetcherFunction = (startIndex: bigint, endIndex?: bigint, limit?: U32) => Promise<UtxoFetchResult>;
1538
+ /**
1539
+ * Arguments for creating a UTXO data fetcher function.
1540
+ *
1541
+ * @example
1542
+ * ```typescript
1543
+ * const args: GetUtxoDataFetcherArgs = {
1544
+ * apiEndpoint: 'https://indexer.umbra.finance'
1545
+ * };
1546
+ * ```
1547
+ *
1548
+ * @see {@link UtxoDataFetcherFunction}
1549
+ * @public
1550
+ */
1551
+ interface GetUtxoDataFetcherArgs {
1552
+ /** The HTTP endpoint of the indexer service */
1553
+ apiEndpoint: string;
1554
+ }
1555
+ /**
1556
+ * Optional dependencies for the UTXO data fetcher factory.
1557
+ *
1558
+ * @remarks
1559
+ * Allows injection of a custom fetch implementation for testing
1560
+ * or environments without global fetch.
1561
+ *
1562
+ * @see {@link UtxoDataFetcherFunction}
1563
+ * @public
1564
+ */
1565
+ interface GetUtxoDataFetcherDeps {
1566
+ /**
1567
+ * Custom fetch implementation.
1568
+ * @default globalThis.fetch
1569
+ */
1570
+ fetch?: typeof globalThis.fetch;
1571
+ }
1572
+ /**
1573
+ * Decrypted UTXO data from successful AES decryption.
1574
+ *
1575
+ * @remarks
1576
+ * Contains the plaintext values extracted from the AES-encrypted UTXO data,
1577
+ * along with the original UTXO metadata and the determined unlocker type.
1578
+ *
1579
+ * **AES Plaintext Structure (68 bytes):**
1580
+ * | Offset | Size | Field |
1581
+ * |--------|------|-------|
1582
+ * | 0 | 8 | Amount (LE) |
1583
+ * | 8 | 32 | Destination address |
1584
+ * | 40 | 16 | Modified generation index (LE) |
1585
+ * | 56 | 12 | Domain separator |
1586
+ *
1587
+ * @see {@link ClaimableUtxoData}
1588
+ * @public
1589
+ */
1590
+ interface DecryptedUtxoData {
1591
+ /** Decrypted UTXO amount */
1592
+ amount: U64;
1593
+ /** Decrypted destination address */
1594
+ destinationAddress: Address;
1595
+ /** Modified generation index from decrypted AES data */
1596
+ modifiedGenerationIndex: U128LeBytes;
1597
+ /** Tree index containing this UTXO */
1598
+ treeIndex: U32;
1599
+ /** Insertion index within the tree */
1600
+ insertionIndex: U32;
1601
+ /** H1 components for claim proof generation */
1602
+ h1Components: H1Components;
1603
+ /** H1 hash value */
1604
+ h1Hash: U256LeBytes;
1605
+ /** H2 hash value */
1606
+ h2Hash: U256LeBytes;
1607
+ /**
1608
+ * The type of unlocker determined by the domain separator.
1609
+ * - 'self-burnable': Encrypted-balance deposit, self-claimable (you deposited it, you can burn it)
1610
+ * - 'received': Encrypted-balance deposit, receiver-claimable (someone sent it to you)
1611
+ * - 'public-self-burnable': Public-balance deposit, self-claimable (you deposited it via public ATA)
1612
+ * - 'public-received': Public-balance deposit, receiver-claimable (someone sent it to you via public ATA)
1613
+ */
1614
+ unlockerType: "self-burnable" | "received" | "public-self-burnable" | "public-received";
1615
+ }
1616
+ /**
1617
+ * Full claim-ready UTXO data with Merkle proof.
1618
+ *
1619
+ * @remarks
1620
+ * Contains all the data needed to submit a claim transaction,
1621
+ * including the Merkle proof and decrypted values.
1622
+ * This structure is designed to be passed directly to claim functions.
1623
+ *
1624
+ * @see {@link ClaimableUtxoResult}
1625
+ * @see {@link ClaimableUtxoScannerFunction}
1626
+ * @public
1627
+ */
1628
+ interface ClaimableUtxoData {
1629
+ /** Current Merkle root of the mixer tree */
1630
+ merkleRoot: U256LeBytes;
1631
+ /** Array of sibling hashes from leaf to root */
1632
+ merklePath: U256LeBytes[];
1633
+ /** Leaf index in the Merkle tree */
1634
+ leafIndex: U128;
1635
+ /** Decrypted UTXO amount */
1636
+ amount: U64;
1637
+ /** Decrypted destination address */
1638
+ destinationAddress: Address;
1639
+ /** Modified generation index from decrypted AES data */
1640
+ depositModifiedGenerationIndex: U128;
1641
+ /** Protocol version identifier */
1642
+ version: U64;
1643
+ /** Index of the commitment in the Merkle tree */
1644
+ commitmentIndex: U128;
1645
+ /** Lower 128 bits of the sender's address */
1646
+ senderAddressLow: U128;
1647
+ /** Upper 128 bits of the sender's address */
1648
+ senderAddressHigh: U128;
1649
+ /** Fixed SOL fees paid to relayer (in lamports) */
1650
+ relayerFixedSolFees: U64;
1651
+ /** Lower 128 bits of the mint address */
1652
+ mintAddressLow: U128;
1653
+ /** Upper 128 bits of the mint address */
1654
+ mintAddressHigh: U128;
1655
+ /** Timestamp components for TVK derivation */
1656
+ timestamp: TimestampComponents;
1657
+ /** Cumulative SPL token volume in the pool at insertion time (base units) */
1658
+ poolVolumeSpl: U64;
1659
+ /** Cumulative SOL volume in the pool at insertion time (lamports) */
1660
+ poolVolumeSol: U64;
1661
+ }
1662
+ /**
1663
+ * Result from fetching claimable UTXOs.
1664
+ *
1665
+ * @remarks
1666
+ * Groups claimable UTXOs by unlocker type for easy processing.
1667
+ * Each array contains claim-ready data that can be passed directly
1668
+ * to the appropriate claim function.
1669
+ *
1670
+ * @example
1671
+ * ```typescript
1672
+ * const result: ClaimableUtxoResult = await fetchClaimableUtxos({...});
1673
+ * console.log(`Self-burnable: ${result.selfBurnable.length}`);
1674
+ * console.log(`Received: ${result.received.length}`);
1675
+ * ```
1676
+ *
1677
+ * @see {@link ClaimableUtxoScannerFunction}
1678
+ * @see {@link ClaimableUtxoData}
1679
+ * @public
1680
+ */
1681
+ interface ClaimableUtxoResult {
1682
+ /**
1683
+ * Encrypted-balance deposit UTXOs you can burn yourself (you created them).
1684
+ * Pass to `SelfClaimableUtxoToEncryptedBalanceClaimerFunction` or
1685
+ * `SelfClaimableUtxoToPublicBalanceClaimerFunction`.
1686
+ */
1687
+ selfBurnable: ClaimableUtxoData[];
1688
+ /**
1689
+ * Encrypted-balance deposit UTXOs sent to you by others.
1690
+ * Pass to `ReceiverClaimableUtxoToEncryptedBalanceClaimerFunction`.
1691
+ */
1692
+ received: ClaimableUtxoData[];
1693
+ /**
1694
+ * Public-balance deposit UTXOs you can burn yourself (you created them via public ATA).
1695
+ * Pass to `SelfClaimableUtxoToEncryptedBalanceClaimerFunction` or
1696
+ * `SelfClaimableUtxoToPublicBalanceClaimerFunction`.
1697
+ */
1698
+ publicSelfBurnable: ClaimableUtxoData[];
1699
+ /**
1700
+ * Public-balance deposit UTXOs sent to you by others via public ATA.
1701
+ * Pass to `ReceiverClaimableUtxoToEncryptedBalanceClaimerFunction`.
1702
+ */
1703
+ publicReceived: ClaimableUtxoData[];
1704
+ }
1705
+ /**
1706
+ * A decrypted UTXO as returned by the scanner, before merkle proofs are attached.
1707
+ *
1708
+ * @remarks
1709
+ * This is the output of the scan phase. Merkle proofs are fetched later at
1710
+ * claim time, per-batch, via the batch proof endpoint to guarantee a consistent
1711
+ * root across all UTXOs in a ZK proof batch.
1712
+ *
1713
+ * @see {@link ScannedUtxoResult}
1714
+ * @see {@link ClaimableUtxoData} — the enriched type after proofs are attached
1715
+ * @public
1716
+ */
1717
+ type ScannedUtxoData = DecryptedUtxoData;
1718
+ /**
1719
+ * Result from scanning UTXOs (no merkle proofs attached).
1720
+ *
1721
+ * @remarks
1722
+ * Groups scanned UTXOs by unlocker type. Merkle proofs are fetched at claim
1723
+ * time, not scan time, so these entries do not yet contain proof data.
1724
+ *
1725
+ * @see {@link ScannedUtxoData}
1726
+ * @public
1727
+ */
1728
+ interface ScannedUtxoResult {
1729
+ /** Encrypted-balance deposit UTXOs you can burn yourself. */
1730
+ selfBurnable: ScannedUtxoData[];
1731
+ /** Encrypted-balance deposit UTXOs sent to you by others. */
1732
+ received: ScannedUtxoData[];
1733
+ /** Public-balance deposit UTXOs you can burn yourself. */
1734
+ publicSelfBurnable: ScannedUtxoData[];
1735
+ /** Public-balance deposit UTXOs sent to you by others via public ATA. */
1736
+ publicReceived: ScannedUtxoData[];
1737
+ }
1738
+ /**
1739
+ * Result of a batch merkle proof fetch from the indexer.
1740
+ *
1741
+ * @remarks
1742
+ * All proofs share a single `root` because they were generated under a single
1743
+ * tree read lock. This guarantees consistency for ZK batch claims.
1744
+ *
1745
+ * @public
1746
+ */
1747
+ interface BatchMerkleProofResult {
1748
+ /** The shared merkle root for all proofs in this batch. */
1749
+ root: U256LeBytes;
1750
+ /** Per-leaf proof data, keyed by insertion index. */
1751
+ proofs: Map<U32, {
1752
+ merklePath: U256LeBytes[];
1753
+ leaf: U256LeBytes;
1754
+ }>;
1755
+ }
1756
+ /**
1757
+ * Function type for fetching batch merkle proofs with a consistent root.
1758
+ *
1759
+ * @remarks
1760
+ * Used at claim time (not scan time) to fetch proofs for all UTXOs in a
1761
+ * single ZK proof batch. The indexer guarantees all returned proofs share
1762
+ * the same merkle root by holding a single read lock.
1763
+ *
1764
+ * @see {@link BatchMerkleProofResult}
1765
+ * @public
1766
+ */
1767
+ type BatchMerkleProofFetcherFunction = (treeIndex: U32, insertionIndices: readonly U32[]) => Promise<BatchMerkleProofResult>;
1768
+ /**
1769
+ * Function type for fetching claimable UTXOs.
1770
+ *
1771
+ * @remarks
1772
+ * Fetches, decrypts, and categorizes all UTXOs that belong to the client
1773
+ * within the specified tree and index range.
1774
+ *
1775
+ * **Workflow:**
1776
+ * 1. Fetch UTXO data from indexer (paginated)
1777
+ * 2. For each UTXO, try to decrypt using client's X25519 key
1778
+ * 3. Check domain separator to determine unlocker type
1779
+ * 4. Fetch Merkle proofs for successfully decrypted UTXOs
1780
+ * 5. Return grouped results
1781
+ *
1782
+ * @param treeIndex - The Merkle tree index to scan
1783
+ * @param startInsertionIndex - Starting insertion index (inclusive)
1784
+ * @param endInsertionIndex - Optional ending insertion index (inclusive)
1785
+ * @returns Promise resolving to grouped claimable UTXOs
1786
+ *
1787
+ * @example
1788
+ * ```typescript
1789
+ * const fetchClaimable = getClaimableUtxoScannerFunction({ client });
1790
+ *
1791
+ * // Scan tree 0 for claimable UTXOs
1792
+ * const result = await fetchClaimable(0, 0, 10000);
1793
+ *
1794
+ * console.log(`Found ${result.ephemeral.length} self-deposited UTXOs`);
1795
+ * console.log(`Found ${result.receiver.length} UTXOs from others`);
1796
+ * ```
1797
+ *
1798
+ * @see {@link ClaimableUtxoResult}
1799
+ * @public
1800
+ */
1801
+ type ClaimableUtxoScannerFunction = (treeIndex: U32, startInsertionIndex: U32, endInsertionIndex?: U32) => Promise<ScannedUtxoResult>;
1802
+ /**
1803
+ * Arguments for creating a claimable UTXO fetcher function.
1804
+ *
1805
+ * @example
1806
+ * ```typescript
1807
+ * const args: GetClaimableUtxoScannerFunctionArgs = {
1808
+ * client: myUmbraClient
1809
+ * };
1810
+ * ```
1811
+ *
1812
+ * @see {@link ClaimableUtxoScannerFunction}
1813
+ * @public
1814
+ */
1815
+ interface GetClaimableUtxoScannerFunctionArgs {
1816
+ /** The Umbra client providing cryptographic keys for decryption */
1817
+ client: IUmbraClient;
1818
+ }
1819
+ /**
1820
+ * Optional dependencies for the claimable UTXO fetcher factory.
1821
+ *
1822
+ * @remarks
1823
+ * Allows injection of custom implementations for testing
1824
+ * or alternative implementations.
1825
+ *
1826
+ * @see {@link ClaimableUtxoScannerFunction}
1827
+ * @public
1828
+ */
1829
+ interface GetClaimableUtxoScannerFunctionDeps {
1830
+ /**
1831
+ * Custom UTXO data fetcher.
1832
+ * @default Created from client's indexerApiEndpoint
1833
+ */
1834
+ fetchUtxoData?: UtxoDataFetcherFunction;
1835
+ /**
1836
+ * Custom Merkle proof fetcher.
1837
+ * @default Created from client's indexerApiEndpoint
1838
+ */
1839
+ fetchMerkleProof?: MerkleProofFetcherFunction;
1840
+ /**
1841
+ * Custom AES decryptor function.
1842
+ * @default getAesDecryptor()
1843
+ */
1844
+ aesDecryptor?: AesDecryptorFunction;
1845
+ /**
1846
+ * Custom X25519 public key derivation function.
1847
+ * @default x25519.getPublicKey
1848
+ */
1849
+ x25519GetPublicKey?: (privateKey: X25519PrivateKey) => X25519PublicKey;
1850
+ /**
1851
+ * Custom X25519 shared secret computation function.
1852
+ * @default x25519.getSharedSecret
1853
+ */
1854
+ x25519GetSharedSecret?: (privateKey: X25519PrivateKey, publicKey: X25519PublicKey) => Uint8Array;
1855
+ /**
1856
+ * Custom fetch implementation for indexer API calls.
1857
+ * @default globalThis.fetch
1858
+ */
1859
+ fetch?: typeof globalThis.fetch;
1860
+ }
1861
+
1862
+ /**
1863
+ * Umbra Interfaces — Client and signer interfaces — the core SDK configuration object.
1864
+ *
1865
+ * @module umbra/interfaces/client
1866
+ * @since 2.0.0
1867
+ */
1868
+
1869
+ /**
1870
+ * A transaction with blockhash lifetime constraint, ready for signing.
1871
+ *
1872
+ * This is the intersection of a base `Transaction` (containing `messageBytes`
1873
+ * and `signatures`) with `TransactionWithBlockhashLifetime` (containing the
1874
+ * `lifetimeConstraint` with blockhash and lastValidBlockHeight).
1875
+ *
1876
+ * @remarks
1877
+ * All Umbra transaction signing flows expect this type. Construct it by
1878
+ * fetching a recent blockhash and attaching it to a compiled transaction
1879
+ * via the `@solana/kit` utilities before passing to `IUmbraSigner.signTransaction`.
1880
+ *
1881
+ * @example
1882
+ * ```typescript
1883
+ * import { pipe } from "@solana/functional";
1884
+ * import { setTransactionMessageLifetimeUsingBlockhash } from "@solana/kit";
1885
+ *
1886
+ * const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
1887
+ * const signable: SignableTransaction = pipe(
1888
+ * txMessage,
1889
+ * (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
1890
+ * (tx) => compileTransaction(tx),
1891
+ * );
1892
+ * ```
1893
+ *
1894
+ * @see {@link IUmbraSigner}
1895
+ * @public
1896
+ */
1897
+ type SignableTransaction = Transaction & TransactionWithBlockhashLifetime;
1898
+ /**
1899
+ * Result of signing an arbitrary message.
1900
+ *
1901
+ * Contains both the original message and its cryptographic signature,
1902
+ * allowing verification without needing to reconstruct the message.
1903
+ *
1904
+ * @remarks
1905
+ * Returned by {@link IUmbraSigner.signMessage}. All three fields are required
1906
+ * for off-chain signature verification.
1907
+ *
1908
+ * @example
1909
+ * ```typescript
1910
+ * const signed: SignedMessage = await signer.signMessage(
1911
+ * new TextEncoder().encode("Hello, Umbra!")
1912
+ * );
1913
+ * console.log(signed.signer); // base58 address
1914
+ * console.log(signed.signature); // 64-byte Ed25519 signature
1915
+ * ```
1916
+ *
1917
+ * @sealed
1918
+ * @see {@link IUmbraSigner}
1919
+ * @public
1920
+ */
1921
+ interface SignedMessage {
1922
+ /**
1923
+ * The original message bytes that were signed.
1924
+ */
1925
+ readonly message: Uint8Array;
1926
+ /**
1927
+ * The Ed25519 signature over the message.
1928
+ *
1929
+ * This is a 64-byte signature that can be verified using the
1930
+ * signer's public key (address).
1931
+ */
1932
+ readonly signature: SignatureBytes;
1933
+ /**
1934
+ * The address of the signer who produced this signature.
1935
+ *
1936
+ * This can be used to verify the signature against the expected
1937
+ * signer's public key.
1938
+ */
1939
+ readonly signer: Address;
1940
+ }
1941
+ /**
1942
+ * Interface for signing Solana transactions and messages in the Umbra protocol.
1943
+ *
1944
+ * This interface abstracts the signing implementation, allowing different
1945
+ * backends such as:
1946
+ * - In-memory key pairs (for testing or non-sensitive operations)
1947
+ * - Hardware wallets (Ledger, Trezor)
1948
+ * - Mobile secure enclaves
1949
+ * - Browser wallet extensions
1950
+ * - Multi-party computation (MPC) signers
1951
+ *
1952
+ * ## Design Principles
1953
+ *
1954
+ * 1. **Partial Signing**: Methods return partially signed transactions,
1955
+ * allowing for multi-signature workflows where multiple parties must sign.
1956
+ *
1957
+ * 2. **Signature Only**: The signer only signs transactions; it does not
1958
+ * submit them to the network. This separation allows for:
1959
+ * - Transaction inspection before submission
1960
+ * - Batching multiple transactions
1961
+ * - Custom submission strategies (retry logic, priority fees, etc.)
1962
+ *
1963
+ * 3. **Lifetime Preservation**: Transactions already contain their blockhash
1964
+ * and lifetime constraints. The signer preserves this information.
1965
+ *
1966
+ * @example
1967
+ * ```typescript
1968
+ * import { IUmbraSigner, SignableTransaction } from '@umbra-privacy/sdk';
1969
+ *
1970
+ * // Example: Using a signer to sign a transaction
1971
+ * async function signAndInspect(
1972
+ * signer: IUmbraSigner,
1973
+ * transaction: SignableTransaction
1974
+ * ) {
1975
+ * // Get the signer's address
1976
+ * console.log(`Signing with: ${signer.address}`);
1977
+ *
1978
+ * // Sign the transaction
1979
+ * const signedTx = await signer.signTransaction(transaction);
1980
+ *
1981
+ * // Transaction still has its lifetime info
1982
+ * console.log(`Valid until block: ${signedTx.lifetimeConstraint.lastValidBlockHeight}`);
1983
+ *
1984
+ * return signedTx;
1985
+ * }
1986
+ * ```
1987
+ *
1988
+ * @example
1989
+ * ```typescript
1990
+ * // Example: Batch signing multiple transactions
1991
+ * async function batchSign(
1992
+ * signer: IUmbraSigner,
1993
+ * transactions: SignableTransaction[]
1994
+ * ) {
1995
+ * // Sign all transactions in one call
1996
+ * const signedTransactions = await signer.signTransactions(transactions);
1997
+ *
1998
+ * // Each transaction is signed independently
1999
+ * for (const tx of signedTransactions) {
2000
+ * console.log(`Blockhash: ${tx.lifetimeConstraint.blockhash}`);
2001
+ * }
2002
+ *
2003
+ * return signedTransactions;
2004
+ * }
2005
+ * ```
2006
+ *
2007
+ * @example
2008
+ * ```typescript
2009
+ * // Example: Signing an arbitrary message for off-chain verification
2010
+ * async function createSignedAttestation(
2011
+ * signer: IUmbraSigner,
2012
+ * data: string
2013
+ * ) {
2014
+ * const message = new TextEncoder().encode(data);
2015
+ * const signedMessage = await signer.signMessage(message);
2016
+ *
2017
+ * return {
2018
+ * data,
2019
+ * signature: signedMessage.signature,
2020
+ * signer: signedMessage.signer,
2021
+ * };
2022
+ * }
2023
+ * ```
2024
+ *
2025
+ * @public
2026
+ */
2027
+ interface IUmbraSigner {
2028
+ /**
2029
+ * The public address of this signer.
2030
+ *
2031
+ * This is the base58-encoded Ed25519 public key that corresponds to
2032
+ * the private key used for signing. It uniquely identifies this signer
2033
+ * on the Solana network.
2034
+ *
2035
+ * @remarks
2036
+ * The address is derived from the public key and serves as:
2037
+ * - The account owner for token accounts
2038
+ * - The fee payer identifier in transactions
2039
+ * - The key to look up signatures in signed transactions
2040
+ *
2041
+ * @example
2042
+ * ```typescript
2043
+ * const signer: IUmbraSigner = getUmbraSigner(config);
2044
+ * console.log(`Signer address: ${signer.address}`);
2045
+ * // Output: "8xH3kJLmV9..."
2046
+ * ```
2047
+ */
2048
+ readonly address: Address;
2049
+ /**
2050
+ * Signs a single transaction.
2051
+ *
2052
+ * Takes a compiled transaction with its blockhash lifetime already set
2053
+ * and returns the same transaction with the signer's signature added.
2054
+ *
2055
+ * @param transaction - The transaction to sign. Must include:
2056
+ * - `messageBytes`: The serialized transaction message
2057
+ * - `signatures`: Existing signatures map (may be empty)
2058
+ * - `lifetimeConstraint`: Blockhash and last valid block height
2059
+ *
2060
+ * @returns A promise that resolves to the signed transaction with:
2061
+ * - The signer's signature added to the `signatures` map
2062
+ * - All other fields preserved unchanged
2063
+ *
2064
+ * @remarks
2065
+ * ## Partial Signing
2066
+ *
2067
+ * This method performs partial signing, meaning:
2068
+ * - Only adds a signature for this signer's address
2069
+ * - Does not validate that all required signatures are present
2070
+ * - The returned transaction may need additional signatures
2071
+ *
2072
+ * ## Error Conditions
2073
+ *
2074
+ * The method may throw if:
2075
+ * - The signer's address is not in the transaction's account list
2076
+ * - The underlying signing operation fails (hardware wallet disconnected, etc.)
2077
+ * - The user rejects the signing request (for interactive signers)
2078
+ *
2079
+ * @example
2080
+ * ```typescript
2081
+ * const transaction: SignableTransaction = buildShieldTransaction(...);
2082
+ *
2083
+ * // Sign the transaction
2084
+ * const signedTx = await signer.signTransaction(transaction);
2085
+ *
2086
+ * console.log('Transaction signed successfully');
2087
+ * ```
2088
+ */
2089
+ signTransaction: (transaction: SignableTransaction) => Promise<SignedTransaction>;
2090
+ /**
2091
+ * Signs multiple transactions in a batch.
2092
+ *
2093
+ * This method signs an array of transactions, returning them in the
2094
+ * same order with signatures added. Each transaction is signed
2095
+ * independently with its own blockhash lifetime preserved.
2096
+ *
2097
+ * @param transactions - Array of transactions to sign. Each must include
2098
+ * the same fields as required by `signTransaction`.
2099
+ *
2100
+ * @returns A promise that resolves to an array of signed transactions,
2101
+ * in the same order as the input array.
2102
+ *
2103
+ * @remarks
2104
+ * ## Batch Efficiency
2105
+ *
2106
+ * Implementations may optimize batch signing by:
2107
+ * - Reducing round-trips to hardware wallets
2108
+ * - Batching user approval prompts
2109
+ * - Parallelizing cryptographic operations
2110
+ *
2111
+ * ## Atomicity
2112
+ *
2113
+ * Batch signing is **not atomic**. If signing fails partway through:
2114
+ * - Some transactions may be signed, others not
2115
+ * - The method will throw, but partial results may not be recoverable
2116
+ * - Callers should handle failures by re-signing the entire batch
2117
+ *
2118
+ * ## Order Preservation
2119
+ *
2120
+ * The returned array maintains the same order as the input:
2121
+ * - `result[i]` is the signed version of `transactions[i]`
2122
+ * - Each transaction retains its original blockhash lifetime
2123
+ *
2124
+ * @example
2125
+ * ```typescript
2126
+ * const transactions: SignableTransaction[] = [
2127
+ * buildShieldTransaction(mint1, amount1),
2128
+ * buildShieldTransaction(mint2, amount2),
2129
+ * buildShieldTransaction(mint3, amount3),
2130
+ * ];
2131
+ *
2132
+ * // Sign all transactions at once
2133
+ * const signedTransactions = await signer.signTransactions(transactions);
2134
+ *
2135
+ * // Submit each signed transaction
2136
+ * for (const tx of signedTransactions) {
2137
+ * await submitTransaction(tx);
2138
+ * }
2139
+ * ```
2140
+ */
2141
+ signTransactions: (transactions: readonly SignableTransaction[]) => Promise<SignedTransaction[]>;
2142
+ /**
2143
+ * Signs an arbitrary message.
2144
+ *
2145
+ * This method signs a raw byte array using the signer's private key,
2146
+ * producing an Ed25519 signature. This is useful for:
2147
+ * - Off-chain message authentication
2148
+ * - Proving ownership of an address
2149
+ * - Creating verifiable attestations
2150
+ *
2151
+ * @param message - The raw bytes to sign. Can be any data, but common
2152
+ * patterns include:
2153
+ * - UTF-8 encoded strings
2154
+ * - Structured data (JSON, protobuf, etc.)
2155
+ * - Hash digests
2156
+ *
2157
+ * @returns A promise that resolves to a signed message containing:
2158
+ * - The original message bytes
2159
+ * - The 64-byte Ed25519 signature
2160
+ * - The signer's address for verification
2161
+ *
2162
+ * @remarks
2163
+ * ## Message Prefixing
2164
+ *
2165
+ * Some signer implementations may prefix the message with a domain
2166
+ * separator (e.g., "\x19Solana Signed Message:\n") to prevent
2167
+ * signature reuse attacks. Verifiers must use the same prefix.
2168
+ *
2169
+ * ## Security Considerations
2170
+ *
2171
+ * - Never sign messages you don't understand
2172
+ * - Be cautious of messages that look like transaction data
2173
+ * - Consider using structured message formats with clear semantics
2174
+ *
2175
+ * @example
2176
+ * ```typescript
2177
+ * // Sign a simple text message
2178
+ * const message = new TextEncoder().encode('Hello, Umbra!');
2179
+ * const signedMessage = await signer.signMessage(message);
2180
+ *
2181
+ * // The signature can be verified off-chain
2182
+ * const isValid = await verifySignature(
2183
+ * signedMessage.message,
2184
+ * signedMessage.signature,
2185
+ * signedMessage.signer
2186
+ * );
2187
+ * ```
2188
+ *
2189
+ * @example
2190
+ * ```typescript
2191
+ * // Sign structured data
2192
+ * const attestation = {
2193
+ * action: 'verify_ownership',
2194
+ * address: signer.address,
2195
+ * timestamp: Date.now(),
2196
+ * };
2197
+ *
2198
+ * const message = new TextEncoder().encode(JSON.stringify(attestation));
2199
+ * const signedAttestation = await signer.signMessage(message);
2200
+ * ```
2201
+ */
2202
+ signMessage: (message: Uint8Array) => Promise<SignedMessage>;
2203
+ }
2204
+ /**
2205
+ * Function type for retrieving the master seed from secure storage.
2206
+ *
2207
+ * This function type is used to abstract the retrieval of the master seed,
2208
+ * which is the root cryptographic secret used to derive all keys in the
2209
+ * Umbra protocol (viewing keys, spending keys, encryption keys, etc.).
2210
+ *
2211
+ * @returns A `Promise` that resolves to the `MasterSeed` - a 64-byte
2212
+ * Keccak-512 hash that serves as the root of the key hierarchy.
2213
+ *
2214
+ * @remarks
2215
+ * ## Why Use a Function?
2216
+ *
2217
+ * The master seed is stored in the device's secure storage (e.g., iOS Keychain,
2218
+ * Android Keystore, or platform-specific secure enclaves) rather than being
2219
+ * held in memory. Using a function to retrieve it provides several benefits:
2220
+ *
2221
+ * - **Lazy Loading**: The seed is only loaded into memory when needed
2222
+ * - **Security**: Minimizes the time sensitive data spends in application memory
2223
+ * - **Abstraction**: Allows different implementations for different platforms
2224
+ * (mobile secure storage, hardware wallets, browser extensions, etc.)
2225
+ * - **Async Support**: Secure storage APIs are typically asynchronous
2226
+ *
2227
+ * ## Security Considerations
2228
+ *
2229
+ * - The master seed should NEVER be logged, transmitted, or stored in plain text
2230
+ * - Implementations should clear the seed from memory after use when possible
2231
+ * - Consider using secure memory handling techniques on supported platforms
2232
+ * - The seed should only be accessed when cryptographic operations are required
2233
+ *
2234
+ * @example
2235
+ * ```typescript
2236
+ * import { GetMasterSeedFunction } from '@umbra-privacy/sdk';
2237
+ * import * as SecureStore from 'expo-secure-store';
2238
+ *
2239
+ * // Example implementation using Expo SecureStore
2240
+ * const getMasterSeed: GetMasterSeedFunction = async () => {
2241
+ * const seedHex = await SecureStore.getItemAsync('umbra_master_seed');
2242
+ * if (!seedHex) {
2243
+ * throw new Error('Master seed not found in secure storage');
2244
+ * }
2245
+ * return hexToBytes(seedHex) as MasterSeed;
2246
+ * };
2247
+ * ```
2248
+ *
2249
+ * @see {@link IUmbraClient}
2250
+ * @public
2251
+ */
2252
+ type GetMasterSeedFunction = () => Promise<MasterSeed>;
2253
+ /**
2254
+ * Configuration interface for the Umbra client.
2255
+ *
2256
+ * This interface defines the required configuration for initializing an Umbra
2257
+ * client instance. It includes network endpoints, the master seed retrieval
2258
+ * function, and other essential settings for interacting with the Umbra
2259
+ * privacy protocol on Solana.
2260
+ *
2261
+ * @remarks
2262
+ * ## Master Seed Function
2263
+ *
2264
+ * The `getMasterSeed` property is a function rather than a direct value because
2265
+ * the master seed is typically stored in the device's secure storage system:
2266
+ *
2267
+ * - **iOS**: Keychain Services
2268
+ * - **Android**: Android Keystore
2269
+ * - **Desktop**: OS-specific credential managers
2270
+ * - **Browser**: Web Crypto API or extension-based secure storage
2271
+ *
2272
+ * By using a function, we ensure:
2273
+ * 1. The seed is retrieved on-demand, not held in memory unnecessarily
2274
+ * 2. Each retrieval can include biometric/PIN verification if configured
2275
+ * 3. The implementation can vary across platforms without changing the interface
2276
+ *
2277
+ * ## Network Configuration
2278
+ *
2279
+ * The client requires both HTTP and WebSocket endpoints:
2280
+ * - `rpcUrl`: Used for sending transactions and querying account state
2281
+ * - `rpcSubscriptionsUrl`: Used for real-time account change notifications
2282
+ *
2283
+ * @example
2284
+ * ```typescript
2285
+ * import { IUmbraClient } from '@umbra-privacy/sdk';
2286
+ * import * as SecureStore from 'expo-secure-store';
2287
+ *
2288
+ * const config: IUmbraClient = {
2289
+ * // Solana RPC endpoint for transactions and queries
2290
+ * rpcUrl: 'https://api.mainnet-beta.solana.com',
2291
+ *
2292
+ * // WebSocket endpoint for real-time subscriptions
2293
+ * rpcSubscriptionsUrl: 'wss://api.mainnet-beta.solana.com',
2294
+ *
2295
+ * // Function to retrieve master seed from secure storage
2296
+ * // This is called on-demand when cryptographic operations are needed
2297
+ * getMasterSeed: async () => {
2298
+ * const seedHex = await SecureStore.getItemAsync('umbra_master_seed');
2299
+ * if (!seedHex) {
2300
+ * throw new Error('Master seed not found');
2301
+ * }
2302
+ * return hexToBytes(seedHex) as MasterSeed;
2303
+ * },
2304
+ *
2305
+ * // Optional: Commitment level for transactions
2306
+ * commitment: 'confirmed',
2307
+ * };
2308
+ *
2309
+ * const client = createUmbraClient(config);
2310
+ * ```
2311
+ *
2312
+ * @example
2313
+ * ```typescript
2314
+ * // React Native with biometric protection
2315
+ * import * as LocalAuthentication from 'expo-local-authentication';
2316
+ *
2317
+ * const secureConfig: IUmbraClient = {
2318
+ * rpcUrl: process.env.SOLANA_RPC_URL,
2319
+ * rpcSubscriptionsUrl: process.env.SOLANA_WS_URL,
2320
+ * getMasterSeed: async () => {
2321
+ * // Require biometric authentication before accessing seed
2322
+ * const authResult = await LocalAuthentication.authenticateAsync({
2323
+ * promptMessage: 'Authenticate to access your private keys',
2324
+ * });
2325
+ *
2326
+ * if (!authResult.success) {
2327
+ * throw new Error('Biometric authentication failed');
2328
+ * }
2329
+ *
2330
+ * const seedHex = await SecureStore.getItemAsync('umbra_master_seed');
2331
+ * return hexToBytes(seedHex) as MasterSeed;
2332
+ * },
2333
+ * };
2334
+ * ```
2335
+ *
2336
+ * @public
2337
+ */
2338
+ interface IUmbraClient {
2339
+ /**
2340
+ * The signer used for signing transactions and messages.
2341
+ *
2342
+ * This signer is used for:
2343
+ * - Signing transactions during registration, shielding, unshielding
2344
+ * - Paying transaction fees (as the fee payer)
2345
+ * - Identifying the user's address for PDA derivation
2346
+ * - Generating the master seed (via signature-based derivation)
2347
+ *
2348
+ * The signer is stored when the client is created via `getUmbraClient`
2349
+ * and reused for all subsequent operations.
2350
+ */
2351
+ readonly signer: IUmbraSigner;
2352
+ /**
2353
+ * Network environment for the client.
2354
+ *
2355
+ * @remarks
2356
+ * - `'mainnet'`: Production network
2357
+ * - `'devnet'`: Development/testing network
2358
+ * - `'localnet'`: Local validator for development
2359
+ */
2360
+ readonly network: Network;
2361
+ /**
2362
+ * Network-specific configuration for the protocol deployment.
2363
+ *
2364
+ * Contains the program ID, MXE account address, MXE X25519 public key,
2365
+ * Arcium program address, and cluster offset for the current network.
2366
+ *
2367
+ * @remarks
2368
+ * Populated at client construction time from the SDK's per-network
2369
+ * config (see `packages/sdk/src/constants/networks.ts`). If the
2370
+ * network has not been configured, client construction will throw.
2371
+ */
2372
+ readonly networkConfig: NetworkConfig;
2373
+ /**
2374
+ * Version specifications for protocol, algorithm, and scheme.
2375
+ *
2376
+ * These version specifiers are used during key derivation to ensure
2377
+ * keys are derived with the correct versioning context.
2378
+ *
2379
+ * @remarks
2380
+ * Each specifier is a function that returns a version object with:
2381
+ * - `name`: The version identifier (e.g., "umbra", "kmac", "default")
2382
+ * - `version`: Semver string (e.g., "1.0.0")
2383
+ */
2384
+ readonly versions: {
2385
+ readonly protocol: ProtocolVersionSpecifierFunction;
2386
+ readonly algorithm: AlgorithmVersionSpecifierFunction;
2387
+ readonly scheme: SchemeVersionSpecifierFunction;
2388
+ readonly network: NetworkSpecifierFunction;
2389
+ };
2390
+ /**
2391
+ * U512 offsets for key derivation.
2392
+ *
2393
+ * Each offset is used in the domain separator during key derivation
2394
+ * to create distinct keys for different purposes.
2395
+ *
2396
+ * @remarks
2397
+ * - masterViewingKey: Offset for master viewing key derivation
2398
+ * - poseidonPrivateKey: Offset for Poseidon private key derivation
2399
+ * - x25519UserAccountPrivateKey: Offset for user account X25519 keypair (token registration)
2400
+ * - x25519MasterViewingKeyEncryptingPrivateKey: Offset for MVK-encrypting X25519 keypair (anonymous registration)
2401
+ * - mintX25519PrivateKey: Offset for per-mint X25519 keypair (reencrypt_shared operations)
2402
+ * - rescueCommitmentBlindingFactor: Offset for Rescue commitment blinding
2403
+ * - randomCommitmentFactor: Offset for random commitment factor
2404
+ *
2405
+ * Time-based keys (yearly/monthly/daily) and mint viewing keys do not
2406
+ * use offsets as they have parameters that provide sufficient separation.
2407
+ */
2408
+ readonly offsets: {
2409
+ readonly masterViewingKey: U512;
2410
+ readonly poseidonPrivateKey: U512;
2411
+ readonly x25519UserAccountPrivateKey: U512;
2412
+ readonly x25519MasterViewingKeyEncryptingPrivateKey: U512;
2413
+ readonly mintX25519PrivateKey: U512;
2414
+ readonly rescueCommitmentBlindingFactor: U512;
2415
+ readonly randomCommitmentFactor: U512;
2416
+ };
2417
+ /**
2418
+ * Pre-constructed Solana infrastructure dependencies.
2419
+ *
2420
+ * These dependencies are constructed by the client factory from URLs
2421
+ * or custom implementations provided in the factory options.
2422
+ */
2423
+ readonly accountInfoProvider: AccountInfoProviderFunction;
2424
+ readonly blockhashProvider: GetLatestBlockhash;
2425
+ readonly transactionForwarder: TransactionForwarder;
2426
+ readonly epochInfoProvider: GetEpochInfo;
2427
+ /**
2428
+ * Optional computation monitor for tracking Arcium MPC computation status.
2429
+ *
2430
+ * @remarks
2431
+ * When provided, enables monitoring of ComputationAccount status changes
2432
+ * (Queued → Finalized) after queue_computation transactions. Callers invoke
2433
+ * `computationMonitor.awaitComputation(address)` to wait for finalization.
2434
+ *
2435
+ * If not provided, callers must implement their own monitoring logic or
2436
+ * use fire-and-forget behavior (send the queue transaction and don't wait
2437
+ * for the callback).
2438
+ *
2439
+ * Constructed by the client factory from `rpcUrl` and `rpcSubscriptionsUrl`
2440
+ * using the WebSocket-based strategy by default. Can be overridden in
2441
+ * `GetUmbraClientDeps`.
2442
+ */
2443
+ readonly computationMonitor?: ComputationMonitor;
2444
+ /**
2445
+ * Optional indexer functions for UTXO discovery.
2446
+ *
2447
+ * Constructed by the client factory from indexerApiEndpoint URL
2448
+ * or custom implementations provided in the factory options.
2449
+ *
2450
+ * Required for fetching claimable UTXOs. The indexer maintains an off-chain
2451
+ * database of protocol state for efficient querying of UTXOs, Merkle proofs,
2452
+ * and nullifier status.
2453
+ *
2454
+ * @remarks
2455
+ * If not provided, UTXO discovery operations will not be available.
2456
+ */
2457
+ readonly fetchMerkleProof?: MerkleProofFetcherFunction;
2458
+ readonly fetchBatchMerkleProof?: BatchMerkleProofFetcherFunction;
2459
+ readonly fetchUtxoData?: UtxoDataFetcherFunction;
2460
+ /**
2461
+ * Master seed storage operations.
2462
+ *
2463
+ * The master seed is the root of all key derivation. These functions
2464
+ * control how the seed is loaded, stored, and generated.
2465
+ *
2466
+ * @remarks
2467
+ * - `load`: Attempts to load existing seed from storage
2468
+ * - `store`: Persists the seed to storage
2469
+ * - `generate`: Generates a new seed via signature-based derivation
2470
+ * - `getMasterSeed`: Convenience method combining load and generate
2471
+ */
2472
+ readonly masterSeed: {
2473
+ readonly load: MasterSeedLoaderFunction;
2474
+ readonly store: MasterSeedStorerFunction;
2475
+ readonly generate: MasterSeedGeneratorFunction;
2476
+ readonly getMasterSeed: () => Promise<MasterSeed>;
2477
+ };
2478
+ /**
2479
+ * Master viewing key storage operations.
2480
+ *
2481
+ * @remarks
2482
+ * The master viewing key is derived from the master seed and is used
2483
+ * to derive all other viewing keys in the hierarchy.
2484
+ */
2485
+ readonly masterViewingKey: {
2486
+ readonly load: LoaderFunction<MasterViewingKey>;
2487
+ readonly store: StorerFunction<MasterViewingKey>;
2488
+ readonly generate: GeneratorFunction<MasterViewingKey>;
2489
+ };
2490
+ /**
2491
+ * Poseidon private key storage operations.
2492
+ *
2493
+ * @remarks
2494
+ * Used for Poseidon hash-based cryptographic operations.
2495
+ */
2496
+ readonly poseidonPrivateKey: {
2497
+ readonly load: LoaderFunction<PoseidonKey>;
2498
+ readonly store: StorerFunction<PoseidonKey>;
2499
+ readonly generate: GeneratorFunction<PoseidonKey>;
2500
+ };
2501
+ /**
2502
+ * X25519 private key storage operations.
2503
+ *
2504
+ * @remarks
2505
+ * Used for elliptic curve Diffie-Hellman key exchange.
2506
+ */
2507
+ readonly x25519PrivateKey: {
2508
+ readonly load: LoaderFunction<X25519PrivateKey>;
2509
+ readonly store: StorerFunction<X25519PrivateKey>;
2510
+ readonly generate: GeneratorFunction<X25519PrivateKey>;
2511
+ };
2512
+ /**
2513
+ * Yearly viewing key storage operations.
2514
+ *
2515
+ * @remarks
2516
+ * Time-based viewing keys are parameterized by year.
2517
+ */
2518
+ readonly yearlyViewingKey: {
2519
+ readonly load: ParameterizedLoaderFunction<YearlyViewingKey, {
2520
+ year: Year;
2521
+ }>;
2522
+ readonly store: ParameterizedStorerFunction<YearlyViewingKey, {
2523
+ year: Year;
2524
+ }>;
2525
+ readonly generate: ParameterizedGeneratorFunction<YearlyViewingKey, {
2526
+ year: Year;
2527
+ }>;
2528
+ };
2529
+ /**
2530
+ * Monthly viewing key storage operations.
2531
+ *
2532
+ * @remarks
2533
+ * Time-based viewing keys are parameterized by year and month.
2534
+ */
2535
+ readonly monthlyViewingKey: {
2536
+ readonly load: ParameterizedLoaderFunction<MonthlyViewingKey, {
2537
+ year: Year;
2538
+ month: Month;
2539
+ }>;
2540
+ readonly store: ParameterizedStorerFunction<MonthlyViewingKey, {
2541
+ year: Year;
2542
+ month: Month;
2543
+ }>;
2544
+ readonly generate: ParameterizedGeneratorFunction<MonthlyViewingKey, {
2545
+ year: Year;
2546
+ month: Month;
2547
+ }>;
2548
+ };
2549
+ /**
2550
+ * Daily viewing key storage operations.
2551
+ *
2552
+ * @remarks
2553
+ * Time-based viewing keys are parameterized by year, month, and day.
2554
+ */
2555
+ readonly dailyViewingKey: {
2556
+ readonly load: ParameterizedLoaderFunction<DailyViewingKey, {
2557
+ year: Year;
2558
+ month: Month;
2559
+ day: Day;
2560
+ }>;
2561
+ readonly store: ParameterizedStorerFunction<DailyViewingKey, {
2562
+ year: Year;
2563
+ month: Month;
2564
+ day: Day;
2565
+ }>;
2566
+ readonly generate: ParameterizedGeneratorFunction<DailyViewingKey, {
2567
+ year: Year;
2568
+ month: Month;
2569
+ day: Day;
2570
+ }>;
2571
+ };
2572
+ /**
2573
+ * Mint viewing key storage operations.
2574
+ *
2575
+ * @remarks
2576
+ * Mint-specific viewing keys are parameterized by mint address.
2577
+ */
2578
+ readonly mintViewingKey: {
2579
+ readonly load: ParameterizedLoaderFunction<MintViewingKey, {
2580
+ mint: Address;
2581
+ }>;
2582
+ readonly store: ParameterizedStorerFunction<MintViewingKey, {
2583
+ mint: Address;
2584
+ }>;
2585
+ readonly generate: ParameterizedGeneratorFunction<MintViewingKey, {
2586
+ mint: Address;
2587
+ }>;
2588
+ };
2589
+ /**
2590
+ * Rescue commitment blinding factor storage operations.
2591
+ *
2592
+ * @remarks
2593
+ * Used for blinding Rescue-based commitments.
2594
+ */
2595
+ readonly rescueCommitmentBlindingFactor: {
2596
+ readonly load: LoaderFunction<Bn254FieldElement>;
2597
+ readonly store: StorerFunction<Bn254FieldElement>;
2598
+ readonly generate: GeneratorFunction<Bn254FieldElement>;
2599
+ };
2600
+ /**
2601
+ * Random commitment factor storage operations.
2602
+ *
2603
+ * @remarks
2604
+ * Used for randomness in commitment schemes.
2605
+ */
2606
+ readonly randomCommitmentFactor: {
2607
+ readonly load: LoaderFunction<Curve25519FieldElement>;
2608
+ readonly store: StorerFunction<Curve25519FieldElement>;
2609
+ readonly generate: GeneratorFunction<Curve25519FieldElement>;
2610
+ };
2611
+ }
2612
+
2613
+ export { type MerkleProofData as $, type AccountInfoProviderFunction as A, type BatchMerkleProofFetcherFunction as B, type CreateSolanaRpcFunction as C, DEFAULT_MAX_SLOT_WINDOW as D, type PollingBasedComputationMonitorDeps as E, type PollingComputationMonitorOptions as F, type GetLatestBlockhash as G, type WebsocketBasedComputationMonitorDeps as H, type IUmbraSigner as I, getPollingComputationMonitor as J, getWebsocketComputationMonitor as K, type GetMasterSeedFunction as L, type MerkleProofFetcherFunction as M, type ClaimableUtxoResult as N, type DecryptedUtxoData as O, type PollingBasedComputationMonitorConfig as P, type EpochInfoResult as Q, type FireAndForget as R, type SendAndConfirmTransactionFactoryFunction as S, type TransactionForwarder as T, type UtxoDataFetcherFunction as U, type ForwardInParallel as V, type WebsocketBasedComputationMonitorConfig as W, type ForwardSequentially as X, type H1Components as Y, type IUmbraIndexer as Z, type LatestBlockhashResult as _, type GetEpochInfo as a, type ScannedUtxoResult as a0, type SignableTransaction as a1, type SignedMessage as a2, type TimestampComponents as a3, type UtxoDataItem as a4, type UtxoFetchResult as a5, type CreateSolanaRpcSubscriptionsFunction as b, type ComputationMonitor as c, type IUmbraClient as d, type GetMerkleProofFetcherArgs as e, type GetMerkleProofFetcherDeps as f, type GetUtxoDataFetcherArgs as g, type GetUtxoDataFetcherDeps as h, type ScannedUtxoData as i, type BatchMerkleProofResult as j, type ClaimableUtxoData as k, type GetClaimableUtxoScannerFunctionArgs as l, type GetClaimableUtxoScannerFunctionDeps as m, type ClaimableUtxoScannerFunction as n, type AesDecryptorFunction as o, type AesEncryptorFunction as p, type ComputationFinalizedResult as q, type ComputationFinalizedResultWithSignature as r, type ComputationMonitorOptions as s, type ComputationMonitorProgressEvent as t, type ComputationMonitorResult as u, type ComputationMonitorResultWithSignature as v, type ComputationPrunedResult as w, DEFAULT_POLLING_INTERVAL_MS as x, DEFAULT_SAFETY_TIMEOUT_MS as y, DEFAULT_SIGNATURE_RETRIEVAL_LIMIT as z };