@circle-fin/provider-cctp-v2 1.4.0 → 1.4.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
@@ -33,7 +33,6 @@ import { TransactionInstruction, Signer, AddressLookupTableAccount } from '@sola
33
33
  */
34
34
  /**
35
35
  * Represents basic information about a currency or token.
36
- * @interface Currency
37
36
  * @category Types
38
37
  * @description Provides the essential properties of a cryptocurrency or token.
39
38
  * @example
@@ -65,7 +64,6 @@ interface Currency {
65
64
  }
66
65
  /**
67
66
  * Base information that all chain definitions must include.
68
- * @interface BaseChainDefinition
69
67
  * @category Types
70
68
  * @description Provides the common properties shared by all blockchain definitions.
71
69
  * @example
@@ -125,6 +123,11 @@ interface BaseChainDefinition {
125
123
  * @description Its presence indicates that USDC is supported.
126
124
  */
127
125
  usdcAddress: string | null;
126
+ /**
127
+ * The contract address for USDT.
128
+ * @description Its presence indicates that USDT is supported.
129
+ */
130
+ usdtAddress: string | null;
128
131
  /**
129
132
  * Optional CCTP configuration.
130
133
  * @description If provided, the chain supports CCTP.
@@ -166,7 +169,6 @@ interface BaseChainDefinition {
166
169
  }
167
170
  /**
168
171
  * Represents chain definitions for Ethereum Virtual Machine (EVM) compatible blockchains.
169
- * @interface EVMChainDefinition
170
172
  * @extends BaseChainDefinition
171
173
  * @category Types
172
174
  * @description Adds properties specific to EVM chains.
@@ -198,7 +200,6 @@ interface EVMChainDefinition extends BaseChainDefinition {
198
200
  }
199
201
  /**
200
202
  * Represents chain definitions for non-EVM blockchains.
201
- * @interface NonEVMChainDefinition
202
203
  * @extends BaseChainDefinition
203
204
  * @category Types
204
205
  * @description Contains properties for blockchains that do not use the EVM.
@@ -251,6 +252,7 @@ type ChainType = EVMChainDefinition['type'] | NonEVMChainDefinition['type'];
251
252
  * rpcEndpoints: ['https://eth.example.com'],
252
253
  * eurcAddress: null,
253
254
  * usdcAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
255
+ * usdtAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
254
256
  * cctp: {
255
257
  * domain: 0,
256
258
  * contracts: {
@@ -314,17 +316,74 @@ type ChainDefinitionWithCCTPv2 = ChainDefinition & {
314
316
  * - A string literal of the blockchain value (e.g., "Ethereum")
315
317
  */
316
318
  type ChainIdentifier$1 = ChainDefinition | Blockchain | `${Blockchain}`;
319
+ /**
320
+ * Split CCTP contract configuration.
321
+ *
322
+ * Used by chains that deploy separate TokenMessenger and MessageTransmitter contracts.
323
+ * This is the traditional CCTP architecture used by most EVM chains.
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * const splitConfig: CCTPSplitConfig = {
328
+ * type: 'split',
329
+ * tokenMessenger: '0x1234567890abcdef1234567890abcdef12345678',
330
+ * messageTransmitter: '0xabcdef1234567890abcdef1234567890abcdef12',
331
+ * confirmations: 12
332
+ * }
333
+ * ```
334
+ */
317
335
  interface CCTPSplitConfig {
318
336
  type: 'split';
319
337
  tokenMessenger: string;
320
338
  messageTransmitter: string;
321
339
  confirmations: number;
322
340
  }
341
+ /**
342
+ * Merged CCTP contract configuration.
343
+ *
344
+ * Used by chains that deploy a single unified CCTP contract.
345
+ * This simplified architecture is used by newer chain integrations.
346
+ *
347
+ * @example
348
+ * ```typescript
349
+ * const mergedConfig: CCTPMergedConfig = {
350
+ * type: 'merged',
351
+ * contract: '0x9876543210fedcba9876543210fedcba98765432',
352
+ * confirmations: 1
353
+ * }
354
+ * ```
355
+ */
323
356
  interface CCTPMergedConfig {
324
357
  type: 'merged';
325
358
  contract: string;
326
359
  confirmations: number;
327
360
  }
361
+ /**
362
+ * Version configuration for CCTP contracts.
363
+ *
364
+ * Defines whether the chain uses split or merged CCTP contract architecture.
365
+ * Split configuration uses separate TokenMessenger and MessageTransmitter contracts,
366
+ * while merged configuration uses a single unified contract.
367
+ *
368
+ * @example Split configuration (most EVM chains)
369
+ * ```typescript
370
+ * const splitConfig: VersionConfig = {
371
+ * type: 'split',
372
+ * tokenMessenger: '0x1234567890abcdef1234567890abcdef12345678',
373
+ * messageTransmitter: '0xabcdef1234567890abcdef1234567890abcdef12',
374
+ * confirmations: 12
375
+ * }
376
+ * ```
377
+ *
378
+ * @example Merged configuration (newer chains)
379
+ * ```typescript
380
+ * const mergedConfig: VersionConfig = {
381
+ * type: 'merged',
382
+ * contract: '0x9876543210fedcba9876543210fedcba98765432',
383
+ * confirmations: 1
384
+ * }
385
+ * ```
386
+ */
328
387
  type VersionConfig = CCTPSplitConfig | CCTPMergedConfig;
329
388
  type CCTPContracts = Partial<{
330
389
  v1: VersionConfig;
@@ -334,7 +393,6 @@ type CCTPContracts = Partial<{
334
393
  }>;
335
394
  /**
336
395
  * Configuration for the Cross-Chain Transfer Protocol (CCTP).
337
- * @interface CCTPConfig
338
396
  * @category Types
339
397
  * @description Contains the domain and required contract addresses for CCTP support.
340
398
  * @example
@@ -388,7 +446,7 @@ interface CCTPConfig {
388
446
  * const invalidType: KitContractType = 'invalid' // TypeScript error
389
447
  * ```
390
448
  */
391
- type KitContractType = 'bridge';
449
+ type KitContractType = 'bridge' | 'adapter';
392
450
  /**
393
451
  * Kit-specific contract addresses for enhanced chain functionality.
394
452
  *
@@ -659,8 +717,20 @@ type EvmPreparedChainRequestParams = {
659
717
  interface SolanaPreparedChainRequestParams {
660
718
  /**
661
719
  * The array of instructions to include in the transaction.
720
+ *
721
+ * @remarks
722
+ * Used for instruction-based transaction building. Mutually exclusive with
723
+ * `serializedTransaction`.
724
+ */
725
+ instructions?: TransactionInstruction[];
726
+ /**
727
+ * A pre-serialized transaction as a Uint8Array (e.g., from a service like Jupiter).
728
+ *
729
+ * @remarks
730
+ * Used for executing pre-built transactions from external services.
731
+ * The transaction may be partially signed. Mutually exclusive with `instructions`.
662
732
  */
663
- instructions: TransactionInstruction[];
733
+ serializedTransaction?: Uint8Array;
664
734
  /**
665
735
  * Additional signers besides the Adapter's wallet (e.g. program-derived authorities).
666
736
  */
@@ -1457,31 +1527,443 @@ interface CCTPActionMap {
1457
1527
  }
1458
1528
 
1459
1529
  /**
1460
- * Action map for native token operations (ETH, SOL, MATIC, etc.).
1530
+ * Permit signature standards for gasless token approvals.
1461
1531
  *
1462
- * Native tokens are the primary currency of each blockchain network,
1463
- * used for paying transaction fees and as a store of value.
1464
- * These actions operate on the native token without requiring
1465
- * a separate token contract address.
1532
+ * Defines the permit types that can be used to approve token spending
1533
+ * without requiring a separate approval transaction.
1466
1534
  *
1467
1535
  * @remarks
1468
- * Native token operations differ from ERC-20/SPL token operations
1469
- * in that they don't require contract interactions for basic transfers
1470
- * and balance checks.
1536
+ * - NONE: No permit, tokens must be pre-approved via separate transaction
1537
+ * - EIP2612: Standard ERC-20 permit (USDC, DAI v2, and most modern tokens)
1538
+ */
1539
+ declare enum PermitType {
1540
+ /** No permit required - tokens must be pre-approved */
1541
+ NONE = 0,
1542
+ /** EIP-2612 standard permit */
1543
+ EIP2612 = 1
1544
+ }
1545
+ /**
1546
+ * Token input with permit signature for gasless approval.
1471
1547
  *
1472
- * @see {@link ActionMap} for the complete action structure
1548
+ * The Adapter Contract uses this to pull tokens from the user's wallet
1549
+ * using permit signatures instead of requiring separate approval transactions.
1550
+ *
1551
+ * @example
1552
+ * ```typescript
1553
+ * const tokenInput: TokenInput = {
1554
+ * permitType: PermitType.EIP2612,
1555
+ * token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1556
+ * from: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
1557
+ * amount: 1000000n, // 1 USDC
1558
+ * permitCalldata: '0x...' // Encoded permit(value, deadline, v, r, s)
1559
+ * }
1560
+ * ```
1473
1561
  */
1474
- interface NativeActionMap {
1562
+ interface TokenInput {
1475
1563
  /**
1476
- * Get the native token balance (SOL, ETH, etc.) for a wallet address.
1564
+ * Type of permit to execute.
1477
1565
  */
1478
- balanceOf: ActionParameters & {
1479
- /**
1480
- * The address to check the native balance for. If not provided, it will be
1481
- * automatically derived from the adapter context.
1482
- */
1483
- walletAddress?: string | undefined;
1484
- };
1566
+ permitType: PermitType;
1567
+ /**
1568
+ * Token contract address to pull from user.
1569
+ */
1570
+ token: `0x${string}`;
1571
+ /**
1572
+ * Amount of tokens to pull via permit.
1573
+ */
1574
+ amount: bigint;
1575
+ /**
1576
+ * ABI-encoded permit calldata.
1577
+ *
1578
+ * For EIP-2612: encode(value, deadline, v, r, s)
1579
+ * For Permit2: encode(permit, signature)
1580
+ *
1581
+ * @example '0x0000000000000000000000000000000000000000000000000000000000989680...'
1582
+ */
1583
+ permitCalldata: `0x${string}`;
1584
+ }
1585
+ /**
1586
+ * Single instruction to execute within the Adapter Contract.
1587
+ *
1588
+ * Each instruction represents a contract call (swap, fee collection, etc.)
1589
+ * with pre-execution approval and post-execution validation.
1590
+ *
1591
+ * @example
1592
+ * ```typescript
1593
+ * const swapInstruction: Instruction = {
1594
+ * target: '0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE', // LiFi Diamond
1595
+ * data: '0x...', // LiFi swap calldata
1596
+ * value: 0n,
1597
+ * tokenIn: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1598
+ * amountToApprove: 1000000000n, // 1000 USDC to approve
1599
+ * tokenOut: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
1600
+ * minTokenOut: 995000000n // 995 USDT minimum (0.5% slippage)
1601
+ * }
1602
+ * ```
1603
+ */
1604
+ interface Instruction {
1605
+ /**
1606
+ * Target contract address to call.
1607
+ *
1608
+ * Can be a DEX router, fee taker contract, or token contract.
1609
+ */
1610
+ target: `0x${string}`;
1611
+ /**
1612
+ * ABI-encoded calldata for the target contract.
1613
+ */
1614
+ data: `0x${string}`;
1615
+ /**
1616
+ * ETH value to send with the call (for native token operations).
1617
+ *
1618
+ * @defaultValue 0n
1619
+ */
1620
+ value: bigint;
1621
+ /**
1622
+ * Token to approve to target before executing instruction.
1623
+ *
1624
+ * Set to zero address (0x00...00) to disable pre-approval.
1625
+ */
1626
+ tokenIn: `0x${string}`;
1627
+ /**
1628
+ * Amount of tokenIn to approve to target before executing instruction.
1629
+ *
1630
+ * @remarks
1631
+ * Field name matches the adapter contract's `amountToApprove` parameter exactly.
1632
+ *
1633
+ * @defaultValue 0n if tokenIn is zero address
1634
+ */
1635
+ amountToApprove: bigint;
1636
+ /**
1637
+ * Token to validate minimum balance after instruction.
1638
+ *
1639
+ * Set to zero address (0x00...00) to disable post-validation.
1640
+ */
1641
+ tokenOut: `0x${string}`;
1642
+ /**
1643
+ * Minimum required balance of tokenOut after instruction.
1644
+ *
1645
+ * @defaultValue 0n if tokenOut is zero address
1646
+ */
1647
+ minTokenOut: bigint;
1648
+ }
1649
+ /**
1650
+ * Token recipient for residual sweep.
1651
+ *
1652
+ * After all instructions complete, the Adapter Contract sweeps
1653
+ * any remaining balances to the specified beneficiaries.
1654
+ */
1655
+ interface TokenRecipient {
1656
+ /**
1657
+ * Token contract address to sweep.
1658
+ */
1659
+ token: `0x${string}`;
1660
+ /**
1661
+ * Address to receive swept tokens.
1662
+ */
1663
+ beneficiary: `0x${string}`;
1664
+ }
1665
+ /**
1666
+ * Execution parameters for the Adapter Contract.
1667
+ *
1668
+ * This struct is signed via EIP-712 by the Circle proxy and verified
1669
+ * on-chain to ensure the execution is authorized.
1670
+ *
1671
+ * @remarks
1672
+ * The executeParams are provided by the stablecoin-service and must be
1673
+ * passed to the Adapter Contract exactly as received (no modification).
1674
+ *
1675
+ * @example
1676
+ * ```typescript
1677
+ * const executeParams: ExecuteParams = {
1678
+ * instructions: [
1679
+ * { target: dexRouter, data: swapCalldata, ... }
1680
+ * ],
1681
+ * tokens: [
1682
+ * { token: USDC, beneficiary: userAddress },
1683
+ * { token: USDT, beneficiary: userAddress }
1684
+ * ],
1685
+ * execId: 123456789n,
1686
+ * deadline: BigInt(Math.floor(Date.now() / 1000) + 1800),
1687
+ * metadata: '0x'
1688
+ * }
1689
+ * ```
1690
+ */
1691
+ interface ExecuteParams {
1692
+ /**
1693
+ * Array of instructions to execute sequentially.
1694
+ *
1695
+ * Each instruction can be a swap, fee collection, or other contract call.
1696
+ */
1697
+ instructions: Instruction[];
1698
+ /**
1699
+ * Token recipients for residual sweep.
1700
+ *
1701
+ * Typically a 2-tuple: [tokenIn recipient, tokenOut recipient]
1702
+ */
1703
+ tokens: TokenRecipient[];
1704
+ /**
1705
+ * Unique execution identifier for replay protection.
1706
+ *
1707
+ * Must be globally unique and is marked as used after execution.
1708
+ */
1709
+ execId: bigint;
1710
+ /**
1711
+ * Execution deadline timestamp (Unix seconds).
1712
+ *
1713
+ * Transaction reverts if block.timestamp is greater than deadline.
1714
+ */
1715
+ deadline: bigint;
1716
+ /**
1717
+ * Optional metadata for tracking and analytics.
1718
+ */
1719
+ metadata: `0x${string}`;
1720
+ }
1721
+ /**
1722
+ * Parameters for executing a swap transaction via the Adapter smart contract.
1723
+ *
1724
+ * This action executes swap transactions through the Adapter Contract, which
1725
+ * handles token approvals via permits (EIP-2612, Permit2, etc.) and executes
1726
+ * multi-step swap instructions atomically on-chain.
1727
+ *
1728
+ * @remarks
1729
+ * The swap flow uses the Adapter Contract pattern:
1730
+ * 1. Service provides `executeParams` and `signature` (proxy-signed EIP-712)
1731
+ * 2. SDK builds `tokenInputs` with permit signatures for gasless approvals
1732
+ * 3. SDK calls AdapterContract.execute(executeParams, tokenInputs, signature)
1733
+ * 4. Adapter Contract pulls tokens via permits, executes swaps, validates outputs
1734
+ *
1735
+ * This enables:
1736
+ * - Single atomic transaction (permit + swap in one tx)
1737
+ * - Gasless approvals via EIP-2612/Permit2
1738
+ * - Slippage protection enforced on-chain
1739
+ * - Multi-step instructions (swap + fees) atomically
1740
+ *
1741
+ * **Permit Support**: The SDK constructs `TokenInput` with `permitCalldata`
1742
+ * containing the encoded permit signature. The Adapter Contract executes
1743
+ * the permit on-chain before pulling tokens.
1744
+ *
1745
+ * @example
1746
+ * ```typescript
1747
+ * import type { ExecuteSwapParams } from '@core/adapter'
1748
+ * import { createSwap } from '@core/service-client'
1749
+ * import { PermitType } from '@core/adapter'
1750
+ *
1751
+ * // Get swap transaction from service
1752
+ * const swapResponse = await createSwap({
1753
+ * tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1754
+ * tokenOutAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
1755
+ * tokenInChain: 'Ethereum',
1756
+ * fromAddress: '0x...',
1757
+ * toAddress: '0x...',
1758
+ * amount: '1000000',
1759
+ * apiKey: 'KIT_KEY:...',
1760
+ * })
1761
+ *
1762
+ * // Build token inputs with permit
1763
+ * const tokenInputs: TokenInput[] = [{
1764
+ * permitType: PermitType.EIP2612,
1765
+ * token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1766
+ * from: userAddress,
1767
+ * amount: 1000000n,
1768
+ * permitCalldata: '0x...' // Encoded permit signature
1769
+ * }]
1770
+ *
1771
+ * // Prepare action parameters
1772
+ * const params: ExecuteSwapParams = {
1773
+ * executeParams: swapResponse.transaction.executeParams,
1774
+ * tokenInputs,
1775
+ * signature: swapResponse.transaction.signature,
1776
+ * inputAmount: BigInt(swapResponse.amount),
1777
+ * tokenInAddress: swapResponse.tokenInAddress as `0x${string}`
1778
+ * }
1779
+ * ```
1780
+ */
1781
+ interface ExecuteSwapEVMParams extends ActionParameters {
1782
+ /**
1783
+ * Execution parameters from the stablecoin-service.
1784
+ *
1785
+ * Contains instructions, token recipients, execution ID, deadline, and metadata.
1786
+ * This is an EIP-712 signed struct that the Adapter Contract validates.
1787
+ *
1788
+ * Provided by the service - do not modify.
1789
+ */
1790
+ executeParams: ExecuteParams;
1791
+ /**
1792
+ * Token inputs with permit signatures for gasless approvals.
1793
+ *
1794
+ * The SDK constructs this array with permit data for each token that needs
1795
+ * to be pulled from the user's wallet. The Adapter Contract executes these
1796
+ * permits on-chain before executing swap instructions.
1797
+ *
1798
+ * @remarks
1799
+ * For EIP-2612 permits, the SDK must:
1800
+ * 1. Build typed data with token, spender (Adapter), amount, nonce, deadline
1801
+ * 2. Get user signature via `adapter.signTypedData()`
1802
+ * 3. Encode as permitCalldata: encode(value, deadline, v, r, s)
1803
+ *
1804
+ * @example
1805
+ * ```typescript
1806
+ * [{
1807
+ * permitType: PermitType.EIP2612,
1808
+ * token: '0xUSDC',
1809
+ * from: userAddress,
1810
+ * amount: 1000000n,
1811
+ * permitCalldata: '0x...'
1812
+ * }]
1813
+ * ```
1814
+ */
1815
+ tokenInputs: TokenInput[];
1816
+ /**
1817
+ * EIP-712 signature from the Circle proxy service.
1818
+ *
1819
+ * The service signs the executeParams to authorize the execution.
1820
+ * The Adapter Contract verifies this signature on-chain.
1821
+ *
1822
+ * Provided by the service - do not modify.
1823
+ */
1824
+ signature: `0x${string}`;
1825
+ /**
1826
+ * Swap input amount in base units.
1827
+ *
1828
+ * @remarks
1829
+ * The amount of tokens being swapped, provided in the token's base units (e.g., wei for ETH,
1830
+ * smallest denomination for ERC20 tokens). This value should be extracted from the service
1831
+ * response, as it represents the authoritative swap amount for the operation.
1832
+ *
1833
+ * For native currency swaps (ETH → USDC), this amount is sent as the transaction `value`.
1834
+ * For ERC20 swaps (USDC → USDT), this amount determines the permit or approval quantity.
1835
+ *
1836
+ * @see CreateSwapResponse.amount - Service response field containing this value
1837
+ *
1838
+ * @example
1839
+ * ```typescript
1840
+ * import { createSwap } from '@core/service-client'
1841
+ *
1842
+ * // Get swap transaction from service
1843
+ * const response = await createSwap({
1844
+ * tokenInAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1845
+ * amount: '1000000', // 1 USDC (6 decimals)
1846
+ * ...
1847
+ * })
1848
+ *
1849
+ * // Prepare swap execution using service response amount
1850
+ * await adapter.prepareAction('swap.execute', {
1851
+ * executeParams: response.transaction.executeParams,
1852
+ * tokenInputs,
1853
+ * signature: response.transaction.signature,
1854
+ * inputAmount: BigInt(response.amount),
1855
+ * tokenInAddress: response.tokenInAddress,
1856
+ * }, context)
1857
+ * ```
1858
+ */
1859
+ inputAmount: bigint;
1860
+ /**
1861
+ * Token address being swapped from.
1862
+ *
1863
+ * @remarks
1864
+ * Used to determine if the swap involves native currency (ETH, MATIC, etc.) or ERC20 tokens.
1865
+ * When tokenInAddress is NATIVE_TOKEN_ADDRESS (0xEeee...), the inputAmount is sent as tx.value.
1866
+ *
1867
+ * @see CreateSwapResponse.tokenInAddress - Service response field containing this value
1868
+ *
1869
+ * @example '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' for ETH
1870
+ * @example '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC
1871
+ */
1872
+ tokenInAddress: `0x${string}`;
1873
+ }
1874
+ /**
1875
+ * Parameters for executing a swap transaction on Solana.
1876
+ *
1877
+ * This action executes swap transactions on Solana chains by deserializing
1878
+ * and executing a pre-built transaction provided by the stablecoin-service.
1879
+ *
1880
+ * @remarks
1881
+ * Unlike EVM chains that use the Adapter Contract pattern, Solana swaps
1882
+ * execute a fully serialized transaction provided by the service. The
1883
+ * transaction is base64-encoded and contains all necessary instructions
1884
+ * for the swap operation.
1885
+ *
1886
+ * The service handles:
1887
+ * - DEX aggregator routing (Jupiter, etc.)
1888
+ * - Fee collection
1889
+ * - Slippage protection
1890
+ * - Token account management
1891
+ *
1892
+ * @example
1893
+ * ```typescript
1894
+ * import type { ExecuteSwapSolanaParams } from '@core/adapter'
1895
+ * import { createSwap } from '@core/service-client'
1896
+ *
1897
+ * // Get swap transaction from service
1898
+ * const swapResponse = await createSwap({
1899
+ * tokenInAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
1900
+ * tokenOutAddress: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
1901
+ * tokenInChain: 'Solana',
1902
+ * fromAddress: 'YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP',
1903
+ * toAddress: 'YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP',
1904
+ * amount: '1000000',
1905
+ * apiKey: 'KIT_KEY:...',
1906
+ * })
1907
+ *
1908
+ * // Prepare action parameters
1909
+ * const params: ExecuteSwapSolanaParams = {
1910
+ * serializedTransaction: swapResponse.transaction.data
1911
+ * }
1912
+ * ```
1913
+ */
1914
+ interface ExecuteSwapSolanaParams extends ActionParameters {
1915
+ /**
1916
+ * Base64-encoded serialized Solana transaction.
1917
+ *
1918
+ * This transaction is fully constructed by the stablecoin-service and
1919
+ * contains all swap instructions, fee payments, and token account setup.
1920
+ * The transaction must be deserialized, signed, and submitted to the network.
1921
+ *
1922
+ * Provided by the service - do not modify.
1923
+ *
1924
+ * @example 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAJFQg...'
1925
+ */
1926
+ serializedTransaction: string;
1927
+ }
1928
+ /**
1929
+ * Parameters accepted by the swap.execute action, supporting both EVM and Solana chains.
1930
+ *
1931
+ * @remarks
1932
+ * This union type covers all chain-specific swap execution parameter interfaces
1933
+ * currently supported by the App Kit. Extend this union to support
1934
+ * additional blockchains as needed. Each member provides all fields required
1935
+ * to prepare and execute a pre-built swap transaction on its respective chain.
1936
+ *
1937
+ * **Type Narrowing**: The correct parameter type is inferred from the chain type
1938
+ * in the `OperationContext` passed to `adapter.prepareAction()`. Action handlers
1939
+ * use property-based type guards (checking for `executeParams`/`tokenInputs` for EVM
1940
+ * or `serializedTransaction` for Solana) to narrow the union type at runtime.
1941
+ *
1942
+ * - {@link ExecuteSwapEVMParams} - For EVM chains (has `executeParams` and `tokenInputs`)
1943
+ * - {@link ExecuteSwapSolanaParams} - For Solana chains (has `serializedTransaction`)
1944
+ */
1945
+ type ExecuteSwapParams = ExecuteSwapEVMParams | ExecuteSwapSolanaParams;
1946
+ /**
1947
+ * Action map for swap operations on EVM chains.
1948
+ *
1949
+ * This namespace contains actions related to token swapping operations.
1950
+ * These actions handle the execution of pre-built swap transactions from
1951
+ * DEX aggregators and routing services.
1952
+ *
1953
+ * @remarks
1954
+ * The swap namespace is designed to be extensible for future swap-related
1955
+ * operations such as multi-hop swaps, batched swaps, or swap-and-bridge
1956
+ * compositions.
1957
+ */
1958
+ interface SwapActionMap {
1959
+ /**
1960
+ * Execute a pre-built swap transaction.
1961
+ *
1962
+ * This action prepares and executes swap transactions constructed by the
1963
+ * stablecoin-service API. It accepts transaction parameters (to, data, value)
1964
+ * and returns a prepared chain request suitable for gas estimation or execution.
1965
+ */
1966
+ readonly execute: ExecuteSwapParams;
1485
1967
  }
1486
1968
 
1487
1969
  interface TokenActionMap {
@@ -1696,6 +2178,81 @@ interface USDCActionMap {
1696
2178
  balanceOf: Omit<BaseUSDCActions['balanceOf'], 'tokenAddress'>;
1697
2179
  }
1698
2180
 
2181
+ /**
2182
+ * USDT-specific operations that automatically resolve the token address.
2183
+ *
2184
+ * These include standard ERC20 operations. The interface provides the same core
2185
+ * operations as {@link TokenActionMap} but without requiring a `tokenAddress`
2186
+ * parameter.
2187
+ *
2188
+ * @example
2189
+ * ```typescript
2190
+ * // USDT operations (address auto-resolved)
2191
+ * await adapter.action('usdt.transfer', {
2192
+ * to: '0x1234...',
2193
+ * amount: '1000000' // 1 USDT
2194
+ * })
2195
+ *
2196
+ * // vs. general token operations (address required)
2197
+ * await adapter.action('token.transfer', {
2198
+ * tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
2199
+ * to: '0x1234...',
2200
+ * amount: '1000000'
2201
+ * })
2202
+ * ```
2203
+ */
2204
+ type BaseUSDTActions = {
2205
+ [K in keyof TokenActionMap]: Omit<TokenActionMap[K], 'tokenAddress'>;
2206
+ };
2207
+ /**
2208
+ * USDT action map with standard ERC20 operations.
2209
+ *
2210
+ * This provides standard token operations for USDT transfers.
2211
+ */
2212
+ interface USDTActionMap {
2213
+ /**
2214
+ * Transfer USDT tokens directly from the wallet to another address.
2215
+ *
2216
+ * Automatically uses the USDT contract address for the current chain.
2217
+ */
2218
+ transfer: BaseUSDTActions['transfer'];
2219
+ }
2220
+
2221
+ /**
2222
+ * Native token-related action maps for the bridge kit.
2223
+ *
2224
+ * This module provides action definitions for native token operations.
2225
+ */
2226
+ interface NativeActionMap {
2227
+ /**
2228
+ * Transfer native tokens directly from the wallet to another address.
2229
+ */
2230
+ transfer: ActionParameters & {
2231
+ /**
2232
+ * The chain to transfer the native tokens on.
2233
+ */
2234
+ chain?: ChainIdentifier$1;
2235
+ /**
2236
+ * The address to send the native tokens to.
2237
+ */
2238
+ to: string;
2239
+ /**
2240
+ * The amount of native tokens to transfer.
2241
+ */
2242
+ amount: bigint;
2243
+ };
2244
+ /**
2245
+ * Get the native token balance (SOL, ETH, etc.) for a wallet address.
2246
+ */
2247
+ balanceOf: ActionParameters & {
2248
+ /**
2249
+ * The address to check the native balance for. If not provided, it will be
2250
+ * automatically derived from the adapter context.
2251
+ */
2252
+ walletAddress?: string | undefined;
2253
+ };
2254
+ }
2255
+
1699
2256
  /**
1700
2257
  * Central registry of all available action namespaces and their operations.
1701
2258
  *
@@ -1715,12 +2272,16 @@ interface USDCActionMap {
1715
2272
  interface ActionMap {
1716
2273
  /** CCTP-specific operations with automatic address resolution. */
1717
2274
  readonly cctp: CCTPActionMap;
1718
- /** Native token operations (ETH, SOL, MATIC, etc.). */
1719
- readonly native: NativeActionMap;
1720
2275
  /** General token operations requiring explicit token addresses. */
1721
2276
  readonly token: TokenActionMap;
1722
2277
  /** USDC-specific operations with automatic address resolution. */
1723
2278
  readonly usdc: USDCActionMap;
2279
+ /** USDT-specific operations with automatic address resolution. */
2280
+ readonly usdt: USDTActionMap;
2281
+ /** Native token operations. */
2282
+ readonly native: NativeActionMap;
2283
+ /** Swap operations for DEX aggregator integrations. */
2284
+ readonly swap: SwapActionMap;
1724
2285
  }
1725
2286
  /**
1726
2287
  * Determine if a type represents an action parameter object (leaf node).
@@ -1859,7 +2420,7 @@ type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActi
1859
2420
  * This type defines a registry object where each key is a valid action key
1860
2421
  * (as defined by {@link ActionKeys}) and each value is an {@link ActionHandler}
1861
2422
  * capable of processing the payload for that action. This enables strongly-typed
1862
- * handler registration and lookup for all supported actions in the Stablecoin Kits.
2423
+ * handler registration and lookup for all supported actions in the App Kits.
1863
2424
  *
1864
2425
  * @remarks
1865
2426
  * Each handler is typed as {@link ActionHandler}, which means the handler
@@ -2121,11 +2682,11 @@ interface AdapterCapabilities {
2121
2682
  /**
2122
2683
  * Abstract class defining the standard interface for an adapter that interacts with a specific blockchain.
2123
2684
  *
2124
- * A `Adapter` is responsible for encapsulating chain-specific logic necessary to
2685
+ * An `Adapter` is responsible for encapsulating chain-specific logic necessary to
2125
2686
  * perform operations like sending transactions, querying balances, or interacting with smart contracts.
2126
2687
  * Implementations of this class will provide concrete logic for a particular blockchain protocol.
2127
2688
  *
2128
- * This abstraction allows the Stablecoin Kits to work with multiple blockchains in a uniform way.
2689
+ * This abstraction allows the App Kit to work with multiple blockchains in a uniform way.
2129
2690
  *
2130
2691
  * @typeParam TAdapterCapabilities - The adapter capabilities type for compile-time address validation.
2131
2692
  * When provided, enables strict typing of operation context based on the adapter's address control model.
@@ -2386,6 +2947,35 @@ declare abstract class Adapter<TAdapterCapabilities extends AdapterCapabilities
2386
2947
  * @returns A promise that resolves to the total transaction fee as a bigint.
2387
2948
  */
2388
2949
  abstract calculateTransactionFee(baseComputeUnits: bigint, bufferBasisPoints: bigint | undefined, chain: ChainDefinition): Promise<EstimatedGas>;
2950
+ /**
2951
+ * Get the decimal places for a token address on a given chain.
2952
+ *
2953
+ * This method fetches the number of decimal places from a token contract.
2954
+ * Different chain types implement this differently:
2955
+ * - EVM: Calls the `decimals()` function on ERC-20 contracts
2956
+ * - Solana: Reads the `decimals` field from the SPL token mint account
2957
+ *
2958
+ * @param tokenAddress - The token contract address (EVM) or mint address (Solana)
2959
+ * @param chain - The chain definition where the token is deployed
2960
+ * @returns Promise resolving to the number of decimal places for the token
2961
+ * @throws Error when the token contract doesn't exist or decimals cannot be fetched
2962
+ *
2963
+ * @example
2964
+ * ```typescript
2965
+ * import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
2966
+ * import { Ethereum } from '@core/chains'
2967
+ *
2968
+ * const adapter = new EthersAdapter({ signer })
2969
+ *
2970
+ * // Fetch decimals for DAI token
2971
+ * const decimals = await adapter.getTokenDecimals(
2972
+ * '0x6B175474E89094C44Da98b954EedeAC495271d0F',
2973
+ * Ethereum
2974
+ * )
2975
+ * console.log(decimals) // 18
2976
+ * ```
2977
+ */
2978
+ abstract getTokenDecimals(tokenAddress: string, chain: ChainDefinition): Promise<number>;
2389
2979
  }
2390
2980
 
2391
2981
  /**
@@ -2578,6 +3168,20 @@ declare module './types' {
2578
3168
  */
2579
3169
  interface TokenSymbolRegistry {
2580
3170
  USDC: true;
3171
+ USDT: true;
3172
+ EURC: true;
3173
+ DAI: true;
3174
+ USDE: true;
3175
+ PYUSD: true;
3176
+ WETH: true;
3177
+ WBTC: true;
3178
+ WSOL: true;
3179
+ WAVAX: true;
3180
+ WPOL: true;
3181
+ ETH: true;
3182
+ POL: true;
3183
+ PLUME: true;
3184
+ MON: true;
2581
3185
  }
2582
3186
  }
2583
3187
 
@@ -2755,7 +3359,8 @@ interface TokenDefinition {
2755
3359
  */
2756
3360
  readonly symbol: string;
2757
3361
  /**
2758
- * The number of decimal places for the token.
3362
+ * The default number of decimal places for the token.
3363
+ * Used when no chain-specific override exists in {@link chainDecimals}.
2759
3364
  * @example 6 for USDC, 18 for most ERC20 tokens
2760
3365
  */
2761
3366
  readonly decimals: number;
@@ -2765,6 +3370,15 @@ interface TokenDefinition {
2765
3370
  * Not all chains need to be present - tokens may only exist on a subset of chains.
2766
3371
  */
2767
3372
  readonly locators: Partial<ChainLocatorMap>;
3373
+ /**
3374
+ * Optional per-chain decimal overrides.
3375
+ *
3376
+ * Some tokens have different decimal places on different chains
3377
+ * (e.g., USDe is 18 decimals on EVM but 9 decimals on Solana).
3378
+ * When present, the value for a specific chain takes precedence
3379
+ * over the default {@link decimals}.
3380
+ */
3381
+ readonly chainDecimals?: Partial<Record<ChainIdentifier, number>>;
2768
3382
  }
2769
3383
  /**
2770
3384
  * A raw token locator selector with explicit decimals.
@@ -2923,6 +3537,15 @@ interface TokenRegistry {
2923
3537
  * @throws When the token cannot be resolved (unknown symbol, missing decimals, etc.).
2924
3538
  */
2925
3539
  resolve(selector: TokenSelector, chainId: ChainIdentifier): ResolvedToken;
3540
+ /**
3541
+ * Resolve a token by chain-specific locator (address/program ID).
3542
+ *
3543
+ * @param address - The token locator to resolve.
3544
+ * @param chainId - The chain identifier to resolve for.
3545
+ * @returns The resolved token information.
3546
+ * @throws When no registry token matches the locator on the chain.
3547
+ */
3548
+ resolveByAddress(address: string, chainId: ChainIdentifier): ResolvedToken;
2926
3549
  /**
2927
3550
  * Get a token definition by symbol.
2928
3551
  *
@@ -3288,7 +3911,7 @@ interface Timer {
3288
3911
  * ```typescript
3289
3912
  * // Create a scoped metrics instance
3290
3913
  * const appMetrics = metrics.child({
3291
- * service: 'stablecoin-kit',
3914
+ * service: 'app-kit',
3292
3915
  * version: '1.0.0',
3293
3916
  * })
3294
3917
  *