@circle-fin/app-kit 1.13.0 → 1.15.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 (53) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/README.md +3 -3
  3. package/bridge.cjs +8388 -515
  4. package/bridge.d.cts +640 -61
  5. package/bridge.d.mts +640 -61
  6. package/bridge.d.ts +640 -61
  7. package/bridge.mjs +8389 -516
  8. package/chains.cjs +275 -15
  9. package/chains.d.cts +117 -2
  10. package/chains.d.mts +117 -2
  11. package/chains.d.ts +117 -2
  12. package/chains.mjs +275 -16
  13. package/context.d.cts +577 -57
  14. package/context.d.mts +577 -57
  15. package/context.d.ts +577 -57
  16. package/earn.cjs +973 -271
  17. package/earn.d.cts +577 -57
  18. package/earn.d.mts +577 -57
  19. package/earn.d.ts +577 -57
  20. package/earn.mjs +919 -221
  21. package/estimateBridge.cjs +8388 -518
  22. package/estimateBridge.d.cts +704 -82
  23. package/estimateBridge.d.mts +704 -82
  24. package/estimateBridge.d.ts +704 -82
  25. package/estimateBridge.mjs +8390 -520
  26. package/estimateSwap.cjs +982 -237
  27. package/estimateSwap.d.cts +577 -57
  28. package/estimateSwap.d.mts +577 -57
  29. package/estimateSwap.d.ts +577 -57
  30. package/estimateSwap.mjs +981 -237
  31. package/index.cjs +21401 -8522
  32. package/index.d.cts +6045 -2149
  33. package/index.d.mts +6045 -2149
  34. package/index.d.ts +6045 -2149
  35. package/index.mjs +21401 -8524
  36. package/package.json +17 -6
  37. package/server.cjs +10040 -0
  38. package/server.cjs.map +1 -0
  39. package/server.d.cts +2467 -0
  40. package/server.d.mts +2467 -0
  41. package/server.d.ts +2467 -0
  42. package/server.mjs +10028 -0
  43. package/server.mjs.map +1 -0
  44. package/swap.cjs +982 -237
  45. package/swap.d.cts +577 -57
  46. package/swap.d.mts +577 -57
  47. package/swap.d.ts +577 -57
  48. package/swap.mjs +981 -237
  49. package/unifiedBalance.cjs +20510 -7599
  50. package/unifiedBalance.d.cts +807 -201
  51. package/unifiedBalance.d.mts +807 -201
  52. package/unifiedBalance.d.ts +807 -201
  53. package/unifiedBalance.mjs +20513 -7603
package/server.d.ts ADDED
@@ -0,0 +1,2467 @@
1
+ /**
2
+ * Copyright (c) 2026, Circle Internet Group, Inc. All rights reserved.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import { z } from '/home/runner/_work/stablecoin-kits-private/stablecoin-kits-private/node_modules/zod/dist/types/index.d.ts';
20
+
21
+ /**
22
+ * Module augmentation to register known token symbols.
23
+ *
24
+ * @remarks
25
+ * This file augments the `TokenSymbolRegistry` interface to provide
26
+ * type-safe autocomplete for built-in tokens.
27
+ *
28
+ * When imported, TypeScript will recognize 'USDC' as a valid
29
+ * `TokenSymbol` value with autocomplete support.
30
+ *
31
+ * Other packages or applications can create their own augmentations
32
+ * to add additional tokens.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import '@core/tokens' // Automatically includes this augmentation
37
+ *
38
+ * const symbol: TokenSymbol = 'USDC' // ✓ Autocomplete shows USDC
39
+ * ```
40
+ */
41
+ declare module './types' {
42
+ /**
43
+ * Module augmentation: Adds known token symbols as valid keys
44
+ * to the TokenSymbolRegistry interface.
45
+ *
46
+ * Keys are explicitly listed to ensure IDE autocomplete works properly.
47
+ */
48
+ interface TokenSymbolRegistry {
49
+ USDC: true;
50
+ USDT: true;
51
+ EURC: true;
52
+ DAI: true;
53
+ USDE: true;
54
+ PYUSD: true;
55
+ WETH: true;
56
+ WBTC: true;
57
+ WSOL: true;
58
+ WAVAX: true;
59
+ WPOL: true;
60
+ ETH: true;
61
+ POL: true;
62
+ PLUME: true;
63
+ MON: true;
64
+ cirBTC: true;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Enumeration of all blockchains known to this library.
70
+ *
71
+ * This enum contains every blockchain that has a chain definition, regardless
72
+ * of whether bridging is currently supported. For chains that support bridging
73
+ * via CCTPv2, see {@link BridgeChain}.
74
+ *
75
+ * @enum
76
+ * @category Enums
77
+ * @description Provides string identifiers for each blockchain with a definition.
78
+ * @see {@link BridgeChain} for the subset of chains that support CCTPv2 bridging.
79
+ */
80
+ declare enum Blockchain {
81
+ Algorand = "Algorand",
82
+ Algorand_Testnet = "Algorand_Testnet",
83
+ Aptos = "Aptos",
84
+ Aptos_Testnet = "Aptos_Testnet",
85
+ Arbitrum = "Arbitrum",
86
+ Arbitrum_Sepolia = "Arbitrum_Sepolia",
87
+ Arc = "Arc",
88
+ Arc_Testnet = "Arc_Testnet",
89
+ Avalanche = "Avalanche",
90
+ Avalanche_Fuji = "Avalanche_Fuji",
91
+ Base = "Base",
92
+ Base_Sepolia = "Base_Sepolia",
93
+ Celo = "Celo",
94
+ Celo_Alfajores_Testnet = "Celo_Alfajores_Testnet",
95
+ Codex = "Codex",
96
+ Codex_Testnet = "Codex_Testnet",
97
+ Cronos = "Cronos",
98
+ Cronos_Testnet = "Cronos_Testnet",
99
+ Edge = "Edge",
100
+ Edge_Testnet = "Edge_Testnet",
101
+ Ethereum = "Ethereum",
102
+ Ethereum_Sepolia = "Ethereum_Sepolia",
103
+ Hedera = "Hedera",
104
+ Hedera_Testnet = "Hedera_Testnet",
105
+ HyperEVM = "HyperEVM",
106
+ HyperEVM_Testnet = "HyperEVM_Testnet",
107
+ Injective = "Injective",
108
+ Injective_Testnet = "Injective_Testnet",
109
+ Ink = "Ink",
110
+ Ink_Testnet = "Ink_Testnet",
111
+ Linea = "Linea",
112
+ Linea_Sepolia = "Linea_Sepolia",
113
+ Monad = "Monad",
114
+ Monad_Testnet = "Monad_Testnet",
115
+ Morph = "Morph",
116
+ Morph_Testnet = "Morph_Testnet",
117
+ NEAR = "NEAR",
118
+ NEAR_Testnet = "NEAR_Testnet",
119
+ Noble = "Noble",
120
+ Noble_Testnet = "Noble_Testnet",
121
+ Optimism = "Optimism",
122
+ Optimism_Sepolia = "Optimism_Sepolia",
123
+ Pharos = "Pharos",
124
+ Pharos_Testnet = "Pharos_Testnet",
125
+ Plasma = "Plasma",
126
+ Plasma_Testnet = "Plasma_Testnet",
127
+ Polkadot_Asset_Hub = "Polkadot_Asset_Hub",
128
+ Polkadot_Westmint = "Polkadot_Westmint",
129
+ Plume = "Plume",
130
+ Plume_Testnet = "Plume_Testnet",
131
+ Polygon = "Polygon",
132
+ Polygon_Amoy_Testnet = "Polygon_Amoy_Testnet",
133
+ Sei = "Sei",
134
+ Sei_Testnet = "Sei_Testnet",
135
+ Solana = "Solana",
136
+ Solana_Devnet = "Solana_Devnet",
137
+ Sonic = "Sonic",
138
+ Sonic_Testnet = "Sonic_Testnet",
139
+ Stellar = "Stellar",
140
+ Stellar_Testnet = "Stellar_Testnet",
141
+ Sui = "Sui",
142
+ Sui_Testnet = "Sui_Testnet",
143
+ Unichain = "Unichain",
144
+ Unichain_Sepolia = "Unichain_Sepolia",
145
+ World_Chain = "World_Chain",
146
+ World_Chain_Sepolia = "World_Chain_Sepolia",
147
+ XDC = "XDC",
148
+ XDC_Apothem = "XDC_Apothem",
149
+ X_Layer = "X_Layer",
150
+ X_Layer_Testnet = "X_Layer_Testnet",
151
+ ZKSync_Era = "ZKSync_Era",
152
+ ZKSync_Sepolia = "ZKSync_Sepolia"
153
+ }
154
+
155
+ /**
156
+ * Module augmentation to register Blockchain enum values as ChainIdentifiers.
157
+ *
158
+ * @remarks
159
+ * This file augments the `ChainRegistry` interface to provide type-safe
160
+ * autocomplete for all `Blockchain` enum values from `@core/chains`.
161
+ *
162
+ * When this augmentation is imported (via `@core/tokens`), TypeScript will
163
+ * recognize all blockchain identifiers as valid `ChainIdentifier` values
164
+ * with IDE autocomplete support.
165
+ *
166
+ * The `Blockchain` enum values are converted to their string representations,
167
+ * enabling both enum values and string literals to be accepted as chain identifiers.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * import { Blockchain } from '@core/chains'
172
+ * import type { ChainIdentifier } from '@core/tokens'
173
+ *
174
+ * // Using enum value
175
+ * const chain1: ChainIdentifier = Blockchain.Ethereum
176
+ *
177
+ * // Using string literal (with autocomplete!)
178
+ * const chain2: ChainIdentifier = 'Base'
179
+ *
180
+ * // Arbitrary strings also work (escape hatch for custom chains)
181
+ * const chain3: ChainIdentifier = 'my-custom-chain'
182
+ * ```
183
+ */
184
+
185
+ declare module './types' {
186
+ /**
187
+ * Module augmentation: Adds all Blockchain enum values as valid keys
188
+ * to the ChainRegistry interface for type-safe chain identifier support.
189
+ *
190
+ * This ensures both enum property access (e.g., Blockchain.Ethereum) and plain
191
+ * string literals (e.g., 'Ethereum') are accepted by TypeScript as chain keys,
192
+ * providing robust autocomplete and error checking.
193
+ *
194
+ * NOTE:
195
+ * - This interface intentionally has no body. It merges a mapped Record type
196
+ * into ChainRegistry solely for type augmentation.
197
+ * - This empty-body construct is a necessary TypeScript idiom for module
198
+ * augmentation with Record types—directly listing mapped keys is not
199
+ * feasible in interface extensions.
200
+ *
201
+ * eslint-disable-next-line directives below suppress linter complaints about
202
+ * the empty interface/mapping, which are benign and required for this pattern.
203
+ */
204
+ interface ChainRegistry extends Record<`${Blockchain}`, true> {
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Creates a union type that preserves IDE autocomplete for known literals
210
+ * while still accepting any string at runtime.
211
+ *
212
+ * @remarks
213
+ * This pattern uses `Record<never, never>` (an empty record type) to prevent
214
+ * TypeScript from widening string literals to just `string`. This gives us
215
+ * the best of both worlds: autocomplete for known values and flexibility
216
+ * for arbitrary strings.
217
+ *
218
+ * @typeParam T - The known string literal union to preserve.
219
+ */
220
+ type LiteralUnion<T extends string> = T | (string & Record<never, never>);
221
+ /**
222
+ * Registry for known chain identifiers (augmentation target).
223
+ *
224
+ * @remarks
225
+ * This empty interface exists solely for module augmentation. Extend it to
226
+ * register chain identifiers for type-safe token definitions.
227
+ *
228
+ * **Why an interface?** TypeScript only allows module augmentation on
229
+ * interfaces, not type aliases.
230
+ *
231
+ * **Note:** This is NOT the EVM "chain ID" (numeric like 1 for Ethereum).
232
+ * It's a human-readable identifier like "Ethereum", "Solana", "Base".
233
+ *
234
+ * **Usage**
235
+ *
236
+ * Without augmentation, `ChainIdentifier` defaults to `string`.
237
+ * With `@core/chains` imported, you get autocomplete for all `Blockchain` values.
238
+ *
239
+ * **Custom Chains**
240
+ *
241
+ * ```typescript
242
+ * declare module '@core/tokens' {
243
+ * interface ChainRegistry {
244
+ * MyChain: true
245
+ * MyTestnet: true
246
+ * }
247
+ * }
248
+ * // Now ChainIdentifier includes 'MyChain' | 'MyTestnet' | ...
249
+ * ```
250
+ *
251
+ * The value (`true`) is a placeholder—only the keys matter.
252
+ *
253
+ * NOTE: The eslint-disable below suppresses warnings about empty interfaces.
254
+ * This is intentional—the interface exists solely as an augmentation target.
255
+ */
256
+ interface ChainRegistry {
257
+ }
258
+ /**
259
+ * Union of all registered chain identifiers.
260
+ *
261
+ * @remarks
262
+ * Derived from `ChainRegistry` keys:
263
+ * - Without augmentation: `string`
264
+ * - With `@core/chains`: `'Ethereum' | 'Solana' | ...` plus any string
265
+ *
266
+ * Uses `LiteralUnion` to preserve IDE autocomplete while allowing
267
+ * arbitrary strings at runtime.
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * const chain: ChainIdentifier = 'Ethereum' // Autocomplete works
272
+ * const custom: ChainIdentifier = 'my-chain' // Also valid
273
+ * ```
274
+ */
275
+ type ChainIdentifier = keyof ChainRegistry extends never ? string : LiteralUnion<Extract<keyof ChainRegistry, string>>;
276
+ /**
277
+ * Maps chain identifiers to their token locators.
278
+ *
279
+ * @remarks
280
+ * The key is a chain identifier (type-safe when `KnownChainIdentifiers` is
281
+ * augmented). This enables a single token definition to work across chains.
282
+ *
283
+ * When `@core/chains` is imported, you get autocomplete for known chains
284
+ * like `Ethereum`, `Base`, `Solana`, etc.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * import { Blockchain } from '@core/chains'
289
+ *
290
+ * const usdcLocators: ChainLocatorMap = {
291
+ * [Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
292
+ * [Blockchain.Solana]: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
293
+ * [Blockchain.Base]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
294
+ * }
295
+ *
296
+ * // Or with string keys (always works)
297
+ * const locators: ChainLocatorMap = {
298
+ * 'ethereum': '0xa0b86991...',
299
+ * 'my-custom-chain': '0x1234...',
300
+ * }
301
+ * ```
302
+ */
303
+ type ChainLocatorMap = Record<ChainIdentifier, string>;
304
+ /**
305
+ * Complete definition of a token including metadata and chain locators.
306
+ *
307
+ * @remarks
308
+ * This is the canonical representation of a token in the registry.
309
+ * It includes the symbol, decimals, and chain-specific locators.
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * const usdc: TokenDefinition = {
314
+ * symbol: 'USDC',
315
+ * decimals: 6,
316
+ * locators: {
317
+ * [Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
318
+ * [Blockchain.Solana]: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
319
+ * },
320
+ * }
321
+ * ```
322
+ */
323
+ interface TokenDefinition {
324
+ /**
325
+ * The token symbol (e.g., "USDC", "EURC").
326
+ */
327
+ readonly symbol: string;
328
+ /**
329
+ * The default number of decimal places for the token.
330
+ * Used when no chain-specific override exists in {@link chainDecimals}.
331
+ * @example 6 for USDC, 18 for most ERC20 tokens
332
+ */
333
+ readonly decimals: number;
334
+ /**
335
+ * Chain-specific locators for the token.
336
+ * Keys are chain identifiers, values are the token address/locator on that chain.
337
+ * Not all chains need to be present - tokens may only exist on a subset of chains.
338
+ */
339
+ readonly locators: Partial<ChainLocatorMap>;
340
+ /**
341
+ * Optional per-chain decimal overrides.
342
+ *
343
+ * Some tokens have different decimal places on different chains
344
+ * (e.g., USDe is 18 decimals on EVM but 9 decimals on Solana).
345
+ * When present, the value for a specific chain takes precedence
346
+ * over the default {@link decimals}.
347
+ */
348
+ readonly chainDecimals?: Partial<Record<ChainIdentifier, number>>;
349
+ }
350
+ /**
351
+ * A raw token locator selector with explicit decimals.
352
+ *
353
+ * @remarks
354
+ * Use this form when working with arbitrary tokens not in the registry.
355
+ * The `locator` is the chain-specific address, and `decimals` is required
356
+ * unless using lenient mode.
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * // Selecting a custom token by address
361
+ * const selector: RawTokenSelector = {
362
+ * locator: '0x1234567890abcdef1234567890abcdef12345678',
363
+ * decimals: 18,
364
+ * }
365
+ * ```
366
+ */
367
+ interface RawTokenSelector {
368
+ /**
369
+ * The chain-specific token locator (address, program ID, etc.).
370
+ */
371
+ readonly locator: string;
372
+ /**
373
+ * The number of decimal places.
374
+ * Required in strict mode, optional in lenient mode.
375
+ */
376
+ readonly decimals?: number;
377
+ }
378
+ /**
379
+ * Registry for known token symbols (augmentation target).
380
+ *
381
+ * @remarks
382
+ * This empty interface exists solely for module augmentation. Extend it to
383
+ * register token symbols for type-safe selection.
384
+ *
385
+ * **Why an interface?** TypeScript only allows module augmentation on
386
+ * interfaces, not type aliases.
387
+ *
388
+ * **Usage**
389
+ *
390
+ * Without augmentation, `TokenSymbol` defaults to `string`.
391
+ *
392
+ * ```typescript
393
+ * declare module '@core/tokens' {
394
+ * interface TokenSymbolRegistry {
395
+ * USDC: true
396
+ * EURC: true
397
+ * }
398
+ * }
399
+ * // Now TokenSymbol includes 'USDC' | 'EURC' | ...
400
+ * ```
401
+ *
402
+ * NOTE: The eslint-disable below suppresses warnings about empty interfaces.
403
+ * This is intentional—the interface exists solely as an augmentation target.
404
+ */
405
+ interface TokenSymbolRegistry {
406
+ }
407
+ /**
408
+ * Union type of all registered token symbols.
409
+ *
410
+ * @remarks
411
+ * This type is derived from the keys of `TokenSymbolRegistry`:
412
+ * - **Without augmentation** — Simply `string` (any value)
413
+ * - **With augmentation** — `'USDC' | 'USDT' | ...` plus any string
414
+ *
415
+ * Uses `LiteralUnion` to preserve autocomplete for known values while
416
+ * still accepting any string at runtime.
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * // With symbols.augment imported - autocomplete works
421
+ * const symbol: TokenSymbol = 'USDC'
422
+ *
423
+ * // Custom strings still accepted
424
+ * const symbol: TokenSymbol = 'MY_TOKEN'
425
+ * ```
426
+ */
427
+ type TokenSymbol = keyof TokenSymbolRegistry extends never ? string : LiteralUnion<Extract<keyof TokenSymbolRegistry, string>>;
428
+ /**
429
+ * Token selector accepted by adapters and the static
430
+ * {@link TokenRegistry.resolve} method.
431
+ *
432
+ * @remarks
433
+ * Keep this alias at adapter and registry boundaries so their accepted token
434
+ * forms remain explicit even when other product surfaces define narrower
435
+ * token inputs.
436
+ */
437
+ type RegistryTokenSelector = TokenSymbol | RawTokenSelector;
438
+ /**
439
+ * The resolved token information after registry lookup.
440
+ *
441
+ * @remarks
442
+ * This is the result of resolving a `TokenSelector` against a chain.
443
+ * It always contains the locator and decimals, and optionally the symbol
444
+ * if the token was resolved from the registry.
445
+ */
446
+ interface ResolvedToken {
447
+ /**
448
+ * The token symbol, if known.
449
+ * Present when resolved from registry, absent for raw locators.
450
+ */
451
+ readonly symbol?: string;
452
+ /**
453
+ * The number of decimal places for the token.
454
+ */
455
+ readonly decimals: number;
456
+ /**
457
+ * The chain-specific token locator (address, program ID, etc.).
458
+ */
459
+ readonly locator: string;
460
+ }
461
+ /**
462
+ * Interface for the token registry.
463
+ *
464
+ * @remarks
465
+ * The registry is the sole source of truth for token information.
466
+ * It supports both symbol-based and raw locator-based token selection.
467
+ *
468
+ * @example
469
+ * ```typescript
470
+ * import { createTokenRegistry } from '@core/tokens'
471
+ *
472
+ * // Create registry (includes built-in tokens like USDC)
473
+ * const registry = createTokenRegistry()
474
+ *
475
+ * // Resolve by symbol
476
+ * const usdc = registry.resolve('USDC', 'Ethereum')
477
+ * console.log(usdc.locator) // '0xa0b86991...'
478
+ *
479
+ * // Resolve raw locator
480
+ * const custom = registry.resolve({ locator: '0x...', decimals: 18 }, 'Ethereum')
481
+ * ```
482
+ */
483
+ interface TokenRegistry {
484
+ /**
485
+ * Resolve a token selector to concrete token information for a chain.
486
+ *
487
+ * @param selector - The token to resolve. Accepts a symbol or raw locator.
488
+ * @param chainId - The chain identifier to resolve for.
489
+ * @returns The resolved token information.
490
+ * @throws When the token cannot be resolved (unknown symbol, missing decimals, etc.).
491
+ */
492
+ resolve(selector: RegistryTokenSelector, chainId: ChainIdentifier): ResolvedToken;
493
+ /**
494
+ * Resolve a token by chain-specific locator (address/program ID).
495
+ *
496
+ * @param address - The token locator to resolve.
497
+ * @param chainId - The chain identifier to resolve for.
498
+ * @returns The resolved token information.
499
+ * @throws When no registry token matches the locator on the chain.
500
+ */
501
+ resolveByAddress(address: string, chainId: ChainIdentifier): ResolvedToken;
502
+ /**
503
+ * Get a token definition by symbol.
504
+ *
505
+ * @param symbol - The token symbol (e.g., "USDC").
506
+ * @returns The token definition, or undefined if not found.
507
+ */
508
+ get(symbol: string): TokenDefinition | undefined;
509
+ /**
510
+ * Check if a symbol is registered.
511
+ *
512
+ * @param symbol - The token symbol to check.
513
+ * @returns True if the symbol is in the registry.
514
+ */
515
+ has(symbol: string): boolean;
516
+ /**
517
+ * Get all registered token symbols.
518
+ *
519
+ * @returns An array of registered symbol strings.
520
+ */
521
+ symbols(): string[];
522
+ /**
523
+ * Get all registered token definitions.
524
+ *
525
+ * @returns An array of all TokenDefinition objects in the registry.
526
+ */
527
+ entries(): TokenDefinition[];
528
+ }
529
+
530
+ /**
531
+ * Valid recoverability values for error handling strategies.
532
+ *
533
+ * - FATAL errors are thrown immediately (invalid inputs, insufficient funds)
534
+ * - RETRYABLE errors are returned when a flow fails to start but could work later
535
+ * - RESUMABLE errors are returned when a flow fails mid-execution but can be continued
536
+ */
537
+ declare const RECOVERABILITY_VALUES: readonly ["RETRYABLE", "RESUMABLE", "FATAL"];
538
+ /**
539
+ * Error handling strategy for different types of failures.
540
+ *
541
+ * - FATAL errors are thrown immediately (invalid inputs, insufficient funds)
542
+ * - RETRYABLE errors are returned when a flow fails to start but could work later
543
+ * - RESUMABLE errors are returned when a flow fails mid-execution but can be continued
544
+ */
545
+ type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
546
+ /**
547
+ * Array of valid error type values for validation.
548
+ * Derived from ERROR_TYPES const object.
549
+ */
550
+ declare const ERROR_TYPE_VALUES: ("INPUT" | "BALANCE" | "ONCHAIN" | "RPC" | "NETWORK" | "RATE_LIMIT" | "SERVICE" | "LIQUIDITY" | "UNKNOWN")[];
551
+ /**
552
+ * Error type indicating the category of the error.
553
+ */
554
+ type ErrorType = (typeof ERROR_TYPE_VALUES)[number];
555
+ /**
556
+ * Structured error details with consistent properties for programmatic handling.
557
+ *
558
+ * This interface provides a standardized format for all errors in the
559
+ * App Kits system, enabling developers to handle different error
560
+ * types consistently and provide appropriate user feedback.
561
+ *
562
+ * @example
563
+ * ```typescript
564
+ * const error: ErrorDetails = {
565
+ * code: 1001,
566
+ * name: "INPUT_NETWORK_MISMATCH",
567
+ * type: "INPUT",
568
+ * recoverability: "FATAL",
569
+ * message: "Source and destination networks must be different",
570
+ * cause: {
571
+ * trace: { sourceChain: "ethereum", destChain: "ethereum" }
572
+ * }
573
+ * }
574
+ * ```
575
+ *
576
+ * @example
577
+ * ```typescript
578
+ * const error: ErrorDetails = {
579
+ * code: 9001,
580
+ * name: "BALANCE_INSUFFICIENT_TOKEN",
581
+ * type: "BALANCE",
582
+ * recoverability: "FATAL",
583
+ * message: "Insufficient USDC balance on Ethereum",
584
+ * cause: {
585
+ * trace: { token: "USDC", chain: "Ethereum" }
586
+ * }
587
+ * }
588
+ * ```
589
+ */
590
+ interface ErrorDetails {
591
+ /** Numeric identifier following standardized ranges (see error code registry) */
592
+ code: number;
593
+ /** Human-readable ID (e.g., "INPUT_NETWORK_MISMATCH", "BALANCE_INSUFFICIENT_TOKEN") */
594
+ name: string;
595
+ /** Error category indicating where the error originated */
596
+ type: ErrorType;
597
+ /** Error handling strategy */
598
+ recoverability: Recoverability;
599
+ /** User-friendly explanation with context */
600
+ message: string;
601
+ /** Raw error details, context, or the original error that caused this one. */
602
+ cause?: {
603
+ /**
604
+ * Free-form error payload from the underlying system.
605
+ *
606
+ * The shape is **not uniform across error codes**: most codes set `trace`
607
+ * to the raw underlying error, while a few set a structured wrapper object
608
+ * `{ rawError, ...extras }` (e.g. `INPUT_AMOUNT_OUT_OF_RANGE` and
609
+ * `LIQUIDITY_INSUFFICIENT` add `minAmount` / `maxAmount` / `token`).
610
+ * Consumers must branch on `error.code` before reading structured fields off
611
+ * `trace`, and should treat the raw error as the fallback for all other codes.
612
+ */
613
+ trace?: unknown;
614
+ };
615
+ }
616
+ /**
617
+ * Simplified error information structure for logging and events.
618
+ *
619
+ * @remarks
620
+ * This lightweight type is used for error reporting in events, logs, and
621
+ * observability systems. It provides essential error context without the
622
+ * full ErrorDetails structure. Used across retry mechanisms, adapters,
623
+ * and other subsystems that need to record error information.
624
+ *
625
+ * @example
626
+ * ```typescript
627
+ * import { ErrorInfo } from '@core/errors'
628
+ *
629
+ * const info: ErrorInfo = {
630
+ * name: 'NETWORK_TIMEOUT',
631
+ * message: 'Request timed out after 5000ms',
632
+ * code: 3002
633
+ * }
634
+ * ```
635
+ */
636
+ interface ErrorInfo {
637
+ /** Error name (e.g., 'TypeError', 'KitError', 'NETWORK_TIMEOUT'). */
638
+ name: string;
639
+ /** Error message describing what went wrong. */
640
+ message: string;
641
+ /** Optional error code if the error has one (e.g., KitError codes). */
642
+ code?: number;
643
+ /** Error category (e.g., INPUT, RPC, ONCHAIN, BALANCE, NETWORK, UNKNOWN). Only set for KitError instances. */
644
+ type?: string;
645
+ }
646
+
647
+ declare class KitError extends Error implements ErrorDetails {
648
+ /** Numeric identifier following standardized ranges (1000+ for INPUT errors) */
649
+ readonly code: number;
650
+ /** Human-readable ID (e.g., "NETWORK_MISMATCH") */
651
+ readonly name: string;
652
+ /** Error category indicating where the error originated */
653
+ readonly type: ErrorType;
654
+ /** Error handling strategy */
655
+ readonly recoverability: Recoverability;
656
+ /** Raw error details, context, or the original error that caused this one. */
657
+ readonly cause?: {
658
+ /** Free-form error payload from underlying system */
659
+ trace?: unknown;
660
+ };
661
+ /**
662
+ * Create a new KitError instance.
663
+ *
664
+ * @param details - The error details object containing all required properties.
665
+ * @throws \{TypeError\} When details parameter is missing or invalid.
666
+ */
667
+ constructor(details: ErrorDetails);
668
+ }
669
+
670
+ /**
671
+ * Structured fields that can be attached to log entries.
672
+ */
673
+ type LogFields = Record<string, unknown>;
674
+ /**
675
+ * Logger interface providing structured logging with child scoping.
676
+ *
677
+ * @remarks
678
+ * This interface defines a minimal, framework-agnostic logging contract.
679
+ * The underlying implementation uses pino for transport handling (console,
680
+ * file, remote, JSON, pretty, etc.) but consumers only interact with this
681
+ * stable interface.
682
+ *
683
+ * @example
684
+ * ```typescript
685
+ * import { createLogger } from '@core/runtime'
686
+ *
687
+ * const logger = createLogger({ level: 'debug' })
688
+ *
689
+ * // Simple message
690
+ * logger.info('Server started')
691
+ *
692
+ * // Message with structured fields
693
+ * logger.info('Request received', { method: 'POST', path: '/api/transfer' })
694
+ *
695
+ * // Create child logger with context
696
+ * const requestLogger = logger.child({ requestId: 'abc-123' })
697
+ * requestLogger.debug('Processing transfer')
698
+ * // Output includes: requestId in all subsequent logs
699
+ * ```
700
+ */
701
+ interface Logger {
702
+ /**
703
+ * Log a debug-level message.
704
+ * @param message - The log message.
705
+ * @param fields - Optional structured fields.
706
+ * @returns void
707
+ */
708
+ debug(message: string, fields?: LogFields): void;
709
+ /**
710
+ * Log an info-level message.
711
+ * @param message - The log message.
712
+ * @param fields - Optional structured fields.
713
+ * @returns void
714
+ */
715
+ info(message: string, fields?: LogFields): void;
716
+ /**
717
+ * Log a warning-level message.
718
+ * @param message - The log message.
719
+ * @param fields - Optional structured fields.
720
+ * @returns void
721
+ */
722
+ warn(message: string, fields?: LogFields): void;
723
+ /**
724
+ * Log an error-level message.
725
+ * @param message - The log message.
726
+ * @param fields - Optional structured fields.
727
+ * @returns void
728
+ */
729
+ error(message: string, fields?: LogFields): void;
730
+ /**
731
+ * Create a child logger with additional contextual bindings.
732
+ *
733
+ * @param tags - Key-value pairs to add to the child logger's context.
734
+ * Undefined values are filtered out automatically.
735
+ * @returns A new Logger instance with merged bindings.
736
+ *
737
+ * @example
738
+ * ```typescript
739
+ * const requestLogger = logger.child({ requestId: 'req-123' })
740
+ * const userLogger = requestLogger.child({ userId: 'user-456' })
741
+ * // All logs from userLogger include both requestId and userId
742
+ * ```
743
+ */
744
+ child(tags: LogFields): Logger;
745
+ }
746
+
747
+ /**
748
+ * Handler function for event subscriptions.
749
+ */
750
+ type EventHandler = (event: Event) => void | Promise<void>;
751
+ /**
752
+ * Event bus for publishing and subscribing to events.
753
+ *
754
+ * @remarks
755
+ * Supports wildcard topic subscriptions:
756
+ * - `*` matches exactly one segment
757
+ * - `**` matches zero or more segments
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * const bus = createEventBus()
762
+ *
763
+ * // Subscribe to all events
764
+ * bus.on((event) => console.log(event))
765
+ *
766
+ * // Subscribe to specific topic
767
+ * bus.on('tx.wait.started', (event) => console.log(event))
768
+ *
769
+ * // Subscribe with wildcard
770
+ * bus.on('tx.wait.*', (event) => console.log(event))
771
+ * bus.on('tx.**', (event) => console.log(event))
772
+ *
773
+ * // Emit events
774
+ * bus.emit({ name: 'tx.wait.started', data: { txId: '0x123' } })
775
+ * ```
776
+ */
777
+ interface EventBus {
778
+ /**
779
+ * Emit an event to all matching subscribers.
780
+ *
781
+ * @param event - The event to emit.
782
+ * @remarks
783
+ * Synchronous and never throws. Handler errors are isolated.
784
+ */
785
+ emit(event: Event): void;
786
+ /**
787
+ * Create a child event bus with scoped tags.
788
+ *
789
+ * @param tags - Tags to merge into all emitted events.
790
+ * @returns A new EventBus with merged tags.
791
+ */
792
+ child(tags: Tags): EventBus;
793
+ /**
794
+ * Subscribe to all events.
795
+ *
796
+ * @param handler - Function called for every event.
797
+ * @returns Unsubscribe function.
798
+ */
799
+ on(handler: EventHandler): () => void;
800
+ /**
801
+ * Subscribe to events matching a pattern.
802
+ *
803
+ * @param pattern - Topic pattern (supports `*` and `**` wildcards).
804
+ * @param handler - Function called for matching events.
805
+ * @returns Unsubscribe function.
806
+ *
807
+ * @remarks
808
+ * Wildcard semantics:
809
+ * - `*` matches exactly one segment (no dots)
810
+ * - `**` matches zero or more segments (only valid at end)
811
+ *
812
+ * @example
813
+ * ```typescript
814
+ * bus.on('*', handler) // matches 'tx', 'user' (single segment only)
815
+ * bus.on('tx.wait.*', handler) // matches tx.wait.started, tx.wait.failed
816
+ * bus.on('tx.wait.**', handler) // matches tx.wait, tx.wait.started, tx.wait.foo.bar
817
+ * bus.on('**', handler) // matches all events
818
+ * ```
819
+ */
820
+ on(pattern: string, handler: EventHandler): () => void;
821
+ }
822
+
823
+ /**
824
+ * Lifecycle event types and constants for pipeline phase tracking.
825
+ *
826
+ * @packageDocumentation
827
+ */
828
+
829
+ /**
830
+ * Terminal state of a lifecycle phase.
831
+ *
832
+ * @remarks
833
+ * Exported as a discriminated union so typed consumers of the event
834
+ * stream (agents, dashboards, test assertions) can exhaustively switch
835
+ * on phase outcomes instead of string-comparing event names.
836
+ *
837
+ * @remarks
838
+ * Carried on every lifecycle event's `data.status` (see
839
+ * {@link LifecycleEventData}) so consumers can switch on the outcome
840
+ * without re-deriving it from the event name.
841
+ *
842
+ * @example
843
+ * ```typescript
844
+ * import type { LifecycleEventData } from '@core/runtime'
845
+ *
846
+ * function handle(data: LifecycleEventData) {
847
+ * switch (data.status) {
848
+ * case 'started': return // ...
849
+ * case 'succeeded': return // ...
850
+ * case 'failed': return // ...
851
+ * }
852
+ * }
853
+ * ```
854
+ */
855
+ type OperationPhaseStatus = 'started' | 'succeeded' | 'failed';
856
+ /**
857
+ * Data payload for lifecycle events.
858
+ *
859
+ * @remarks
860
+ * These events are emitted by pipeline middleware to track phase execution.
861
+ * Field availability by event:
862
+ * - `op.phase.started`: `status`, `meta`, `inputSummary`
863
+ * - `op.phase.succeeded`: `status`, `meta`, `inputSummary`, `durationMs`
864
+ * - `op.phase.failed`: `status`, `meta`, `inputSummary`, `durationMs`, `error`
865
+ */
866
+ interface LifecycleEventData {
867
+ /**
868
+ * Terminal status of the phase, mirroring the {@link OperationPhaseStatus}
869
+ * discriminant carried by the event name. Present on every lifecycle
870
+ * event so typed consumers can `switch (data.status)` without parsing
871
+ * the event name.
872
+ */
873
+ status: OperationPhaseStatus;
874
+ /** Metadata from the pipeline context. */
875
+ meta?: Record<string, unknown> | undefined;
876
+ /** Shallow summary of input (type + keys) to avoid PII exposure. */
877
+ inputSummary?: {
878
+ type: string;
879
+ keys?: string[];
880
+ } | undefined;
881
+ /** Duration of the phase in milliseconds (only for succeeded/failed). */
882
+ durationMs?: number;
883
+ /** Error information (only for failed events). */
884
+ error?: ErrorInfo | undefined;
885
+ }
886
+
887
+ /**
888
+ * Augmentable event type registry for the App Kits ecosystem.
889
+ *
890
+ * @remarks
891
+ * This module provides a type-safe event system using TypeScript's
892
+ * module augmentation pattern. Packages can extend `KitEventMap`
893
+ * to register their own event types.
894
+ *
895
+ * **How to Augment:**
896
+ *
897
+ * Other packages can add their own event types by augmenting the
898
+ * `KitEventMap` interface:
899
+ *
900
+ * ```typescript
901
+ * // In your package's types file (e.g., my-package/src/types.ts)
902
+ * declare module '@core/runtime' {
903
+ * interface KitEventMap {
904
+ * 'tx.wait.started': { txId: string }
905
+ * 'tx.wait.completed': { txId: string; confirmations: number }
906
+ * 'tx.wait.failed': { txId: string; error: string }
907
+ * }
908
+ * }
909
+ * ```
910
+ *
911
+ * After augmentation, the event system will be fully typed:
912
+ *
913
+ * ```typescript
914
+ * // Type-safe event emission
915
+ * emit('tx.wait.started', { txId: '0x123' }) // ✓ OK
916
+ * emit('tx.wait.started', { wrong: 'field' }) // ✗ Type error
917
+ * emit('unknown.event', {}) // ✗ Type error (if strict)
918
+ * ```
919
+ *
920
+ * @example
921
+ * ```typescript
922
+ * // bridge-kit/src/events.ts
923
+ * declare module '@core/runtime' {
924
+ * interface KitEventMap {
925
+ * 'bridge.transfer.initiated': {
926
+ * sourceChain: string
927
+ * destChain: string
928
+ * amount: string
929
+ * }
930
+ * 'bridge.transfer.completed': {
931
+ * txHash: string
932
+ * duration: number
933
+ * }
934
+ * }
935
+ * }
936
+ * ```
937
+ */
938
+ /**
939
+ * The core event map interface for module augmentation.
940
+ *
941
+ * @remarks
942
+ * This interface pre-registers the lifecycle events that are always
943
+ * emitted by the pipeline middleware. Packages can extend it via
944
+ * TypeScript's declaration merging to register additional event types.
945
+ *
946
+ * **Pre-registered events:**
947
+ * - `op.phase.started` - Emitted when a pipeline phase begins
948
+ * - `op.phase.succeeded` - Emitted when a pipeline phase completes successfully
949
+ * - `op.phase.failed` - Emitted when a pipeline phase throws an error
950
+ *
951
+ * @example
952
+ * ```typescript
953
+ * // Add your own events via module augmentation
954
+ * declare module '@core/runtime' {
955
+ * interface KitEventMap {
956
+ * 'my.custom.event': { payload: string }
957
+ * }
958
+ * }
959
+ * ```
960
+ */
961
+ interface KitEventMap {
962
+ 'op.phase.started': LifecycleEventData;
963
+ 'op.phase.succeeded': LifecycleEventData;
964
+ 'op.phase.failed': LifecycleEventData;
965
+ }
966
+ /**
967
+ * Generic event map type for event-related constraints.
968
+ *
969
+ * @remarks
970
+ * Use this when you need to accept any event map without requiring
971
+ * the specific `KitEventMap` augmentations.
972
+ *
973
+ * Uses `any` to accept both interface and type declarations.
974
+ * `unknown` would reject interfaces without index signatures.
975
+ */
976
+ type EventMap = Record<string, any>;
977
+
978
+ /**
979
+ * Type-level event pattern matching utilities.
980
+ *
981
+ * @remarks
982
+ * These types provide compile-time pattern matching for event keys,
983
+ * mirroring the runtime matcher semantics:
984
+ * - Delimiter: `.`
985
+ * - `*` matches exactly one segment
986
+ * - `**` matches zero or more segments (only valid as last segment)
987
+ * - Exact matching otherwise
988
+ * - Invalid patterns (empty segments, `**` not last) yield `never`
989
+ *
990
+ * See `matching.test-d.ts` for type-level tests.
991
+ */
992
+
993
+ /**
994
+ * Extract string keys from an event map.
995
+ *
996
+ * @typeParam M - The event map type.
997
+ * @returns Union of string keys from the map.
998
+ */
999
+ type Keys<M extends EventMap> = Extract<keyof M, string>;
1000
+ /**
1001
+ * Filter keys that match a pattern.
1002
+ *
1003
+ * @typeParam K - Union of string keys to filter.
1004
+ * @typeParam P - Pattern to match against.
1005
+ * @returns Union of keys that match the pattern, or `never` if pattern is invalid.
1006
+ *
1007
+ * @example
1008
+ * ```typescript
1009
+ * type Events = {
1010
+ * 'tx.wait.started': { txId: string }
1011
+ * 'tx.wait.failed': { error: string }
1012
+ * 'tx.send.completed': { hash: string }
1013
+ * }
1014
+ *
1015
+ * // Match single segment wildcard
1016
+ * type WaitEvents = MatchKeys<keyof Events, 'tx.wait.*'>
1017
+ * // = 'tx.wait.started' | 'tx.wait.failed'
1018
+ *
1019
+ * // Match multi-segment wildcard
1020
+ * type AllTxEvents = MatchKeys<keyof Events, 'tx.**'>
1021
+ * // = 'tx.wait.started' | 'tx.wait.failed' | 'tx.send.completed'
1022
+ *
1023
+ * // Match all events
1024
+ * type All = MatchKeys<keyof Events, '**'>
1025
+ * // = keyof Events
1026
+ * ```
1027
+ */
1028
+ type MatchKeys<K extends string, P extends string> = ParsePattern<P> extends never ? never : ParsePattern<P> extends infer PSegs extends string[] ? K extends unknown ? MatchKey<K, PSegs> : never : never;
1029
+ /**
1030
+ * Split a string by '.' delimiter into a tuple of segments.
1031
+ * Returns `never` if any segment is empty (handles `.a`, `a.`, `a..b`).
1032
+ */
1033
+ type SplitDot<S extends string> = S extends '' ? [] : S extends `${infer Head}.${infer Tail}` ? Head extends '' ? never : Tail extends '' ? never : SplitDot<Tail> extends infer Rest ? Rest extends never ? never : Rest extends string[] ? [Head, ...Rest] : never : never : [S];
1034
+ /**
1035
+ * Validate that `**` only appears as the last segment (or is the entire pattern).
1036
+ * Returns `true` if valid, `false` if invalid.
1037
+ */
1038
+ type ValidateGlob<Segs extends string[]> = Segs extends [] ? true : Segs extends [infer Head extends string, ...infer Tail extends string[]] ? Head extends '**' ? Tail extends [] ? true : false : ValidateGlob<Tail> : true;
1039
+ /**
1040
+ * Parse and validate a pattern string.
1041
+ * Returns the segments tuple if valid, `never` if invalid.
1042
+ */
1043
+ type ParsePattern<P extends string> = SplitDot<P> extends infer Segs ? Segs extends never ? never : Segs extends string[] ? ValidateGlob<Segs> extends true ? Segs : never : never : never;
1044
+ /**
1045
+ * Match a single key against parsed pattern segments.
1046
+ * Returns the key if it matches, `never` otherwise.
1047
+ */
1048
+ type MatchKey<K extends string, PSegs extends string[]> = SplitDot<K> extends infer KSegs ? KSegs extends never ? never : KSegs extends string[] ? MatchSegments<KSegs, PSegs> extends true ? K : never : never : never;
1049
+ /**
1050
+ * Recursively match key segments against pattern segments.
1051
+ *
1052
+ * Rules:
1053
+ * - If pattern exhausted: key must also be exhausted
1054
+ * - If pattern head is `**`: match (since it's validated to be last)
1055
+ * - If pattern head is `*`: consume one key segment
1056
+ * - Otherwise: exact segment match required
1057
+ */
1058
+ type MatchSegments<KSegs extends string[], PSegs extends string[]> = PSegs extends [] ? KSegs extends [] ? true : false : PSegs extends [infer PHead extends string, ...infer PTail extends string[]] ? PHead extends '**' ? true : KSegs extends [
1059
+ infer KHead extends string,
1060
+ ...infer KTail extends string[]
1061
+ ] ? PHead extends '*' ? MatchSegments<KTail, PTail> : PHead extends KHead ? MatchSegments<KTail, PTail> : false : false : false;
1062
+
1063
+ /**
1064
+ * Type-safe wrapper for the untyped EventBus.
1065
+ *
1066
+ * @remarks
1067
+ * This module provides compile-time type safety for event emission
1068
+ * and subscription while maintaining zero runtime overhead.
1069
+ */
1070
+
1071
+ /**
1072
+ * A strongly-typed event with known name and data types.
1073
+ *
1074
+ * @typeParam Name - The event name literal type.
1075
+ * @typeParam Data - The event payload type.
1076
+ */
1077
+ type TypedEvent<Name extends string, Data> = Omit<Event, 'name' | 'data'> & {
1078
+ name: Name;
1079
+ data: Data;
1080
+ };
1081
+ /**
1082
+ * Create a discriminated union of typed events from an event map.
1083
+ *
1084
+ * @typeParam M - The event map.
1085
+ * @typeParam K - The keys to include (defaults to all keys).
1086
+ *
1087
+ * @remarks
1088
+ * This creates a proper discriminated union where TypeScript can narrow
1089
+ * the `data` type based on checking the `name` field.
1090
+ */
1091
+ type EventUnion<M extends EventMap, K extends Keys<M> = Keys<M>> = {
1092
+ [N in K]: TypedEvent<N, M[N]>;
1093
+ }[K];
1094
+ /**
1095
+ * Handler for typed events.
1096
+ */
1097
+ type TypedEventHandler<E> = (event: E) => void | Promise<void>;
1098
+
1099
+ /**
1100
+ * Metrics type definitions for the Runtime module.
1101
+ *
1102
+ * @remarks
1103
+ * Define a minimal, pluggable metrics interface that can be backed by any
1104
+ * metrics library (hot-shots, dd-trace, prom-client, etc.).
1105
+ *
1106
+ * The interface supports:
1107
+ * - Counters for monotonically increasing values
1108
+ * - Histograms for distributions (latencies, sizes)
1109
+ * - Timers as a convenience wrapper for timing operations
1110
+ * - Label scoping via `child()` for dimensional metrics
1111
+ *
1112
+ * @example
1113
+ * ```typescript
1114
+ * // Basic usage
1115
+ * metrics.counter('requests.total').inc({ method: 'POST' })
1116
+ * metrics.histogram('request.duration').observe({ status: 200 }, 42.5)
1117
+ *
1118
+ * // Timer convenience
1119
+ * const stop = metrics.timer('db.query').start({ table: 'users' })
1120
+ * await query()
1121
+ * stop() // Records duration automatically
1122
+ *
1123
+ * // Scoping adds base labels to all metrics
1124
+ * const scoped = metrics.child({ service: 'bridge', env: 'prod' })
1125
+ * scoped.counter('transfers').inc() // Includes service + env labels
1126
+ * ```
1127
+ */
1128
+ /**
1129
+ * Labels for dimensional metrics.
1130
+ *
1131
+ * @remarks
1132
+ * Labels (also called tags in some systems) are key-value pairs that
1133
+ * provide dimensions for metric aggregation and filtering.
1134
+ * Values must be primitives for serialization compatibility.
1135
+ *
1136
+ * @example
1137
+ * ```typescript
1138
+ * const labels: MetricLabels = {
1139
+ * chain: 'Ethereum',
1140
+ * status: 'success',
1141
+ * retries: 3,
1142
+ * cached: true,
1143
+ * }
1144
+ * ```
1145
+ */
1146
+ type MetricLabels = Record<string, string | number | boolean>;
1147
+ /**
1148
+ * A counter metric for monotonically increasing values.
1149
+ *
1150
+ * @remarks
1151
+ * Use counters for values that only go up: request counts, error counts,
1152
+ * bytes processed, etc. The value resets only on process restart.
1153
+ *
1154
+ * @see {@link Metrics.counter} to obtain a Counter instance.
1155
+ *
1156
+ * @example
1157
+ * ```typescript
1158
+ * const counter = metrics.counter('http.requests')
1159
+ *
1160
+ * // Increment by 1
1161
+ * counter.inc()
1162
+ * counter.inc({ method: 'GET' })
1163
+ *
1164
+ * // Increment by specific value
1165
+ * counter.inc(5)
1166
+ * counter.inc({ method: 'POST' }, 3)
1167
+ * ```
1168
+ */
1169
+ interface Counter {
1170
+ /**
1171
+ * Increment the counter value.
1172
+ *
1173
+ * @param labelsOrValue - The labels object or increment value.
1174
+ * When a number, increments by that amount with no labels.
1175
+ * When an object, uses as labels with optional value in second param.
1176
+ * @param value - The increment value when first arg is labels. Default: 1.
1177
+ * @returns void
1178
+ *
1179
+ * @example
1180
+ * ```typescript
1181
+ * counter.inc() // +1, no labels
1182
+ * counter.inc(5) // +5, no labels
1183
+ * counter.inc({ method: 'GET' }) // +1, with labels
1184
+ * counter.inc({ method: 'POST' }, 3) // +3, with labels
1185
+ * ```
1186
+ */
1187
+ inc(labelsOrValue?: MetricLabels | number, value?: number): void;
1188
+ }
1189
+ /**
1190
+ * A histogram metric for recording value distributions.
1191
+ *
1192
+ * @remarks
1193
+ * Use histograms for values that vary and need percentile analysis:
1194
+ * request durations, response sizes, queue depths, etc.
1195
+ *
1196
+ * @see {@link Metrics.histogram} to obtain a Histogram instance.
1197
+ *
1198
+ * @example
1199
+ * ```typescript
1200
+ * const histogram = metrics.histogram('http.duration')
1201
+ *
1202
+ * // Record a value
1203
+ * histogram.observe(42.5)
1204
+ * histogram.observe({ status: 200 }, 42.5)
1205
+ * ```
1206
+ */
1207
+ interface Histogram {
1208
+ /**
1209
+ * Record an observation value.
1210
+ *
1211
+ * @param labelsOrValue - The labels object or observed value.
1212
+ * When a number, records that value with no labels.
1213
+ * When an object, uses as labels with value in second param.
1214
+ * @param value - The observed value when first arg is labels. Default: 0.
1215
+ * @returns void
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * histogram.observe(42.5) // Value only
1220
+ * histogram.observe({ status: 200 }, 42.5) // With labels
1221
+ * ```
1222
+ */
1223
+ observe(labelsOrValue?: MetricLabels | number, value?: number): void;
1224
+ }
1225
+ /**
1226
+ * A timer metric for measuring operation durations.
1227
+ *
1228
+ * @remarks
1229
+ * Timers provide a convenience wrapper that automatically records durations
1230
+ * to an underlying histogram. Call `start()` to begin timing and the
1231
+ * returned function to stop and record the elapsed time in milliseconds.
1232
+ *
1233
+ * @see {@link Metrics.timer} to obtain a Timer instance.
1234
+ *
1235
+ * @example
1236
+ * ```typescript
1237
+ * const timer = metrics.timer('db.query')
1238
+ *
1239
+ * // Start timing
1240
+ * const stop = timer.start({ table: 'users' })
1241
+ * await performQuery()
1242
+ * stop() // Records duration in milliseconds
1243
+ * ```
1244
+ */
1245
+ interface Timer {
1246
+ /**
1247
+ * Start timing an operation.
1248
+ *
1249
+ * @param labels - The optional labels for the timing observation.
1250
+ * @returns A stop function that records the duration when called.
1251
+ *
1252
+ * @example
1253
+ * ```typescript
1254
+ * const stop = timer.start({ operation: 'fetch' })
1255
+ * await fetchData()
1256
+ * stop() // Records elapsed time
1257
+ * ```
1258
+ */
1259
+ start(labels?: MetricLabels): () => void;
1260
+ }
1261
+ /**
1262
+ * Main metrics interface for instrumentation.
1263
+ *
1264
+ * @remarks
1265
+ * This interface is designed to be thin and pluggable. Implementations
1266
+ * can delegate to any metrics library:
1267
+ *
1268
+ * - **hot-shots**: StatsD/DogStatsD client
1269
+ * - **dd-trace**: Datadog APM
1270
+ * - **prom-client**: Prometheus
1271
+ * - **opentelemetry-js**: OpenTelemetry
1272
+ *
1273
+ * The `child()` method creates a scoped metrics instance that automatically
1274
+ * includes base labels on all metric operations.
1275
+ *
1276
+ * @see {@link createMockMetrics} for testing.
1277
+ * @see {@link noopMetrics} for a no-op implementation.
1278
+ *
1279
+ * @example
1280
+ * ```typescript
1281
+ * // Create a scoped metrics instance
1282
+ * const appMetrics = metrics.child({
1283
+ * service: 'app-kit',
1284
+ * version: '1.0.0',
1285
+ * })
1286
+ *
1287
+ * // All metrics include service + version labels
1288
+ * appMetrics.counter('transfers.initiated').inc({ chain: 'ethereum' })
1289
+ * ```
1290
+ */
1291
+ interface Metrics {
1292
+ /**
1293
+ * Get or create a counter metric by name.
1294
+ *
1295
+ * @param name - The metric name (e.g., 'http.requests.total').
1296
+ * @returns A Counter instance for the given name.
1297
+ *
1298
+ * @example
1299
+ * ```typescript
1300
+ * const counter = metrics.counter('requests.total')
1301
+ * counter.inc({ method: 'GET' })
1302
+ * ```
1303
+ */
1304
+ counter(name: string): Counter;
1305
+ /**
1306
+ * Get or create a histogram metric by name.
1307
+ *
1308
+ * @param name - The metric name (e.g., 'http.request.duration').
1309
+ * @returns A Histogram instance for the given name.
1310
+ *
1311
+ * @example
1312
+ * ```typescript
1313
+ * const histogram = metrics.histogram('request.duration')
1314
+ * histogram.observe({ status: 200 }, 42.5)
1315
+ * ```
1316
+ */
1317
+ histogram(name: string): Histogram;
1318
+ /**
1319
+ * Get or create a timer metric by name.
1320
+ *
1321
+ * @param name - The metric name (e.g., 'db.query.duration').
1322
+ * @returns A Timer instance for the given name.
1323
+ *
1324
+ * @example
1325
+ * ```typescript
1326
+ * const stop = metrics.timer('db.query').start()
1327
+ * await query()
1328
+ * stop()
1329
+ * ```
1330
+ */
1331
+ timer(name: string): Timer;
1332
+ /**
1333
+ * Create a child metrics instance with scoped labels.
1334
+ *
1335
+ * @param labels - The base labels to include on all metric operations.
1336
+ * @returns A new Metrics instance with merged labels.
1337
+ *
1338
+ * @remarks
1339
+ * Labels from the child are merged with any labels passed to individual
1340
+ * metric operations. Call-site labels take precedence for the same key.
1341
+ *
1342
+ * @example
1343
+ * ```typescript
1344
+ * const scoped = metrics.child({ chain: 'Ethereum' })
1345
+ * scoped.counter('transfers').inc({ status: 'success' })
1346
+ * // Labels: { chain: 'Ethereum', status: 'success' }
1347
+ * ```
1348
+ */
1349
+ child(labels: MetricLabels): Metrics;
1350
+ }
1351
+
1352
+ /**
1353
+ * Core type definitions for the runtime package.
1354
+ *
1355
+ * @remarks
1356
+ * This module defines the foundational types used throughout the SDK:
1357
+ *
1358
+ * - {@link Runtime} - Complete runtime with all services (clock, logger, metrics, events)
1359
+ * - {@link ExecutionContext} - Context for middleware with observability surface
1360
+ * - {@link Clock}, {@link Tags}, {@link Event} - Supporting types
1361
+ *
1362
+ * **Naming Convention**
1363
+ *
1364
+ * | Input Type | Resolved Type | Description |
1365
+ * |------------|---------------|-------------|
1366
+ * | `Partial<Runtime>` | `Runtime` | Runtime services |
1367
+ * | `OperationMeta` | `OperationContext` | WHAT - operation target |
1368
+ * | `InvocationMeta` | `InvocationContext` | WHO/HOW - call chain |
1369
+ *
1370
+ * @packageDocumentation
1371
+ */
1372
+
1373
+ /**
1374
+ * Clock interface for time operations.
1375
+ *
1376
+ * @remarks
1377
+ * Abstracting time allows tests to control timing without real delays.
1378
+ * Production code uses {@link defaultClock}, tests use mock implementations.
1379
+ *
1380
+ * @example
1381
+ * ```typescript
1382
+ * import { defaultClock, type Clock } from '@core/runtime'
1383
+ *
1384
+ * const start = defaultClock.now()
1385
+ * // ... do work ...
1386
+ * const elapsed = defaultClock.since(start)
1387
+ * ```
1388
+ */
1389
+ interface Clock {
1390
+ /**
1391
+ * Return the current timestamp in milliseconds since Unix epoch.
1392
+ *
1393
+ * @returns Current time in milliseconds.
1394
+ */
1395
+ now(): number;
1396
+ /**
1397
+ * Calculate elapsed time since a given timestamp.
1398
+ *
1399
+ * @param start - The start timestamp in milliseconds.
1400
+ * @returns Elapsed time in milliseconds (`now() - start`).
1401
+ */
1402
+ since: (start: number) => number;
1403
+ }
1404
+ /**
1405
+ * Contextual metadata tags for logging and metrics.
1406
+ *
1407
+ * @remarks
1408
+ * Tags are key-value pairs attached to log entries and metrics.
1409
+ * Values can be primitives or undefined (undefined values are filtered out).
1410
+ *
1411
+ * Common tags include:
1412
+ * - `opId` - Operation identifier for correlation
1413
+ * - `chain` - Blockchain network name
1414
+ * - `phase` - Current pipeline phase
1415
+ *
1416
+ * @example
1417
+ * ```typescript
1418
+ * import type { Tags } from '@core/runtime'
1419
+ *
1420
+ * const tags: Tags = {
1421
+ * opId: 'op-abc123',
1422
+ * chain: 'Ethereum',
1423
+ * phase: 'validate',
1424
+ * optional: undefined, // Will be filtered out
1425
+ * }
1426
+ * ```
1427
+ */
1428
+ type Tags = Record<string, string | number | boolean | undefined>;
1429
+ /**
1430
+ * A structured event emitted by the runtime.
1431
+ *
1432
+ * @remarks
1433
+ * Events provide a standardized way to capture lifecycle moments,
1434
+ * actions, and state changes throughout the SDK.
1435
+ */
1436
+ interface Event {
1437
+ /** The event name/identifier. */
1438
+ name: string;
1439
+ /** Log level for the event. */
1440
+ level?: 'debug' | 'info' | 'warn' | 'error';
1441
+ /** Timestamp (epoch ms) when the event occurred. */
1442
+ at?: number;
1443
+ /** Contextual tags for filtering/categorization. */
1444
+ tags?: Tags;
1445
+ /** Arbitrary payload data associated with the event. */
1446
+ data?: unknown;
1447
+ }
1448
+ /**
1449
+ * Complete runtime with all services guaranteed present.
1450
+ *
1451
+ * @remarks
1452
+ * The runtime is the container for all cross-cutting concerns: logging,
1453
+ * timing, events, and metrics. All services are guaranteed to be available.
1454
+ *
1455
+ * **Creating a Runtime**
1456
+ *
1457
+ * Use {@link createRuntime} to create a fully-configured runtime:
1458
+ * ```typescript
1459
+ * import { createRuntime } from '@core/runtime'
1460
+ *
1461
+ * const runtime = createRuntime()
1462
+ * runtime.logger.info('Hello')
1463
+ * runtime.metrics.counter('requests').inc()
1464
+ * ```
1465
+ *
1466
+ * **Partial Runtime Input**
1467
+ *
1468
+ * When accepting runtime configuration as input, use `Partial<Runtime>`:
1469
+ * ```typescript
1470
+ * function myFunction(options: { runtime?: Partial<Runtime> }) {
1471
+ * const runtime = createRuntime(options.runtime)
1472
+ * // ...
1473
+ * }
1474
+ * ```
1475
+ *
1476
+ * @example
1477
+ * ```typescript
1478
+ * import { createRuntime, type Runtime } from '@core/runtime'
1479
+ *
1480
+ * const runtime: Runtime = createRuntime()
1481
+ *
1482
+ * // All services are guaranteed present
1483
+ * runtime.logger.info('Processing request')
1484
+ * runtime.metrics.counter('requests').inc()
1485
+ * runtime.events.emit({ name: 'request.received' })
1486
+ * const now = runtime.clock.now()
1487
+ * ```
1488
+ */
1489
+ interface Runtime {
1490
+ /**
1491
+ * Clock for time operations.
1492
+ *
1493
+ * @remarks
1494
+ * Provides the current timestamp. Use {@link defaultClock} for production
1495
+ * or custom clocks for deterministic testing.
1496
+ */
1497
+ clock: Clock;
1498
+ /**
1499
+ * Logger for structured logging.
1500
+ *
1501
+ * @remarks
1502
+ * Provides debug, info, warn, error methods with structured data support.
1503
+ */
1504
+ logger: Logger;
1505
+ /**
1506
+ * Metrics collector for observability.
1507
+ *
1508
+ * @remarks
1509
+ * Provides counters, histograms, and timers for application metrics.
1510
+ */
1511
+ metrics: Metrics;
1512
+ /**
1513
+ * Event bus for pub/sub events.
1514
+ *
1515
+ * @remarks
1516
+ * Enables decoupled event emission and subscription across the SDK.
1517
+ */
1518
+ events: EventBus;
1519
+ }
1520
+ /**
1521
+ * A component in the call chain.
1522
+ *
1523
+ * @remarks
1524
+ * Each caller identifies itself with a type (app, kit, provider, adapter)
1525
+ * and a name/version. This enables proper attribution in logs, metrics, and traces.
1526
+ *
1527
+ * @example
1528
+ * ```typescript
1529
+ * import type { Caller } from '@core/runtime'
1530
+ *
1531
+ * const appCaller: Caller = { type: 'app', name: 'MyDApp', version: '1.0.0' }
1532
+ * const kitCaller: Caller = { type: 'kit', name: 'BridgeKit', version: '2.0.0' }
1533
+ * ```
1534
+ */
1535
+ interface Caller {
1536
+ /**
1537
+ * Type of component in the call hierarchy.
1538
+ *
1539
+ * @remarks
1540
+ * Common types: `app`, `kit`, `provider`, `adapter`
1541
+ */
1542
+ readonly type: string;
1543
+ /** Name of the component (e.g., 'BridgeKit', 'cctp-v2'). */
1544
+ readonly name: string;
1545
+ /** Version of the component (e.g., '1.0.0'). */
1546
+ readonly version?: string | undefined;
1547
+ }
1548
+ /**
1549
+ * User input for invocation metadata.
1550
+ *
1551
+ * @remarks
1552
+ * Defines **WHO** called and **HOW** to observe: trace correlation, runtime override,
1553
+ * and caller chain. This is the user-facing input type, resolved to `InvocationContext`.
1554
+ *
1555
+ * Passed as the optional invocation argument to actions and primitives.
1556
+ *
1557
+ * @example
1558
+ * ```typescript
1559
+ * import type { InvocationMeta } from '@core/runtime'
1560
+ *
1561
+ * // Minimal - just traceId
1562
+ * const meta: InvocationMeta = { traceId: 'abc-123' }
1563
+ *
1564
+ * // Full - with runtime override and caller chain
1565
+ * const meta: InvocationMeta = {
1566
+ * traceId: 'abc-123',
1567
+ * runtime: myRuntime,
1568
+ * callers: [
1569
+ * { type: 'app', name: 'MyDApp', version: '1.0.0' },
1570
+ * ],
1571
+ * }
1572
+ * ```
1573
+ */
1574
+ interface InvocationMeta {
1575
+ /**
1576
+ * Trace ID for distributed tracing correlation.
1577
+ *
1578
+ * @remarks
1579
+ * If not provided, generated automatically.
1580
+ */
1581
+ readonly traceId?: string | undefined;
1582
+ /**
1583
+ * Runtime override (complete replacement).
1584
+ *
1585
+ * @remarks
1586
+ * When provided, this runtime completely replaces the default runtime.
1587
+ * Must be a complete Runtime instance (e.g., from `createRuntime()`).
1588
+ * If not provided, the default runtime is used.
1589
+ */
1590
+ readonly runtime?: Runtime | undefined;
1591
+ /**
1592
+ * Token registry override (complete replacement).
1593
+ *
1594
+ * @remarks
1595
+ * When provided, this registry completely replaces the default token registry.
1596
+ * Enables kits to pass their token registry to adapters.
1597
+ * If not provided, the default token registry is used.
1598
+ */
1599
+ readonly tokens?: TokenRegistry | undefined;
1600
+ /**
1601
+ * Call chain - each caller appends itself.
1602
+ *
1603
+ * @remarks
1604
+ * Ordered from outermost (first) to innermost (last).
1605
+ * Example: [app, kit, provider]
1606
+ */
1607
+ readonly callers?: readonly Caller[] | undefined;
1608
+ /**
1609
+ * Cooperative cancellation signal for the invocation.
1610
+ *
1611
+ * @remarks
1612
+ * When provided, the signal is threaded onto the resolved
1613
+ * {@link InvocationContext} so operations can forward it to
1614
+ * cancellable work (e.g. `fetch`, timers, adapter calls). Optional and
1615
+ * backwards-compatible: callers that do not support cancellation simply
1616
+ * omit it. Aborting the signal is the caller's responsibility; the
1617
+ * runtime only propagates it.
1618
+ */
1619
+ readonly signal?: AbortSignal | undefined;
1620
+ }
1621
+
1622
+ /**
1623
+ * Operation primitives.
1624
+ *
1625
+ * @remarks
1626
+ * Operations are the unit of public surface a kit exposes. Each operation
1627
+ * has a name, a parameter shape, an optional Zod schema, and a `run`
1628
+ * function bound to a {@link KitContext}.
1629
+ *
1630
+ * The critical type-level concern here is preservation of per-operation
1631
+ * parameter generics so that `AdapterContext`-driven conditional typing
1632
+ * (notably {@link AddressField} narrowing on user-controlled vs.
1633
+ * developer-controlled adapters) survives end-to-end through
1634
+ * {@link createKit}'s method surface.
1635
+ *
1636
+ * @packageDocumentation
1637
+ */
1638
+
1639
+ /**
1640
+ * The bound, callable shape of a kit operation.
1641
+ *
1642
+ * @typeParam TParams - The operation's parameter shape.
1643
+ * @typeParam TResult - The operation's result shape.
1644
+ *
1645
+ * @remarks
1646
+ * Parameter generics are preserved on this type and on every container
1647
+ * that holds it. Containers must avoid `KitOperation<unknown, unknown>`
1648
+ * (generic erasure); use mapped types or `infer` instead.
1649
+ */
1650
+ interface KitOperation<TParams = unknown, TResult = unknown> {
1651
+ readonly name: string;
1652
+ (params: TParams, invocation?: InvocationMeta): Promise<TResult>;
1653
+ }
1654
+
1655
+ /**
1656
+ * Kit event subscription surface, backed by `runtime.events`.
1657
+ *
1658
+ * @remarks
1659
+ * kit-base no longer ships a bespoke event bus. Instead, the kit's
1660
+ * public `on` / `off` are a thin, strongly-typed wrapper over the
1661
+ * single `EventBus` owned by the kit's {@link Runtime}. This is the same
1662
+ * bus the operation middleware (lifecycle/retry) and any providers /
1663
+ * adapters in the call tree emit on — so one subscription observes the
1664
+ * whole tree. Wildcard (`*`) and namespace (`**`) patterns work via the
1665
+ * `EventBus` matcher.
1666
+ *
1667
+ * Mirrors `createAdapterEvents` from `@core/adapter-base` and augments
1668
+ * the same `@core/runtime` `KitEventMap`. Kits register their event keys
1669
+ * by augmenting that interface (see the package README).
1670
+ *
1671
+ * @packageDocumentation
1672
+ */
1673
+
1674
+ /**
1675
+ * Strongly-typed event subscription surface attached to every
1676
+ * {@link Kit} and `CompositeKit` instance.
1677
+ *
1678
+ * @remarks
1679
+ * `on` returns an unsubscribe function (modern pattern). `off` accepts
1680
+ * the original handler reference and removes it for callers that prefer
1681
+ * explicit cleanup. Both are typed against the augmentable
1682
+ * {@link KitEventMap} from `@core/runtime`.
1683
+ *
1684
+ * @typeParam M - The event map (defaults to {@link KitEventMap}).
1685
+ *
1686
+ * @example
1687
+ * ```ts
1688
+ * // Subscribe to a specific event
1689
+ * kit.on('kit.bridge.completed', (event) => console.log(event.data))
1690
+ *
1691
+ * // Subscribe with a namespace pattern
1692
+ * kit.on('kit.bridge.*', (event) => console.log(event.name, event.data))
1693
+ *
1694
+ * // Subscribe to the runtime lifecycle events the middleware emits
1695
+ * kit.on('op.phase.*', (event) => console.log(event.name))
1696
+ *
1697
+ * // Unsubscribe via the returned function or via off()
1698
+ * const unsub = kit.on('kit.bridge.failed', handler)
1699
+ * unsub()
1700
+ * ```
1701
+ */
1702
+ interface KitEventSubscription<M extends EventMap = KitEventMap> {
1703
+ /**
1704
+ * Subscribe to all events.
1705
+ *
1706
+ * @param handler - Handler receiving any event as a discriminated union.
1707
+ * @returns Unsubscribe function.
1708
+ */
1709
+ on(handler: TypedEventHandler<EventUnion<M>>): () => void;
1710
+ /**
1711
+ * Subscribe to a specific event by exact name.
1712
+ *
1713
+ * @typeParam K - The event name literal.
1714
+ * @param name - The event name.
1715
+ * @param handler - Handler receiving the typed event.
1716
+ * @returns Unsubscribe function.
1717
+ */
1718
+ on<K extends Keys<M>>(name: K, handler: TypedEventHandler<TypedEvent<K, M[K]>>): () => void;
1719
+ /**
1720
+ * Subscribe to events matching a glob pattern.
1721
+ *
1722
+ * @typeParam P - The pattern string (supports `*` and `**` wildcards).
1723
+ * @param pattern - The pattern to match event names against.
1724
+ * @param handler - Handler receiving matched events as a discriminated union.
1725
+ * @returns Unsubscribe function.
1726
+ */
1727
+ on<P extends string>(pattern: P, handler: TypedEventHandler<EventUnion<M, MatchKeys<Keys<M>, P>>>): () => void;
1728
+ /**
1729
+ * Remove a previously registered handler.
1730
+ *
1731
+ * @param handler - The handler function reference to remove.
1732
+ */
1733
+ off(handler: TypedEventHandler<EventUnion<M>>): void;
1734
+ /**
1735
+ * Remove subscriptions registered with this handler reference.
1736
+ *
1737
+ * @remarks
1738
+ * Removal is **by handler reference**, mirroring `createControllerEvents`
1739
+ * and the `@core/adapter-base` event surfaces. The `name` is accepted
1740
+ * for symmetry with {@link on}, but every subscription for `handler` is
1741
+ * removed regardless of the event name it was registered under. Unknown
1742
+ * handlers are a no-op.
1743
+ *
1744
+ * @typeParam K - The event name literal.
1745
+ * @param name - The event name (accepted for symmetry; not used to
1746
+ * scope removal).
1747
+ * @param handler - The handler function reference to remove.
1748
+ */
1749
+ off<K extends Keys<M>>(name: K, handler: TypedEventHandler<TypedEvent<K, M[K]>>): void;
1750
+ }
1751
+
1752
+ /**
1753
+ * Session wire format shared by the server kit (which mints sessions)
1754
+ * and the client kit (which consumes them to launch the widget).
1755
+ *
1756
+ * @remarks
1757
+ * The server kit speaks to `wallets-api` and unwraps its envelope into
1758
+ * the shape exported below. The same shape is what the client kit
1759
+ * consumes via `onrampKit.mountIframe({ session, container })` /
1760
+ * `onrampKit.openWindow({ session })`, so a host application can pass
1761
+ * the server result through verbatim — no manual mapping.
1762
+ *
1763
+ * @packageDocumentation
1764
+ */
1765
+ /**
1766
+ * One session as returned by the Onramp session endpoint
1767
+ * (`POST /v1/stablecoinKits/sessions`), after the server kit unwraps
1768
+ * the `{ data }` envelope.
1769
+ *
1770
+ * @remarks
1771
+ * This is a **plain type**, not a runtime schema. The kit does not
1772
+ * validate the session response against a closed shape — an additive
1773
+ * change to the Onramp API (a new field, a new optional) must never
1774
+ * break minting. The index signature keeps the type tolerant of extra
1775
+ * fields on the wire. Note that `createSession` applies an outbound
1776
+ * allow-list before returning: only the modeled fields below cross the
1777
+ * server→browser trust boundary, so unmodeled upstream fields are
1778
+ * dropped rather than forwarded.
1779
+ *
1780
+ * Field-by-field rationale:
1781
+ *
1782
+ * - `sessionId` — opaque, server-issued identifier; surfaced on every
1783
+ * widget event for cross-side correlation.
1784
+ * - `sessionToken` — short-lived bearer credential the widget URL
1785
+ * embeds. Never sent back by the client; it is redeemed inside the
1786
+ * widget origin only.
1787
+ * - `widgetUrl` — fully composed launch URL (origin + path + token +
1788
+ * `destinationWallet`). The server kit prefers to compose this itself
1789
+ * so the client kit has no exposure to the widget origin. The client
1790
+ * still accepts a bare `sessionToken` and composes a URL locally as a
1791
+ * fallback. `getOnrampUrl` is the single place that enforces the
1792
+ * https-scheme / origin-pin safety checks before the URL reaches the
1793
+ * DOM — that is a security boundary, not response validation.
1794
+ * - `destinationWallet` — the wallet that receives funds. The widget
1795
+ * requires it as a launch query param, so the server kit echoes the
1796
+ * `destinationAddress` it was minted with here (and bakes it into
1797
+ * `widgetUrl`). Used by the client fallback path when it has to
1798
+ * compose the URL from a bare `sessionToken`.
1799
+ * - `expiresAt` — RFC 3339 timestamp. The client refuses to launch an
1800
+ * expired session and throws an `INPUT` `KitError` so the host can
1801
+ * re-mint.
1802
+ * - `traceId` — the trace id the server stamped when minting. Echoed
1803
+ * back so the client can tag widget events with the same id.
1804
+ */
1805
+ interface OnrampSession {
1806
+ /**
1807
+ * Opaque server-issued session identifier.
1808
+ *
1809
+ * @remarks
1810
+ * Surfaced on every widget event for cross-side correlation.
1811
+ */
1812
+ readonly sessionId: string;
1813
+ /**
1814
+ * Short-lived bearer credential the widget URL embeds.
1815
+ *
1816
+ * @remarks
1817
+ * Redeemed inside the widget origin only — never sent back by the
1818
+ * client kit.
1819
+ */
1820
+ readonly sessionToken: string;
1821
+ /**
1822
+ * Fully composed launch URL (origin + path + token +
1823
+ * `destinationWallet`).
1824
+ *
1825
+ * @remarks
1826
+ * The server kit prefers to compose this itself; the client falls
1827
+ * back to composing locally from `sessionToken` when absent.
1828
+ */
1829
+ readonly widgetUrl?: string;
1830
+ /**
1831
+ * Wallet address that will receive funds at the end of the onramp
1832
+ * flow.
1833
+ *
1834
+ * @remarks
1835
+ * Echoed verbatim from the `destinationAddress` the server kit
1836
+ * minted with. Used by the client kit's URL-composition fallback
1837
+ * when `widgetUrl` is absent.
1838
+ */
1839
+ readonly destinationWallet?: string;
1840
+ /**
1841
+ * RFC 3339 expiry timestamp.
1842
+ *
1843
+ * @remarks
1844
+ * The client refuses to launch an expired session and throws an
1845
+ * `INPUT` `KitError` so the host can re-mint.
1846
+ */
1847
+ readonly expiresAt: string;
1848
+ /**
1849
+ * Trace identifier stamped by the server kit at minting time.
1850
+ *
1851
+ * @remarks
1852
+ * Echoed back so the client can tag widget events with the same
1853
+ * id.
1854
+ */
1855
+ readonly traceId?: string;
1856
+ /**
1857
+ * Index signature keeping the type tolerant of additive fields.
1858
+ *
1859
+ * @remarks
1860
+ * The kit does not assert a closed shape, so the type accepts extra
1861
+ * fields. At runtime, however, `createSession` rebuilds the result
1862
+ * from an allow-list of the modeled fields above and does **not**
1863
+ * forward unmodeled upstream fields across the server→browser
1864
+ * boundary.
1865
+ */
1866
+ readonly [key: string]: unknown;
1867
+ }
1868
+ /**
1869
+ * Session shape always returned by `onrampServerKit.createSession()`.
1870
+ *
1871
+ * @remarks
1872
+ * The server kit normalises {@link OnrampSession} so that `widgetUrl`
1873
+ * and `traceId` are guaranteed to be populated by the time the host
1874
+ * passes the session through to the client. Use this alias when
1875
+ * declaring SSR / serializer contracts that round-trip the value
1876
+ * unchanged.
1877
+ */
1878
+ interface MintedOnrampSession extends OnrampSession {
1879
+ /**
1880
+ * Fully composed launch URL — guaranteed present.
1881
+ */
1882
+ readonly widgetUrl: string;
1883
+ /**
1884
+ * Trace identifier stamped by the server kit — guaranteed present.
1885
+ */
1886
+ readonly traceId: string;
1887
+ }
1888
+
1889
+ /**
1890
+ * Wire-format schema for the `createSession` request body.
1891
+ *
1892
+ * @remarks
1893
+ * Lives in the shared `protocol/` subtree so both the server kit (which
1894
+ * validates inbound parameters before calling wallets-api) and the
1895
+ * client kit (which POSTs the same shape to a host-owned session
1896
+ * endpoint via {@link fetchOnrampSession}) speak the exact same
1897
+ * contract.
1898
+ *
1899
+ * Validation is intentionally conservative: only the fields the kit
1900
+ * actually consumes (or rejects on shape grounds) are checked. Free-
1901
+ * form fields like `metadata` pass through so wallets-api can layer
1902
+ * its own validation on top without the SDK lagging behind.
1903
+ *
1904
+ * @packageDocumentation
1905
+ */
1906
+
1907
+ /**
1908
+ * Zod schema for {@link OnrampSessionRequest}.
1909
+ */
1910
+ declare const onrampSessionRequestSchema: z.ZodObject<{
1911
+ appUserId: z.ZodString;
1912
+ destinationAddress: z.ZodString;
1913
+ destinationChain: z.ZodOptional<z.ZodString>;
1914
+ amount: z.ZodOptional<z.ZodString>;
1915
+ currency: z.ZodOptional<z.ZodString>;
1916
+ email: z.ZodOptional<z.ZodString>;
1917
+ assets: z.ZodOptional<z.ZodObject<{
1918
+ tokens: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1919
+ chains: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1920
+ pairs: z.ZodOptional<z.ZodArray<z.ZodObject<{
1921
+ token: z.ZodString;
1922
+ chain: z.ZodString;
1923
+ }, "strip", z.ZodTypeAny, {
1924
+ token: string;
1925
+ chain: string;
1926
+ }, {
1927
+ token: string;
1928
+ chain: string;
1929
+ }>, "many">>;
1930
+ }, "strip", z.ZodTypeAny, {
1931
+ tokens?: string[] | undefined;
1932
+ chains?: string[] | undefined;
1933
+ pairs?: {
1934
+ token: string;
1935
+ chain: string;
1936
+ }[] | undefined;
1937
+ }, {
1938
+ tokens?: string[] | undefined;
1939
+ chains?: string[] | undefined;
1940
+ pairs?: {
1941
+ token: string;
1942
+ chain: string;
1943
+ }[] | undefined;
1944
+ }>>;
1945
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1946
+ }, "strip", z.ZodTypeAny, {
1947
+ appUserId: string;
1948
+ destinationAddress: string;
1949
+ destinationChain?: string | undefined;
1950
+ amount?: string | undefined;
1951
+ currency?: string | undefined;
1952
+ email?: string | undefined;
1953
+ assets?: {
1954
+ tokens?: string[] | undefined;
1955
+ chains?: string[] | undefined;
1956
+ pairs?: {
1957
+ token: string;
1958
+ chain: string;
1959
+ }[] | undefined;
1960
+ } | undefined;
1961
+ metadata?: Record<string, unknown> | undefined;
1962
+ }, {
1963
+ appUserId: string;
1964
+ destinationAddress: string;
1965
+ destinationChain?: string | undefined;
1966
+ amount?: string | undefined;
1967
+ currency?: string | undefined;
1968
+ email?: string | undefined;
1969
+ assets?: {
1970
+ tokens?: string[] | undefined;
1971
+ chains?: string[] | undefined;
1972
+ pairs?: {
1973
+ token: string;
1974
+ chain: string;
1975
+ }[] | undefined;
1976
+ } | undefined;
1977
+ metadata?: Record<string, unknown> | undefined;
1978
+ }>;
1979
+ /**
1980
+ * The wire-format request body accepted by the onramp `createSession`
1981
+ * operation.
1982
+ *
1983
+ * @remarks
1984
+ * Shared between the server kit (`onrampServerKit.createSession`) and
1985
+ * the client-side REST fetcher (`fetchOnrampSession({ url, body })`).
1986
+ *
1987
+ * - `appUserId`: opaque host-controlled identifier (most hosts use their
1988
+ * internal primary key). Required so wallets-api can correlate a
1989
+ * session with the host's user record.
1990
+ * - `destinationAddress`: wallet that receives funds at the end of the
1991
+ * onramp flow. The widget displays this as a confirmation step but
1992
+ * the SDK does not validate it on the client beyond
1993
+ * "non-empty string" — wallets-api owns chain-specific validation.
1994
+ * - `destinationChain`: optional. Defaults to "Ethereum" inside
1995
+ * wallets-api. Pass to pre-select a chain in the widget.
1996
+ * - `amount`, `currency`: optional pre-fills.
1997
+ * - `email`: optional KYC routing hint.
1998
+ * - `assets`: optional host-app scoping for the asset selector (which
1999
+ * token/chain pairs the widget offers). See {@link OnrampAssetSelection}.
2000
+ * Baked into the launch URL at mint time; never forwarded to wallets-api.
2001
+ * - `metadata`: free-form passthrough — useful for re-stitching the
2002
+ * session back to the host's order ledger.
2003
+ *
2004
+ * Note: the embedding-domain allowlist entry (`referrerDomain`) is **not**
2005
+ * part of this request. It is a server-only concern configured on
2006
+ * {@link OnrampServerKitOptions.referrerDomain} so it can never be set from
2007
+ * a client-submitted body.
2008
+ */
2009
+ type OnrampSessionRequest = z.infer<typeof onrampSessionRequestSchema>;
2010
+
2011
+ /**
2012
+ * `createSession` type surface.
2013
+ *
2014
+ * @packageDocumentation
2015
+ */
2016
+
2017
+ /**
2018
+ * Parameters accepted by `onrampServerKit.createSession()`.
2019
+ *
2020
+ * @remarks
2021
+ * - `appUserId`: opaque host-controlled identifier (most hosts use their
2022
+ * internal primary key). Required so wallets-api can correlate a
2023
+ * session with the host's user record.
2024
+ * - `destinationAddress`: wallet that receives funds at the end of the
2025
+ * onramp flow. The widget displays this as a confirmation step but
2026
+ * the SDK does not validate it on the client beyond
2027
+ * "non-empty string" — wallets-api owns chain-specific validation.
2028
+ * - `destinationChain`: optional. Defaults to "Ethereum" inside
2029
+ * wallets-api. Pass to pre-select a chain in the widget.
2030
+ * - `amount`, `currency`: optional pre-fills.
2031
+ * - `email`: optional KYC routing hint.
2032
+ * - `metadata`: free-form passthrough — useful for re-stitching the
2033
+ * session back to the host's order ledger.
2034
+ */
2035
+ type CreateSessionParams = OnrampSessionRequest;
2036
+ /**
2037
+ * Strongly-typed handle to the `createSession` kit operation.
2038
+ *
2039
+ * @remarks
2040
+ * Exposed as a public type so host applications can pass the operation
2041
+ * around (e.g. dependency-injected into a route handler) without
2042
+ * losing param/result inference.
2043
+ */
2044
+ type CreateSessionOperation = KitOperation<CreateSessionParams, MintedOnrampSession>;
2045
+
2046
+ /**
2047
+ * Shared types for the onramp server kit factory and its operations.
2048
+ *
2049
+ * @packageDocumentation
2050
+ */
2051
+
2052
+ /**
2053
+ * Options accepted by {@link createOnrampServerKit}.
2054
+ *
2055
+ * @remarks
2056
+ * Apart from the credential, every field carries a sensible production
2057
+ * default and is exposed strictly so test rigs and staging environments
2058
+ * can override individual primitives without forking the SDK.
2059
+ */
2060
+ interface OnrampServerKitOptions {
2061
+ /**
2062
+ * Long-lived API credential issued by Circle to the host
2063
+ * application's server.
2064
+ *
2065
+ * @remarks
2066
+ * Use the value exactly as issued by the Circle console. Keys look like
2067
+ * `<ENV>_API_KEY:<keyId>:<keySecret>`. The kit sends it verbatim as a
2068
+ * bearer token (`Authorization: Bearer <value>`), so do not strip or
2069
+ * re-add the prefix.
2070
+ *
2071
+ * Must never be shipped to a browser. Use the resulting `sessionToken`
2072
+ * client-side instead.
2073
+ */
2074
+ readonly apiKey: string;
2075
+ /**
2076
+ * Override the wallets-api base URL.
2077
+ *
2078
+ * @remarks
2079
+ * Defaults to {@link DEFAULT_API_BASE_URL}. Override for staging
2080
+ * environments or local emulators.
2081
+ */
2082
+ readonly baseUrl?: string | undefined;
2083
+ /**
2084
+ * Override the hosted onramp widget origin.
2085
+ *
2086
+ * @remarks
2087
+ * Defaults to {@link DEFAULT_WIDGET_BASE_URL}. The server kit uses
2088
+ * this to compose `OnrampSession.widgetUrl` when wallets-api does
2089
+ * not return one. Override for staging environments.
2090
+ */
2091
+ readonly widgetBaseUrl?: string | undefined;
2092
+ /**
2093
+ * Bare hostname of the page that embeds the widget in an iframe, e.g.
2094
+ * `'portal.arc.io'`. Forwarded to the proxy, which seals it into the
2095
+ * session JWT and passes it to Transak as the `referrerDomain` claim so
2096
+ * the host page is authorized as a frame ancestor of Transak's inner
2097
+ * iframe (its `frame-ancestors` CSP).
2098
+ *
2099
+ * @remarks
2100
+ * Set it whenever you embed the widget in an iframe on your own site;
2101
+ * omit it when the widget runs as a top-level page or popup. Value
2102
+ * rules:
2103
+ *
2104
+ * - Hostname only — no scheme, port, path, or wildcard. Correct:
2105
+ * `'portal.arc.io'`. Wrong: `'https://portal.arc.io'`,
2106
+ * `'portal.arc.io:443'`, `'portal.arc.io/buy'`, `'*.arc.io'`.
2107
+ * - For a subdomain, pass the exact host the page is served from
2108
+ * (`'buy.arc.io'`), not the apex domain.
2109
+ *
2110
+ * This is a **server-only construction option**, not a per-session
2111
+ * parameter, precisely so it is derived from your own trusted config
2112
+ * (e.g. a per-environment constant) and can never be taken from a
2113
+ * client-submitted session request or an `Origin`/`Referer` header — a
2114
+ * client-supplied value would let a caller widen the frame-ancestor
2115
+ * allowlist.
2116
+ */
2117
+ readonly referrerDomain?: string | undefined;
2118
+ /**
2119
+ * Per-request timeout in milliseconds for outbound HTTP calls.
2120
+ *
2121
+ * @remarks
2122
+ * Defaults to {@link DEFAULT_REQUEST_TIMEOUT_MS} (15 s). Set to `0`
2123
+ * to disable timeouts (not recommended outside tests).
2124
+ */
2125
+ readonly requestTimeoutMs?: number | undefined;
2126
+ /**
2127
+ * Override the `fetch` implementation used for outbound HTTP.
2128
+ *
2129
+ * @remarks
2130
+ * Defaults to `globalThis.fetch`. Provide a custom function in
2131
+ * environments without a global `fetch`, in tests, or when you want
2132
+ * to thread Node's `undici` configuration explicitly.
2133
+ */
2134
+ readonly fetch?: typeof globalThis.fetch | undefined;
2135
+ /**
2136
+ * Optional extra HTTP headers merged onto every outbound request.
2137
+ *
2138
+ * @remarks
2139
+ * Useful for routing labels, internal proxy auth, or experiment
2140
+ * flags. The kit ignores reserved headers (`Authorization`,
2141
+ * `Content-Type`, `Accept`) to keep the wire format predictable.
2142
+ */
2143
+ readonly extraHeaders?: Readonly<Record<string, string>> | undefined;
2144
+ }
2145
+ /**
2146
+ * The fully-assembled server kit instance returned by
2147
+ * {@link createOnrampServerKit}.
2148
+ *
2149
+ * @remarks
2150
+ * The shape mirrors {@link Kit} from `@core/kit-base` — operation
2151
+ * methods plus the {@link KitEventSubscription} `on` / `off` pair backed
2152
+ * by the kit's runtime bus — but is hand-rolled so the public type stays
2153
+ * narrow (just `createSession`) without leaking the broader
2154
+ * operation-factory mapped-type machinery.
2155
+ */
2156
+ interface OnrampServerKit extends KitEventSubscription {
2157
+ /**
2158
+ * Mint a short-lived session for the embedded onramp widget.
2159
+ *
2160
+ * @see {@link CreateSessionOperation}
2161
+ */
2162
+ readonly createSession: CreateSessionOperation;
2163
+ }
2164
+
2165
+ /**
2166
+ * Options accepted by {@link createSessionRouteHandler}.
2167
+ */
2168
+ interface CreateSessionRouteHandlerOptions {
2169
+ /**
2170
+ * Authorize the inbound request before the session is minted.
2171
+ *
2172
+ * @remarks
2173
+ * Receives the raw {@link Request}. The handler is **fail-closed**:
2174
+ * only an explicit `true` or `undefined` (the "no opinion" return)
2175
+ * allows the request through. Any other value — `false`, `null`,
2176
+ * `0`, `''`, or an unexpected object from a plain-JS caller — short-
2177
+ * circuits with a `401`. Throw a {@link KitError} to surface a
2178
+ * custom status (see {@link createSessionRouteHandler} for the
2179
+ * type → status map).
2180
+ *
2181
+ * Common patterns:
2182
+ *
2183
+ * - Read your own host session cookie and assert the user is logged
2184
+ * in.
2185
+ * - Verify a CSRF token from the request headers.
2186
+ * - Apply rate limiting per-user before incurring the wallets-api
2187
+ * round-trip.
2188
+ *
2189
+ * @example
2190
+ * ```ts
2191
+ * createSessionRouteHandler(server, {
2192
+ * authorize: async (request) => {
2193
+ * const session = await getHostSession(request)
2194
+ * return session?.user != null
2195
+ * },
2196
+ * })
2197
+ * ```
2198
+ */
2199
+ readonly authorize?: ((request: Request) => boolean | undefined | Promise<boolean | undefined>) | undefined;
2200
+ /**
2201
+ * Side-channel hook for logging / metrics on every failure path.
2202
+ *
2203
+ * @remarks
2204
+ * Invoked with the original error (typed `unknown`) and the inbound
2205
+ * {@link Request}. Errors thrown from this hook are swallowed to
2206
+ * keep the response path deterministic; emit metrics here, do not
2207
+ * mutate state.
2208
+ *
2209
+ * Return value is ignored. The handler still maps the error to an
2210
+ * HTTP response in the usual way.
2211
+ */
2212
+ readonly onError?: ((error: unknown, request: Request) => void | Promise<void>) | undefined;
2213
+ }
2214
+ /**
2215
+ * Fetch-API request handler returned by
2216
+ * {@link createSessionRouteHandler}.
2217
+ */
2218
+ type SessionRouteHandler = (request: Request) => Promise<Response>;
2219
+ /**
2220
+ * Build a drop-in route handler that wraps
2221
+ * {@link OnrampServerKit.createSession}.
2222
+ *
2223
+ * @remarks
2224
+ * **Security — read before deploying.** This handler is
2225
+ * **unauthenticated by default**: without an `authorize` hook it will
2226
+ * mint a session for any caller that POSTs a well-formed body, which
2227
+ * burns your API-key quota and lets anyone drive the onramp flow with
2228
+ * an attacker-chosen `destinationAddress`. Always pass an `authorize`
2229
+ * callback (host-session check, CSRF token, and/or per-user rate
2230
+ * limiting) in production. The kit cannot supply a safe default
2231
+ * because authentication is host-specific.
2232
+ *
2233
+ * Behaviour:
2234
+ *
2235
+ * - Accepts `POST` only (returns `405` otherwise).
2236
+ * - Validates the JSON body via {@link parseOnrampSessionRequest};
2237
+ * `400` on shape mismatch.
2238
+ * - Calls `serverKit.createSession(body)` and returns the resulting
2239
+ * session as JSON (`200`).
2240
+ * - Maps thrown {@link KitError}s to HTTP status:
2241
+ * `INPUT` → 400, `NETWORK` → 504, `RATE_LIMIT` → 429,
2242
+ * `SERVICE` / `RPC` → 502, `UNKNOWN` and everything else → 500.
2243
+ * - Sets `Cache-Control: no-store` on every response — session
2244
+ * tokens are short-lived and must never be cached by intermediaries.
2245
+ * - **Never** echoes the upstream wallets-api response body in the
2246
+ * error payload (the underlying `createSession` operation already
2247
+ * scrubs it); only `{ code, name, type, message }` from the
2248
+ * `KitError` is exposed to the client.
2249
+ *
2250
+ * Hosts that need bespoke error handling, response shaping, or non-
2251
+ * Fetch-API runtimes (Express, Fastify) should keep calling
2252
+ * `serverKit.createSession()` directly.
2253
+ *
2254
+ * @param serverKit - An {@link OnrampServerKit} returned by
2255
+ * {@link createOnrampServerKit}.
2256
+ * @param options - Optional hooks (auth, error logging).
2257
+ * @returns A `(request: Request) => Promise<Response>` handler.
2258
+ *
2259
+ * @example Next.js App Router (one-liner)
2260
+ * ```ts
2261
+ * // app/api/onramp/sessions/route.ts
2262
+ * import {
2263
+ * createOnrampServerKit,
2264
+ * createSessionRouteHandler,
2265
+ * } from '@circle-fin/onramp-kit/server'
2266
+ *
2267
+ * const server = createOnrampServerKit({ apiKey: process.env.ONRAMP_API_KEY! })
2268
+ * export const POST = createSessionRouteHandler(server)
2269
+ * ```
2270
+ *
2271
+ * @example With an authn check
2272
+ * ```ts
2273
+ * import { auth } from '@/lib/auth'
2274
+ *
2275
+ * export const POST = createSessionRouteHandler(server, {
2276
+ * authorize: async (request) => {
2277
+ * const session = await auth(request)
2278
+ * return session?.user != null
2279
+ * },
2280
+ * })
2281
+ * ```
2282
+ */
2283
+ declare function createSessionRouteHandler(serverKit: OnrampServerKit, options?: CreateSessionRouteHandlerOptions): SessionRouteHandler;
2284
+
2285
+ /**
2286
+ * Identity for the server surface.
2287
+ *
2288
+ * @remarks
2289
+ * Shares the same `name` and `version` as {@link ONRAMP_KIT_IDENTITY}
2290
+ * but is exported under a distinct symbol so callers that import both
2291
+ * surfaces in the same module get clean autocompletion (`OnrampKit` vs
2292
+ * `OnrampServerKit`).
2293
+ */
2294
+ declare const ONRAMP_SERVER_KIT_IDENTITY: {
2295
+ readonly name: "onramp-kit";
2296
+ readonly version: string;
2297
+ };
2298
+
2299
+ /**
2300
+ * Coerce an unknown value into an {@link OnrampSession}.
2301
+ *
2302
+ * @param value - Value of unknown shape, typically the JSON-decoded
2303
+ * body of a host-app session endpoint.
2304
+ * @returns The session, with the `{ data }` envelope unwrapped when
2305
+ * present.
2306
+ *
2307
+ * @throws KitError - `INPUT_INVALID_SESSION` (code `1904`) when the
2308
+ * value (after envelope unwrapping) is not a non-null object — i.e.
2309
+ * not a usable session at all.
2310
+ *
2311
+ * @remarks
2312
+ * This helper does **not** assert a closed session schema — by design.
2313
+ * The kit never pins the Onramp API response to a fixed shape, so an
2314
+ * additive API change (a new field, a new optional) cannot break it.
2315
+ * The only checks are unwrapping the `{ data: session }` envelope (some
2316
+ * hosts proxy it straight through) and a minimal structural guard that
2317
+ * the result is a non-null object, so the returned value is at least
2318
+ * minimally backed rather than an unchecked cast. The security-critical
2319
+ * checks (https scheme, origin pin, expiry) still run later in
2320
+ * `getOnrampUrl`, right before the URL reaches the DOM.
2321
+ *
2322
+ * @example
2323
+ * ```ts
2324
+ * const session = parseOnrampSession(await response.json())
2325
+ * onramp.mountIframe({ session, container })
2326
+ * ```
2327
+ */
2328
+ declare function parseOnrampSession(value: unknown): OnrampSession;
2329
+ /**
2330
+ * Parse an unknown value as an {@link OnrampSessionRequest}.
2331
+ *
2332
+ * @param value - Value of unknown shape, typically the JSON-decoded
2333
+ * request body received by a host-app session minting endpoint.
2334
+ * @returns The validated request body.
2335
+ *
2336
+ * @throws KitError - When the value does not satisfy the request
2337
+ * schema.
2338
+ *
2339
+ * @example
2340
+ * ```ts
2341
+ * app.post('/api/onramp/sessions', async (req, res) => {
2342
+ * const body = parseOnrampSessionRequest(await req.json())
2343
+ * const session = await onrampServerKit.createSession(body)
2344
+ * res.json(session)
2345
+ * })
2346
+ * ```
2347
+ */
2348
+ declare function parseOnrampSessionRequest(value: unknown): OnrampSessionRequest;
2349
+
2350
+ /**
2351
+ * Factory for `@circle-fin/app-kit/server`.
2352
+ *
2353
+ * @remarks
2354
+ * Composes the server-only sub-kits that AppKit ships. Today there
2355
+ * is one: `onramp`, an {@link OnrampServerKit} that mints onramp
2356
+ * sessions using the host's long-lived `apiKey`. The factory is the
2357
+ * only place that touches the secret — by keeping it behind a
2358
+ * dedicated `/server` entry, bundlers reliably exclude it from
2359
+ * browser builds.
2360
+ *
2361
+ * @packageDocumentation
2362
+ */
2363
+
2364
+ /**
2365
+ * Onramp slice of {@link AppServerKitConfig}.
2366
+ *
2367
+ * @remarks
2368
+ * Re-exported here as a named type so consumers do not need to
2369
+ * reach into `@circle-fin/onramp-kit/server` for the option shape.
2370
+ */
2371
+ type AppServerKitOnrampConfig = OnrampServerKitOptions;
2372
+ /**
2373
+ * Options accepted by {@link createAppServerKit}.
2374
+ *
2375
+ * @example
2376
+ * ```typescript
2377
+ * import { createAppServerKit } from '@circle-fin/app-kit/server'
2378
+ *
2379
+ * const server = createAppServerKit({
2380
+ * onramp: {
2381
+ * apiKey: process.env.ONRAMP_API_KEY!,
2382
+ * // Required when embedding the widget in an iframe — the bare
2383
+ * // hostname of your embedding page.
2384
+ * referrerDomain: 'portal.arc.io',
2385
+ * },
2386
+ * })
2387
+ * ```
2388
+ */
2389
+ interface AppServerKitConfig {
2390
+ /**
2391
+ * Configuration for the onramp server kit (session minting).
2392
+ *
2393
+ * @remarks
2394
+ * `apiKey` is required. If you embed the widget in an iframe, also set
2395
+ * `referrerDomain` (the bare hostname of your embedding page) — it has
2396
+ * no default and authorizes that page as a frame ancestor of the
2397
+ * provider's iframe. All remaining fields carry sensible production
2398
+ * defaults — see {@link OnrampServerKitOptions}.
2399
+ */
2400
+ readonly onramp: AppServerKitOnrampConfig;
2401
+ }
2402
+ /**
2403
+ * Fully-assembled server kit for `@circle-fin/app-kit/server`.
2404
+ *
2405
+ * @remarks
2406
+ * Hand-rolled namespace surface so additional server-only kits can
2407
+ * slot in over time without leaking implementation types into the
2408
+ * public API.
2409
+ *
2410
+ * @example
2411
+ * ```typescript
2412
+ * import {
2413
+ * createAppServerKit,
2414
+ * createSessionRouteHandler,
2415
+ * } from '@circle-fin/app-kit/server'
2416
+ *
2417
+ * const server = createAppServerKit({
2418
+ * onramp: { apiKey: process.env.ONRAMP_API_KEY! },
2419
+ * })
2420
+ *
2421
+ * export const POST = createSessionRouteHandler(server.onramp)
2422
+ * ```
2423
+ */
2424
+ interface AppServerKit {
2425
+ /**
2426
+ * Server-side onramp surface — mints sessions for the embedded
2427
+ * onramp widget.
2428
+ *
2429
+ * @remarks
2430
+ * Pass `server.onramp` straight to `createSessionRouteHandler` to
2431
+ * mount the canonical session endpoint, or call
2432
+ * `server.onramp.createSession(params)` from a custom handler.
2433
+ */
2434
+ readonly onramp: OnrampServerKit;
2435
+ }
2436
+ /**
2437
+ * Build the app server kit.
2438
+ *
2439
+ * @param config - {@link AppServerKitConfig}.
2440
+ * @returns A frozen {@link AppServerKit} ready to mint sessions.
2441
+ *
2442
+ * @throws KitError - When `config` is not an object, `config.onramp`
2443
+ * is missing / non-object, or the wrapped onramp factory rejects
2444
+ * its options (invalid `apiKey`, malformed URL overrides, etc.).
2445
+ *
2446
+ * @remarks
2447
+ * Stateless beyond closures. Cache one instance per app.
2448
+ *
2449
+ * @example
2450
+ * ```typescript
2451
+ * import {
2452
+ * createAppServerKit,
2453
+ * createSessionRouteHandler,
2454
+ * } from '@circle-fin/app-kit/server'
2455
+ *
2456
+ * const server = createAppServerKit({
2457
+ * onramp: { apiKey: process.env.ONRAMP_API_KEY! },
2458
+ * })
2459
+ *
2460
+ * // Wire the session route in one line:
2461
+ * export const POST = createSessionRouteHandler(server.onramp)
2462
+ * ```
2463
+ */
2464
+ declare function createAppServerKit(config: AppServerKitConfig): AppServerKit;
2465
+
2466
+ export { KitError, ONRAMP_SERVER_KIT_IDENTITY, createAppServerKit, onrampSessionRequestSchema as createSessionParamsSchema, createSessionRouteHandler, parseOnrampSession, parseOnrampSessionRequest };
2467
+ export type { AppServerKit, AppServerKitConfig, AppServerKitOnrampConfig, CreateSessionOperation, CreateSessionParams, CreateSessionRouteHandlerOptions, MintedOnrampSession, OnrampServerKit, OnrampServerKitOptions, OnrampSession, OnrampSessionRequest, SessionRouteHandler };