@umbra-privacy/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/dist/addresses-Brzgurv_.d.ts +145 -0
  4. package/dist/addresses-D_0YAS6B.d.cts +145 -0
  5. package/dist/chunk-2Q75CQQJ.js +12 -0
  6. package/dist/chunk-2Q75CQQJ.js.map +1 -0
  7. package/dist/chunk-7QVYU63E.js +6 -0
  8. package/dist/chunk-7QVYU63E.js.map +1 -0
  9. package/dist/chunk-BM7N6N7E.js +1883 -0
  10. package/dist/chunk-BM7N6N7E.js.map +1 -0
  11. package/dist/chunk-GXKSUB2U.cjs +4416 -0
  12. package/dist/chunk-GXKSUB2U.cjs.map +1 -0
  13. package/dist/chunk-HOEXDXRC.cjs +792 -0
  14. package/dist/chunk-HOEXDXRC.cjs.map +1 -0
  15. package/dist/chunk-MDFSBU5W.cjs +2033 -0
  16. package/dist/chunk-MDFSBU5W.cjs.map +1 -0
  17. package/dist/chunk-MQY7HDIA.js +600 -0
  18. package/dist/chunk-MQY7HDIA.js.map +1 -0
  19. package/dist/chunk-MVKTV3FT.cjs +20 -0
  20. package/dist/chunk-MVKTV3FT.cjs.map +1 -0
  21. package/dist/chunk-PG2J6V6Y.js +4094 -0
  22. package/dist/chunk-PG2J6V6Y.js.map +1 -0
  23. package/dist/chunk-PK6SKIKE.cjs +8 -0
  24. package/dist/chunk-PK6SKIKE.cjs.map +1 -0
  25. package/dist/chunk-VEGLTTYQ.cjs +621 -0
  26. package/dist/chunk-VEGLTTYQ.cjs.map +1 -0
  27. package/dist/chunk-WVHQ46DD.js +758 -0
  28. package/dist/chunk-WVHQ46DD.js.map +1 -0
  29. package/dist/constants/index.cjs +316 -0
  30. package/dist/constants/index.cjs.map +1 -0
  31. package/dist/constants/index.d.cts +739 -0
  32. package/dist/constants/index.d.ts +739 -0
  33. package/dist/constants/index.js +193 -0
  34. package/dist/constants/index.js.map +1 -0
  35. package/dist/cryptography-BTGC72u-.d.cts +4809 -0
  36. package/dist/cryptography-BTGC72u-.d.ts +4809 -0
  37. package/dist/errors/index.cjs +141 -0
  38. package/dist/errors/index.cjs.map +1 -0
  39. package/dist/errors/index.d.cts +1415 -0
  40. package/dist/errors/index.d.ts +1415 -0
  41. package/dist/errors/index.js +4 -0
  42. package/dist/errors/index.js.map +1 -0
  43. package/dist/index-B9pDY73x.d.ts +12933 -0
  44. package/dist/index-CLj_zWSD.d.ts +235 -0
  45. package/dist/index-CX6_pIRS.d.cts +235 -0
  46. package/dist/index-D33yo0qB.d.cts +12933 -0
  47. package/dist/index.cjs +22464 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.cts +11694 -0
  50. package/dist/index.d.ts +11694 -0
  51. package/dist/index.js +22314 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/interfaces/index.cjs +4 -0
  54. package/dist/interfaces/index.cjs.map +1 -0
  55. package/dist/interfaces/index.d.cts +8 -0
  56. package/dist/interfaces/index.d.ts +8 -0
  57. package/dist/interfaces/index.js +3 -0
  58. package/dist/interfaces/index.js.map +1 -0
  59. package/dist/networks-C-orpSFW.d.ts +65 -0
  60. package/dist/networks-FxYERGD1.d.cts +65 -0
  61. package/dist/types/index.cjs +605 -0
  62. package/dist/types/index.cjs.map +1 -0
  63. package/dist/types/index.d.cts +1853 -0
  64. package/dist/types/index.d.ts +1853 -0
  65. package/dist/types/index.js +4 -0
  66. package/dist/types/index.js.map +1 -0
  67. package/dist/types-BBuELtY8.d.cts +495 -0
  68. package/dist/types-n-sHFcgr.d.ts +495 -0
  69. package/dist/utils/index.cjs +1295 -0
  70. package/dist/utils/index.cjs.map +1 -0
  71. package/dist/utils/index.d.cts +9559 -0
  72. package/dist/utils/index.d.ts +9559 -0
  73. package/dist/utils/index.js +6 -0
  74. package/dist/utils/index.js.map +1 -0
  75. package/dist/versions-D9PqsEvj.d.cts +173 -0
  76. package/dist/versions-D9PqsEvj.d.ts +173 -0
  77. package/package.json +151 -0
@@ -0,0 +1,1853 @@
1
+ import { a3 as MasterSeed, K as U512, B as BrandedType, S as SubBrandedType, a2 as SubSubBrandedType, c as Bytes, V as U8, X as X25519PublicKey$1, k as PoseidonHash, U as U128, F as U256LeBytes } from '../cryptography-BTGC72u-.cjs';
2
+ export { am as AES_AUTH_TAG_LENGTH, an as AES_IV_LENGTH, ao as AES_KEY_LENGTH, ap as AES_METADATA_OVERHEAD, a7 as AesCiphertextWithMetadata, a6 as AesKey, a8 as AesPlaintext, aq as BASE85_LIMB_MAX, ar as BN254_FIELD_PRIME, a1 as Base85Limb, a0 as Base85LimbTuple, a as BeBytes, b as Bn254FieldElement, as as CURVE25519_FIELD_PRIME, at as CryptographyAssertionError, C as Curve25519FieldElement, ad as DailyViewingKey, au as ExtractBrand, av as GROTH16_G1_BYTE_LENGTH, aw as GROTH16_G2_BYTE_LENGTH, ax as GenerationSeed, ay as Groth16Proof, aj as Groth16ProofA, ak as Groth16ProofB, al as Groth16ProofC, ae as HourlyViewingKey, I as I1024, az as I1024_MAX, aA as I1024_MIN, d as I128, aB as I128_MAX, aC as I128_MIN, e as I16, aD as I16_MAX, aE as I16_MIN, f as I256, aF as I256_MAX, aG as I256_MIN, g as I32, aH as I32_MAX, aI as I32_MIN, h as I512, aJ as I512_MAX, aK as I512_MIN, i as I64, aL as I64_MAX, aM as I64_MIN, j as I8, aN as I8_MAX, aO as I8_MIN, aP as Keccak256Hash, aQ as Keccak512Hash, L as LeBytes, ab as MasterViewingKey, aR as MathematicsAssertionError, af as MintViewingKey, ag as MinuteViewingKey, ah as MonthlyViewingKey, a4 as Nonce, aS as OPTIONAL_DATA_BYTE_LENGTH, a5 as OptionalData32, P as PoseidonCiphertext, a9 as PoseidonCounter, l as PoseidonKey, aa as PoseidonKeystream, m as PoseidonPlaintext, R as RcCiphertext, n as RcCounter, o as RcEncryptionNonce, p as RcKey, q as RcPlaintext, ac as SecondViewingKey, r as SharedSecret, s as SignedInteger, aT as SubSubSubBrandedType, aU as SubSubSubSubBrandedType, t as U1024, u as U1024BeBytes, v as U1024LeBytes, aV as U1024_BYTE_LENGTH, aW as U1024_MAX, w as U128BeBytes, x as U128LeBytes, aX as U128_BYTE_LENGTH, aY as U128_MAX, y as U16, z as U16BeBytes, A as U16LeBytes, aZ as U16_BYTE_LENGTH, a_ as U16_MAX, D as U256, E as U256BeBytes, a$ as U256_BYTE_LENGTH, b0 as U256_MAX, G as U32, H as U32BeBytes, J as U32LeBytes, b1 as U32_BYTE_LENGTH, b2 as U32_MAX, M as U512BeBytes, N as U512LeBytes, b3 as U512_BYTE_LENGTH, b4 as U512_MAX, O as U64, Q as U64BeBytes, T as U64LeBytes, b5 as U64_BYTE_LENGTH, b6 as U64_MAX, W as U8BeBytes, Y as U8LeBytes, b7 as U8_BYTE_LENGTH, b8 as U8_MAX, Z as UnsignedInteger, b9 as UnwrapBrand, _ as X25519Bytes, ba as X25519Keypair, $ as X25519PrivateKey, bb as X25519_BYTE_LENGTH, ai as YearlyViewingKey, bc as ZK_PROOF_BYTE_LENGTH, bd as ZkProofBytes, be as assertAesCiphertextWithMetadata, bf as assertAesKey, bg as assertAesPlaintext, bh as assertBase85Limb, bi as assertBeBytes, bj as assertBn254FieldElement, bk as assertBytes, bl as assertCurve25519FieldElement, bm as assertDailyViewingKey, bn as assertGenerationSeed, bo as assertGroth16ProofA, bp as assertGroth16ProofB, bq as assertGroth16ProofC, br as assertHourlyViewingKey, bs as assertI1024, bt as assertI128, bu as assertI16, bv as assertI256, bw as assertI32, bx as assertI512, by as assertI64, bz as assertI8, bA as assertKeccak256Hash, bB as assertKeccak512Hash, bC as assertLeBytes, bD as assertMasterSeed, bE as assertMasterViewingKey, bF as assertMintViewingKey, bG as assertMinuteViewingKey, bH as assertMonthlyViewingKey, bI as assertOptionalData32, bJ as assertPoseidonCiphertext, bK as assertPoseidonCounter, bL as assertPoseidonHash, bM as assertPoseidonKey, bN as assertPoseidonKeystream, bO as assertPoseidonPlaintext, bP as assertRcCiphertext, bQ as assertRcCounter, bR as assertRcEncryptionNonce, bS as assertRcKey, bT as assertRcPlaintext, bU as assertSecondViewingKey, bV as assertSharedSecret, bW as assertSignedInteger, bX as assertU1024, bY as assertU1024BeBytes, bZ as assertU1024LeBytes, b_ as assertU128, b$ as assertU128BeBytes, c0 as assertU128LeBytes, c1 as assertU16, c2 as assertU16BeBytes, c3 as assertU16LeBytes, c4 as assertU256, c5 as assertU256BeBytes, c6 as assertU256LeBytes, c7 as assertU32, c8 as assertU32BeBytes, c9 as assertU32LeBytes, ca as assertU512, cb as assertU512BeBytes, cc as assertU512LeBytes, cd as assertU64, ce as assertU64BeBytes, cf as assertU64LeBytes, cg as assertU8, ch as assertU8BeBytes, ci as assertU8LeBytes, cj as assertUnsignedInteger, ck as assertX25519Bytes, cl as assertX25519Keypair, cm as assertX25519PrivateKey, cn as assertX25519PublicKey, co as assertYearlyViewingKey, cp as assertZkProofBytes } from '../cryptography-BTGC72u-.cjs';
3
+ import { N as Network } from '../versions-D9PqsEvj.cjs';
4
+ import { Transaction, TransactionWithBlockhashLifetime } from '@solana/kit';
5
+ export { b as DAY_MAX, c as DAY_MIN, D as Day, d as HOUR_MAX, e as HOUR_MIN, H as Hour, f as MINUTE_MAX, g as MINUTE_MIN, h as MONTH_MAX, i as MONTH_MIN, a as Minute, M as Month, j as SECOND_MAX, k as SECOND_MIN, S as Second, T as TemporalAssertionError, l as TimestampComponent, m as YEAR_MAX, n as YEAR_MIN, Y as Year, o as assertDay, p as assertHour, q as assertMinute, r as assertMonth, s as assertSecond, t as assertTimestampComponent, u as assertYear } from '../types-BBuELtY8.cjs';
6
+
7
+ /**
8
+ * Storage Types for Key Management
9
+ *
10
+ * This module defines types and interfaces for loading, storing, and generating
11
+ * cryptographic keys and derived values. The storage system supports both persistent
12
+ * storage (e.g., IndexedDB, local storage) and ephemeral storage (in-memory only).
13
+ *
14
+ * @remarks
15
+ * The storage abstraction allows callers to supply custom persistence backends for
16
+ * the SDK's cryptographic keys without coupling the SDK to any particular storage
17
+ * technology. The most security-sensitive type here is `MasterSeed`, whose loader,
18
+ * storer, and generator functions control the full lifecycle of the root key.
19
+ *
20
+ * All load/store operations are asynchronous to support remote key management services
21
+ * (e.g., cloud HSMs, encrypted databases) without blocking the main thread.
22
+ *
23
+ * @packageDocumentation
24
+ * @module types/storage
25
+ */
26
+
27
+ /**
28
+ * Result of a load operation.
29
+ *
30
+ * @remarks
31
+ * A discriminated union that signals whether a stored value was found. When `exists` is
32
+ * `true`, the `seed` field contains the loaded value. When `exists` is `false`, the caller
33
+ * should generate a new value and store it.
34
+ *
35
+ * @typeParam T - The type of value being loaded
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const result = await loadMasterSeed();
40
+ * if (result.exists) {
41
+ * // Use result.seed
42
+ * } else {
43
+ * // Generate and store a new seed
44
+ * }
45
+ * ```
46
+ *
47
+ * @public
48
+ */
49
+ type LoadResult<T> = {
50
+ readonly exists: true;
51
+ readonly seed: T;
52
+ } | {
53
+ readonly exists: false;
54
+ };
55
+ /**
56
+ * Result of a store operation.
57
+ *
58
+ * @remarks
59
+ * A discriminated union that signals whether the store succeeded. When `success` is `false`,
60
+ * the `error` field contains a human-readable description of what went wrong (e.g., quota
61
+ * exceeded, permission denied, serialization failure).
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const result = await storeMasterSeed(seed);
66
+ * if (!result.success) {
67
+ * console.error("Failed to persist seed:", result.error);
68
+ * // Optionally continue with in-memory seed only
69
+ * }
70
+ * ```
71
+ *
72
+ * @public
73
+ */
74
+ type StoreResult = {
75
+ readonly success: true;
76
+ } | {
77
+ readonly success: false;
78
+ readonly error: string;
79
+ };
80
+ /**
81
+ * Context information for key storage operations.
82
+ *
83
+ * This context is passed to load and store functions to provide all the necessary
84
+ * information about the key being stored or loaded, including versioning information,
85
+ * network, and derivation parameters.
86
+ *
87
+ * @remarks
88
+ * The context ensures that keys are stored and retrieved with the correct version and
89
+ * parameter information, preventing version mismatches across SDK upgrades. The combination
90
+ * of `signerAddress`, `network`, `domainSeparator`, and all three version strings forms a
91
+ * unique storage key that can be used as a lookup identifier in any key-value store.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const context: KeyStorageContext = {
96
+ * signerAddress: "7xKXt...",
97
+ * domainSeparator: "MasterViewingKey/0",
98
+ * network: "mainnet-beta",
99
+ * protocolVersion: "1.0.0",
100
+ * algorithmVersion: "1.0.0",
101
+ * schemeVersion: "1.0.0",
102
+ * };
103
+ * const result = await loaderFn(context);
104
+ * ```
105
+ *
106
+ * @public
107
+ */
108
+ interface KeyStorageContext {
109
+ /**
110
+ * The signer's public key / wallet address (user identifier).
111
+ *
112
+ * @remarks
113
+ * Used to namespace stored keys per user so that multiple wallets can use the same
114
+ * storage backend without interference.
115
+ * @readonly
116
+ */
117
+ readonly signerAddress: string;
118
+ /**
119
+ * Domain separator for key derivation (e.g., `"MasterViewingKey/0"`).
120
+ *
121
+ * @remarks
122
+ * The domain separator ensures that keys derived for different purposes are
123
+ * cryptographically independent even when derived from the same root material.
124
+ * @readonly
125
+ */
126
+ readonly domainSeparator: string;
127
+ /**
128
+ * Network environment (e.g., `"mainnet-beta"`, `"devnet"`).
129
+ *
130
+ * @remarks
131
+ * Prevents keys generated on devnet from being mistakenly used on mainnet.
132
+ * @readonly
133
+ */
134
+ readonly network: Network;
135
+ /**
136
+ * Protocol version string (e.g., `"1.0.0"`).
137
+ *
138
+ * @remarks
139
+ * Bumped when the on-chain protocol changes in a way that requires fresh keys.
140
+ * @readonly
141
+ */
142
+ readonly protocolVersion: string;
143
+ /**
144
+ * Algorithm version string (e.g., `"1.0.0"`).
145
+ *
146
+ * @remarks
147
+ * Bumped when the cryptographic algorithm (hash function, cipher) changes.
148
+ * @readonly
149
+ */
150
+ readonly algorithmVersion: string;
151
+ /**
152
+ * Scheme version string (e.g., `"1.0.0"`).
153
+ *
154
+ * @remarks
155
+ * Bumped when the key derivation scheme (domain separators, input ordering) changes.
156
+ * @readonly
157
+ */
158
+ readonly schemeVersion: string;
159
+ /**
160
+ * Optional derivation parameters (e.g., `{ year: "2024", mint: "7xKXt..." }`).
161
+ *
162
+ * @remarks
163
+ * Supplied for parameterized keys (yearly viewing keys, mint-specific keys) to distinguish
164
+ * storage entries for different time periods or token mints.
165
+ * @readonly
166
+ */
167
+ readonly derivationParams?: Record<string, string>;
168
+ /**
169
+ * Optional offset used in key derivation.
170
+ *
171
+ * @remarks
172
+ * Used when a key is derived with an explicit 512-bit offset (e.g., for generation-indexed
173
+ * AES keys). Most keys do not use this field.
174
+ * @readonly
175
+ */
176
+ readonly offset?: U512;
177
+ }
178
+ /**
179
+ * Loads a value from storage.
180
+ *
181
+ * @remarks
182
+ * Implementations should be idempotent: calling load multiple times with the same context
183
+ * must return the same result (assuming no concurrent stores).
184
+ *
185
+ * @typeParam T - The type of value being loaded
186
+ * @param context - Storage context with version and parameter information
187
+ * @returns A promise that resolves to a `LoadResult` indicating whether the value exists
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const loader: LoaderFunction<MasterViewingKey> = async (context) => {
192
+ * const raw = await db.get(buildKey(context));
193
+ * if (!raw) return { exists: false };
194
+ * return { exists: true, seed: parseMvk(raw) };
195
+ * };
196
+ * ```
197
+ *
198
+ * @public
199
+ */
200
+ type LoaderFunction<T> = (context: KeyStorageContext) => Promise<LoadResult<T>>;
201
+ /**
202
+ * Stores a value to storage.
203
+ *
204
+ * @remarks
205
+ * Implementations should overwrite any previously stored value for the same context.
206
+ * Failures must be reported via a `StoreResult` with `success: false` rather than throwing,
207
+ * unless the failure is catastrophic.
208
+ *
209
+ * @typeParam T - The type of value being stored
210
+ * @param value - The value to store
211
+ * @param context - Storage context with version and parameter information
212
+ * @returns A promise that resolves to a `StoreResult` indicating success or describing the failure
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const storer: StorerFunction<MasterViewingKey> = async (value, context) => {
217
+ * try {
218
+ * await db.put(buildKey(context), serializeMvk(value));
219
+ * return { success: true };
220
+ * } catch (error) {
221
+ * return { success: false, error: String(error) };
222
+ * }
223
+ * };
224
+ * ```
225
+ *
226
+ * @public
227
+ */
228
+ type StorerFunction<T> = (value: T, context: KeyStorageContext) => Promise<StoreResult>;
229
+ /**
230
+ * Generates a new value.
231
+ *
232
+ * @remarks
233
+ * Called when no stored value is found. The implementation should use the context to
234
+ * deterministically or randomly generate a fresh value. For security-critical keys, the
235
+ * generator should use a cryptographically secure random source.
236
+ *
237
+ * @typeParam T - The type of value being generated
238
+ * @param context - Storage context with version and parameter information
239
+ * @returns A promise that resolves to the freshly generated value
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const generator: GeneratorFunction<MasterViewingKey> = async (context) => {
244
+ * const entropy = crypto.getRandomValues(new Uint8Array(32));
245
+ * return deriveMasterViewingKey(entropy, context.domainSeparator);
246
+ * };
247
+ * ```
248
+ *
249
+ * @public
250
+ */
251
+ type GeneratorFunction<T> = (context: KeyStorageContext) => Promise<T>;
252
+ /**
253
+ * Loads a value that requires additional parameters (e.g., year, mint address).
254
+ *
255
+ * @remarks
256
+ * Similar to `LoaderFunction`, but accepts an extra `params` argument to disambiguate
257
+ * storage entries when the same key type can exist for multiple parameter values (e.g.,
258
+ * a yearly viewing key for 2023 vs. 2024).
259
+ *
260
+ * @typeParam T - The type of value being loaded
261
+ * @typeParam TParams - The type of extra parameters required for lookup
262
+ * @param params - Parameters for key derivation and lookup (e.g., `{ year: 2024n }`)
263
+ * @param context - Storage context with version and base parameter information
264
+ * @returns A promise that resolves to a `LoadResult` indicating whether the value exists
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * const loader: ParameterizedLoaderFunction<YearlyViewingKey, { year: bigint }> =
269
+ * async (params, context) => {
270
+ * const key = buildYearKey(context, params.year);
271
+ * const raw = await db.get(key);
272
+ * if (!raw) return { exists: false };
273
+ * return { exists: true, seed: parseYvk(raw) };
274
+ * };
275
+ * ```
276
+ *
277
+ * @see {@link LoaderFunction}
278
+ * @public
279
+ */
280
+ type ParameterizedLoaderFunction<T, TParams> = (params: TParams, context: KeyStorageContext) => Promise<LoadResult<T>>;
281
+ /**
282
+ * Stores a value that requires additional parameters.
283
+ *
284
+ * @remarks
285
+ * Similar to `StorerFunction`, but accepts an extra `params` argument so the implementation
286
+ * can construct a unique storage key for each parameter combination.
287
+ *
288
+ * @typeParam T - The type of value being stored
289
+ * @typeParam TParams - The type of extra parameters required for storage
290
+ * @param value - The value to store
291
+ * @param params - Parameters for key derivation and storage (e.g., `{ year: 2024n }`)
292
+ * @param context - Storage context with version and base parameter information
293
+ * @returns A promise that resolves to a `StoreResult` indicating success or describing the failure
294
+ *
295
+ * @see {@link StorerFunction}
296
+ * @public
297
+ */
298
+ type ParameterizedStorerFunction<T, TParams> = (value: T, params: TParams, context: KeyStorageContext) => Promise<StoreResult>;
299
+ /**
300
+ * Generates a value that requires additional parameters.
301
+ *
302
+ * @remarks
303
+ * Similar to `GeneratorFunction`, but accepts `params` to derive a key that is specific to
304
+ * a given parameter set (e.g., deriving a yearly viewing key scoped to a particular year and mint).
305
+ *
306
+ * @typeParam T - The type of value being generated
307
+ * @typeParam TParams - The type of extra parameters required for derivation
308
+ * @param params - Parameters for key derivation (e.g., `{ year: 2024n, mint: "7xKXt..." }`)
309
+ * @param context - Storage context with version and base parameter information
310
+ * @returns A promise that resolves to the freshly generated value
311
+ *
312
+ * @see {@link GeneratorFunction}
313
+ * @public
314
+ */
315
+ type ParameterizedGeneratorFunction<T, TParams> = (params: TParams, context: KeyStorageContext) => Promise<T>;
316
+ /**
317
+ * Loads the master seed from storage.
318
+ *
319
+ * @remarks
320
+ * The master seed is the root of all key derivation. This function should:
321
+ * - Check if a master seed exists in storage
322
+ * - Return the seed if it exists
323
+ * - Return `{ exists: false }` if no seed is stored (caller will then generate one)
324
+ *
325
+ * This function takes no context argument because the master seed is not scoped to any
326
+ * particular set of derivation parameters — it is the single universal root.
327
+ *
328
+ * @returns A promise that resolves to a `LoadResult` containing the master seed if found
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const loader: MasterSeedLoaderFunction = async () => {
333
+ * const encrypted = localStorage.getItem("umbraMasterSeed");
334
+ * if (!encrypted) return { exists: false };
335
+ * const seed = await decrypt(encrypted);
336
+ * return { exists: true, seed };
337
+ * };
338
+ * ```
339
+ *
340
+ * @see {@link MasterSeed}
341
+ * @see {@link MasterSeedStorerFunction}
342
+ * @see {@link MasterSeedGeneratorFunction}
343
+ * @public
344
+ */
345
+ type MasterSeedLoaderFunction = () => Promise<LoadResult<MasterSeed>>;
346
+ /**
347
+ * Stores the master seed to storage.
348
+ *
349
+ * @remarks
350
+ * This function should securely persist the master seed. The default SDK implementation
351
+ * uses an in-memory closure-based store, but production applications should provide a
352
+ * custom implementation that encrypts the seed before persisting it (e.g., AES-GCM
353
+ * with a password-derived key, or storing in a platform secure enclave).
354
+ *
355
+ * Security guidance:
356
+ * - Never store the raw seed in plaintext on disk or in localStorage
357
+ * - Use authenticated encryption (e.g., AES-256-GCM) to protect the seed at rest
358
+ * - Consider using the platform keychain (Keychain on iOS/macOS, Keystore on Android)
359
+ *
360
+ * @param seed - The master seed to store (64 bytes)
361
+ * @returns A promise that resolves to a `StoreResult` indicating success or describing the failure
362
+ *
363
+ * @example
364
+ * ```typescript
365
+ * const storer: MasterSeedStorerFunction = async (seed) => {
366
+ * try {
367
+ * const encrypted = await encryptWithUserPassword(seed);
368
+ * localStorage.setItem("umbraMasterSeed", encrypted);
369
+ * return { success: true };
370
+ * } catch (error) {
371
+ * return { success: false, error: String(error) };
372
+ * }
373
+ * };
374
+ * ```
375
+ *
376
+ * @see {@link MasterSeed}
377
+ * @see {@link MasterSeedLoaderFunction}
378
+ * @public
379
+ */
380
+ type MasterSeedStorerFunction = (seed: MasterSeed) => Promise<StoreResult>;
381
+ /**
382
+ * Generates a new master seed.
383
+ *
384
+ * @remarks
385
+ * The default SDK implementation follows these steps:
386
+ * 1. Constructs the message: `"Umbra Privacy - Master Seed Generation - {signerAddress}"`
387
+ * 2. Signs the message with the user's wallet signer (producing a deterministic Ed25519 signature)
388
+ * 3. Hashes the signature with KMAC256 (key derivation length = 64) to produce the 512-bit seed
389
+ *
390
+ * This approach makes seed generation deterministic and tied to the user's wallet keypair,
391
+ * so the same wallet always regenerates the same master seed. Applications that prefer
392
+ * non-deterministic seeds can supply a custom generator that uses `crypto.getRandomValues`.
393
+ *
394
+ * @returns A promise that resolves to the freshly generated `MasterSeed` (64 bytes)
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * // Deterministic (default): derived from wallet signature
399
+ * const generator: MasterSeedGeneratorFunction = async () => {
400
+ * const msg = `Umbra Privacy - Master Seed Generation - ${signerAddress}`;
401
+ * const sig = await signer.signMessage(msg);
402
+ * return kmac256(sig, { dkLen: 64 }) as MasterSeed;
403
+ * };
404
+ * ```
405
+ *
406
+ * @see {@link MasterSeed}
407
+ * @see {@link MasterSeedLoaderFunction}
408
+ * @see {@link MasterSeedStorerFunction}
409
+ * @public
410
+ */
411
+ type MasterSeedGeneratorFunction = () => Promise<MasterSeed>;
412
+
413
+ /**
414
+ * Solana Types Module.
415
+ *
416
+ * This module provides branded types and runtime assertion functions for
417
+ * Solana-specific data structures. By attaching nominal brands to primitive
418
+ * `string` and `Uint8Array` values, and to `@solana/kit` transaction objects,
419
+ * the SDK achieves compile-time safety that prevents common mistakes such as:
420
+ * - Passing a raw string where a `TransactionSignature` is expected.
421
+ * - Submitting an unsigned transaction to a `TransactionForwarder`.
422
+ * - Mixing up different byte-array representations.
423
+ *
424
+ * @remarks
425
+ * **Type hierarchy overview:**
426
+ *
427
+ * String types:
428
+ * - {@link String} — root branded string (base type for all string sub-brands)
429
+ * - {@link TransactionSignature} — base58-encoded Ed25519 signature string
430
+ *
431
+ * Byte array types:
432
+ * - {@link SolanaBytes} — root branded `Uint8Array` for Solana binary data
433
+ * - {@link SignatureBytes} — exactly 64-byte raw Ed25519 signature
434
+ *
435
+ * Transaction types (wrapping `@solana/kit`'s `Transaction`):
436
+ * - {@link UnsignedTransaction} — no signatures present
437
+ * - {@link SignedTransaction} — at least one signature; includes blockhash lifetime
438
+ * - {@link PartiallySignedTransaction} — some but not all required signatures
439
+ * - {@link FullySignedTransaction} — all required signatures present; ready for submission
440
+ *
441
+ * **Runtime assertions:**
442
+ * - {@link assertString} — narrows `string` to `String`
443
+ * - {@link assertTransactionSignature} — narrows `string` to `TransactionSignature` (base58 validated)
444
+ * - {@link assertSolanaBytes} — narrows `Uint8Array` to `SolanaBytes`
445
+ * - {@link assertSignatureBytes} — narrows `Uint8Array` to `SignatureBytes` (64-byte validated)
446
+ *
447
+ * **Error class:**
448
+ * - {@link SolanaAssertionError} — thrown by all assertion functions with structured context
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * import {
453
+ * assertTransactionSignature,
454
+ * assertSignatureBytes,
455
+ * TransactionSignature,
456
+ * SignatureBytes,
457
+ * } from "./types";
458
+ *
459
+ * const sigString = "5wHu1qwD7q5menT3ydT9VdFPQfkLaWvqPgVbqsM1qwD7";
460
+ * assertTransactionSignature(sigString);
461
+ * // sigString is now typed as TransactionSignature
462
+ *
463
+ * const sigBytes = new Uint8Array(64);
464
+ * assertSignatureBytes(sigBytes);
465
+ * // sigBytes is now typed as SignatureBytes
466
+ * ```
467
+ *
468
+ * @see {@link BrandedType} for the underlying branding utility
469
+ * @see {@link Bytes} for the generic byte array base type
470
+ *
471
+ * @packageDocumentation
472
+ * @module types/solana
473
+ */
474
+
475
+ /**
476
+ * Length of an Ed25519 signature in bytes.
477
+ *
478
+ * The Ed25519 signature scheme, used by Solana for all transaction signing,
479
+ * always produces exactly 64-byte signatures:
480
+ * - Bytes 0–31: the R component (a compressed point on the Ed25519 curve)
481
+ * - Bytes 32–63: the S component (a scalar value)
482
+ *
483
+ * @remarks
484
+ * This constant is used by {@link assertSignatureBytes} to validate the length
485
+ * of raw signature byte arrays before branding them as {@link SignatureBytes}.
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * const raw = new Uint8Array(SIGNATURE_BYTE_LENGTH); // 64-byte zeroed buffer
490
+ * assertSignatureBytes(raw);
491
+ * ```
492
+ *
493
+ * @public
494
+ */
495
+ declare const SIGNATURE_BYTE_LENGTH = 64;
496
+ /**
497
+ * Error thrown when a Solana type assertion function fails.
498
+ *
499
+ * All assertion functions in this module (`assertString`,
500
+ * `assertTransactionSignature`, `assertSolanaBytes`, `assertSignatureBytes`)
501
+ * throw `SolanaAssertionError` when the supplied value does not satisfy the
502
+ * type constraint. The error carries structured fields that make it easy to
503
+ * log diagnostics or write type-specific error handlers.
504
+ *
505
+ * @remarks
506
+ * `SolanaAssertionError` sets `Error.captureStackTrace` (available in V8
507
+ * environments) to exclude the assertion function's own frame from the stack,
508
+ * making the stack trace point to the caller rather than the assertion body.
509
+ *
510
+ * The prototype is explicitly reset via `Object.setPrototypeOf` to ensure
511
+ * `instanceof` works correctly across CommonJS module boundary re-exports.
512
+ *
513
+ * @example
514
+ * Catching and inspecting a failed assertion:
515
+ * ```typescript
516
+ * import { assertTransactionSignature, SolanaAssertionError } from "./types";
517
+ *
518
+ * try {
519
+ * assertTransactionSignature("invalid!sig");
520
+ * } catch (error) {
521
+ * if (error instanceof SolanaAssertionError) {
522
+ * console.error(`Expected: ${error.expectedType}`);
523
+ * console.error(`Constraint: ${error.constraint}`);
524
+ * console.error(`Got: ${String(error.value)}`);
525
+ * }
526
+ * }
527
+ * ```
528
+ *
529
+ * @public
530
+ */
531
+ declare class SolanaAssertionError extends Error {
532
+ /**
533
+ * The actual value that was passed to the assertion function and failed
534
+ * the type check.
535
+ *
536
+ * @remarks
537
+ * Typed as `unknown` because assertion functions accept values of unknown
538
+ * type before narrowing. Inspect carefully — the value may be `undefined`,
539
+ * `null`, or any primitive or object.
540
+ */
541
+ readonly value: unknown;
542
+ /**
543
+ * The name of the expected type (e.g., `"TransactionSignature"`,
544
+ * `"SignatureBytes"`).
545
+ *
546
+ * @remarks
547
+ * Matches the TypeScript type name for the intended branded type, not a
548
+ * JavaScript `typeof` string.
549
+ */
550
+ readonly expectedType: string;
551
+ /**
552
+ * A human-readable description of the specific constraint that was violated,
553
+ * if applicable.
554
+ *
555
+ * @remarks
556
+ * Examples:
557
+ * - `"length > 0"` — empty string passed to `assertTransactionSignature`
558
+ * - `"length === 64"` — wrong byte count passed to `assertSignatureBytes`
559
+ * - `"characters must be in base58 alphabet: 123...xyz"` — invalid character
560
+ *
561
+ * `undefined` when the only constraint is the TypeScript type itself
562
+ * (e.g., `assertString` only checks `typeof value === "string"`).
563
+ */
564
+ readonly constraint: string | undefined;
565
+ /**
566
+ * Creates a new `SolanaAssertionError`.
567
+ *
568
+ * @param message - Human-readable description of the assertion failure.
569
+ * @param options - Structured context for the failed assertion.
570
+ * @param options.value - The value that failed the assertion.
571
+ * @param options.expectedType - The name of the expected branded type.
572
+ * @param options.constraint - The specific constraint that was violated, if any.
573
+ */
574
+ constructor(message: string, options: {
575
+ value: unknown;
576
+ expectedType: string;
577
+ constraint?: string;
578
+ });
579
+ }
580
+ /**
581
+ * Root branded string type for the Solana types module.
582
+ *
583
+ * This is the base type from which all specialized Solana string types derive.
584
+ * Branding it prevents raw `string` literals from being used where a validated
585
+ * Solana string is required, while still allowing structural compatibility with
586
+ * `string` via the underlying primitive.
587
+ *
588
+ * @remarks
589
+ * Prefer the more specific sub-types (e.g., {@link TransactionSignature}) over
590
+ * `String` when the string has additional semantic meaning. Use `String` only
591
+ * when building generic utilities that operate on any validated Solana string
592
+ * and need to accept multiple sub-brands.
593
+ *
594
+ * @example
595
+ * ```typescript
596
+ * function logSolanaString(s: String): void {
597
+ * console.log("Solana string:", s);
598
+ * }
599
+ *
600
+ * const raw = "hello";
601
+ * assertString(raw);
602
+ * logSolanaString(raw); // OK — raw is now branded as String
603
+ * ```
604
+ *
605
+ * @see {@link assertString} for the corresponding runtime assertion
606
+ * @public
607
+ */
608
+ type String = BrandedType<string, "String">;
609
+ /**
610
+ * Base58-encoded Solana transaction signature.
611
+ *
612
+ * A transaction signature is the result of an Ed25519 sign operation on the
613
+ * serialized transaction message. Solana encodes it as a base58 string
614
+ * (approximately 87–88 characters) for human-readable display and API usage.
615
+ *
616
+ * @remarks
617
+ * **Encoding details:**
618
+ * - Underlying binary: 64 bytes (see {@link SignatureBytes})
619
+ * - Base58 alphabet: 58 characters (`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`)
620
+ * - Excluded characters: `0`, `O`, `I`, `l` (visually ambiguous)
621
+ * - Typical string length: 87–88 characters
622
+ *
623
+ * **Type safety:** The {@link assertTransactionSignature} function validates
624
+ * that a `string` value is non-empty and contains only Base58 characters before
625
+ * branding it as `TransactionSignature`. This catches obvious data errors at
626
+ * the ingestion boundary.
627
+ *
628
+ * **Note:** Validation is character-level only. The assertion does NOT verify
629
+ * cryptographic correctness (i.e., it does not verify that the signature was
630
+ * produced by a specific keypair).
631
+ *
632
+ * @example
633
+ * Narrowing a raw string to `TransactionSignature`:
634
+ * ```typescript
635
+ * const raw = "5wHu1qwD7q5menT3ydT9VdFPQfkLaWvqPgVbqsM1qwD7";
636
+ * assertTransactionSignature(raw);
637
+ * // raw is now typed as TransactionSignature
638
+ * ```
639
+ *
640
+ * @example
641
+ * Using in a function signature:
642
+ * ```typescript
643
+ * async function getTransactionDetails(sig: TransactionSignature) {
644
+ * return await rpc.getTransaction(sig).send();
645
+ * }
646
+ * ```
647
+ *
648
+ * @see {@link assertTransactionSignature} for the runtime assertion
649
+ * @see {@link SignatureBytes} for the raw binary equivalent
650
+ * @public
651
+ */
652
+ type TransactionSignature = SubBrandedType<String, "TransactionSignature">;
653
+ /**
654
+ * Root branded `Uint8Array` type for Solana binary data.
655
+ *
656
+ * This is the base type for all Solana-specific byte array types. It derives
657
+ * from the generic `Bytes` type and adds the `"SolanaBytes"` nominal brand,
658
+ * distinguishing Solana binary data from other `Uint8Array` values in the SDK.
659
+ *
660
+ * @remarks
661
+ * No specific length constraint — the length depends on the particular data
662
+ * being represented. Sub-types like {@link SignatureBytes} impose their own
663
+ * length requirements.
664
+ *
665
+ * Use `SolanaBytes` when the binary data is Solana-specific but does not fall
666
+ * into a more precise category (e.g., serialized account data, raw message
667
+ * bytes).
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * const accountData = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
672
+ * assertSolanaBytes(accountData);
673
+ * // accountData is now typed as SolanaBytes
674
+ * ```
675
+ *
676
+ * @see {@link assertSolanaBytes} for the runtime assertion
677
+ * @see {@link SignatureBytes} for the 64-byte Ed25519 signature sub-type
678
+ * @public
679
+ */
680
+ type SolanaBytes = SubBrandedType<Bytes, "SolanaBytes">;
681
+ /**
682
+ * 64-byte raw Ed25519 signature in binary form.
683
+ *
684
+ * This type represents the binary encoding of an Ed25519 signature as used
685
+ * internally by the Solana runtime and the `@solana/kit` library. It is the
686
+ * binary equivalent of a {@link TransactionSignature} string — the same 64
687
+ * bytes, without the Base58 encoding.
688
+ *
689
+ * @remarks
690
+ * **Structure:**
691
+ * - Bytes 0–31: R component — a compressed Ed25519 curve point
692
+ * - Bytes 32–63: S component — a scalar in the range `[0, l)` where `l` is
693
+ * the order of the Ed25519 base point
694
+ *
695
+ * **Conversion:**
696
+ * - `SignatureBytes` → `TransactionSignature`: Base58-encode the bytes
697
+ * - `TransactionSignature` → `SignatureBytes`: Base58-decode the string
698
+ *
699
+ * The {@link assertSignatureBytes} function validates both that the value is a
700
+ * `Uint8Array` and that it is exactly {@link SIGNATURE_BYTE_LENGTH} (64) bytes.
701
+ *
702
+ * @example
703
+ * Creating and validating a signature byte array:
704
+ * ```typescript
705
+ * const sigBytes = new Uint8Array(64);
706
+ * // ... fill sigBytes with actual Ed25519 signature material ...
707
+ * assertSignatureBytes(sigBytes);
708
+ * // sigBytes is now typed as SignatureBytes
709
+ * ```
710
+ *
711
+ * @example
712
+ * Using with a Solana transaction builder:
713
+ * ```typescript
714
+ * declare function attachSignature(
715
+ * tx: UnsignedTransaction,
716
+ * publicKey: Address,
717
+ * signature: SignatureBytes,
718
+ * ): PartiallySignedTransaction;
719
+ * ```
720
+ *
721
+ * @see {@link assertSignatureBytes} for the runtime assertion
722
+ * @see {@link TransactionSignature} for the base58-encoded equivalent
723
+ * @see {@link SIGNATURE_BYTE_LENGTH} for the required byte length constant
724
+ * @public
725
+ */
726
+ type SignatureBytes = SubSubBrandedType<SolanaBytes, "SignatureBytes">;
727
+ /**
728
+ * An unsigned Solana transaction — a transaction that has been constructed
729
+ * but has not yet received any signatures.
730
+ *
731
+ * @remarks
732
+ * This type wraps `Transaction` from `@solana/kit` with the `"UnsignedTransaction"`
733
+ * brand. The brand prevents an unsigned transaction from being passed to a
734
+ * `TransactionForwarder` or any function that requires a {@link SignedTransaction},
735
+ * catching the mistake at compile time.
736
+ *
737
+ * **Lifecycle:** Build the transaction message → compile to `Transaction` →
738
+ * brand as `UnsignedTransaction` → sign to produce {@link SignedTransaction}.
739
+ *
740
+ * @example
741
+ * Type-safe transaction building:
742
+ * ```typescript
743
+ * import { UnsignedTransaction } from "./types";
744
+ *
745
+ * function buildTransfer(from: Address, to: Address, amount: bigint): UnsignedTransaction {
746
+ * // ... build and compile message ...
747
+ * return compiledTx as UnsignedTransaction;
748
+ * }
749
+ *
750
+ * const tx = buildTransfer(sender, recipient, 1_000_000n);
751
+ * // tx cannot be passed to forwarder.forwardSequentially — compile error
752
+ * ```
753
+ *
754
+ * @see {@link SignedTransaction} for the signed counterpart
755
+ * @public
756
+ */
757
+ type UnsignedTransaction = BrandedType<Transaction, "UnsignedTransaction">;
758
+ /**
759
+ * A Solana transaction that has at least one signature and a blockhash
760
+ * lifetime constraint.
761
+ *
762
+ * This is the base type for all signed transaction variants. It intersects
763
+ * `Transaction` with `TransactionWithBlockhashLifetime` from `@solana/kit`,
764
+ * ensuring the blockhash expiry window (`blockhash` + `lastValidBlockHeight`)
765
+ * is present alongside the signature data.
766
+ *
767
+ * @remarks
768
+ * **Blockhash lifetime** — The `TransactionWithBlockhashLifetime` intersection
769
+ * ensures that every `SignedTransaction` carries `lifetimeConstraint.blockhash`
770
+ * and `lifetimeConstraint.lastValidBlockHeight`. The forwarder uses these to
771
+ * detect expiry before submission.
772
+ *
773
+ * **Sub-types** — `SignedTransaction` is the common type used in forwarder
774
+ * method signatures because it accepts both {@link PartiallySignedTransaction}
775
+ * and {@link FullySignedTransaction}. Use the more specific sub-types when the
776
+ * exact signing completeness matters to the API contract.
777
+ *
778
+ * @example
779
+ * Accepting any signed transaction (partial or full):
780
+ * ```typescript
781
+ * function logSignedTx(tx: SignedTransaction): void {
782
+ * console.log(`Valid until block: ${tx.lifetimeConstraint.lastValidBlockHeight}`);
783
+ * }
784
+ * ```
785
+ *
786
+ * @see {@link PartiallySignedTransaction} for partial signing state
787
+ * @see {@link FullySignedTransaction} for full signing state
788
+ * @see {@link UnsignedTransaction} for the unsigned state
789
+ * @public
790
+ */
791
+ type SignedTransaction = BrandedType<Transaction & TransactionWithBlockhashLifetime, "SignedTransaction">;
792
+ /**
793
+ * A Solana transaction with some but potentially not all required signatures.
794
+ *
795
+ * A sub-brand of {@link SignedTransaction}. The transaction has been signed by
796
+ * at least one party but may still be missing signatures from other required
797
+ * signers. This state is common in multi-signature workflows where different
798
+ * parties sign at different times or different locations.
799
+ *
800
+ * @remarks
801
+ * In the Umbra SDK, partial signing arises when:
802
+ * - The user's wallet signs the transaction locally.
803
+ * - The relayer counter-signs before submission.
804
+ * - A hardware wallet adds its signature after an initial software signature.
805
+ *
806
+ * A `PartiallySignedTransaction` cannot be submitted to the network until all
807
+ * required signatures are collected, at which point it can be cast (or built
808
+ * up) to {@link FullySignedTransaction}.
809
+ *
810
+ * @example
811
+ * Multi-sig workflow:
812
+ * ```typescript
813
+ * const partial: PartiallySignedTransaction = await userWallet.sign(unsigned);
814
+ * const full: FullySignedTransaction = await relayer.countersign(partial);
815
+ * await forwarder.forwardSequentially([full]);
816
+ * ```
817
+ *
818
+ * @see {@link FullySignedTransaction} for the fully-signed state
819
+ * @see {@link SignedTransaction} for the base signed state
820
+ * @public
821
+ */
822
+ type PartiallySignedTransaction = SubBrandedType<SignedTransaction, "PartiallySignedTransaction">;
823
+ /**
824
+ * A Solana transaction with all required signatures present and ready for
825
+ * network submission.
826
+ *
827
+ * This is the terminal transaction state in the signing lifecycle. A
828
+ * `FullySignedTransaction` has been signed by every required signer and can be
829
+ * submitted to the Solana network via a {@link TransactionForwarder}.
830
+ *
831
+ * @remarks
832
+ * **Compile-time guarantee** — The {@link TransactionForwarder} interface's
833
+ * `forwardSequentially` and `forwardInParallel` methods accept
834
+ * `readonly SignedTransaction[]` (the common base type). Callers that track
835
+ * signing state explicitly can use `FullySignedTransaction` in their own
836
+ * function signatures to signal that all signatures are present.
837
+ *
838
+ * **Branding vs. validation** — The brand is a compile-time assertion — the
839
+ * runtime does NOT verify that all required pubkeys have corresponding
840
+ * signatures. It is the responsibility of the signing workflow to ensure
841
+ * completeness before casting to `FullySignedTransaction`.
842
+ *
843
+ * @example
844
+ * Enforcing full signing at a function boundary:
845
+ * ```typescript
846
+ * import { FullySignedTransaction } from "./types";
847
+ * import type { TransactionForwarder } from "./interfaces";
848
+ *
849
+ * async function submitAll(
850
+ * forwarder: TransactionForwarder,
851
+ * txs: readonly FullySignedTransaction[],
852
+ * ) {
853
+ * return forwarder.forwardSequentially(txs);
854
+ * }
855
+ * ```
856
+ *
857
+ * @see {@link PartiallySignedTransaction} for partial signing state
858
+ * @see {@link SignedTransaction} for the base signed state
859
+ * @see {@link TransactionForwarder} for the submission interface
860
+ * @public
861
+ */
862
+ type FullySignedTransaction = SubSubBrandedType<PartiallySignedTransaction, "FullySignedTransaction">;
863
+ /**
864
+ * Asserts that a value is a primitive `string` and narrows it to {@link String}.
865
+ *
866
+ * This is the base assertion for all Solana branded string types. It only
867
+ * checks that the input is a primitive `string` — no format or content
868
+ * validation is performed.
869
+ *
870
+ * @param value - The value to assert. Must be a primitive string.
871
+ * @throws {SolanaAssertionError} If `typeof value !== "string"`.
872
+ *
873
+ * @remarks
874
+ * For more specific string types, use the dedicated assertion functions:
875
+ * - {@link assertTransactionSignature} — for base58-encoded signatures
876
+ *
877
+ * @example
878
+ * ```typescript
879
+ * const raw: unknown = "hello world";
880
+ * assertString(raw as string);
881
+ * // raw is now typed as String
882
+ *
883
+ * assertString(123 as unknown as string); // Throws: not a string
884
+ * assertString(null as unknown as string); // Throws: not a string
885
+ * ```
886
+ *
887
+ * @see {@link String} for the branded type
888
+ * @see {@link assertTransactionSignature} for the signature-specific assertion
889
+ * @public
890
+ */
891
+ declare function assertString(value: string): asserts value is String;
892
+ /**
893
+ * Asserts that a value is a valid base58-encoded Solana transaction signature
894
+ * and narrows it to {@link TransactionSignature}.
895
+ *
896
+ * Validation rules:
897
+ * 1. `typeof value === "string"`
898
+ * 2. `value.length > 0` (non-empty)
899
+ * 3. Every character is in the Base58 alphabet (`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`)
900
+ *
901
+ * @param value - The string to assert as a base58 transaction signature.
902
+ * @throws {SolanaAssertionError} If the value is not a string, is empty, or
903
+ * contains characters outside the Base58 alphabet. The error's `constraint`
904
+ * field identifies which rule was violated, and for alphabet violations,
905
+ * includes the position and character that failed.
906
+ *
907
+ * @remarks
908
+ * **Validation scope** — This function performs character-level validation only.
909
+ * It does NOT verify cryptographic correctness (i.e., it does not check that
910
+ * the 64 decoded bytes constitute a valid Ed25519 signature, nor that the
911
+ * signature was produced by any particular keypair).
912
+ *
913
+ * **Excluded characters** — The Base58 alphabet deliberately omits `0` (zero),
914
+ * `O` (capital O), `I` (capital I), and `l` (lowercase L) to avoid
915
+ * transcription errors. Any of these characters in `value` will cause a throw.
916
+ *
917
+ * **Typical usage** — Call this function at SDK ingestion boundaries (e.g.,
918
+ * when accepting a signature string from user input or an external API) to
919
+ * ensure downstream code only ever sees branded, validated values.
920
+ *
921
+ * @example
922
+ * Validating a signature from an external source:
923
+ * ```typescript
924
+ * const rawSig: string = apiResponse.signature;
925
+ * assertTransactionSignature(rawSig);
926
+ * // rawSig is now typed as TransactionSignature
927
+ * ```
928
+ *
929
+ * @example
930
+ * Invalid inputs:
931
+ * ```typescript
932
+ * assertTransactionSignature(""); // Throws: empty string
933
+ * assertTransactionSignature("hello!world"); // Throws: invalid char '!'
934
+ * assertTransactionSignature("0abc"); // Throws: '0' not in Base58
935
+ * assertTransactionSignature("IIII"); // Throws: 'I' not in Base58
936
+ * ```
937
+ *
938
+ * @see {@link TransactionSignature} for the branded type
939
+ * @see {@link SignatureBytes} for the binary equivalent
940
+ * @public
941
+ */
942
+ declare function assertTransactionSignature(value: string): asserts value is TransactionSignature;
943
+ /**
944
+ * Asserts that a value is a `Uint8Array` and narrows it to {@link SolanaBytes}.
945
+ *
946
+ * This is the base assertion for all Solana byte array types. It only checks
947
+ * that the input is a `Uint8Array` instance — no length validation is performed.
948
+ *
949
+ * @param value - The `Uint8Array` to assert. Must be an instance of `Uint8Array`.
950
+ * @throws {SolanaAssertionError} If `!(value instanceof Uint8Array)`.
951
+ *
952
+ * @remarks
953
+ * For byte arrays with specific length requirements, use the more specific
954
+ * assertion function:
955
+ * - {@link assertSignatureBytes} — for 64-byte Ed25519 signature arrays
956
+ *
957
+ * @example
958
+ * ```typescript
959
+ * const data = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
960
+ * assertSolanaBytes(data);
961
+ * // data is now typed as SolanaBytes
962
+ *
963
+ * assertSolanaBytes([] as unknown as Uint8Array); // Throws: not a Uint8Array
964
+ * assertSolanaBytes("bytes" as unknown as Uint8Array); // Throws: not a Uint8Array
965
+ * ```
966
+ *
967
+ * @see {@link SolanaBytes} for the branded type
968
+ * @see {@link assertSignatureBytes} for the length-constrained variant
969
+ * @public
970
+ */
971
+ declare function assertSolanaBytes(value: Uint8Array): asserts value is SolanaBytes;
972
+ /**
973
+ * Asserts that a value is a `Uint8Array` of exactly {@link SIGNATURE_BYTE_LENGTH}
974
+ * (64) bytes and narrows it to {@link SignatureBytes}.
975
+ *
976
+ * Validation rules:
977
+ * 1. `value instanceof Uint8Array`
978
+ * 2. `value.length === 64`
979
+ *
980
+ * @param value - The `Uint8Array` to assert as a 64-byte Ed25519 signature.
981
+ * @throws {SolanaAssertionError} If the value is not a `Uint8Array` or is not
982
+ * exactly 64 bytes. The error's `constraint` field specifies
983
+ * `"length === 64"` for length violations.
984
+ *
985
+ * @remarks
986
+ * The 64-byte requirement is defined by the Ed25519 specification and is
987
+ * invariant across all Solana Ed25519 signatures. Passing a 63- or 65-byte
988
+ * array will always throw, regardless of the content.
989
+ *
990
+ * **Structure:**
991
+ * - Bytes 0–31: R component (compressed curve point)
992
+ * - Bytes 32–63: S component (scalar)
993
+ *
994
+ * @example
995
+ * Validating a signature byte array:
996
+ * ```typescript
997
+ * const sigBytes = new Uint8Array(64);
998
+ * // ... populate with actual Ed25519 signature bytes ...
999
+ * assertSignatureBytes(sigBytes);
1000
+ * // sigBytes is now typed as SignatureBytes
1001
+ * ```
1002
+ *
1003
+ * @example
1004
+ * Invalid inputs:
1005
+ * ```typescript
1006
+ * assertSignatureBytes(new Uint8Array(63)); // Throws: expected 64 bytes, got 63
1007
+ * assertSignatureBytes(new Uint8Array(65)); // Throws: expected 64 bytes, got 65
1008
+ * assertSignatureBytes([] as unknown as Uint8Array); // Throws: not a Uint8Array
1009
+ * ```
1010
+ *
1011
+ * @see {@link SignatureBytes} for the branded type
1012
+ * @see {@link SIGNATURE_BYTE_LENGTH} for the required length constant
1013
+ * @see {@link TransactionSignature} for the base58-encoded equivalent
1014
+ * @public
1015
+ */
1016
+ declare function assertSignatureBytes(value: Uint8Array): asserts value is SignatureBytes;
1017
+ /**
1018
+ * Brands a compiled `Transaction` as a {@link SignedTransaction} for relay
1019
+ * submission.
1020
+ *
1021
+ * @remarks
1022
+ * This function is used for transactions that will be signed by the **relayer**,
1023
+ * not by the client. In the Umbra relay flow, the client builds and serializes
1024
+ * a transaction message, which is then passed to the relayer service. The
1025
+ * relayer signs and submits the transaction. Because the blockhash lifetime is
1026
+ * already embedded in the compiled message bytes (`messageBytes`), the
1027
+ * transaction is treated as carrying a blockhash constraint even though
1028
+ * `lifetimeConstraint` is not set as a TypeScript property.
1029
+ *
1030
+ * **This is an escape hatch** — it performs an unchecked cast. Use only when
1031
+ * you are certain the compiled message bytes include a valid blockhash and the
1032
+ * relayer will supply the required signature before submission.
1033
+ *
1034
+ * @param tx - A `Transaction` object whose compiled message bytes already
1035
+ * embed the blockhash lifetime constraint.
1036
+ * @returns The same `Transaction` value cast to {@link SignedTransaction}.
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * import { asRelayableSignedTransaction } from "./types";
1041
+ *
1042
+ * const compiledTx: Transaction = compileTransactionMessage(txMessage);
1043
+ * const relayable = asRelayableSignedTransaction(compiledTx);
1044
+ * // relayable can now be passed to relayer submission APIs
1045
+ * ```
1046
+ *
1047
+ * @public
1048
+ */
1049
+ declare function asRelayableSignedTransaction(tx: Transaction): SignedTransaction;
1050
+
1051
+ /**
1052
+ * Umbra Protocol Types
1053
+ *
1054
+ * Defines the TypeScript interfaces for the core on-chain state accounts used by the
1055
+ * Umbra privacy protocol, and the discriminated union result types returned by SDK
1056
+ * query functions.
1057
+ *
1058
+ * ## EncryptedUserAccount
1059
+ *
1060
+ * The central on-chain record for each Umbra user. It is stored at a PDA derived from
1061
+ * the user's on-chain wallet address and contains:
1062
+ * - Protocol version and PDA metadata
1063
+ * - Status flags that gate access to privacy features
1064
+ * - The X25519 public key used for shared-mode encryption
1065
+ * - The Poseidon commitment to the user's secret key tree
1066
+ * - A generation counter for deterministic nonce derivation
1067
+ * - A random seed for additional entropy during nonce computation
1068
+ *
1069
+ * ## Result Types
1070
+ *
1071
+ * `QueryUserAccountResult` and `QueryComplianceGrantResult` are discriminated unions
1072
+ * whose `state` field acts as a type discriminant. Pattern-match on `state` to safely
1073
+ * access the data payload:
1074
+ *
1075
+ * ```typescript
1076
+ * const result = await queryUserAccount(address);
1077
+ * if (result.state === "exists") {
1078
+ * // result.data: EncryptedUserAccount
1079
+ * }
1080
+ * ```
1081
+ *
1082
+ * @packageDocumentation
1083
+ * @module umbra/types
1084
+ */
1085
+
1086
+ /**
1087
+ * The decoded on-chain state of a user's Arcium encrypted user account.
1088
+ *
1089
+ * @remarks
1090
+ * This account is the root of a user's participation in the Umbra protocol. It is a
1091
+ * Program Derived Account (PDA) owned by the Umbra program and indexed by the user's
1092
+ * wallet public key. The account is written by `init_encrypted_user_account`
1093
+ * and mutated by registration and conversion instructions.
1094
+ *
1095
+ * ### Token Account Mode Logic
1096
+ *
1097
+ * Umbra supports two modes for encrypted token accounts:
1098
+ *
1099
+ * - **MXE-only** — balances are encrypted under the Arcium MXE (Multi-party eXecution
1100
+ * Environment) network key. Only the MXE can decrypt them; the user themselves cannot
1101
+ * decrypt without going through MPC. Available to all users regardless of X25519 key
1102
+ * registration.
1103
+ * - **Shared** — balances are encrypted under the user's X25519 public key. The user
1104
+ * can decrypt locally without MPC involvement. Only available after
1105
+ * `isUserAccountX25519KeyRegistered` is `true`.
1106
+ *
1107
+ * ### Status Flag Progression
1108
+ *
1109
+ * A freshly initialized account will have all flags `false`. The user registers their
1110
+ * keys via separate instructions:
1111
+ *
1112
+ * 1. `isInitialized = true` — set by `init_encrypted_user_account`.
1113
+ * 2. `isUserAccountX25519KeyRegistered = true` — set by `register_x25519_public_key`.
1114
+ * 3. `isUserCommitmentRegistered = true` — set by `register_user_commitment`.
1115
+ * 4. `isActiveForAnonymousUsage = true` — set by `activate_for_anonymous_usage`
1116
+ * (requires step 2 and 3 to be complete).
1117
+ *
1118
+ * ### Nonce Derivation
1119
+ *
1120
+ * New token account nonces are derived deterministically from:
1121
+ * - `generationIndex` (incremented each time a new token account is created or a
1122
+ * conversion is performed)
1123
+ * - `randomGenerationSeed` (fixed at registration; can be rotated via
1124
+ * `update_random_generation_seed`)
1125
+ * - `x25519PublicKey` (user identity anchor)
1126
+ *
1127
+ * This ensures that a given user's token account nonces are unique across all mints and
1128
+ * instruction variants without requiring on-chain storage of each nonce individually.
1129
+ *
1130
+ * @example
1131
+ * ```typescript
1132
+ * import { getQueryUserAccountFunction } from "@umbra-privacy/sdk";
1133
+ * import type { EncryptedUserAccount } from "@umbra-privacy/sdk";
1134
+ *
1135
+ * const query = getQueryUserAccountFunction({ accountInfoProvider });
1136
+ * const result = await query(userWalletAddress);
1137
+ *
1138
+ * if (result.state === "exists") {
1139
+ * const account: EncryptedUserAccount = result.data;
1140
+ *
1141
+ * // Check whether Shared mode token accounts are available:
1142
+ * if (!account.isUserAccountX25519KeyRegistered) {
1143
+ * console.warn("Register X25519 key first to enable Shared mode.");
1144
+ * }
1145
+ *
1146
+ * // Use the generation index for nonce derivation:
1147
+ * console.log("Current generation index:", account.generationIndex);
1148
+ * }
1149
+ * ```
1150
+ *
1151
+ * @see {@link QueryUserAccountResult} for the result wrapper returned by query functions.
1152
+ * @public
1153
+ */
1154
+ interface EncryptedUserAccount {
1155
+ /**
1156
+ * Protocol version byte stored at the beginning of the account discriminator.
1157
+ *
1158
+ * @remarks
1159
+ * Used for forward-compatibility checks. The SDK verifies that the decoded version
1160
+ * matches the expected protocol version before further processing. A mismatch
1161
+ * indicates that the account was created by an incompatible version of the program.
1162
+ *
1163
+ * @readonly
1164
+ */
1165
+ readonly versionByte: U8;
1166
+ /**
1167
+ * Canonical bump seed for this account's PDA.
1168
+ *
1169
+ * @remarks
1170
+ * Stored on-chain to avoid recomputing `findProgramAddress` in callbacks. Anchor
1171
+ * macro-generated accounts always store their canonical bump as the first non-discriminator
1172
+ * field. The SDK reads it back during PDA validation to confirm account authenticity.
1173
+ *
1174
+ * @readonly
1175
+ */
1176
+ readonly canonicalBump: U8;
1177
+ /**
1178
+ * Whether the account has been fully initialized by `init_encrypted_user_account`.
1179
+ *
1180
+ * @remarks
1181
+ * Set to `true` during the initial `init_encrypted_user_account` instruction. If
1182
+ * `false`, all other fields should be considered uninitialized / zero-valued. The
1183
+ * on-chain program checks this flag before allowing any state-mutating instruction to
1184
+ * proceed.
1185
+ *
1186
+ * @readonly
1187
+ */
1188
+ readonly isInitialised: boolean;
1189
+ /**
1190
+ * Whether anonymous usage (mixer transactions using unspent output notes) has been enabled for this
1191
+ * account.
1192
+ *
1193
+ * @remarks
1194
+ * Controlled by the `activate_for_anonymous_usage` instruction. Both
1195
+ * `isUserAccountX25519KeyRegistered` and `isUserCommitmentRegistered` must be `true` before
1196
+ * anonymous usage can be activated. When `false`, the user cannot submit output note
1197
+ * creation or claim instructions.
1198
+ *
1199
+ * @readonly
1200
+ */
1201
+ readonly isActiveForAnonymousUsage: boolean;
1202
+ /**
1203
+ * Whether the user has registered a Poseidon commitment to their secret key tree.
1204
+ *
1205
+ * @remarks
1206
+ * Set by the `register_user_commitment` instruction. The commitment is the Poseidon
1207
+ * hash of the root node of the user's binary secret tree (see {@link userCommitment}).
1208
+ * It is used in challenge transcript computation and ZK proof public inputs for note
1209
+ * claim proofs to bind the proof to the user's identity without revealing any private
1210
+ * key material.
1211
+ *
1212
+ * @readonly
1213
+ */
1214
+ readonly isUserCommitmentRegistered: boolean;
1215
+ /**
1216
+ * Whether the user has registered an X25519 public key for shared-mode encryption.
1217
+ *
1218
+ * @remarks
1219
+ * Set by the `register_x25519_public_key` instruction. Until this flag is `true`:
1220
+ * - The `x25519PublicKey` field is zero-valued (all bytes are 0).
1221
+ * - Token accounts must be created in MXE-only mode; Shared mode is unavailable.
1222
+ * - Anonymous usage cannot be activated.
1223
+ *
1224
+ * Once `true`, the user can create Shared-mode token accounts and the stored key is
1225
+ * used in nonce derivation for all subsequent account creation operations.
1226
+ *
1227
+ * @readonly
1228
+ */
1229
+ readonly isUserAccountX25519KeyRegistered: boolean;
1230
+ /**
1231
+ * The user's X25519 public key for shared-mode token account encryption and note
1232
+ * operations.
1233
+ *
1234
+ * @remarks
1235
+ * This is the 32-byte Curve25519 public key derived from the user's X25519 private
1236
+ * key during the `register_x25519_public_key` instruction. It serves as the
1237
+ * user's persistent on-chain identity for:
1238
+ *
1239
+ * - Encrypting Shared-mode token account balances: the sender encrypts under this key
1240
+ * so the receiver can decrypt locally without MPC.
1241
+ * - Identity anchoring in challenge transcripts and ZK proof public inputs:
1242
+ * the key is hashed into the challenge transcript and the aggregated Poseidon hash
1243
+ * to bind proofs to this user.
1244
+ * - Nonce derivation for new token account initialization: the key is included in the
1245
+ * nonce hash pre-image alongside `generationIndex` and `randomGenerationSeed`.
1246
+ *
1247
+ * If `isUserAccountX25519KeyRegistered` is `false`, this field contains a zero-valued byte
1248
+ * array and must not be used.
1249
+ *
1250
+ * @readonly
1251
+ */
1252
+ readonly x25519PublicKey: X25519PublicKey$1;
1253
+ /**
1254
+ * Poseidon hash commitment to the root of the user's secret binary tree.
1255
+ *
1256
+ * @remarks
1257
+ * The user's private key material is arranged as a 4-leaf binary tree whose structure
1258
+ * is committed to on-chain:
1259
+ *
1260
+ * ```
1261
+ * userCommitment (this field)
1262
+ * |
1263
+ * +-------------+-------------+
1264
+ * | |
1265
+ * +------+------+ +------+------+
1266
+ * | | | |
1267
+ * masterViewing masterViewing shieldingPriv shieldingPriv
1268
+ * Key Commitment Key KeyBlindingFactor
1269
+ * ```
1270
+ *
1271
+ * The on-chain program never sees any leaf values — only this root commitment. ZK proofs
1272
+ * (ZK proofs) demonstrate knowledge of the leaves and their correct Poseidon relationship
1273
+ * to this root. The Fiat-Shamir challenge computation also includes this commitment to
1274
+ * prevent replay attacks.
1275
+ *
1276
+ * Set by `register_user_commitment`; the commitment is recomputed from private inputs
1277
+ * in the ZK circuit and must match the on-chain stored value for proof verification
1278
+ * to succeed.
1279
+ *
1280
+ * If `isUserCommitmentRegistered` is `false`, this field is zero-valued.
1281
+ *
1282
+ * @readonly
1283
+ */
1284
+ readonly userCommitment: PoseidonHash;
1285
+ /**
1286
+ * Monotonically increasing 128-bit counter used for deterministic nonce derivation.
1287
+ *
1288
+ * @remarks
1289
+ * Incremented by the on-chain program at the end of the handler instruction (before
1290
+ * the MPC callback fires) for each of the following operations:
1291
+ *
1292
+ * - Creating a new MXE-mode encrypted token account.
1293
+ * - Creating a new Shared-mode encrypted token account.
1294
+ * - Converting an existing MXE-mode token account to Shared-mode.
1295
+ *
1296
+ * When the SDK computes the nonce for a new token account (`newNonce`), it reads the
1297
+ * current `generationIndex` from the fetched `EncryptedUserAccount` and combines it
1298
+ * with `randomGenerationSeed` and `x25519PublicKey` in a domain-separated Poseidon
1299
+ * hash. The handler then increments this counter on-chain so that the next account
1300
+ * creation produces a distinct nonce.
1301
+ *
1302
+ * For existing token accounts the nonce is stored in the `ArciumEncryptedTokenAccount`
1303
+ * PDA and is validated by the callback without using `generationIndex`.
1304
+ *
1305
+ * @readonly
1306
+ */
1307
+ readonly generationIndex: U128;
1308
+ /**
1309
+ * 256-bit random seed providing additional entropy during nonce derivation.
1310
+ *
1311
+ * @remarks
1312
+ * Set once during account initialization (via `init_encrypted_user_account` or the
1313
+ * first registration call) using a client-generated random value. Can be rotated by
1314
+ * the user via the `update_random_generation_seed` instruction without invalidating
1315
+ * existing token accounts (which store their own nonces).
1316
+ *
1317
+ * Included in the nonce hash pre-image alongside `generationIndex` and
1318
+ * `x25519PublicKey`. Its purpose is to ensure that even if an adversary learns the
1319
+ * user's `generationIndex`, they cannot predict token account nonces without also
1320
+ * knowing this seed.
1321
+ *
1322
+ * Stored as a 32-byte little-endian byte array (`U256LeBytes`).
1323
+ *
1324
+ * @readonly
1325
+ */
1326
+ readonly randomGenerationSeed: U256LeBytes;
1327
+ }
1328
+ /**
1329
+ * Result of querying whether an `EncryptedUserAccount` exists on-chain for a given
1330
+ * wallet address.
1331
+ *
1332
+ * @remarks
1333
+ * Returned by `getQueryUserAccountFunction` implementations. The `state` field is the
1334
+ * discriminant for narrowing:
1335
+ *
1336
+ * - `"non_existent"` — no account was found at the expected PDA. The user has not yet
1337
+ * called `init_encrypted_user_account`.
1338
+ * - `"exists"` — the account was found and successfully decoded. The `data` property
1339
+ * contains the parsed `EncryptedUserAccount`.
1340
+ *
1341
+ * Pattern-match on `state` to safely access `data`:
1342
+ *
1343
+ * ```typescript
1344
+ * const result: QueryUserAccountResult = await query(walletAddress);
1345
+ *
1346
+ * switch (result.state) {
1347
+ * case "non_existent":
1348
+ * console.log("User not registered — call initEncryptedUserAccount first.");
1349
+ * break;
1350
+ * case "exists":
1351
+ * const { isUserAccountX25519KeyRegistered, generationIndex } = result.data;
1352
+ * break;
1353
+ * }
1354
+ * ```
1355
+ *
1356
+ * @example
1357
+ * ```typescript
1358
+ * import { getQueryUserAccountFunction } from "@umbra-privacy/sdk";
1359
+ *
1360
+ * const query = getQueryUserAccountFunction({ accountInfoProvider });
1361
+ * const result = await query(userAddress);
1362
+ *
1363
+ * if (result.state === "non_existent") {
1364
+ * // Prompt the user to register.
1365
+ * return;
1366
+ * }
1367
+ *
1368
+ * // Narrowed: result.data is EncryptedUserAccount
1369
+ * console.log("Generation index:", result.data.generationIndex);
1370
+ * ```
1371
+ *
1372
+ * @see {@link EncryptedUserAccount} for the account data shape.
1373
+ * @public
1374
+ */
1375
+ type QueryUserAccountResult = {
1376
+ readonly state: "non_existent";
1377
+ } | {
1378
+ readonly state: "exists";
1379
+ readonly data: EncryptedUserAccount;
1380
+ };
1381
+ /**
1382
+ * Result of checking whether a compliance grant PDA exists on-chain for a given
1383
+ * (granter, nonce, receiver) triple.
1384
+ *
1385
+ * @remarks
1386
+ * Compliance grants are marker accounts — their existence on-chain is the sole signal
1387
+ * that a grant is active. There is no structured data payload to decode; only the
1388
+ * account's presence matters.
1389
+ *
1390
+ * - `"non_existent"` — no grant PDA was found. The granter has not granted the
1391
+ * receiver access to view their encrypted balances for the given nonce.
1392
+ * - `"exists"` — the grant PDA exists. The receiver is permitted to request
1393
+ * re-encryption of the granter's encrypted outputs (subject to on-chain program checks).
1394
+ *
1395
+ * Returned by `getQueryComplianceGrantFunction` implementations.
1396
+ *
1397
+ * @example
1398
+ * ```typescript
1399
+ * import { getQueryComplianceGrantFunction } from "@umbra-privacy/sdk";
1400
+ *
1401
+ * const query = getQueryComplianceGrantFunction({ accountInfoProvider });
1402
+ * const result = await query(granterAddress, nonce, receiverAddress);
1403
+ *
1404
+ * if (result.state === "non_existent") {
1405
+ * console.log("No compliance grant — receiver cannot view balances.");
1406
+ * } else {
1407
+ * console.log("Compliance grant active — receiver has been granted access.");
1408
+ * }
1409
+ * ```
1410
+ *
1411
+ * @see {@link QueryUserAccountResult} for the analogous user account query result type.
1412
+ * @public
1413
+ */
1414
+ type QueryComplianceGrantResult = {
1415
+ readonly state: "non_existent";
1416
+ } | {
1417
+ readonly state: "exists";
1418
+ };
1419
+
1420
+ /**
1421
+ * Key Derivation Types
1422
+ *
1423
+ * This module defines branded types for Curve25519 (Ed25519/X25519) key exchange,
1424
+ * Keccak hashing, master seeds, and hierarchical viewing key derivation.
1425
+ *
1426
+ * @remarks
1427
+ * All types in this module are "branded" nominal types built on top of primitive
1428
+ * TypeScript types (`Uint8Array` or `bigint`). Branding prevents accidental
1429
+ * cross-use of structurally identical values that have different semantic meanings
1430
+ * (e.g., passing an X25519 public key where a private key is expected).
1431
+ *
1432
+ * ## Type Hierarchy Overview
1433
+ *
1434
+ * ```
1435
+ * Bytes
1436
+ * └── X25519Bytes (32 bytes, endianness-agnostic)
1437
+ * ├── X25519PrivateKey — secret scalar; never share
1438
+ * ├── X25519PublicKey — public curve point; safe to share
1439
+ * └── SharedSecret — ECDH output; feed into a KDF before use
1440
+ *
1441
+ * LeBytes
1442
+ * └── U256LeBytes
1443
+ * └── Keccak256Hash — 32-byte Keccak-256 digest
1444
+ * └── U512LeBytes
1445
+ * └── Keccak512Hash — 64-byte Keccak-512 digest
1446
+ * ├── MasterSeed — root of the key hierarchy; 64 bytes
1447
+ * └── GenerationSeed — ephemeral seed input; 64 bytes
1448
+ *
1449
+ * bigint
1450
+ * └── U256
1451
+ * └── Bn254FieldElement
1452
+ * ├── MasterViewingKey — < 2^252, views all txs
1453
+ * ├── YearlyViewingKey — views one calendar year
1454
+ * ├── MonthlyViewingKey — views one calendar month
1455
+ * ├── DailyViewingKey — views one calendar day
1456
+ * ├── HourlyViewingKey — views one calendar hour
1457
+ * ├── MinuteViewingKey — views one calendar minute
1458
+ * ├── SecondViewingKey — views one calendar second
1459
+ * └── MintViewingKey — views one token (mint)
1460
+ * ```
1461
+ *
1462
+ * ## Security Model
1463
+ *
1464
+ * - The `MasterSeed` is the single secret from which all other keys are derived.
1465
+ * Compromising it compromises the entire key hierarchy.
1466
+ * - KMAC256 domain separation ensures that different derived keys are
1467
+ * computationally independent: knowledge of one does not reveal another.
1468
+ * - Viewing keys (MVK and sub-keys) grant read-only access to transaction
1469
+ * history and can be selectively shared for compliance purposes.
1470
+ * - X25519 private keys are used for ECDH with token senders to enable
1471
+ * encrypted token account balance decryption.
1472
+ *
1473
+ * @packageDocumentation
1474
+ * @public
1475
+ *
1476
+ * @module crypto/key-derivation/types
1477
+ */
1478
+
1479
+ /**
1480
+ * Base branded byte-array type for X25519 key exchange operations.
1481
+ *
1482
+ * X25519 is an elliptic curve Diffie-Hellman (ECDH) protocol using Curve25519
1483
+ * in Montgomery form. All X25519 values (public keys, private keys, shared
1484
+ * secrets) are exactly 32 bytes.
1485
+ *
1486
+ * @remarks
1487
+ * - Size: 32 bytes (256 bits)
1488
+ * - Used as the parent brand for X25519PrivateKey, X25519PublicKey, and SharedSecret
1489
+ * - Parallel to LeBytes/BeBytes as a sub-brand of Bytes
1490
+ * - Endianness-agnostic: the X25519 spec defines a fixed byte ordering
1491
+ *
1492
+ * ## Type Hierarchy
1493
+ * ```
1494
+ * Bytes (base)
1495
+ * └── X25519Bytes (sub-brand, 32 bytes)
1496
+ * ├── X25519PrivateKey
1497
+ * ├── X25519PublicKey
1498
+ * └── SharedSecret
1499
+ * ```
1500
+ *
1501
+ * @see {@link X25519PrivateKey}
1502
+ * @see {@link X25519PublicKey}
1503
+ * @see {@link SharedSecret}
1504
+ * @see https://cr.yp.to/ecdh/curve25519-20060209.pdf
1505
+ * @see https://tools.ietf.org/html/rfc7748
1506
+ * @public
1507
+ */
1508
+ type X25519Bytes = SubBrandedType<Bytes, "X25519Bytes">;
1509
+ /**
1510
+ * X25519 private key for elliptic curve Diffie-Hellman key exchange.
1511
+ *
1512
+ * A private key is a 32-byte scalar derived from the master seed via KMAC256
1513
+ * with domain separator `"UserAccountX25519Keypair"`. It is used together
1514
+ * with a counterparty's public key to compute a shared secret.
1515
+ *
1516
+ * @remarks
1517
+ * - Size: 32 bytes (256 bits)
1518
+ * - MUST be kept secret and never shared or logged
1519
+ * - The X25519 algorithm applies RFC 8032 clamping to the scalar during use
1520
+ * - In Umbra, private keys are derived deterministically from the master seed;
1521
+ * they must never be generated independently with a random number generator
1522
+ *
1523
+ * ## Security Warning
1524
+ *
1525
+ * Exposure of this key allows the holder to decrypt all balances encrypted to
1526
+ * the corresponding public key. Store it only in memory during use.
1527
+ *
1528
+ * ## Type Hierarchy
1529
+ * ```
1530
+ * Bytes (base)
1531
+ * └── X25519Bytes (sub-brand, 32 bytes)
1532
+ * └── X25519PrivateKey (sub-sub-brand)
1533
+ * ```
1534
+ *
1535
+ * @example
1536
+ * ```typescript
1537
+ * // Generate a new private key
1538
+ * const rawPrivateKey = crypto.getRandomValues(new Uint8Array(32));
1539
+ * assertX25519PrivateKey(rawPrivateKey);
1540
+ * // rawPrivateKey is now typed as X25519PrivateKey
1541
+ *
1542
+ * // Derive the public key
1543
+ * const publicKey = x25519GetPublicKey(rawPrivateKey);
1544
+ * ```
1545
+ *
1546
+ * @see {@link assertX25519PrivateKey}
1547
+ * @see {@link X25519Keypair}
1548
+ * @see https://tools.ietf.org/html/rfc7748#section-5
1549
+ * @public
1550
+ */
1551
+ type X25519PrivateKey = SubSubBrandedType<X25519Bytes, "X25519PrivateKey">;
1552
+ /**
1553
+ * X25519 public key for elliptic curve Diffie-Hellman key exchange.
1554
+ *
1555
+ * A public key is a 32-byte Montgomery curve point derived from a private key
1556
+ * via scalar multiplication of the Curve25519 base point. It is stored on-chain
1557
+ * in the encrypted token account and used by token senders to encrypt balances
1558
+ * for the account holder.
1559
+ *
1560
+ * @remarks
1561
+ * - Size: 32 bytes (256 bits)
1562
+ * - Safe to transmit over insecure channels and store on-chain
1563
+ * - Derived from the corresponding X25519PrivateKey
1564
+ * - Used as input to X25519 ECDH: both parties independently compute the same shared secret
1565
+ *
1566
+ * ## Type Hierarchy
1567
+ * ```
1568
+ * Bytes (base)
1569
+ * └── X25519Bytes (sub-brand, 32 bytes)
1570
+ * └── X25519PublicKey (sub-sub-brand)
1571
+ * ```
1572
+ *
1573
+ * @example
1574
+ * ```typescript
1575
+ * // Receive a public key from another party
1576
+ * const theirPublicKey = receivePublicKey();
1577
+ * assertX25519PublicKey(theirPublicKey);
1578
+ * // theirPublicKey is now typed as X25519PublicKey
1579
+ *
1580
+ * // Compute shared secret
1581
+ * const sharedSecret = x25519(myPrivateKey, theirPublicKey);
1582
+ * ```
1583
+ *
1584
+ * @see {@link assertX25519PublicKey}
1585
+ * @see {@link X25519Keypair}
1586
+ * @see https://tools.ietf.org/html/rfc7748#section-5
1587
+ * @public
1588
+ */
1589
+ type X25519PublicKey = SubSubBrandedType<X25519Bytes, "X25519PublicKey">;
1590
+ /**
1591
+ * An X25519 key pair consisting of a private key and its corresponding public key.
1592
+ *
1593
+ * X25519 is an elliptic curve Diffie-Hellman (ECDH) protocol using Curve25519
1594
+ * in Montgomery form. In Umbra, this keypair is derived deterministically from
1595
+ * the master seed and is used to establish shared secrets with token senders,
1596
+ * enabling the account holder to decrypt their encrypted balance.
1597
+ *
1598
+ * @remarks
1599
+ * ## Key Generation
1600
+ * - Private key: 32 bytes derived via KMAC256 from the master seed
1601
+ * - Public key: Scalar multiplication of the private key with the Curve25519 base point
1602
+ *
1603
+ * ## Security Properties
1604
+ * - Private key MUST be kept secret; it enables decryption of all balances sent to this account
1605
+ * - Public key can be freely shared and is stored on-chain in the token account PDA
1606
+ * - Shared secret is computed as: `X25519(myPrivate, senderPublic)` — symmetric by construction
1607
+ * - Compromise of the private key does not reveal the master seed or other derived keys
1608
+ *
1609
+ * ## Use Cases in Umbra
1610
+ * - `registerTokenPublicKey`: The public key is registered on-chain for a token account
1611
+ * - Balance decryption: The private key is used to decrypt AES-GCM ciphertexts from senders
1612
+ * - ECDH with ephemeral sender keys for forward secrecy of individual transfers
1613
+ *
1614
+ * @example
1615
+ * ```typescript
1616
+ * import { X25519Keypair, generateX25519Keypair } from "./cryptography";
1617
+ *
1618
+ * // Generate a new keypair
1619
+ * const keypair: X25519Keypair = await generateX25519Keypair();
1620
+ *
1621
+ * // Share public key with peer
1622
+ * sendPublicKey(peer, keypair.publicKey);
1623
+ *
1624
+ * // Compute shared secret with peer's public key
1625
+ * const sharedSecret = x25519(keypair.privateKey, peerPublicKey);
1626
+ * ```
1627
+ *
1628
+ * @example
1629
+ * ```typescript
1630
+ * // Ephemeral key exchange for forward secrecy
1631
+ * const ephemeralKeypair: X25519Keypair = await generateX25519Keypair();
1632
+ *
1633
+ * // Use ephemeral keypair for this session only
1634
+ * const sessionKey = deriveSessionKey(
1635
+ * x25519(ephemeralKeypair.privateKey, recipientPublicKey)
1636
+ * );
1637
+ *
1638
+ * // Discard private key after use for forward secrecy
1639
+ * ```
1640
+ *
1641
+ * @see {@link assertX25519Keypair}
1642
+ * @see {@link X25519PrivateKey}
1643
+ * @see {@link X25519PublicKey}
1644
+ * @public
1645
+ */
1646
+ interface X25519Keypair {
1647
+ /**
1648
+ * The X25519 private key (32 bytes).
1649
+ *
1650
+ * This key MUST be kept secret. It is used to:
1651
+ * - Compute shared secrets with other parties' public keys
1652
+ * - Derive the corresponding public key
1653
+ *
1654
+ * @remarks
1655
+ * The private key is derived from the master seed via KMAC256 with the
1656
+ * domain separator `"UserAccountX25519Keypair"`. The X25519 algorithm applies
1657
+ * RFC 8032 §5.1.5 clamping to the scalar during use.
1658
+ *
1659
+ * @readonly
1660
+ */
1661
+ readonly privateKey: X25519PrivateKey;
1662
+ /**
1663
+ * The X25519 public key (32 bytes).
1664
+ *
1665
+ * This key can be freely shared. It is:
1666
+ * - Computed from the private key via scalar multiplication with the base point
1667
+ * - Used by other parties to compute shared secrets with their own private key
1668
+ * - Stored on-chain in the Umbra token account PDA
1669
+ * - Safe to transmit over insecure channels
1670
+ *
1671
+ * @readonly
1672
+ */
1673
+ readonly publicKey: X25519PublicKey;
1674
+ }
1675
+ /**
1676
+ * Ed25519 keypair for digital signatures on the Edwards form of Curve25519.
1677
+ *
1678
+ * Ed25519 is the signing scheme defined in RFC 8032. In Umbra, an Ed25519
1679
+ * keypair is derived from the same 32-byte seed as the corresponding X25519
1680
+ * keypair (they are related via the birational equivalence of Curve25519 in
1681
+ * Edwards vs Montgomery form). The Ed25519 public key is used as the on-chain
1682
+ * signer identity in registration transactions.
1683
+ *
1684
+ * @remarks
1685
+ * ## Key Derivation
1686
+ * - Seed: First 32 bytes of a 64-byte KMAC256 output keyed by the master seed
1687
+ * - Public key: Derived via `ed25519.getPublicKey(seed)`; uses SHA-512 internally
1688
+ * - The relationship to X25519: the Ed25519 public key can be converted to the
1689
+ * Montgomery form via `ed25519.utils.toMontgomery(edPublicKey)`
1690
+ *
1691
+ * ## Relationship to X25519
1692
+ * - Ed25519 uses compressed Edwards curve coordinates
1693
+ * - X25519 uses Montgomery curve coordinates
1694
+ * - Both represent points on the same underlying elliptic curve (Curve25519)
1695
+ * - The birational map between them is cheap and deterministic
1696
+ *
1697
+ * @example
1698
+ * ```typescript
1699
+ * import { ed25519 } from "@noble/curves/ed25519";
1700
+ *
1701
+ * const seed = crypto.getRandomValues(new Uint8Array(32));
1702
+ * const publicKey = ed25519.getPublicKey(seed);
1703
+ *
1704
+ * const keypair: Ed25519Keypair = { seed, publicKey };
1705
+ * ```
1706
+ *
1707
+ * @see {@link assertEd25519Keypair}
1708
+ * @see {@link Curve25519KeypairResult}
1709
+ * @public
1710
+ */
1711
+ interface Ed25519Keypair {
1712
+ /**
1713
+ * The Ed25519 private key seed (32 bytes).
1714
+ *
1715
+ * This is the raw 32-byte seed from which both the signing scalar and the
1716
+ * public key are derived (via SHA-512 key expansion defined in RFC 8032).
1717
+ * MUST be kept secret.
1718
+ */
1719
+ readonly seed: Uint8Array;
1720
+ /**
1721
+ * The Ed25519 public key (32 bytes).
1722
+ *
1723
+ * A compressed Edwards curve point derived from the seed via SHA-512 key
1724
+ * expansion and scalar multiplication. Can be freely shared and is used
1725
+ * as the on-chain signer identity.
1726
+ */
1727
+ readonly publicKey: Uint8Array;
1728
+ }
1729
+ /**
1730
+ * Combined Curve25519 keypair result containing both Ed25519 and X25519 keypairs.
1731
+ *
1732
+ * This interface represents the result of deriving both Ed25519 (Edwards curve)
1733
+ * and X25519 (Montgomery curve) keypairs from a single 32-byte seed. Both
1734
+ * keypairs are cryptographically linked through the same underlying Curve25519
1735
+ * and are derived together for efficiency.
1736
+ *
1737
+ * @remarks
1738
+ * ## Derivation Pipeline
1739
+ *
1740
+ * 1. **Ed25519 Keypair**:
1741
+ * - Input: First 32 bytes of a 64-byte KMAC256 output
1742
+ * - Output: Ed25519 public key via `ed25519.getPublicKey(seed)`
1743
+ *
1744
+ * 2. **X25519 Keypair**:
1745
+ * - Hash seed with SHA-512 → 64 bytes
1746
+ * - Clamp first 32 bytes per RFC 8032 §5.1.5
1747
+ * - Use clamped bytes as X25519 private key
1748
+ * - Derive X25519 public key via birational map: `ed25519.utils.toMontgomery(ed25519Pub)`
1749
+ *
1750
+ * ## Security Properties
1751
+ *
1752
+ * - **Deterministic**: Same master seed always produces the same keypairs
1753
+ * - **Domain Separated**: Independent from all other key derivations via KMAC256
1754
+ * - **Cryptographically Linked**: Both keypairs share the same Curve25519 foundation
1755
+ *
1756
+ * @example
1757
+ * ```typescript
1758
+ * import { getUserAccountX25519KeypairGenerator } from "@umbra-privacy/sdk";
1759
+ *
1760
+ * const generator = getUserAccountX25519KeypairGenerator({ client });
1761
+ * const result: Curve25519KeypairResult = await generator();
1762
+ *
1763
+ * // Use Ed25519 for signing
1764
+ * const signature = ed25519.sign(message, result.ed25519Keypair.seed);
1765
+ *
1766
+ * // Use X25519 for key exchange
1767
+ * const sharedSecret = x25519.getSharedSecret(
1768
+ * result.x25519Keypair.privateKey,
1769
+ * peerPublicKey
1770
+ * );
1771
+ * ```
1772
+ *
1773
+ * @see {@link Ed25519Keypair}
1774
+ * @see {@link X25519Keypair}
1775
+ * @see {@link assertCurve25519KeypairResult}
1776
+ * @public
1777
+ */
1778
+ interface Curve25519KeypairResult {
1779
+ /**
1780
+ * Ed25519 keypair for digital signatures.
1781
+ *
1782
+ * Contains the 32-byte seed and the derived 32-byte compressed Edwards
1783
+ * public key. Used as the on-chain signer for registration transactions.
1784
+ */
1785
+ readonly ed25519Keypair: Ed25519Keypair;
1786
+ /**
1787
+ * X25519 keypair for Diffie-Hellman key exchange.
1788
+ *
1789
+ * Contains the RFC 8032-clamped 32-byte private key (derived from SHA-512
1790
+ * of the Ed25519 seed) and the derived 32-byte Montgomery public key (via
1791
+ * birational conversion from the Ed25519 public key).
1792
+ */
1793
+ readonly x25519Keypair: X25519Keypair;
1794
+ }
1795
+ /**
1796
+ * Asserts that a value is a valid Ed25519Keypair.
1797
+ *
1798
+ * Validates that the value is a non-null object with `seed` (exactly 32 bytes)
1799
+ * and `publicKey` (exactly 32 bytes) properties.
1800
+ *
1801
+ * @param value - The object to assert as an Ed25519Keypair (must have seed and publicKey properties)
1802
+ * @throws {CryptographyAssertionError} If the value is not a non-null object
1803
+ * @throws {CryptographyAssertionError} If `seed` or `publicKey` are missing
1804
+ * @throws {CryptographyAssertionError} If `seed` or `publicKey` are not Uint8Array(32)
1805
+ *
1806
+ * @example
1807
+ * ```typescript
1808
+ * const keypair = { seed, publicKey };
1809
+ * assertEd25519Keypair(keypair);
1810
+ * // keypair is now typed as Ed25519Keypair
1811
+ * ```
1812
+ *
1813
+ * @see {@link Ed25519Keypair}
1814
+ * @public
1815
+ */
1816
+ declare function assertEd25519Keypair(value: {
1817
+ seed: Uint8Array;
1818
+ publicKey: Uint8Array;
1819
+ }): asserts value is Ed25519Keypair;
1820
+ /**
1821
+ * Asserts that a value is a valid Curve25519KeypairResult.
1822
+ *
1823
+ * Validates that the value is a non-null object with valid `ed25519Keypair`
1824
+ * and `x25519Keypair` fields, each of which must pass their respective assertions.
1825
+ *
1826
+ * @param value - The object to assert as a Curve25519KeypairResult
1827
+ * @throws {CryptographyAssertionError} If the value is not a non-null object
1828
+ * @throws {CryptographyAssertionError} If either nested keypair is missing or invalid
1829
+ *
1830
+ * @example
1831
+ * ```typescript
1832
+ * const result = { ed25519Keypair, x25519Keypair };
1833
+ * assertCurve25519KeypairResult(result);
1834
+ * // result is now typed as Curve25519KeypairResult
1835
+ * ```
1836
+ *
1837
+ * @see {@link Curve25519KeypairResult}
1838
+ * @see {@link assertEd25519Keypair}
1839
+ * @see {@link assertX25519Keypair}
1840
+ * @public
1841
+ */
1842
+ declare function assertCurve25519KeypairResult(value: {
1843
+ ed25519Keypair: {
1844
+ seed: Uint8Array;
1845
+ publicKey: Uint8Array;
1846
+ };
1847
+ x25519Keypair: {
1848
+ privateKey: Uint8Array;
1849
+ publicKey: Uint8Array;
1850
+ };
1851
+ }): asserts value is Curve25519KeypairResult;
1852
+
1853
+ export { BrandedType, Bytes, type Curve25519KeypairResult, type Ed25519Keypair, type EncryptedUserAccount, type FullySignedTransaction, type GeneratorFunction, type KeyStorageContext, type LoadResult, type LoaderFunction, MasterSeed, type MasterSeedGeneratorFunction, type MasterSeedLoaderFunction, type MasterSeedStorerFunction, type ParameterizedGeneratorFunction, type ParameterizedLoaderFunction, type ParameterizedStorerFunction, type PartiallySignedTransaction, PoseidonHash, type QueryComplianceGrantResult, type QueryUserAccountResult, SIGNATURE_BYTE_LENGTH, type SignatureBytes, type SignedTransaction, SolanaAssertionError, type SolanaBytes, type StoreResult, type StorerFunction, type String, SubBrandedType, SubSubBrandedType, type TransactionSignature, U128, U256LeBytes, U512, U8, type UnsignedTransaction, X25519PublicKey$1 as X25519PublicKey, asRelayableSignedTransaction, assertCurve25519KeypairResult, assertEd25519Keypair, assertSignatureBytes, assertSolanaBytes, assertString, assertTransactionSignature };