@circle-fin/adapter-ethers-v6 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -35,7 +35,6 @@ import { TransactionInstruction, Signer, AddressLookupTableAccount } from '@sola
35
35
  */
36
36
  /**
37
37
  * Represents basic information about a currency or token.
38
- * @interface Currency
39
38
  * @category Types
40
39
  * @description Provides the essential properties of a cryptocurrency or token.
41
40
  * @example
@@ -67,7 +66,6 @@ interface Currency {
67
66
  }
68
67
  /**
69
68
  * Base information that all chain definitions must include.
70
- * @interface BaseChainDefinition
71
69
  * @category Types
72
70
  * @description Provides the common properties shared by all blockchain definitions.
73
71
  * @example
@@ -127,6 +125,11 @@ interface BaseChainDefinition {
127
125
  * @description Its presence indicates that USDC is supported.
128
126
  */
129
127
  usdcAddress: string | null;
128
+ /**
129
+ * The contract address for USDT.
130
+ * @description Its presence indicates that USDT is supported.
131
+ */
132
+ usdtAddress: string | null;
130
133
  /**
131
134
  * Optional CCTP configuration.
132
135
  * @description If provided, the chain supports CCTP.
@@ -168,7 +171,6 @@ interface BaseChainDefinition {
168
171
  }
169
172
  /**
170
173
  * Represents chain definitions for Ethereum Virtual Machine (EVM) compatible blockchains.
171
- * @interface EVMChainDefinition
172
174
  * @extends BaseChainDefinition
173
175
  * @category Types
174
176
  * @description Adds properties specific to EVM chains.
@@ -200,7 +202,6 @@ interface EVMChainDefinition extends BaseChainDefinition {
200
202
  }
201
203
  /**
202
204
  * Represents chain definitions for non-EVM blockchains.
203
- * @interface NonEVMChainDefinition
204
205
  * @extends BaseChainDefinition
205
206
  * @category Types
206
207
  * @description Contains properties for blockchains that do not use the EVM.
@@ -253,6 +254,7 @@ type ChainType = EVMChainDefinition['type'] | NonEVMChainDefinition['type'];
253
254
  * rpcEndpoints: ['https://eth.example.com'],
254
255
  * eurcAddress: null,
255
256
  * usdcAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
257
+ * usdtAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
256
258
  * cctp: {
257
259
  * domain: 0,
258
260
  * contracts: {
@@ -316,17 +318,74 @@ type ChainDefinitionWithCCTPv2 = ChainDefinition & {
316
318
  * - A string literal of the blockchain value (e.g., "Ethereum")
317
319
  */
318
320
  type ChainIdentifier = ChainDefinition | Blockchain | `${Blockchain}`;
321
+ /**
322
+ * Split CCTP contract configuration.
323
+ *
324
+ * Used by chains that deploy separate TokenMessenger and MessageTransmitter contracts.
325
+ * This is the traditional CCTP architecture used by most EVM chains.
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * const splitConfig: CCTPSplitConfig = {
330
+ * type: 'split',
331
+ * tokenMessenger: '0x1234567890abcdef1234567890abcdef12345678',
332
+ * messageTransmitter: '0xabcdef1234567890abcdef1234567890abcdef12',
333
+ * confirmations: 12
334
+ * }
335
+ * ```
336
+ */
319
337
  interface CCTPSplitConfig {
320
338
  type: 'split';
321
339
  tokenMessenger: string;
322
340
  messageTransmitter: string;
323
341
  confirmations: number;
324
342
  }
343
+ /**
344
+ * Merged CCTP contract configuration.
345
+ *
346
+ * Used by chains that deploy a single unified CCTP contract.
347
+ * This simplified architecture is used by newer chain integrations.
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * const mergedConfig: CCTPMergedConfig = {
352
+ * type: 'merged',
353
+ * contract: '0x9876543210fedcba9876543210fedcba98765432',
354
+ * confirmations: 1
355
+ * }
356
+ * ```
357
+ */
325
358
  interface CCTPMergedConfig {
326
359
  type: 'merged';
327
360
  contract: string;
328
361
  confirmations: number;
329
362
  }
363
+ /**
364
+ * Version configuration for CCTP contracts.
365
+ *
366
+ * Defines whether the chain uses split or merged CCTP contract architecture.
367
+ * Split configuration uses separate TokenMessenger and MessageTransmitter contracts,
368
+ * while merged configuration uses a single unified contract.
369
+ *
370
+ * @example Split configuration (most EVM chains)
371
+ * ```typescript
372
+ * const splitConfig: VersionConfig = {
373
+ * type: 'split',
374
+ * tokenMessenger: '0x1234567890abcdef1234567890abcdef12345678',
375
+ * messageTransmitter: '0xabcdef1234567890abcdef1234567890abcdef12',
376
+ * confirmations: 12
377
+ * }
378
+ * ```
379
+ *
380
+ * @example Merged configuration (newer chains)
381
+ * ```typescript
382
+ * const mergedConfig: VersionConfig = {
383
+ * type: 'merged',
384
+ * contract: '0x9876543210fedcba9876543210fedcba98765432',
385
+ * confirmations: 1
386
+ * }
387
+ * ```
388
+ */
330
389
  type VersionConfig = CCTPSplitConfig | CCTPMergedConfig;
331
390
  type CCTPContracts = Partial<{
332
391
  v1: VersionConfig;
@@ -336,7 +395,6 @@ type CCTPContracts = Partial<{
336
395
  }>;
337
396
  /**
338
397
  * Configuration for the Cross-Chain Transfer Protocol (CCTP).
339
- * @interface CCTPConfig
340
398
  * @category Types
341
399
  * @description Contains the domain and required contract addresses for CCTP support.
342
400
  * @example
@@ -390,7 +448,7 @@ interface CCTPConfig {
390
448
  * const invalidType: KitContractType = 'invalid' // TypeScript error
391
449
  * ```
392
450
  */
393
- type KitContractType = 'bridge';
451
+ type KitContractType = 'bridge' | 'adapter';
394
452
  /**
395
453
  * Kit-specific contract addresses for enhanced chain functionality.
396
454
  *
@@ -443,6 +501,8 @@ declare enum Blockchain {
443
501
  Celo_Alfajores_Testnet = "Celo_Alfajores_Testnet",
444
502
  Codex = "Codex",
445
503
  Codex_Testnet = "Codex_Testnet",
504
+ Edge = "Edge",
505
+ Edge_Testnet = "Edge_Testnet",
446
506
  Ethereum = "Ethereum",
447
507
  Ethereum_Sepolia = "Ethereum_Sepolia",
448
508
  Hedera = "Hedera",
@@ -455,6 +515,8 @@ declare enum Blockchain {
455
515
  Linea_Sepolia = "Linea_Sepolia",
456
516
  Monad = "Monad",
457
517
  Monad_Testnet = "Monad_Testnet",
518
+ Morph = "Morph",
519
+ Morph_Testnet = "Morph_Testnet",
458
520
  NEAR = "NEAR",
459
521
  NEAR_Testnet = "NEAR_Testnet",
460
522
  Noble = "Noble",
@@ -661,8 +723,20 @@ type EvmPreparedChainRequestParams = {
661
723
  interface SolanaPreparedChainRequestParams {
662
724
  /**
663
725
  * The array of instructions to include in the transaction.
726
+ *
727
+ * @remarks
728
+ * Used for instruction-based transaction building. Mutually exclusive with
729
+ * `serializedTransaction`.
730
+ */
731
+ instructions?: TransactionInstruction[];
732
+ /**
733
+ * A pre-serialized transaction as a Uint8Array (e.g., from a service like Jupiter).
734
+ *
735
+ * @remarks
736
+ * Used for executing pre-built transactions from external services.
737
+ * The transaction may be partially signed. Mutually exclusive with `instructions`.
664
738
  */
665
- instructions: TransactionInstruction[];
739
+ serializedTransaction?: Uint8Array;
666
740
  /**
667
741
  * Additional signers besides the Adapter's wallet (e.g. program-derived authorities).
668
742
  */
@@ -1459,31 +1533,443 @@ interface CCTPActionMap {
1459
1533
  }
1460
1534
 
1461
1535
  /**
1462
- * Action map for native token operations (ETH, SOL, MATIC, etc.).
1536
+ * Permit signature standards for gasless token approvals.
1463
1537
  *
1464
- * Native tokens are the primary currency of each blockchain network,
1465
- * used for paying transaction fees and as a store of value.
1466
- * These actions operate on the native token without requiring
1467
- * a separate token contract address.
1538
+ * Defines the permit types that can be used to approve token spending
1539
+ * without requiring a separate approval transaction.
1468
1540
  *
1469
1541
  * @remarks
1470
- * Native token operations differ from ERC-20/SPL token operations
1471
- * in that they don't require contract interactions for basic transfers
1472
- * and balance checks.
1542
+ * - NONE: No permit, tokens must be pre-approved via separate transaction
1543
+ * - EIP2612: Standard ERC-20 permit (USDC, DAI v2, and most modern tokens)
1544
+ */
1545
+ declare enum PermitType {
1546
+ /** No permit required - tokens must be pre-approved */
1547
+ NONE = 0,
1548
+ /** EIP-2612 standard permit */
1549
+ EIP2612 = 1
1550
+ }
1551
+ /**
1552
+ * Token input with permit signature for gasless approval.
1553
+ *
1554
+ * The Adapter Contract uses this to pull tokens from the user's wallet
1555
+ * using permit signatures instead of requiring separate approval transactions.
1473
1556
  *
1474
- * @see {@link ActionMap} for the complete action structure
1557
+ * @example
1558
+ * ```typescript
1559
+ * const tokenInput: TokenInput = {
1560
+ * permitType: PermitType.EIP2612,
1561
+ * token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1562
+ * from: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
1563
+ * amount: 1000000n, // 1 USDC
1564
+ * permitCalldata: '0x...' // Encoded permit(value, deadline, v, r, s)
1565
+ * }
1566
+ * ```
1475
1567
  */
1476
- interface NativeActionMap {
1568
+ interface TokenInput {
1477
1569
  /**
1478
- * Get the native token balance (SOL, ETH, etc.) for a wallet address.
1570
+ * Type of permit to execute.
1479
1571
  */
1480
- balanceOf: ActionParameters & {
1481
- /**
1482
- * The address to check the native balance for. If not provided, it will be
1483
- * automatically derived from the adapter context.
1484
- */
1485
- walletAddress?: string | undefined;
1486
- };
1572
+ permitType: PermitType;
1573
+ /**
1574
+ * Token contract address to pull from user.
1575
+ */
1576
+ token: `0x${string}`;
1577
+ /**
1578
+ * Amount of tokens to pull via permit.
1579
+ */
1580
+ amount: bigint;
1581
+ /**
1582
+ * ABI-encoded permit calldata.
1583
+ *
1584
+ * For EIP-2612: encode(value, deadline, v, r, s)
1585
+ * For Permit2: encode(permit, signature)
1586
+ *
1587
+ * @example '0x0000000000000000000000000000000000000000000000000000000000989680...'
1588
+ */
1589
+ permitCalldata: `0x${string}`;
1590
+ }
1591
+ /**
1592
+ * Single instruction to execute within the Adapter Contract.
1593
+ *
1594
+ * Each instruction represents a contract call (swap, fee collection, etc.)
1595
+ * with pre-execution approval and post-execution validation.
1596
+ *
1597
+ * @example
1598
+ * ```typescript
1599
+ * const swapInstruction: Instruction = {
1600
+ * target: '0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE', // LiFi Diamond
1601
+ * data: '0x...', // LiFi swap calldata
1602
+ * value: 0n,
1603
+ * tokenIn: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1604
+ * amountToApprove: 1000000000n, // 1000 USDC to approve
1605
+ * tokenOut: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
1606
+ * minTokenOut: 995000000n // 995 USDT minimum (0.5% slippage)
1607
+ * }
1608
+ * ```
1609
+ */
1610
+ interface Instruction {
1611
+ /**
1612
+ * Target contract address to call.
1613
+ *
1614
+ * Can be a DEX router, fee taker contract, or token contract.
1615
+ */
1616
+ target: `0x${string}`;
1617
+ /**
1618
+ * ABI-encoded calldata for the target contract.
1619
+ */
1620
+ data: `0x${string}`;
1621
+ /**
1622
+ * ETH value to send with the call (for native token operations).
1623
+ *
1624
+ * @defaultValue 0n
1625
+ */
1626
+ value: bigint;
1627
+ /**
1628
+ * Token to approve to target before executing instruction.
1629
+ *
1630
+ * Set to zero address (0x00...00) to disable pre-approval.
1631
+ */
1632
+ tokenIn: `0x${string}`;
1633
+ /**
1634
+ * Amount of tokenIn to approve to target before executing instruction.
1635
+ *
1636
+ * @remarks
1637
+ * Field name matches the adapter contract's `amountToApprove` parameter exactly.
1638
+ *
1639
+ * @defaultValue 0n if tokenIn is zero address
1640
+ */
1641
+ amountToApprove: bigint;
1642
+ /**
1643
+ * Token to validate minimum balance after instruction.
1644
+ *
1645
+ * Set to zero address (0x00...00) to disable post-validation.
1646
+ */
1647
+ tokenOut: `0x${string}`;
1648
+ /**
1649
+ * Minimum required balance of tokenOut after instruction.
1650
+ *
1651
+ * @defaultValue 0n if tokenOut is zero address
1652
+ */
1653
+ minTokenOut: bigint;
1654
+ }
1655
+ /**
1656
+ * Token recipient for residual sweep.
1657
+ *
1658
+ * After all instructions complete, the Adapter Contract sweeps
1659
+ * any remaining balances to the specified beneficiaries.
1660
+ */
1661
+ interface TokenRecipient {
1662
+ /**
1663
+ * Token contract address to sweep.
1664
+ */
1665
+ token: `0x${string}`;
1666
+ /**
1667
+ * Address to receive swept tokens.
1668
+ */
1669
+ beneficiary: `0x${string}`;
1670
+ }
1671
+ /**
1672
+ * Execution parameters for the Adapter Contract.
1673
+ *
1674
+ * This struct is signed via EIP-712 by the Circle proxy and verified
1675
+ * on-chain to ensure the execution is authorized.
1676
+ *
1677
+ * @remarks
1678
+ * The executeParams are provided by the stablecoin-service and must be
1679
+ * passed to the Adapter Contract exactly as received (no modification).
1680
+ *
1681
+ * @example
1682
+ * ```typescript
1683
+ * const executeParams: ExecuteParams = {
1684
+ * instructions: [
1685
+ * { target: dexRouter, data: swapCalldata, ... }
1686
+ * ],
1687
+ * tokens: [
1688
+ * { token: USDC, beneficiary: userAddress },
1689
+ * { token: USDT, beneficiary: userAddress }
1690
+ * ],
1691
+ * execId: 123456789n,
1692
+ * deadline: BigInt(Math.floor(Date.now() / 1000) + 1800),
1693
+ * metadata: '0x'
1694
+ * }
1695
+ * ```
1696
+ */
1697
+ interface ExecuteParams {
1698
+ /**
1699
+ * Array of instructions to execute sequentially.
1700
+ *
1701
+ * Each instruction can be a swap, fee collection, or other contract call.
1702
+ */
1703
+ instructions: Instruction[];
1704
+ /**
1705
+ * Token recipients for residual sweep.
1706
+ *
1707
+ * Typically a 2-tuple: [tokenIn recipient, tokenOut recipient]
1708
+ */
1709
+ tokens: TokenRecipient[];
1710
+ /**
1711
+ * Unique execution identifier for replay protection.
1712
+ *
1713
+ * Must be globally unique and is marked as used after execution.
1714
+ */
1715
+ execId: bigint;
1716
+ /**
1717
+ * Execution deadline timestamp (Unix seconds).
1718
+ *
1719
+ * Transaction reverts if block.timestamp is greater than deadline.
1720
+ */
1721
+ deadline: bigint;
1722
+ /**
1723
+ * Optional metadata for tracking and analytics.
1724
+ */
1725
+ metadata: `0x${string}`;
1726
+ }
1727
+ /**
1728
+ * Parameters for executing a swap transaction via the Adapter smart contract.
1729
+ *
1730
+ * This action executes swap transactions through the Adapter Contract, which
1731
+ * handles token approvals via permits (EIP-2612, Permit2, etc.) and executes
1732
+ * multi-step swap instructions atomically on-chain.
1733
+ *
1734
+ * @remarks
1735
+ * The swap flow uses the Adapter Contract pattern:
1736
+ * 1. Service provides `executeParams` and `signature` (proxy-signed EIP-712)
1737
+ * 2. SDK builds `tokenInputs` with permit signatures for gasless approvals
1738
+ * 3. SDK calls AdapterContract.execute(executeParams, tokenInputs, signature)
1739
+ * 4. Adapter Contract pulls tokens via permits, executes swaps, validates outputs
1740
+ *
1741
+ * This enables:
1742
+ * - Single atomic transaction (permit + swap in one tx)
1743
+ * - Gasless approvals via EIP-2612/Permit2
1744
+ * - Slippage protection enforced on-chain
1745
+ * - Multi-step instructions (swap + fees) atomically
1746
+ *
1747
+ * **Permit Support**: The SDK constructs `TokenInput` with `permitCalldata`
1748
+ * containing the encoded permit signature. The Adapter Contract executes
1749
+ * the permit on-chain before pulling tokens.
1750
+ *
1751
+ * @example
1752
+ * ```typescript
1753
+ * import type { ExecuteSwapParams } from '@core/adapter'
1754
+ * import { createSwap } from '@core/service-client'
1755
+ * import { PermitType } from '@core/adapter'
1756
+ *
1757
+ * // Get swap transaction from service
1758
+ * const swapResponse = await createSwap({
1759
+ * tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1760
+ * tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
1761
+ * tokenInChain: 'Ethereum',
1762
+ * fromAddress: '0x...',
1763
+ * toAddress: '0x...',
1764
+ * amount: '1000000',
1765
+ * apiKey: 'KIT_KEY:...',
1766
+ * })
1767
+ *
1768
+ * // Build token inputs with permit
1769
+ * const tokenInputs: TokenInput[] = [{
1770
+ * permitType: PermitType.EIP2612,
1771
+ * token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1772
+ * from: userAddress,
1773
+ * amount: 1000000n,
1774
+ * permitCalldata: '0x...' // Encoded permit signature
1775
+ * }]
1776
+ *
1777
+ * // Prepare action parameters
1778
+ * const params: ExecuteSwapParams = {
1779
+ * executeParams: swapResponse.transaction.executeParams,
1780
+ * tokenInputs,
1781
+ * signature: swapResponse.transaction.signature,
1782
+ * inputAmount: BigInt(swapResponse.amount),
1783
+ * tokenInAddress: swapResponse.tokenInAddress as `0x${string}`
1784
+ * }
1785
+ * ```
1786
+ */
1787
+ interface ExecuteSwapEVMParams extends ActionParameters {
1788
+ /**
1789
+ * Execution parameters from the stablecoin-service.
1790
+ *
1791
+ * Contains instructions, token recipients, execution ID, deadline, and metadata.
1792
+ * This is an EIP-712 signed struct that the Adapter Contract validates.
1793
+ *
1794
+ * Provided by the service - do not modify.
1795
+ */
1796
+ executeParams: ExecuteParams;
1797
+ /**
1798
+ * Token inputs with permit signatures for gasless approvals.
1799
+ *
1800
+ * The SDK constructs this array with permit data for each token that needs
1801
+ * to be pulled from the user's wallet. The Adapter Contract executes these
1802
+ * permits on-chain before executing swap instructions.
1803
+ *
1804
+ * @remarks
1805
+ * For EIP-2612 permits, the SDK must:
1806
+ * 1. Build typed data with token, spender (Adapter), amount, nonce, deadline
1807
+ * 2. Get user signature via `adapter.signTypedData()`
1808
+ * 3. Encode as permitCalldata: encode(value, deadline, v, r, s)
1809
+ *
1810
+ * @example
1811
+ * ```typescript
1812
+ * [{
1813
+ * permitType: PermitType.EIP2612,
1814
+ * token: '0xUSDC',
1815
+ * from: userAddress,
1816
+ * amount: 1000000n,
1817
+ * permitCalldata: '0x...'
1818
+ * }]
1819
+ * ```
1820
+ */
1821
+ tokenInputs: TokenInput[];
1822
+ /**
1823
+ * EIP-712 signature from the Circle proxy service.
1824
+ *
1825
+ * The service signs the executeParams to authorize the execution.
1826
+ * The Adapter Contract verifies this signature on-chain.
1827
+ *
1828
+ * Provided by the service - do not modify.
1829
+ */
1830
+ signature: `0x${string}`;
1831
+ /**
1832
+ * Swap input amount in base units.
1833
+ *
1834
+ * @remarks
1835
+ * The amount of tokens being swapped, provided in the token's base units (e.g., wei for ETH,
1836
+ * smallest denomination for ERC20 tokens). This value should be extracted from the service
1837
+ * response, as it represents the authoritative swap amount for the operation.
1838
+ *
1839
+ * For native currency swaps (ETH → USDC), this amount is sent as the transaction `value`.
1840
+ * For ERC20 swaps (USDC → USDT), this amount determines the permit or approval quantity.
1841
+ *
1842
+ * @see CreateSwapResponse.amount - Service response field containing this value
1843
+ *
1844
+ * @example
1845
+ * ```typescript
1846
+ * import { createSwap } from '@core/service-client'
1847
+ *
1848
+ * // Get swap transaction from service
1849
+ * const response = await createSwap({
1850
+ * tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1851
+ * amount: '1000000', // 1 USDC (6 decimals)
1852
+ * ...
1853
+ * })
1854
+ *
1855
+ * // Prepare swap execution using service response amount
1856
+ * await adapter.prepareAction('swap.execute', {
1857
+ * executeParams: response.transaction.executeParams,
1858
+ * tokenInputs,
1859
+ * signature: response.transaction.signature,
1860
+ * inputAmount: BigInt(response.amount),
1861
+ * tokenInAddress: response.tokenInAddress,
1862
+ * }, context)
1863
+ * ```
1864
+ */
1865
+ inputAmount: bigint;
1866
+ /**
1867
+ * Token address being swapped from.
1868
+ *
1869
+ * @remarks
1870
+ * Used to determine if the swap involves native currency (ETH, MATIC, etc.) or ERC20 tokens.
1871
+ * When tokenInAddress is NATIVE_TOKEN_ADDRESS (0xEeee...), the inputAmount is sent as tx.value.
1872
+ *
1873
+ * @see CreateSwapResponse.tokenInAddress - Service response field containing this value
1874
+ *
1875
+ * @example '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' for ETH
1876
+ * @example '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC
1877
+ */
1878
+ tokenInAddress: `0x${string}`;
1879
+ }
1880
+ /**
1881
+ * Parameters for executing a swap transaction on Solana.
1882
+ *
1883
+ * This action executes swap transactions on Solana chains by deserializing
1884
+ * and executing a pre-built transaction provided by the stablecoin-service.
1885
+ *
1886
+ * @remarks
1887
+ * Unlike EVM chains that use the Adapter Contract pattern, Solana swaps
1888
+ * execute a fully serialized transaction provided by the service. The
1889
+ * transaction is base64-encoded and contains all necessary instructions
1890
+ * for the swap operation.
1891
+ *
1892
+ * The service handles:
1893
+ * - DEX aggregator routing (Jupiter, etc.)
1894
+ * - Fee collection
1895
+ * - Slippage protection
1896
+ * - Token account management
1897
+ *
1898
+ * @example
1899
+ * ```typescript
1900
+ * import type { ExecuteSwapSolanaParams } from '@core/adapter'
1901
+ * import { createSwap } from '@core/service-client'
1902
+ *
1903
+ * // Get swap transaction from service
1904
+ * const swapResponse = await createSwap({
1905
+ * tokenInAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1906
+ * tokenOutAddress: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
1907
+ * tokenInChain: 'Solana',
1908
+ * fromAddress: 'YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP',
1909
+ * toAddress: 'YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP',
1910
+ * amount: '1000000',
1911
+ * apiKey: 'KIT_KEY:...',
1912
+ * })
1913
+ *
1914
+ * // Prepare action parameters
1915
+ * const params: ExecuteSwapSolanaParams = {
1916
+ * serializedTransaction: swapResponse.transaction.data
1917
+ * }
1918
+ * ```
1919
+ */
1920
+ interface ExecuteSwapSolanaParams extends ActionParameters {
1921
+ /**
1922
+ * Base64-encoded serialized Solana transaction.
1923
+ *
1924
+ * This transaction is fully constructed by the stablecoin-service and
1925
+ * contains all swap instructions, fee payments, and token account setup.
1926
+ * The transaction must be deserialized, signed, and submitted to the network.
1927
+ *
1928
+ * Provided by the service - do not modify.
1929
+ *
1930
+ * @example 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAJFQg...'
1931
+ */
1932
+ serializedTransaction: string;
1933
+ }
1934
+ /**
1935
+ * Parameters accepted by the swap.execute action, supporting both EVM and Solana chains.
1936
+ *
1937
+ * @remarks
1938
+ * This union type covers all chain-specific swap execution parameter interfaces
1939
+ * currently supported by the App Kit. Extend this union to support
1940
+ * additional blockchains as needed. Each member provides all fields required
1941
+ * to prepare and execute a pre-built swap transaction on its respective chain.
1942
+ *
1943
+ * **Type Narrowing**: The correct parameter type is inferred from the chain type
1944
+ * in the `OperationContext` passed to `adapter.prepareAction()`. Action handlers
1945
+ * use property-based type guards (checking for `executeParams`/`tokenInputs` for EVM
1946
+ * or `serializedTransaction` for Solana) to narrow the union type at runtime.
1947
+ *
1948
+ * - {@link ExecuteSwapEVMParams} - For EVM chains (has `executeParams` and `tokenInputs`)
1949
+ * - {@link ExecuteSwapSolanaParams} - For Solana chains (has `serializedTransaction`)
1950
+ */
1951
+ type ExecuteSwapParams = ExecuteSwapEVMParams | ExecuteSwapSolanaParams;
1952
+ /**
1953
+ * Action map for swap operations on EVM chains.
1954
+ *
1955
+ * This namespace contains actions related to token swapping operations.
1956
+ * These actions handle the execution of pre-built swap transactions from
1957
+ * DEX aggregators and routing services.
1958
+ *
1959
+ * @remarks
1960
+ * The swap namespace is designed to be extensible for future swap-related
1961
+ * operations such as multi-hop swaps, batched swaps, or swap-and-bridge
1962
+ * compositions.
1963
+ */
1964
+ interface SwapActionMap {
1965
+ /**
1966
+ * Execute a pre-built swap transaction.
1967
+ *
1968
+ * This action prepares and executes swap transactions constructed by the
1969
+ * stablecoin-service API. It accepts transaction parameters (to, data, value)
1970
+ * and returns a prepared chain request suitable for gas estimation or execution.
1971
+ */
1972
+ readonly execute: ExecuteSwapParams;
1487
1973
  }
1488
1974
 
1489
1975
  interface TokenActionMap {
@@ -1698,6 +2184,81 @@ interface USDCActionMap {
1698
2184
  balanceOf: Omit<BaseUSDCActions['balanceOf'], 'tokenAddress'>;
1699
2185
  }
1700
2186
 
2187
+ /**
2188
+ * USDT-specific operations that automatically resolve the token address.
2189
+ *
2190
+ * These include standard ERC20 operations. The interface provides the same core
2191
+ * operations as {@link TokenActionMap} but without requiring a `tokenAddress`
2192
+ * parameter.
2193
+ *
2194
+ * @example
2195
+ * ```typescript
2196
+ * // USDT operations (address auto-resolved)
2197
+ * await adapter.action('usdt.transfer', {
2198
+ * to: '0x1234...',
2199
+ * amount: '1000000' // 1 USDT
2200
+ * })
2201
+ *
2202
+ * // vs. general token operations (address required)
2203
+ * await adapter.action('token.transfer', {
2204
+ * tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
2205
+ * to: '0x1234...',
2206
+ * amount: '1000000'
2207
+ * })
2208
+ * ```
2209
+ */
2210
+ type BaseUSDTActions = {
2211
+ [K in keyof TokenActionMap]: Omit<TokenActionMap[K], 'tokenAddress'>;
2212
+ };
2213
+ /**
2214
+ * USDT action map with standard ERC20 operations.
2215
+ *
2216
+ * This provides standard token operations for USDT transfers.
2217
+ */
2218
+ interface USDTActionMap {
2219
+ /**
2220
+ * Transfer USDT tokens directly from the wallet to another address.
2221
+ *
2222
+ * Automatically uses the USDT contract address for the current chain.
2223
+ */
2224
+ transfer: BaseUSDTActions['transfer'];
2225
+ }
2226
+
2227
+ /**
2228
+ * Native token-related action maps for the bridge kit.
2229
+ *
2230
+ * This module provides action definitions for native token operations.
2231
+ */
2232
+ interface NativeActionMap {
2233
+ /**
2234
+ * Transfer native tokens directly from the wallet to another address.
2235
+ */
2236
+ transfer: ActionParameters & {
2237
+ /**
2238
+ * The chain to transfer the native tokens on.
2239
+ */
2240
+ chain?: ChainIdentifier;
2241
+ /**
2242
+ * The address to send the native tokens to.
2243
+ */
2244
+ to: string;
2245
+ /**
2246
+ * The amount of native tokens to transfer.
2247
+ */
2248
+ amount: bigint;
2249
+ };
2250
+ /**
2251
+ * Get the native token balance (SOL, ETH, etc.) for a wallet address.
2252
+ */
2253
+ balanceOf: ActionParameters & {
2254
+ /**
2255
+ * The address to check the native balance for. If not provided, it will be
2256
+ * automatically derived from the adapter context.
2257
+ */
2258
+ walletAddress?: string | undefined;
2259
+ };
2260
+ }
2261
+
1701
2262
  /**
1702
2263
  * Central registry of all available action namespaces and their operations.
1703
2264
  *
@@ -1717,12 +2278,16 @@ interface USDCActionMap {
1717
2278
  interface ActionMap {
1718
2279
  /** CCTP-specific operations with automatic address resolution. */
1719
2280
  readonly cctp: CCTPActionMap;
1720
- /** Native token operations (ETH, SOL, MATIC, etc.). */
1721
- readonly native: NativeActionMap;
1722
2281
  /** General token operations requiring explicit token addresses. */
1723
2282
  readonly token: TokenActionMap;
1724
2283
  /** USDC-specific operations with automatic address resolution. */
1725
2284
  readonly usdc: USDCActionMap;
2285
+ /** USDT-specific operations with automatic address resolution. */
2286
+ readonly usdt: USDTActionMap;
2287
+ /** Native token operations. */
2288
+ readonly native: NativeActionMap;
2289
+ /** Swap operations for DEX aggregator integrations. */
2290
+ readonly swap: SwapActionMap;
1726
2291
  }
1727
2292
  /**
1728
2293
  * Determine if a type represents an action parameter object (leaf node).
@@ -1861,7 +2426,7 @@ type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActi
1861
2426
  * This type defines a registry object where each key is a valid action key
1862
2427
  * (as defined by {@link ActionKeys}) and each value is an {@link ActionHandler}
1863
2428
  * capable of processing the payload for that action. This enables strongly-typed
1864
- * handler registration and lookup for all supported actions in the Stablecoin Kits.
2429
+ * handler registration and lookup for all supported actions in the App Kits.
1865
2430
  *
1866
2431
  * @remarks
1867
2432
  * Each handler is typed as {@link ActionHandler}, which means the handler
@@ -2123,11 +2688,11 @@ interface AdapterCapabilities {
2123
2688
  /**
2124
2689
  * Abstract class defining the standard interface for an adapter that interacts with a specific blockchain.
2125
2690
  *
2126
- * A `Adapter` is responsible for encapsulating chain-specific logic necessary to
2691
+ * An `Adapter` is responsible for encapsulating chain-specific logic necessary to
2127
2692
  * perform operations like sending transactions, querying balances, or interacting with smart contracts.
2128
2693
  * Implementations of this class will provide concrete logic for a particular blockchain protocol.
2129
2694
  *
2130
- * This abstraction allows the Stablecoin Kits to work with multiple blockchains in a uniform way.
2695
+ * This abstraction allows the App Kit to work with multiple blockchains in a uniform way.
2131
2696
  *
2132
2697
  * @typeParam TAdapterCapabilities - The adapter capabilities type for compile-time address validation.
2133
2698
  * When provided, enables strict typing of operation context based on the adapter's address control model.
@@ -2388,6 +2953,134 @@ declare abstract class Adapter<TAdapterCapabilities extends AdapterCapabilities
2388
2953
  * @returns A promise that resolves to the total transaction fee as a bigint.
2389
2954
  */
2390
2955
  abstract calculateTransactionFee(baseComputeUnits: bigint, bufferBasisPoints: bigint | undefined, chain: ChainDefinition): Promise<EstimatedGas>;
2956
+ /**
2957
+ * Get the decimal places for a token address on a given chain.
2958
+ *
2959
+ * This method fetches the number of decimal places from a token contract.
2960
+ * Different chain types implement this differently:
2961
+ * - EVM: Calls the `decimals()` function on ERC-20 contracts
2962
+ * - Solana: Reads the `decimals` field from the SPL token mint account
2963
+ *
2964
+ * @param tokenAddress - The token contract address (EVM) or mint address (Solana)
2965
+ * @param chain - The chain definition where the token is deployed
2966
+ * @returns Promise resolving to the number of decimal places for the token
2967
+ * @throws Error when the token contract doesn't exist or decimals cannot be fetched
2968
+ *
2969
+ * @example
2970
+ * ```typescript
2971
+ * import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
2972
+ * import { Ethereum } from '@core/chains'
2973
+ *
2974
+ * const adapter = new EthersAdapter({ signer })
2975
+ *
2976
+ * // Fetch decimals for DAI token
2977
+ * const decimals = await adapter.getTokenDecimals(
2978
+ * '0x6B175474E89094C44Da98b954EedeAC495271d0F',
2979
+ * Ethereum
2980
+ * )
2981
+ * console.log(decimals) // 18
2982
+ * ```
2983
+ */
2984
+ abstract getTokenDecimals(tokenAddress: string, chain: ChainDefinition): Promise<number>;
2985
+ }
2986
+
2987
+ /**
2988
+ * Module augmentation to register known token symbols.
2989
+ *
2990
+ * @remarks
2991
+ * This file augments the `TokenSymbolRegistry` interface to provide
2992
+ * type-safe autocomplete for built-in tokens.
2993
+ *
2994
+ * When imported, TypeScript will recognize 'USDC' as a valid
2995
+ * `TokenSymbol` value with autocomplete support.
2996
+ *
2997
+ * Other packages or applications can create their own augmentations
2998
+ * to add additional tokens.
2999
+ *
3000
+ * @example
3001
+ * ```typescript
3002
+ * import '@core/tokens' // Automatically includes this augmentation
3003
+ *
3004
+ * const symbol: TokenSymbol = 'USDC' // ✓ Autocomplete shows USDC
3005
+ * ```
3006
+ */
3007
+ declare module './types' {
3008
+ /**
3009
+ * Module augmentation: Adds known token symbols as valid keys
3010
+ * to the TokenSymbolRegistry interface.
3011
+ *
3012
+ * Keys are explicitly listed to ensure IDE autocomplete works properly.
3013
+ */
3014
+ interface TokenSymbolRegistry {
3015
+ USDC: true;
3016
+ USDT: true;
3017
+ EURC: true;
3018
+ DAI: true;
3019
+ USDE: true;
3020
+ PYUSD: true;
3021
+ WETH: true;
3022
+ WBTC: true;
3023
+ WSOL: true;
3024
+ WAVAX: true;
3025
+ WPOL: true;
3026
+ ETH: true;
3027
+ POL: true;
3028
+ PLUME: true;
3029
+ MON: true;
3030
+ }
3031
+ }
3032
+
3033
+ /**
3034
+ * Module augmentation to register Blockchain enum values as ChainIdentifiers.
3035
+ *
3036
+ * @remarks
3037
+ * This file augments the `ChainRegistry` interface to provide type-safe
3038
+ * autocomplete for all `Blockchain` enum values from `@core/chains`.
3039
+ *
3040
+ * When this augmentation is imported (via `@core/tokens`), TypeScript will
3041
+ * recognize all blockchain identifiers as valid `ChainIdentifier` values
3042
+ * with IDE autocomplete support.
3043
+ *
3044
+ * The `Blockchain` enum values are converted to their string representations,
3045
+ * enabling both enum values and string literals to be accepted as chain identifiers.
3046
+ *
3047
+ * @example
3048
+ * ```typescript
3049
+ * import { Blockchain } from '@core/chains'
3050
+ * import type { ChainIdentifier } from '@core/tokens'
3051
+ *
3052
+ * // Using enum value
3053
+ * const chain1: ChainIdentifier = Blockchain.Ethereum
3054
+ *
3055
+ * // Using string literal (with autocomplete!)
3056
+ * const chain2: ChainIdentifier = 'Base'
3057
+ *
3058
+ * // Arbitrary strings also work (escape hatch for custom chains)
3059
+ * const chain3: ChainIdentifier = 'my-custom-chain'
3060
+ * ```
3061
+ */
3062
+
3063
+ declare module './types' {
3064
+ /**
3065
+ * Module augmentation: Adds all Blockchain enum values as valid keys
3066
+ * to the ChainRegistry interface for type-safe chain identifier support.
3067
+ *
3068
+ * This ensures both enum property access (e.g., Blockchain.Ethereum) and plain
3069
+ * string literals (e.g., 'Ethereum') are accepted by TypeScript as chain keys,
3070
+ * providing robust autocomplete and error checking.
3071
+ *
3072
+ * NOTE:
3073
+ * - This interface intentionally has no body. It merges a mapped Record type
3074
+ * into ChainRegistry solely for type augmentation.
3075
+ * - This empty-body construct is a necessary TypeScript idiom for module
3076
+ * augmentation with Record types—directly listing mapped keys is not
3077
+ * feasible in interface extensions.
3078
+ *
3079
+ * eslint-disable-next-line directives below suppress linter complaints about
3080
+ * the empty interface/mapping, which are benign and required for this pattern.
3081
+ */
3082
+ interface ChainRegistry extends Record<`${Blockchain}`, true> {
3083
+ }
2391
3084
  }
2392
3085
 
2393
3086
  /**
@@ -2834,18 +3527,65 @@ interface EIP2612Options extends Record<string, unknown> {
2834
3527
  /** Optional deadline - will default to 1 hour from now if not provided */
2835
3528
  deadline?: bigint;
2836
3529
  }
3530
+ /**
3531
+ * Minimal adapter interface for EIP-2612 nonce fetching.
3532
+ *
3533
+ * @remarks
3534
+ * This interface represents the minimal contract an adapter must fulfill to
3535
+ * work with `buildEIP2612TypedData`. It's intentionally minimal - only requiring
3536
+ * nonce fetching capability. Signing is handled separately via the adapter's
3537
+ * `signTypedData` method.
3538
+ *
3539
+ * This enables separation of concerns: nonce fetching (read operation) is
3540
+ * independent from signing (write operation).
3541
+ *
3542
+ * @example
3543
+ * ```typescript
3544
+ * import type { EIP2612Adapter } from '@core/adapter-evm'
3545
+ *
3546
+ * // An adapter that implements the minimal interface
3547
+ * class MyAdapter implements EIP2612Adapter {
3548
+ * async fetchEIP2612Nonce(
3549
+ * tokenAddress: `0x${string}`,
3550
+ * ownerAddress: `0x${string}`,
3551
+ * ctx: OperationContext
3552
+ * ): Promise<bigint> {
3553
+ * // Query token contract for nonce
3554
+ * return await this.readContract({
3555
+ * address: tokenAddress,
3556
+ * abi: [{ name: 'nonces', type: 'function', inputs: [...], outputs: [...] }],
3557
+ * functionName: 'nonces',
3558
+ * args: [ownerAddress]
3559
+ * })
3560
+ * }
3561
+ * }
3562
+ * ```
3563
+ */
3564
+ interface EIP2612Adapter {
3565
+ /**
3566
+ * Fetch the current nonce for EIP-2612 permit signatures.
3567
+ *
3568
+ * Queries the token contract's `nonces(address owner)` function to get
3569
+ * the current nonce value for permit signatures.
3570
+ *
3571
+ * @param tokenAddress - The token contract address
3572
+ * @param ownerAddress - The token owner's address
3573
+ * @param ctx - Operation context containing chain and address information
3574
+ * @returns Promise resolving to the current nonce
3575
+ * @throws Error when the contract call fails or token doesn't support EIP-2612
3576
+ */
3577
+ fetchEIP2612Nonce(tokenAddress: `0x${string}`, ownerAddress: `0x${string}`, ctx: OperationContext): Promise<bigint>;
3578
+ }
2837
3579
  /**
2838
3580
  * Function type for fetching nonces from EIP-2612 compatible tokens.
2839
3581
  *
2840
- * @param owner - Token owner address
3582
+ * This type will be deprecated, use {@link EIP2612Adapter} interface instead for better type safety
2841
3583
  * @param token - Token contract address
3584
+ * @param owner - Token owner address
2842
3585
  * @returns Promise resolving to current nonce
2843
3586
  */
2844
3587
  type EIP2612NonceFetcher = (token: `0x${string}`, owner: `0x${string}`) => Promise<bigint>;
2845
3588
 
2846
- interface EIP2612Adapter {
2847
- fetchEIP2612Nonce(tokenAddress: `0x${string}`, ownerAddress: `0x${string}`, ctx: OperationContext): Promise<bigint>;
2848
- }
2849
3589
  /**
2850
3590
  * Build EIP-2612 typed data for permit signing.
2851
3591
  *
@@ -3103,6 +3843,22 @@ declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = A
3103
3843
  * @throws When transaction execution fails after retry attempts.
3104
3844
  */
3105
3845
  private executeTransaction;
3846
+ /**
3847
+ * Common transaction sending logic with nonce management and retry logic.
3848
+ *
3849
+ * This method handles the complete transaction lifecycle:
3850
+ * - Nonce allocation and management via {@link ethersNonceManager}
3851
+ * - Automatic retry on nonce-related errors (up to 3 attempts)
3852
+ * - Graceful handling of user-provided nonces (no retry)
3853
+ * - Proper error handling and wrapping
3854
+ *
3855
+ * @param txRequest - Populated transaction request
3856
+ * @param fromAddress - The address sending the transaction
3857
+ * @param chain - The chain definition for context
3858
+ * @param overrides - Optional transaction overrides
3859
+ * @returns Transaction hash
3860
+ */
3861
+ private sendTransactionWithNonceManagement;
3106
3862
  /**
3107
3863
  * Prepares a contract function call for gas estimation and execution with OperationContext.
3108
3864
  *
@@ -3405,6 +4161,35 @@ declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = A
3405
4161
  * @returns A prepared chain request for read-only function execution.
3406
4162
  */
3407
4163
  private handleReadOnlyFunction;
4164
+ /**
4165
+ * Prepares a native token transfer (ETH, MATIC, etc.) for gas estimation and execution.
4166
+ *
4167
+ * Native transfers are simple value transfers that don't require contract ABI or function calls.
4168
+ * This method reuses the existing transaction execution flow but skips contract-specific logic.
4169
+ *
4170
+ * @param address - The recipient address for the native token transfer
4171
+ * @param value - The amount of native tokens to send (in wei)
4172
+ * @param targetChain - The target chain definition
4173
+ * @param resolvedAddress - The resolved sender address from operation context
4174
+ * @returns Prepared chain request for native transfer
4175
+ * @throws Error when gas estimation fails without fallback
4176
+ * @throws Error when gas price retrieval fails
4177
+ * @throws Error when transaction execution fails
4178
+ *
4179
+ * @example
4180
+ * ```typescript
4181
+ * // Internal usage - called by prepare() when native transfer is detected
4182
+ * const prepared = this.prepareNativeTransfer(
4183
+ * '0x1234567890123456789012345678901234567890',
4184
+ * BigInt(1000000000000000000), // 1 ETH
4185
+ * Ethereum,
4186
+ * '0xsenderAddress'
4187
+ * );
4188
+ * const estimate = await prepared.estimate();
4189
+ * const txHash = await prepared.execute();
4190
+ * ```
4191
+ */
4192
+ private prepareNativeTransfer;
3408
4193
  /**
3409
4194
  * Reads a contract function using Ethers v6.
3410
4195
  *
@@ -3414,6 +4199,39 @@ declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = A
3414
4199
  * @throws Error when contract read fails.
3415
4200
  */
3416
4201
  readContract<TReturnType = unknown>(params: ReadContractParams, chain: EVMChainDefinition): Promise<TReturnType>;
4202
+ /**
4203
+ * Get the decimal places for an ERC-20 token on an EVM chain.
4204
+ *
4205
+ * This method calls the `decimals()` function on the ERC-20 token contract
4206
+ * to fetch the number of decimal places. Ethers v6 returns decimals as bigint,
4207
+ * which is validated and converted to a number.
4208
+ *
4209
+ * @param tokenAddress - The ERC-20 token contract address
4210
+ * @param chain - The EVM chain definition where the token is deployed
4211
+ * @returns Promise resolving to the number of decimal places
4212
+ * @throws Error when the contract doesn't exist, doesn't support decimals(), or returns invalid data
4213
+ *
4214
+ * @remarks
4215
+ * - Ethers v6 returns decimals as bigint
4216
+ * - Validates that decimals are within 0-255 range (ERC-20 uint8 standard)
4217
+ * - Converts bigint to number for consistent API
4218
+ *
4219
+ * @example
4220
+ * ```typescript
4221
+ * import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
4222
+ * import { Ethereum } from '@core/chains'
4223
+ *
4224
+ * const adapter = new EthersAdapter({ signer })
4225
+ *
4226
+ * // Fetch decimals for DAI token
4227
+ * const decimals = await adapter.getTokenDecimals(
4228
+ * '0x6B175474E89094C44Da98b954EedeAC495271d0F',
4229
+ * Ethereum
4230
+ * )
4231
+ * console.log(decimals) // 18
4232
+ * ```
4233
+ */
4234
+ getTokenDecimals(tokenAddress: string, chain: EVMChainDefinition): Promise<number>;
3417
4235
  }
3418
4236
 
3419
4237
  /**