@circle-fin/adapter-ethers-v6 0.0.2-alpha.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +466 -162
- package/index.cjs.js +8395 -6251
- package/index.d.ts +1049 -320
- package/index.mjs +8397 -6254
- package/package.json +5 -5
package/index.d.ts
CHANGED
|
@@ -423,6 +423,10 @@ declare enum Blockchain {
|
|
|
423
423
|
Ethereum_Sepolia = "Ethereum_Sepolia",
|
|
424
424
|
Hedera = "Hedera",
|
|
425
425
|
Hedera_Testnet = "Hedera_Testnet",
|
|
426
|
+
HyperEVM = "HyperEVM",
|
|
427
|
+
HyperEVM_Testnet = "HyperEVM_Testnet",
|
|
428
|
+
Ink = "Ink",
|
|
429
|
+
Ink_Testnet = "Ink_Testnet",
|
|
426
430
|
Linea = "Linea",
|
|
427
431
|
Linea_Sepolia = "Linea_Sepolia",
|
|
428
432
|
NEAR = "NEAR",
|
|
@@ -433,6 +437,8 @@ declare enum Blockchain {
|
|
|
433
437
|
Optimism_Sepolia = "Optimism_Sepolia",
|
|
434
438
|
Polkadot_Asset_Hub = "Polkadot_Asset_Hub",
|
|
435
439
|
Polkadot_Westmint = "Polkadot_Westmint",
|
|
440
|
+
Plume = "Plume",
|
|
441
|
+
Plume_Testnet = "Plume_Testnet",
|
|
436
442
|
Polygon = "Polygon",
|
|
437
443
|
Polygon_Amoy_Testnet = "Polygon_Amoy_Testnet",
|
|
438
444
|
Sei = "Sei",
|
|
@@ -449,6 +455,8 @@ declare enum Blockchain {
|
|
|
449
455
|
Unichain_Sepolia = "Unichain_Sepolia",
|
|
450
456
|
World_Chain = "World_Chain",
|
|
451
457
|
World_Chain_Sepolia = "World_Chain_Sepolia",
|
|
458
|
+
XDC = "XDC",
|
|
459
|
+
XDC_Apothem = "XDC_Apothem",
|
|
452
460
|
ZKSync_Era = "ZKSync_Era",
|
|
453
461
|
ZKSync_Sepolia = "ZKSync_Sepolia"
|
|
454
462
|
}
|
|
@@ -618,10 +626,6 @@ type EvmPreparedChainRequestParams = {
|
|
|
618
626
|
functionName: string;
|
|
619
627
|
/** The arguments to pass to the function. */
|
|
620
628
|
args: unknown[];
|
|
621
|
-
/**
|
|
622
|
-
* The chain the prepared request should be executed on.
|
|
623
|
-
*/
|
|
624
|
-
chain: EVMChainDefinition;
|
|
625
629
|
} & Partial<EvmEstimateOverrides>;
|
|
626
630
|
/**
|
|
627
631
|
* Solana-specific parameters for preparing a transaction.
|
|
@@ -787,6 +791,147 @@ interface WaitForTransactionConfig {
|
|
|
787
791
|
*/
|
|
788
792
|
maxSupportedTransactionVersion?: number;
|
|
789
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* Type utility to extract the address context from adapter capabilities.
|
|
796
|
+
*
|
|
797
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type
|
|
798
|
+
* @returns The address context type or never if capabilities are undefined
|
|
799
|
+
*/
|
|
800
|
+
type ExtractAddressContext<TAdapterCapabilities extends AdapterCapabilities> = TAdapterCapabilities extends {
|
|
801
|
+
addressContext: infer TContext;
|
|
802
|
+
} ? TContext : never;
|
|
803
|
+
type AddressField<TAddressContext> = TAddressContext extends 'user-controlled' ? {
|
|
804
|
+
/**
|
|
805
|
+
* ℹ️ Address is forbidden for user-controlled adapters.
|
|
806
|
+
*
|
|
807
|
+
* User-controlled adapters (like browser wallets or private key adapters)
|
|
808
|
+
* automatically resolve the address from the connected wallet or signer.
|
|
809
|
+
* Providing an explicit address would conflict with this behavior.
|
|
810
|
+
*
|
|
811
|
+
* @example
|
|
812
|
+
* ```typescript
|
|
813
|
+
* // ℹ️ This will cause a TypeScript error:
|
|
814
|
+
* const context: AdapterContext<{ addressContext: 'user-controlled' }> = {
|
|
815
|
+
* adapter: userAdapter,
|
|
816
|
+
* chain: 'Ethereum',
|
|
817
|
+
* address: '0x123...' // Error: Address is forbidden for user-controlled adapters
|
|
818
|
+
* }
|
|
819
|
+
* ```
|
|
820
|
+
*/
|
|
821
|
+
address?: never;
|
|
822
|
+
} : TAddressContext extends 'developer-controlled' ? {
|
|
823
|
+
/**
|
|
824
|
+
* ℹ️ Address is required for developer-controlled adapters.
|
|
825
|
+
*
|
|
826
|
+
* Developer-controlled adapters (like enterprise providers or server-side adapters)
|
|
827
|
+
* require an explicit address for each operation since they don't have a single
|
|
828
|
+
* connected wallet. The address must be provided for every operation.
|
|
829
|
+
*
|
|
830
|
+
* @example
|
|
831
|
+
* ```typescript
|
|
832
|
+
* // ℹ️ This is required:
|
|
833
|
+
* const context: AdapterContext<{ addressContext: 'developer-controlled' }> = {
|
|
834
|
+
* adapter: devAdapter,
|
|
835
|
+
* chain: 'Ethereum',
|
|
836
|
+
* address: '0x123...' // Required for developer-controlled adapters
|
|
837
|
+
* }
|
|
838
|
+
*
|
|
839
|
+
* // ℹ️ This will cause a TypeScript error:
|
|
840
|
+
* const context: AdapterContext<{ addressContext: 'developer-controlled' }> = {
|
|
841
|
+
* adapter: devAdapter,
|
|
842
|
+
* chain: 'Ethereum'
|
|
843
|
+
* // Error: Address is required for developer-controlled adapters
|
|
844
|
+
* }
|
|
845
|
+
* ```
|
|
846
|
+
*/
|
|
847
|
+
address: string;
|
|
848
|
+
} : {
|
|
849
|
+
/**
|
|
850
|
+
* Address is optional for legacy adapters.
|
|
851
|
+
*
|
|
852
|
+
* Legacy adapters without defined capabilities maintain backward compatibility
|
|
853
|
+
* by allowing optional address specification.
|
|
854
|
+
*/
|
|
855
|
+
address?: string;
|
|
856
|
+
};
|
|
857
|
+
/**
|
|
858
|
+
* Generic operation context for adapter methods with compile-time address validation.
|
|
859
|
+
*
|
|
860
|
+
* This type provides compile-time enforcement of address requirements based on the
|
|
861
|
+
* adapter's capabilities. The address field behavior is determined by the adapter's
|
|
862
|
+
* address control model:
|
|
863
|
+
*
|
|
864
|
+
* - **User-controlled adapters** (default): The `address` field is forbidden (never) because
|
|
865
|
+
* the address is automatically resolved from the connected wallet or signer.
|
|
866
|
+
* - **Developer-controlled adapters**: The `address` field is required (string) because
|
|
867
|
+
* each operation must explicitly specify which address to use.
|
|
868
|
+
* - **Legacy adapters**: The `address` field remains optional for backward compatibility.
|
|
869
|
+
*
|
|
870
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type to derive address requirements from
|
|
871
|
+
*
|
|
872
|
+
* @example
|
|
873
|
+
* ```typescript
|
|
874
|
+
* import { OperationContext } from '@core/adapter'
|
|
875
|
+
*
|
|
876
|
+
* // User-controlled adapter context (default - address forbidden)
|
|
877
|
+
* type UserContext = OperationContext<{ addressContext: 'user-controlled', supportedChains: [] }>
|
|
878
|
+
* const userCtx: UserContext = {
|
|
879
|
+
* chain: 'Ethereum'
|
|
880
|
+
* // address: '0x123...' // ❌ TypeScript error: address not allowed
|
|
881
|
+
* }
|
|
882
|
+
*
|
|
883
|
+
* // Developer-controlled adapter context (explicit - address required)
|
|
884
|
+
* type DevContext = OperationContext<{ addressContext: 'developer-controlled', supportedChains: [] }>
|
|
885
|
+
* const devCtx: DevContext = {
|
|
886
|
+
* chain: 'Ethereum',
|
|
887
|
+
* address: '0x123...' // ✅ Required for developer-controlled
|
|
888
|
+
* }
|
|
889
|
+
* ```
|
|
890
|
+
*/
|
|
891
|
+
type OperationContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = {
|
|
892
|
+
/**
|
|
893
|
+
* The blockchain network to use for this operation.
|
|
894
|
+
*/
|
|
895
|
+
chain: ChainIdentifier;
|
|
896
|
+
} & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
|
|
897
|
+
/**
|
|
898
|
+
* Fully resolved context for an adapter operation, with concrete chain and address.
|
|
899
|
+
*
|
|
900
|
+
* This interface guarantees that both the blockchain network (`chain`) and the account
|
|
901
|
+
* address (`address`) are present and valid. It is produced by resolving an {@link OperationContext},
|
|
902
|
+
* which may have optional or conditional fields, into a form suitable for internal logic and action handlers.
|
|
903
|
+
*
|
|
904
|
+
* - `chain`: A fully resolved {@link ChainDefinition}, either explicitly provided or inferred from the adapter.
|
|
905
|
+
* - `address`: A string representing the resolved account address, determined by the context or adapter,
|
|
906
|
+
* depending on the address control model (developer- or user-controlled).
|
|
907
|
+
*
|
|
908
|
+
* Use this type when an operation requires both the chain and address to be unambiguous and available.
|
|
909
|
+
*
|
|
910
|
+
* @example
|
|
911
|
+
* ```ts
|
|
912
|
+
* import { ResolvedOperationContext} from "@core/adapter"
|
|
913
|
+
* import { Solana, ChainDefinition } from '@core/chains';
|
|
914
|
+
*
|
|
915
|
+
* const context: ResolvedOperationContext = {
|
|
916
|
+
* chain: Solana,
|
|
917
|
+
* address: '7Gk1v...abc123', // a valid Solana address
|
|
918
|
+
* };
|
|
919
|
+
*
|
|
920
|
+
* // Use context.chain and context.address in adapter operations
|
|
921
|
+
* ```
|
|
922
|
+
*/
|
|
923
|
+
interface ResolvedOperationContext {
|
|
924
|
+
/**
|
|
925
|
+
* The chain identifier for this operation.
|
|
926
|
+
* Guaranteed to be defined - either from context or adapter default.
|
|
927
|
+
*/
|
|
928
|
+
chain: ChainDefinition;
|
|
929
|
+
/**
|
|
930
|
+
* The address for this operation.
|
|
931
|
+
* Guaranteed to be defined - either specified (developer-controlled) or resolved (user-controlled).
|
|
932
|
+
*/
|
|
933
|
+
address: string;
|
|
934
|
+
}
|
|
790
935
|
|
|
791
936
|
/**
|
|
792
937
|
* Base interface for all action parameter objects.
|
|
@@ -1023,6 +1168,14 @@ interface CCTPv2ActionMap {
|
|
|
1023
1168
|
* Destination chain definition where tokens will be minted.
|
|
1024
1169
|
*/
|
|
1025
1170
|
readonly toChain: ChainDefinitionWithCCTPv2;
|
|
1171
|
+
/**
|
|
1172
|
+
* Optional destination wallet address on the destination chain to receive minted USDC.
|
|
1173
|
+
*
|
|
1174
|
+
* When provided (e.g., for Solana), the mint instruction will derive the
|
|
1175
|
+
* recipient's Associated Token Account (ATA) from this address instead of
|
|
1176
|
+
* the adapter's default address.
|
|
1177
|
+
*/
|
|
1178
|
+
readonly destinationAddress?: string;
|
|
1026
1179
|
};
|
|
1027
1180
|
/**
|
|
1028
1181
|
* Initiate a cross-chain USDC transfer using a custom bridge contract with preapproval funnel.
|
|
@@ -1116,7 +1269,7 @@ interface CCTPv2ActionMap {
|
|
|
1116
1269
|
*
|
|
1117
1270
|
* @defaultValue 0n - no protocol fee for basic usage
|
|
1118
1271
|
*/
|
|
1119
|
-
protocolFee?: bigint;
|
|
1272
|
+
protocolFee?: bigint | undefined;
|
|
1120
1273
|
/**
|
|
1121
1274
|
* Address to receive the protocol fee.
|
|
1122
1275
|
*
|
|
@@ -1126,7 +1279,7 @@ interface CCTPv2ActionMap {
|
|
|
1126
1279
|
*
|
|
1127
1280
|
* @defaultValue bridge contract address - safe fallback for zero fees
|
|
1128
1281
|
*/
|
|
1129
|
-
feeRecipient?: string;
|
|
1282
|
+
feeRecipient?: string | undefined;
|
|
1130
1283
|
/**
|
|
1131
1284
|
* Source chain definition where tokens will be burned.
|
|
1132
1285
|
*/
|
|
@@ -1380,7 +1533,7 @@ interface USDCActionMap {
|
|
|
1380
1533
|
/**
|
|
1381
1534
|
* Central registry of all available action namespaces and their operations.
|
|
1382
1535
|
*
|
|
1383
|
-
* Define the complete action map structure used throughout the
|
|
1536
|
+
* Define the complete action map structure used throughout the bridge kit.
|
|
1384
1537
|
* Each top-level key represents a namespace (e.g., 'token', 'usdc') containing
|
|
1385
1538
|
* related operations. The structure supports arbitrary nesting depth through
|
|
1386
1539
|
* the recursive utility types provided in this module.
|
|
@@ -1473,7 +1626,7 @@ type NestedValue<T, K extends string> = K extends `${infer First}.${infer Rest}`
|
|
|
1473
1626
|
*
|
|
1474
1627
|
* @remarks
|
|
1475
1628
|
* This type serves as the canonical source for all valid action identifiers
|
|
1476
|
-
* in the
|
|
1629
|
+
* in the bridge kit. It ensures compile-time validation of action keys
|
|
1477
1630
|
* and enables type-safe action dispatching throughout the application.
|
|
1478
1631
|
*
|
|
1479
1632
|
* @see {@link ActionPayload} for extracting parameter types
|
|
@@ -1515,18 +1668,23 @@ type ActionPayload<T extends ActionKeys> = Omit<NestedValue<ActionMap, T>, '__is
|
|
|
1515
1668
|
*
|
|
1516
1669
|
* @typeParam TActionKey - The specific action key this handler processes.
|
|
1517
1670
|
* @param params - The action payload matching the specified action key.
|
|
1671
|
+
* @param context - The resolved operation context with concrete chain and address values.
|
|
1518
1672
|
* @returns A promise resolving to a prepared chain request.
|
|
1519
1673
|
*
|
|
1520
1674
|
* @example
|
|
1521
1675
|
* ```typescript
|
|
1522
1676
|
* import type { ActionHandler } from '@core/adapter'
|
|
1523
1677
|
*
|
|
1524
|
-
* const depositHandler: ActionHandler<'cctp.v2.depositForBurn'> = async (params) => {
|
|
1525
|
-
* //
|
|
1678
|
+
* const depositHandler: ActionHandler<'cctp.v2.depositForBurn'> = async (params, context) => {
|
|
1679
|
+
* // context is always defined and has concrete chain and address values
|
|
1680
|
+
* console.log(context.chain.name);
|
|
1681
|
+
* console.log(context.address);
|
|
1682
|
+
* // ... handler logic ...
|
|
1683
|
+
* return preparedRequest;
|
|
1526
1684
|
* }
|
|
1527
1685
|
* ```
|
|
1528
1686
|
*/
|
|
1529
|
-
type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActionKey
|
|
1687
|
+
type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActionKey>, context: ResolvedOperationContext) => Promise<PreparedChainRequest>;
|
|
1530
1688
|
/**
|
|
1531
1689
|
* Type-safe mapping of all available action keys to their corresponding handlers.
|
|
1532
1690
|
*
|
|
@@ -1536,7 +1694,7 @@ type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActi
|
|
|
1536
1694
|
* handler registration and lookup for all supported actions in the Stablecoin Kits.
|
|
1537
1695
|
*
|
|
1538
1696
|
* @remarks
|
|
1539
|
-
* Each handler is typed as {@link ActionHandler
|
|
1697
|
+
* Each handler is typed as {@link ActionHandler}, which means the handler
|
|
1540
1698
|
* must accept the payload type for the specific action key it is registered under.
|
|
1541
1699
|
* This provides type safety for handler registration and execution, but does not
|
|
1542
1700
|
* enforce per-key handler parameterization at the type level. For stricter per-key
|
|
@@ -1548,12 +1706,14 @@ type ActionHandler<TActionKey extends ActionKeys> = (params: ActionPayload<TActi
|
|
|
1548
1706
|
* import type { ActionHandler } from '@core/adapter'
|
|
1549
1707
|
*
|
|
1550
1708
|
* const handlers: ActionHandlers = {
|
|
1551
|
-
* 'cctp.v2.depositForBurn': async (params) => {
|
|
1709
|
+
* 'cctp.v2.depositForBurn': async (params, resolved) => {
|
|
1552
1710
|
* // params is correctly typed for 'cctp.v2.depositForBurn'
|
|
1711
|
+
* // resolved has concrete chain and address values
|
|
1553
1712
|
* // ...handler logic...
|
|
1554
1713
|
* },
|
|
1555
|
-
* 'usdc.approve': async (params) => {
|
|
1714
|
+
* 'usdc.approve': async (params, resolved) => {
|
|
1556
1715
|
* // params is correctly typed for 'usdc.approve'
|
|
1716
|
+
* // resolved has concrete chain and address values
|
|
1557
1717
|
* // ...handler logic...
|
|
1558
1718
|
* }
|
|
1559
1719
|
* }
|
|
@@ -1591,8 +1751,8 @@ declare class ActionRegistry {
|
|
|
1591
1751
|
* @param handler - The handler function for processing this action type.
|
|
1592
1752
|
* @returns Void.
|
|
1593
1753
|
*
|
|
1594
|
-
* @throws
|
|
1595
|
-
* @throws
|
|
1754
|
+
* @throws Error When action parameter is not a valid string.
|
|
1755
|
+
* @throws TypeError When handler parameter is not a function.
|
|
1596
1756
|
*
|
|
1597
1757
|
* @example
|
|
1598
1758
|
* ```typescript
|
|
@@ -1602,7 +1762,7 @@ declare class ActionRegistry {
|
|
|
1602
1762
|
* const registry = new ActionRegistry()
|
|
1603
1763
|
*
|
|
1604
1764
|
* // Register a CCTP deposit handler
|
|
1605
|
-
* const depositHandler: ActionHandler<'cctp.v2.depositForBurn'> = async (params) => {
|
|
1765
|
+
* const depositHandler: ActionHandler<'cctp.v2.depositForBurn'> = async (params, resolved) => {
|
|
1606
1766
|
* console.log('Processing deposit:', params.amount)
|
|
1607
1767
|
* return {
|
|
1608
1768
|
* chainId: params.chainId,
|
|
@@ -1639,14 +1799,14 @@ declare class ActionRegistry {
|
|
|
1639
1799
|
*
|
|
1640
1800
|
* // Register multiple handlers at once
|
|
1641
1801
|
* const tokenHandlers: ActionHandlers = {
|
|
1642
|
-
* 'token.approve': async (params) => ({
|
|
1643
|
-
* chainId:
|
|
1802
|
+
* 'token.approve': async (params, resolved) => ({
|
|
1803
|
+
* chainId: resolved.chain,
|
|
1644
1804
|
* data: '0x095ea7b3...',
|
|
1645
1805
|
* to: params.tokenAddress,
|
|
1646
1806
|
* value: '0'
|
|
1647
1807
|
* }),
|
|
1648
|
-
* 'token.transfer': async (params) => ({
|
|
1649
|
-
* chainId:
|
|
1808
|
+
* 'token.transfer': async (params, resolved) => ({
|
|
1809
|
+
* chainId: resolved.chain,
|
|
1650
1810
|
* data: '0xa9059cbb...',
|
|
1651
1811
|
* to: params.tokenAddress,
|
|
1652
1812
|
* value: '0'
|
|
@@ -1698,13 +1858,14 @@ declare class ActionRegistry {
|
|
|
1698
1858
|
* Execute a registered action handler with type-safe parameters.
|
|
1699
1859
|
*
|
|
1700
1860
|
* Look up and execute the handler associated with the given action key,
|
|
1701
|
-
* passing the provided parameters and returning the resulting prepared
|
|
1861
|
+
* passing the provided parameters and context, returning the resulting prepared
|
|
1702
1862
|
* chain request. TypeScript ensures the parameters match the expected
|
|
1703
1863
|
* structure for the specified action.
|
|
1704
1864
|
*
|
|
1705
1865
|
* @typeParam TActionKey - The specific action key being executed.
|
|
1706
1866
|
* @param action - The action key identifying which handler to execute.
|
|
1707
1867
|
* @param params - The parameters to pass to the action handler.
|
|
1868
|
+
* @param context - The resolved operation context with concrete chain and address values.
|
|
1708
1869
|
* @returns A promise resolving to the prepared chain request.
|
|
1709
1870
|
*
|
|
1710
1871
|
* @throws {Error} When action parameter is not a valid string.
|
|
@@ -1719,78 +1880,76 @@ declare class ActionRegistry {
|
|
|
1719
1880
|
* const registry = new ActionRegistry()
|
|
1720
1881
|
*
|
|
1721
1882
|
* // First register a handler
|
|
1722
|
-
* registry.registerHandler('token.approve', async (params) => ({
|
|
1723
|
-
* chainId:
|
|
1883
|
+
* registry.registerHandler('token.approve', async (params, context) => ({
|
|
1884
|
+
* chainId: context.chain, // Always defined
|
|
1724
1885
|
* data: '0x095ea7b3...',
|
|
1725
1886
|
* to: params.tokenAddress,
|
|
1726
1887
|
* value: '0'
|
|
1727
1888
|
* }))
|
|
1728
1889
|
*
|
|
1729
|
-
* // Execute the action with
|
|
1890
|
+
* // Execute the action with resolved context (typically called from adapter.prepareAction)
|
|
1891
|
+
* const resolvedContext = { chain: 'Base', address: '0x123...' }
|
|
1730
1892
|
* const result = await registry.executeAction('token.approve', {
|
|
1731
1893
|
* chainId: ChainEnum.Ethereum,
|
|
1732
1894
|
* tokenAddress: '0xA0b86a33E6441c8C1c7C16e4c5e3e5b5e4c5e3e5b5e4c5e',
|
|
1733
1895
|
* delegate: '0x1234567890123456789012345678901234567890',
|
|
1734
1896
|
* amount: '1000000'
|
|
1735
|
-
* })
|
|
1897
|
+
* }, resolvedContext)
|
|
1736
1898
|
*
|
|
1737
1899
|
* console.log('Transaction prepared:', result.data)
|
|
1738
1900
|
* ```
|
|
1739
1901
|
*/
|
|
1740
|
-
executeAction<TActionKey extends ActionKeys>(action: TActionKey, params: ActionPayload<TActionKey
|
|
1902
|
+
executeAction<TActionKey extends ActionKeys>(action: TActionKey, params: ActionPayload<TActionKey>, context: ResolvedOperationContext): Promise<PreparedChainRequest>;
|
|
1741
1903
|
}
|
|
1742
1904
|
|
|
1743
1905
|
/**
|
|
1744
1906
|
* Defines the capabilities of an adapter, including address handling patterns and supported chains.
|
|
1745
1907
|
*
|
|
1746
|
-
* @interface
|
|
1908
|
+
* @interface TAdapterCapabilities
|
|
1747
1909
|
* @category Types
|
|
1748
1910
|
* @description
|
|
1749
|
-
* This interface
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1911
|
+
* This interface specifies how an adapter manages address control and which blockchain networks it supports.
|
|
1912
|
+
* It is used for capability discovery, validation, and to inform consumers about the adapter's operational model.
|
|
1913
|
+
*
|
|
1914
|
+
* The `addressContext` property determines both address selection behavior and bridge API requirements:
|
|
1915
|
+
* - `'user-controlled'`: User controls addresses through wallet UI, address optional in operations
|
|
1916
|
+
* - `'developer-controlled'`: Service manages addresses programmatically, address required in operations
|
|
1752
1917
|
*
|
|
1753
1918
|
* @example
|
|
1754
1919
|
* ```typescript
|
|
1755
|
-
* //
|
|
1920
|
+
* // Browser wallet adapter (user-controlled)
|
|
1756
1921
|
* const capabilities: AdapterCapabilities = {
|
|
1757
|
-
* addressContext: '
|
|
1758
|
-
* supportedChains: [Ethereum, Base, Polygon]
|
|
1759
|
-
* availableAddresses: ['0x123...']
|
|
1922
|
+
* addressContext: 'user-controlled', // User selects address in wallet UI
|
|
1923
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
1760
1924
|
* }
|
|
1761
1925
|
*
|
|
1762
|
-
* //
|
|
1926
|
+
* // Enterprise provider adapter (developer-controlled)
|
|
1763
1927
|
* const capabilities: AdapterCapabilities = {
|
|
1764
|
-
* addressContext: '
|
|
1765
|
-
* supportedChains: [Ethereum, Base, Solana]
|
|
1766
|
-
* availableAddresses: undefined // Too many to fetch
|
|
1928
|
+
* addressContext: 'developer-controlled', // Address must be specified per operation
|
|
1929
|
+
* supportedChains: [Ethereum, Base, Solana]
|
|
1767
1930
|
* }
|
|
1768
1931
|
* ```
|
|
1769
1932
|
*/
|
|
1770
1933
|
interface AdapterCapabilities {
|
|
1771
1934
|
/**
|
|
1772
|
-
* Defines
|
|
1935
|
+
* Defines who controls address selection for wallet operations.
|
|
1773
1936
|
*
|
|
1774
|
-
* - `'
|
|
1775
|
-
*
|
|
1776
|
-
*
|
|
1937
|
+
* - `'user-controlled'`: User controls addresses through wallet UI (browser wallets, hardware wallets)
|
|
1938
|
+
* - Address is implicit in bridge operations (uses wallet's current address)
|
|
1939
|
+
* - Adapter may listen for accountsChanged/chainChanged events
|
|
1940
|
+
* - Suitable for MetaMask, Coinbase Wallet, WalletConnect, private keys, etc.
|
|
1941
|
+
*
|
|
1942
|
+
* - `'developer-controlled'`: Service manages addresses programmatically (enterprise providers)
|
|
1943
|
+
* - Address must be explicitly provided in bridge operations
|
|
1944
|
+
* - No event listening (addresses controlled programmatically)
|
|
1945
|
+
* - Suitable for Fireblocks, Circle Wallets, institutional custody, etc.
|
|
1777
1946
|
*/
|
|
1778
|
-
addressContext: '
|
|
1947
|
+
addressContext: 'user-controlled' | 'developer-controlled';
|
|
1779
1948
|
/**
|
|
1780
|
-
*
|
|
1781
|
-
* Used for validation and
|
|
1949
|
+
* The set of blockchain networks this adapter supports.
|
|
1950
|
+
* Used for validation, capability discovery, and to restrict operations to supported chains.
|
|
1782
1951
|
*/
|
|
1783
1952
|
supportedChains: ChainDefinition[];
|
|
1784
|
-
/**
|
|
1785
|
-
* Available addresses for single and user-accounts adapters.
|
|
1786
|
-
*
|
|
1787
|
-
* - For `single` adapters: Contains exactly one address
|
|
1788
|
-
* - For `user-accounts` adapters: Contains user's available addresses
|
|
1789
|
-
* - For `multi-entity` adapters: Should be undefined (too many addresses to list)
|
|
1790
|
-
*
|
|
1791
|
-
* This is populated during adapter creation to avoid repeated network calls.
|
|
1792
|
-
*/
|
|
1793
|
-
availableAddresses?: string[];
|
|
1794
1953
|
}
|
|
1795
1954
|
/**
|
|
1796
1955
|
* Abstract class defining the standard interface for an adapter that interacts with a specific blockchain.
|
|
@@ -1801,63 +1960,41 @@ interface AdapterCapabilities {
|
|
|
1801
1960
|
*
|
|
1802
1961
|
* This abstraction allows the Stablecoin Kits to work with multiple blockchains in a uniform way.
|
|
1803
1962
|
*
|
|
1963
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type for compile-time address validation.
|
|
1964
|
+
* When provided, enables strict typing of operation context based on the adapter's address control model.
|
|
1804
1965
|
*/
|
|
1805
|
-
declare abstract class Adapter {
|
|
1966
|
+
declare abstract class Adapter<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
|
|
1806
1967
|
/**
|
|
1807
1968
|
* The type of the chain.
|
|
1808
1969
|
* @example 'evm', 'solana'
|
|
1809
1970
|
*/
|
|
1810
1971
|
abstract chainType: ChainType;
|
|
1811
1972
|
/**
|
|
1812
|
-
* Capabilities of this adapter, defining address
|
|
1973
|
+
* Capabilities of this adapter, defining address control model and supported chains.
|
|
1813
1974
|
*
|
|
1814
|
-
* This property
|
|
1815
|
-
* and
|
|
1816
|
-
* context in operations.
|
|
1975
|
+
* This property determines how the adapter behaves, especially for address selection
|
|
1976
|
+
* and bridge API requirements. The `addressContext` must match the adapter's type parameter.
|
|
1817
1977
|
*
|
|
1818
1978
|
* @remarks
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1979
|
+
* The `addressContext` value must align with the adapter's generic type parameter for proper
|
|
1980
|
+
* type safety in bridge operations.
|
|
1821
1981
|
*
|
|
1822
1982
|
* @example
|
|
1823
1983
|
* ```typescript
|
|
1824
|
-
* //
|
|
1984
|
+
* // User-controlled adapter (private key, browser wallet)
|
|
1825
1985
|
* capabilities = {
|
|
1826
|
-
* addressContext: '
|
|
1827
|
-
* supportedChains: [Ethereum, Base]
|
|
1828
|
-
* availableAddresses: ['0x123...']
|
|
1986
|
+
* addressContext: 'user-controlled', // Address implicit in bridge operations
|
|
1987
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
1829
1988
|
* }
|
|
1830
1989
|
*
|
|
1831
|
-
* //
|
|
1990
|
+
* // Developer-controlled adapter (enterprise provider)
|
|
1832
1991
|
* capabilities = {
|
|
1833
|
-
* addressContext: '
|
|
1834
|
-
* supportedChains: [Ethereum, Base,
|
|
1835
|
-
* availableAddresses: ['0x123...', '0x456...']
|
|
1992
|
+
* addressContext: 'developer-controlled', // Address required in bridge operations
|
|
1993
|
+
* supportedChains: [Ethereum, Base, Solana]
|
|
1836
1994
|
* }
|
|
1837
1995
|
* ```
|
|
1838
1996
|
*/
|
|
1839
|
-
capabilities?:
|
|
1840
|
-
/**
|
|
1841
|
-
* Default chain for operations when none is explicitly provided.
|
|
1842
|
-
*
|
|
1843
|
-
* This allows adapters to have sensible defaults for chain operations,
|
|
1844
|
-
* reducing the need for explicit chain specification in every call.
|
|
1845
|
-
* Multi-entity adapters typically don't have a default chain.
|
|
1846
|
-
*
|
|
1847
|
-
* @remarks
|
|
1848
|
-
* This is optional for backward compatibility and because some adapter types
|
|
1849
|
-
* (like multi-entity adapters) may not have meaningful defaults.
|
|
1850
|
-
*
|
|
1851
|
-
* @example
|
|
1852
|
-
* ```typescript
|
|
1853
|
-
* // Private key adapter with default chain
|
|
1854
|
-
* defaultChain = Ethereum
|
|
1855
|
-
*
|
|
1856
|
-
* // Multi-entity adapter (no default)
|
|
1857
|
-
* defaultChain = undefined
|
|
1858
|
-
* ```
|
|
1859
|
-
*/
|
|
1860
|
-
defaultChain?: ChainDefinition;
|
|
1997
|
+
capabilities?: TAdapterCapabilities;
|
|
1861
1998
|
/**
|
|
1862
1999
|
* Registry of available actions for this adapter.
|
|
1863
2000
|
*
|
|
@@ -1877,6 +2014,12 @@ declare abstract class Adapter {
|
|
|
1877
2014
|
* {@link PreparedChainRequest} allows developers to estimate gas costs and execute
|
|
1878
2015
|
* the transaction at a later time, enabling pre-flight simulation and deferred execution.
|
|
1879
2016
|
*
|
|
2017
|
+
* **Compile-time Address Validation**: When used with typed adapters that have capabilities,
|
|
2018
|
+
* this method enforces address requirements at compile time:
|
|
2019
|
+
* - **User-controlled adapters**: The `address` field is forbidden in the context
|
|
2020
|
+
* - **Developer-controlled adapters**: The `address` field is required in the context
|
|
2021
|
+
* - **Legacy adapters**: The `address` field remains optional for backward compatibility
|
|
2022
|
+
*
|
|
1880
2023
|
* @remarks
|
|
1881
2024
|
* This method does not send any transaction to the network. Instead, it returns a
|
|
1882
2025
|
* prepared request object with `estimate()` and `execute()` methods, allowing
|
|
@@ -1884,9 +2027,30 @@ declare abstract class Adapter {
|
|
|
1884
2027
|
*
|
|
1885
2028
|
* @param action - The action key identifying which handler to use for preparation.
|
|
1886
2029
|
* @param params - The parameters to pass to the action handler.
|
|
2030
|
+
* @param ctx - Operation context with compile-time validated address requirements based on adapter capabilities.
|
|
1887
2031
|
* @returns A promise that resolves to a {@link PreparedChainRequest} for estimation and execution.
|
|
2032
|
+
* @throws Error If the specified action key does not correspond to a registered handler.
|
|
2033
|
+
* @throws Error If the provided parameters are invalid for the action.
|
|
2034
|
+
* @throws Error If the operation context cannot be resolved.
|
|
2035
|
+
*
|
|
2036
|
+
* @example
|
|
2037
|
+
* ```typescript
|
|
2038
|
+
* // User-controlled adapter (address forbidden)
|
|
2039
|
+
* const userAdapter: Adapter<{ addressContext: 'user-controlled', supportedChains: [] }>
|
|
2040
|
+
* await userAdapter.prepareAction('token.approve', params, {
|
|
2041
|
+
* chain: 'Ethereum'
|
|
2042
|
+
* // address: '0x123...' // ❌ TypeScript error: address not allowed
|
|
2043
|
+
* })
|
|
2044
|
+
*
|
|
2045
|
+
* // Developer-controlled adapter (address required)
|
|
2046
|
+
* const devAdapter: Adapter<{ addressContext: 'developer-controlled', supportedChains: [] }>
|
|
2047
|
+
* await devAdapter.prepareAction('token.approve', params, {
|
|
2048
|
+
* chain: 'Ethereum',
|
|
2049
|
+
* address: '0x123...' // ✅ Required for developer-controlled
|
|
2050
|
+
* })
|
|
2051
|
+
* ```
|
|
1888
2052
|
*/
|
|
1889
|
-
prepareAction<TActionKey extends ActionKeys>(action: TActionKey, params: ActionPayload<TActionKey>): Promise<PreparedChainRequest>;
|
|
2053
|
+
prepareAction<TActionKey extends ActionKeys>(action: TActionKey, params: ActionPayload<TActionKey>, ctx?: OperationContext<TAdapterCapabilities>): Promise<PreparedChainRequest>;
|
|
1890
2054
|
/**
|
|
1891
2055
|
* Prepares a transaction for future gas estimation and execution.
|
|
1892
2056
|
*
|
|
@@ -1899,6 +2063,12 @@ declare abstract class Adapter {
|
|
|
1899
2063
|
* - `execute()`: Asynchronously executes the prepared transaction and returns a promise that resolves
|
|
1900
2064
|
* with the transaction result (e.g., a transaction hash, receipt, or other chain-specific response).
|
|
1901
2065
|
*
|
|
2066
|
+
* **Compile-time Address Validation**: When used with typed adapters that have capabilities,
|
|
2067
|
+
* this method enforces address requirements at compile time:
|
|
2068
|
+
* - **User-controlled adapters**: The `address` field is forbidden in the context
|
|
2069
|
+
* - **Developer-controlled adapters**: The `address` field is required in the context
|
|
2070
|
+
* - **Legacy adapters**: The `address` field remains optional for backward compatibility
|
|
2071
|
+
*
|
|
1902
2072
|
* @remarks
|
|
1903
2073
|
* The specific parameters for `prepare` might vary greatly between chain implementations.
|
|
1904
2074
|
* Consider defining a generic type or a base type for `transactionRequest` if common patterns emerge,
|
|
@@ -1906,28 +2076,38 @@ declare abstract class Adapter {
|
|
|
1906
2076
|
* For this abstract definition, we keep it parameter-less, assuming implementations will add specific
|
|
1907
2077
|
* parameters as needed for their `prepare` method (e.g. `prepare(txDetails: MyChainTxDetails)`).
|
|
1908
2078
|
*
|
|
2079
|
+
* @param params - The prepared chain request parameters for the specific blockchain.
|
|
2080
|
+
* @param ctx - Operation context with compile-time validated address requirements based on adapter capabilities.
|
|
1909
2081
|
* @returns An object containing `estimate` and `execute` methods for the prepared transaction.
|
|
2082
|
+
*
|
|
2083
|
+
* @example
|
|
2084
|
+
* ```typescript
|
|
2085
|
+
* // User-controlled adapter (address forbidden)
|
|
2086
|
+
* const userAdapter: Adapter<{ addressContext: 'user-controlled', supportedChains: [] }>
|
|
2087
|
+
* await userAdapter.prepare(params, {
|
|
2088
|
+
* chain: 'Ethereum'
|
|
2089
|
+
* // address: '0x123...' // ❌ TypeScript error: address not allowed
|
|
2090
|
+
* })
|
|
2091
|
+
*
|
|
2092
|
+
* // Developer-controlled adapter (address required)
|
|
2093
|
+
* const devAdapter: Adapter<{ addressContext: 'developer-controlled', supportedChains: [] }>
|
|
2094
|
+
* await devAdapter.prepare(params, {
|
|
2095
|
+
* chain: 'Ethereum',
|
|
2096
|
+
* address: '0x123...' // ✅ Required for developer-controlled
|
|
2097
|
+
* })
|
|
2098
|
+
* ```
|
|
1910
2099
|
*/
|
|
1911
|
-
abstract prepare(params: PreparedChainRequestParams): Promise<PreparedChainRequest>;
|
|
2100
|
+
abstract prepare(params: PreparedChainRequestParams, ctx: OperationContext<TAdapterCapabilities>): Promise<PreparedChainRequest>;
|
|
1912
2101
|
/**
|
|
1913
2102
|
* Retrieves the public address of the connected wallet.
|
|
1914
2103
|
*
|
|
1915
2104
|
* This address is used as the default sender for transactions
|
|
1916
2105
|
* and interactions initiated by this adapter.
|
|
1917
2106
|
*
|
|
2107
|
+
* @param chain - Optional chain definition for chain-specific address resolution (used by EVM adapters)
|
|
1918
2108
|
* @returns A promise that resolves to the blockchain address as a string.
|
|
1919
2109
|
*/
|
|
1920
|
-
abstract getAddress(): Promise<string>;
|
|
1921
|
-
/**
|
|
1922
|
-
* Retrieves the {@link ChainDefinition} object that describes the blockchain
|
|
1923
|
-
* this adapter is configured to interact with.
|
|
1924
|
-
*
|
|
1925
|
-
* This includes information such as the chain ID, name, native currency, etc.,
|
|
1926
|
-
* as defined by the `ChainDefinition` type.
|
|
1927
|
-
*
|
|
1928
|
-
* @returns A promise that resolves to the {@link ChainDefinition} for the current chain.
|
|
1929
|
-
*/
|
|
1930
|
-
abstract getChain(): Promise<ChainDefinition>;
|
|
2110
|
+
abstract getAddress(chain?: ChainDefinition): Promise<string>;
|
|
1931
2111
|
/**
|
|
1932
2112
|
* Switches the adapter to operate on the specified chain.
|
|
1933
2113
|
*
|
|
@@ -1972,17 +2152,14 @@ declare abstract class Adapter {
|
|
|
1972
2152
|
* - **Browser wallet adapters**: Request chain switch via EIP-1193 or equivalent
|
|
1973
2153
|
* - **Multi-entity adapters**: Validate chain support (operations are contextual)
|
|
1974
2154
|
*
|
|
1975
|
-
* @param chain - The target chain for operations.
|
|
2155
|
+
* @param chain - The target chain for operations.
|
|
1976
2156
|
* @returns A promise that resolves when the adapter is operating on the specified chain.
|
|
1977
2157
|
* @throws When the target chain is not supported or chain switching fails.
|
|
1978
2158
|
*
|
|
1979
2159
|
* @remarks
|
|
1980
|
-
* This method
|
|
1981
|
-
*
|
|
1982
|
-
*
|
|
1983
|
-
* **Backward Compatibility**: The default implementation provides basic validation but
|
|
1984
|
-
* doesn't perform actual chain switching. Concrete adapter implementations should override
|
|
1985
|
-
* this method to provide proper chain switching logic.
|
|
2160
|
+
* This method always calls `switchToChain()` to ensure consistency across all adapter types.
|
|
2161
|
+
* The underlying implementations handle idempotent switching efficiently (e.g., browser wallets
|
|
2162
|
+
* gracefully handle switching to the current chain, private key adapters recreate lightweight clients).
|
|
1986
2163
|
*
|
|
1987
2164
|
* @example
|
|
1988
2165
|
* ```typescript
|
|
@@ -1996,7 +2173,7 @@ declare abstract class Adapter {
|
|
|
1996
2173
|
* await circleWalletsAdapter.ensureChain(Ethereum)
|
|
1997
2174
|
* ```
|
|
1998
2175
|
*/
|
|
1999
|
-
ensureChain(
|
|
2176
|
+
ensureChain(targetChain: ChainDefinition): Promise<void>;
|
|
2000
2177
|
/**
|
|
2001
2178
|
* Validate that the target chain is supported by this adapter.
|
|
2002
2179
|
*
|
|
@@ -2012,9 +2189,10 @@ declare abstract class Adapter {
|
|
|
2012
2189
|
*
|
|
2013
2190
|
* @param txHash - The hash of the transaction to wait for.
|
|
2014
2191
|
* @param config - Optional configuration for waiting behavior including timeout and confirmations.
|
|
2192
|
+
* @param chain - The chain definition where the transaction was submitted.
|
|
2015
2193
|
* @returns Promise resolving to comprehensive transaction details.
|
|
2016
2194
|
*/
|
|
2017
|
-
abstract waitForTransaction(txHash: string, config
|
|
2195
|
+
abstract waitForTransaction(txHash: string, config: WaitForTransactionConfig | undefined, chain: ChainDefinition): Promise<WaitForTransactionResponse>;
|
|
2018
2196
|
/**
|
|
2019
2197
|
* Calculate the total transaction fee including compute cost and buffer for the configured chain.
|
|
2020
2198
|
*
|
|
@@ -2024,11 +2202,25 @@ declare abstract class Adapter {
|
|
|
2024
2202
|
*
|
|
2025
2203
|
* @param baseComputeUnits - The base compute units for the transaction (gas for EVM, compute units for Solana, etc.).
|
|
2026
2204
|
* @param bufferBasisPoints - The buffer to add as basis points (e.g., 500 = 5%). Defaults to implementation-specific value.
|
|
2205
|
+
* @param chain - The chain definition to calculate fees for.
|
|
2027
2206
|
* @returns A promise that resolves to the total transaction fee as a bigint.
|
|
2028
2207
|
*/
|
|
2029
|
-
abstract calculateTransactionFee(baseComputeUnits: bigint, bufferBasisPoints
|
|
2208
|
+
abstract calculateTransactionFee(baseComputeUnits: bigint, bufferBasisPoints: bigint | undefined, chain: ChainDefinition): Promise<EstimatedGas>;
|
|
2030
2209
|
}
|
|
2031
2210
|
|
|
2211
|
+
/**
|
|
2212
|
+
* Type utility that infers the final adapter capabilities from partial overrides.
|
|
2213
|
+
* This provides clean type inference without complex conditional types.
|
|
2214
|
+
*/
|
|
2215
|
+
type InferAdapterCapabilities<T extends Partial<AdapterCapabilities>> = T & {
|
|
2216
|
+
addressContext: T extends {
|
|
2217
|
+
addressContext: infer A;
|
|
2218
|
+
} ? A : 'user-controlled';
|
|
2219
|
+
supportedChains: T extends {
|
|
2220
|
+
supportedChains: infer S;
|
|
2221
|
+
} ? S : ChainDefinition[];
|
|
2222
|
+
};
|
|
2223
|
+
|
|
2032
2224
|
/**
|
|
2033
2225
|
* EIP-712 domain structure for typed data signing.
|
|
2034
2226
|
*
|
|
@@ -2160,12 +2352,19 @@ interface ReadContractParams {
|
|
|
2160
2352
|
* The signTypedData method uses a generic TypedData interface from the signTypedData module,
|
|
2161
2353
|
* making it compatible with any EIP-712 standard (EIP-2612, EIP-7597, ERC-3009, etc.) while
|
|
2162
2354
|
* maintaining type safety throughout the signing process.
|
|
2355
|
+
*
|
|
2356
|
+
* Includes caching and synchronization capabilities for provider-based adapters that need
|
|
2357
|
+
* to respond to account and chain changes from external wallets (e.g., MetaMask).
|
|
2163
2358
|
*/
|
|
2164
|
-
declare abstract class EvmAdapter extends Adapter {
|
|
2359
|
+
declare abstract class EvmAdapter<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> extends Adapter<TAdapterCapabilities> {
|
|
2165
2360
|
/**
|
|
2166
2361
|
* The type of chain this adapter is for.
|
|
2167
2362
|
*/
|
|
2168
2363
|
chainType: ChainType;
|
|
2364
|
+
/**
|
|
2365
|
+
* Cached gas price for the current network.
|
|
2366
|
+
*/
|
|
2367
|
+
cachedGasPrice?: bigint;
|
|
2169
2368
|
/**
|
|
2170
2369
|
* The constructor for the EVM adapter.
|
|
2171
2370
|
*
|
|
@@ -2183,8 +2382,10 @@ declare abstract class EvmAdapter extends Adapter {
|
|
|
2183
2382
|
* @typeParam Types - The EIP-712 types definition for the standard being signed
|
|
2184
2383
|
* @typeParam Message - The message structure for the standard being signed
|
|
2185
2384
|
* @param typedData - The EIP-712 typed data to sign with full type safety
|
|
2385
|
+
* @param ctx - Required operation context specifying the chain and address for this operation
|
|
2186
2386
|
* @returns Promise resolving to the signature as a hex string
|
|
2187
2387
|
* @throws Error when the wallet client is not available or signing fails
|
|
2388
|
+
* @throws Error when OperationContext resolution fails
|
|
2188
2389
|
*
|
|
2189
2390
|
* @example
|
|
2190
2391
|
* ```typescript
|
|
@@ -2192,10 +2393,12 @@ declare abstract class EvmAdapter extends Adapter {
|
|
|
2192
2393
|
* import { buildEIP2612TypedData } from '@core/adapter-evm'
|
|
2193
2394
|
*
|
|
2194
2395
|
* const typedData = await buildEIP2612TypedData(meta, adapter, options)
|
|
2195
|
-
* const signature = await adapter.signTypedData(typedData
|
|
2396
|
+
* const signature = await adapter.signTypedData(typedData, {
|
|
2397
|
+
* chain: 'Base' // Chain specified in context
|
|
2398
|
+
* })
|
|
2196
2399
|
* ```
|
|
2197
2400
|
*/
|
|
2198
|
-
abstract signTypedData<Types extends Record<string, TypedDataField[]>, Message extends Record<string, unknown>>(typedData: TypedData<Types, Message>): Promise<`0x${string}`>;
|
|
2401
|
+
abstract signTypedData<Types extends Record<string, TypedDataField[]>, Message extends Record<string, unknown>>(typedData: TypedData<Types, Message>, ctx: OperationContext<TAdapterCapabilities>): Promise<`0x${string}`>;
|
|
2199
2402
|
/**
|
|
2200
2403
|
* Fetches the current EIP-2612 nonce for a token owner.
|
|
2201
2404
|
*
|
|
@@ -2217,15 +2420,59 @@ declare abstract class EvmAdapter extends Adapter {
|
|
|
2217
2420
|
* )
|
|
2218
2421
|
* ```
|
|
2219
2422
|
*/
|
|
2220
|
-
fetchEIP2612Nonce(tokenAddress: `0x${string}`, ownerAddress: `0x${string}
|
|
2423
|
+
fetchEIP2612Nonce(tokenAddress: `0x${string}`, ownerAddress: `0x${string}`, ctx: OperationContext<TAdapterCapabilities>): Promise<bigint>;
|
|
2221
2424
|
/**
|
|
2222
2425
|
* Read a contract function.
|
|
2223
2426
|
*
|
|
2224
2427
|
* @typeParam TReturnType - The expected return type of the contract function.
|
|
2225
2428
|
* @param params - The parameters for the contract function read.
|
|
2429
|
+
* @param chain - The chain definition where the contract is deployed.
|
|
2226
2430
|
* @returns A promise that resolves to the result of the contract function read.
|
|
2227
2431
|
*/
|
|
2228
|
-
abstract readContract<TReturnType = unknown>(params: ReadContractParams): Promise<TReturnType>;
|
|
2432
|
+
abstract readContract<TReturnType = unknown>(params: ReadContractParams, chain: EVMChainDefinition): Promise<TReturnType>;
|
|
2433
|
+
/**
|
|
2434
|
+
* Fetches the current gas price from the network, bypassing cache.
|
|
2435
|
+
*
|
|
2436
|
+
* This abstract method must be implemented by concrete adapters to fetch
|
|
2437
|
+
* the current gas price using their specific client libraries. This method
|
|
2438
|
+
* should not implement caching - caching is handled by the base class.
|
|
2439
|
+
*
|
|
2440
|
+
* @param chain - The chain definition to fetch gas price for.
|
|
2441
|
+
* @returns Promise resolving to the current gas price in wei
|
|
2442
|
+
* @throws Error when gas price retrieval fails
|
|
2443
|
+
*/
|
|
2444
|
+
abstract fetchGasPrice(chain: EVMChainDefinition): Promise<bigint>;
|
|
2445
|
+
/**
|
|
2446
|
+
* Calculate the total transaction fee including compute cost and buffer for the configured chain.
|
|
2447
|
+
*
|
|
2448
|
+
* This method computes the fee by multiplying the estimated compute units by the
|
|
2449
|
+
* current gas price, then adds a configurable buffer to account for fee fluctuations
|
|
2450
|
+
* and ensure transaction success. The buffer is specified in basis points (1 basis
|
|
2451
|
+
* point = 0.01%).
|
|
2452
|
+
*
|
|
2453
|
+
* @param baseComputeUnits - The base compute units for the transaction.
|
|
2454
|
+
* @param bufferBasisPoints - The buffer to add as basis points (e.g., 500 = 5%). Defaults to DEFAULT_BUFFER_BASIS_POINTS (5%).
|
|
2455
|
+
* @param chain - The chain definition to fetch gas price for.
|
|
2456
|
+
* @returns A promise that resolves to the estimated gas cost including buffer.
|
|
2457
|
+
* @throws Error when gas price retrieval fails.
|
|
2458
|
+
*
|
|
2459
|
+
* @example
|
|
2460
|
+
* ```typescript
|
|
2461
|
+
* import { ViemAdapter } from '@circle-fin/adapter-viem-v2'
|
|
2462
|
+
* import { Ethereum } from '@core/chains'
|
|
2463
|
+
*
|
|
2464
|
+
* const adapter = new ViemAdapter({ publicClient, walletClient })
|
|
2465
|
+
*
|
|
2466
|
+
* // Calculate transaction fee with default 5% buffer
|
|
2467
|
+
* const fee = await adapter.calculateTransactionFee(1000000000n, undefined, Ethereum)
|
|
2468
|
+
* console.log('Transaction fee:', fee.toString(), 'wei')
|
|
2469
|
+
*
|
|
2470
|
+
* // Calculate transaction fee with custom 10% buffer
|
|
2471
|
+
* const feeWithCustomBuffer = await adapter.calculateTransactionFee(1000000000n, 1000n, Ethereum)
|
|
2472
|
+
* console.log('Transaction fee with custom buffer:', feeWithCustomBuffer.toString(), 'wei')
|
|
2473
|
+
* ```
|
|
2474
|
+
*/
|
|
2475
|
+
calculateTransactionFee(baseComputeUnits: bigint, bufferBasisPoints: bigint | undefined, chain: EVMChainDefinition): Promise<EstimatedGas>;
|
|
2229
2476
|
}
|
|
2230
2477
|
|
|
2231
2478
|
/**
|
|
@@ -2234,7 +2481,7 @@ declare abstract class EvmAdapter extends Adapter {
|
|
|
2234
2481
|
*
|
|
2235
2482
|
* A concrete EVM adapter implementation backed by the `ethers` library.
|
|
2236
2483
|
* It provides functionality for gas estimation, contract interaction,
|
|
2237
|
-
* and transaction execution.
|
|
2484
|
+
* and transaction execution with explicit capabilities and OperationContext support.
|
|
2238
2485
|
*/
|
|
2239
2486
|
/**
|
|
2240
2487
|
* Direct client configuration for EthersAdapter using pre-configured Ethers.js clients.
|
|
@@ -2262,31 +2509,81 @@ interface EthersAdapterOptions {
|
|
|
2262
2509
|
signer: Signer$1;
|
|
2263
2510
|
}
|
|
2264
2511
|
/**
|
|
2265
|
-
* Creates a new EthersAdapter instance.
|
|
2512
|
+
* Creates a new EthersAdapter instance with explicit capabilities and OperationContext support.
|
|
2266
2513
|
*
|
|
2267
|
-
*
|
|
2514
|
+
* This constructor is typically not called directly. Instead, use the factory functions
|
|
2515
|
+
* {@link createAdapterFromPrivateKey} or {@link createAdapterFromProvider} which provide
|
|
2516
|
+
* smart defaults and better developer experience.
|
|
2517
|
+
*
|
|
2518
|
+
* @remarks
|
|
2519
|
+
* The constructor requires both configuration options and explicit capabilities to ensure
|
|
2520
|
+
* consistent behavior across all EVM adapters following the OperationContext pattern.
|
|
2521
|
+
*
|
|
2522
|
+
* **Capabilities Configuration:**
|
|
2523
|
+
* - `addressContext`: Defines address control model (`'user-controlled'` or `'developer-controlled'`)
|
|
2524
|
+
* - `supportedChains`: Array of EVM chains this adapter can operate on
|
|
2525
|
+
*
|
|
2526
|
+
* **Factory Functions (Recommended):**
|
|
2527
|
+
* - {@link createAdapterFromPrivateKey} - For server-side/programmatic use with private keys
|
|
2528
|
+
* - {@link createAdapterFromProvider} - For browser wallets (MetaMask, WalletConnect, etc.)
|
|
2529
|
+
*
|
|
2530
|
+
* @param options - Configuration options including provider getter and signer
|
|
2531
|
+
* @param capabilities - Adapter capabilities defining address control and supported chains
|
|
2532
|
+
*
|
|
2533
|
+
* @example
|
|
2534
|
+
* ```typescript
|
|
2535
|
+
* import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
|
|
2536
|
+
* import { Wallet, JsonRpcProvider } from 'ethers'
|
|
2537
|
+
* import { Ethereum, Base } from '@core/chains'
|
|
2538
|
+
*
|
|
2539
|
+
* // Direct construction (advanced usage)
|
|
2540
|
+
* const adapter = new EthersAdapter({
|
|
2541
|
+
* getProvider: ({ chain }) => new JsonRpcProvider('https://...'),
|
|
2542
|
+
* signer: new Wallet('0x...', new JsonRpcProvider('https://...'))
|
|
2543
|
+
* }, {
|
|
2544
|
+
* addressContext: 'user-controlled',
|
|
2545
|
+
* supportedChains: [Ethereum, Base]
|
|
2546
|
+
* })
|
|
2547
|
+
* ```
|
|
2548
|
+
*
|
|
2549
|
+
* @example
|
|
2550
|
+
* ```typescript
|
|
2551
|
+
* // Recommended: Use factory functions instead
|
|
2552
|
+
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2553
|
+
*
|
|
2554
|
+
* // Minimal configuration with default capabilities
|
|
2555
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
2556
|
+
* privateKey: '0x...'
|
|
2557
|
+
* // Defaults: user-controlled + all EVM chains
|
|
2558
|
+
* })
|
|
2559
|
+
* ```
|
|
2268
2560
|
*/
|
|
2269
|
-
declare class EthersAdapter extends EvmAdapter {
|
|
2561
|
+
declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> extends EvmAdapter<TAdapterCapabilities> {
|
|
2270
2562
|
/** The configuration options for this adapter instance. */
|
|
2271
2563
|
options: EthersAdapterOptions;
|
|
2272
2564
|
/** Cached Ethers Signer instance. */
|
|
2273
2565
|
private _signer;
|
|
2274
|
-
/** Cached address of the connected wallet. */
|
|
2275
|
-
private cachedAddress?;
|
|
2276
2566
|
/** Cached providers for different chains. */
|
|
2277
2567
|
private readonly cachedProviders;
|
|
2278
|
-
|
|
2279
|
-
private cachedGasPrice?;
|
|
2280
|
-
/** Cached chain definition for the connected provider. */
|
|
2281
|
-
private cachedChain;
|
|
2282
|
-
/** The resolved chain definition that this adapter was created for. */
|
|
2283
|
-
private resolvedChain;
|
|
2284
|
-
constructor(options: EthersAdapterOptions);
|
|
2568
|
+
constructor(options: EthersAdapterOptions, capabilities: TAdapterCapabilities);
|
|
2285
2569
|
/**
|
|
2286
|
-
*
|
|
2287
|
-
*
|
|
2570
|
+
* Resets all cached state in the adapter, including Ethers-specific caches.
|
|
2571
|
+
*
|
|
2572
|
+
* This method extends the base class resetState() to also clear Ethers-specific
|
|
2573
|
+
* caches like providers and gas prices. It ensures a clean state when
|
|
2574
|
+
* the adapter needs to be reinitialized (e.g., after chain or account changes).
|
|
2575
|
+
*
|
|
2576
|
+
* @override
|
|
2577
|
+
* @example
|
|
2578
|
+
* ```typescript
|
|
2579
|
+
* // Called automatically during chain switches or account changes
|
|
2580
|
+
* adapter.resetState()
|
|
2581
|
+
*
|
|
2582
|
+
* // Or called manually to clear all caches
|
|
2583
|
+
* adapter.resetState()
|
|
2584
|
+
* ```
|
|
2288
2585
|
*/
|
|
2289
|
-
|
|
2586
|
+
resetState(): void;
|
|
2290
2587
|
/**
|
|
2291
2588
|
* Switches the adapter to operate on the specified chain.
|
|
2292
2589
|
*
|
|
@@ -2300,8 +2597,21 @@ declare class EthersAdapter extends EvmAdapter {
|
|
|
2300
2597
|
switchToChain(chain: ChainDefinition): Promise<void>;
|
|
2301
2598
|
/**
|
|
2302
2599
|
* Gets the cached Provider or initializes it from options if not already cached.
|
|
2600
|
+
*
|
|
2601
|
+
* @param chain - The chain definition for which to get the Provider (required).
|
|
2602
|
+
* @returns The Ethers Provider instance.
|
|
2603
|
+
* @remarks
|
|
2604
|
+
* This method ensures we only store one instance of the Provider per chain.
|
|
2605
|
+
* The chain parameter is required to prevent accidentally using the wrong chain,
|
|
2606
|
+
* which could lead to serious issues and real costs for users.
|
|
2607
|
+
* @example
|
|
2608
|
+
* ```typescript
|
|
2609
|
+
* const adapter = new EthersAdapter(options, capabilities);
|
|
2610
|
+
* const provider = await adapter.getProvider(Ethereum);
|
|
2611
|
+
* const blockNumber = await provider.getBlockNumber();
|
|
2612
|
+
* ```
|
|
2303
2613
|
*/
|
|
2304
|
-
getProvider(chain
|
|
2614
|
+
getProvider(chain: EVMChainDefinition): Promise<Provider>;
|
|
2305
2615
|
/** Gets the current Signer instance used by the adapter. */
|
|
2306
2616
|
getSigner(): Signer$1;
|
|
2307
2617
|
/**
|
|
@@ -2314,225 +2624,498 @@ declare class EthersAdapter extends EvmAdapter {
|
|
|
2314
2624
|
private simulateFunctionCall;
|
|
2315
2625
|
/**
|
|
2316
2626
|
* Estimates the gas required for executing a contract function call.
|
|
2627
|
+
*
|
|
2628
|
+
* @param contract - The contract instance to estimate gas for.
|
|
2629
|
+
* @param functionName - The name of the contract function.
|
|
2630
|
+
* @param args - The arguments to pass to the contract function.
|
|
2631
|
+
* @param chain - The chain definition to use for gas price retrieval (prevents race conditions).
|
|
2632
|
+
* @param overrides - Optional estimate overrides.
|
|
2633
|
+
* @returns Promise resolving to the estimated gas, gas price, and total fee.
|
|
2317
2634
|
*/
|
|
2318
2635
|
private estimateGasForFunction;
|
|
2319
2636
|
/**
|
|
2320
2637
|
* Executes a contract function as a transaction on the blockchain.
|
|
2638
|
+
*
|
|
2639
|
+
* @remarks
|
|
2640
|
+
* This method executes a transaction on the blockchain.
|
|
2641
|
+
* - If `overrides.nonce` is provided, it is used verbatim and local allocation is skipped.
|
|
2642
|
+
* - Otherwise, allocates the next process-local nonce for (chainId, fromAddress) to avoid
|
|
2643
|
+
* collisions under concurrent sends.
|
|
2644
|
+
* - On common nonce errors (e.g., "nonce too low", "already known", "replacement fee too low"),
|
|
2645
|
+
* re-syncs from provider pending nonce and retries once with a freshly allocated nonce.
|
|
2646
|
+
*
|
|
2647
|
+
* @param contract - The contract instance to execute the function on.
|
|
2648
|
+
* @param functionName - The name of the contract function to execute.
|
|
2649
|
+
* @param args - The arguments to pass to the contract function.
|
|
2650
|
+
* @param fromAddress - The address to send the transaction from (prevents race conditions).
|
|
2651
|
+
* @param chain - The chain definition to use for this operation (prevents race conditions).
|
|
2652
|
+
* @param overrides - Optional transaction overrides including nonce, gas settings, etc.
|
|
2653
|
+
* @returns The transaction hash as a hex string.
|
|
2654
|
+
*
|
|
2655
|
+
* @throws When the contract function is not found or callable.
|
|
2656
|
+
* @throws When transaction population fails.
|
|
2657
|
+
* @throws When transaction execution fails after retry attempts.
|
|
2321
2658
|
*/
|
|
2322
2659
|
private executeTransaction;
|
|
2323
2660
|
/**
|
|
2324
|
-
* Prepares a
|
|
2661
|
+
* Prepares a contract function call for gas estimation and execution with OperationContext.
|
|
2662
|
+
*
|
|
2663
|
+
* This method follows the OperationContext approach, requiring explicit chain specification
|
|
2664
|
+
* for every operation. The chain is provided via the required OperationContext parameter,
|
|
2665
|
+
* enabling seamless multi-chain operations with a single adapter instance.
|
|
2666
|
+
*
|
|
2667
|
+
* @remarks
|
|
2668
|
+
* **Operation Flow:**
|
|
2669
|
+
* 1. Validates parameters and resolves chain from OperationContext
|
|
2670
|
+
* 2. Switches adapter to target chain if necessary
|
|
2671
|
+
* 3. Resolves address based on adapter's addressContext capability
|
|
2672
|
+
* 4. Creates contract instance and simulates the function call
|
|
2673
|
+
* 5. Returns prepared request with `estimate()` and `execute()` methods
|
|
2674
|
+
*
|
|
2675
|
+
* **Address Resolution:**
|
|
2676
|
+
* - `'user-controlled'`: Address automatically resolved from connected signer
|
|
2677
|
+
* - `'developer-controlled'`: Address must be provided explicitly in OperationContext
|
|
2678
|
+
*
|
|
2679
|
+
* **Read-Only Functions:**
|
|
2680
|
+
* View and pure functions are automatically detected and handled with noop gas estimation.
|
|
2681
|
+
*
|
|
2682
|
+
* @param params - The EVM contract function call parameters
|
|
2683
|
+
* @param ctx - Required operation context specifying the chain for this operation
|
|
2684
|
+
* @returns A promise that resolves to a prepared chain request for estimation and execution
|
|
2685
|
+
* @throws Error when parameters are invalid or function simulation fails
|
|
2686
|
+
* @throws Error when OperationContext resolution fails
|
|
2687
|
+
*
|
|
2688
|
+
* @example
|
|
2689
|
+
* ```typescript
|
|
2690
|
+
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2691
|
+
* import { parseAbi } from 'ethers'
|
|
2692
|
+
*
|
|
2693
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
2694
|
+
* privateKey: process.env.PRIVATE_KEY
|
|
2695
|
+
* })
|
|
2696
|
+
*
|
|
2697
|
+
* // Basic usage - OperationContext specifies the chain
|
|
2698
|
+
* const prepared = await adapter.prepare({
|
|
2699
|
+
* address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
|
|
2700
|
+
* abi: parseAbi(['function transfer(address to, uint256 amount) returns (bool)']),
|
|
2701
|
+
* functionName: 'transfer',
|
|
2702
|
+
* args: ['0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', '1000000']
|
|
2703
|
+
* }, { chain: 'Ethereum' }) // Chain specified in context
|
|
2704
|
+
*
|
|
2705
|
+
* // Estimate gas
|
|
2706
|
+
* const gasEstimate = await prepared.estimate()
|
|
2707
|
+
* console.log('Estimated gas:', gasEstimate.gas)
|
|
2708
|
+
*
|
|
2709
|
+
* // Execute transaction
|
|
2710
|
+
* const txHash = await prepared.execute()
|
|
2711
|
+
* console.log('Transaction hash:', txHash)
|
|
2712
|
+
* ```
|
|
2713
|
+
*
|
|
2714
|
+
* @example
|
|
2715
|
+
* ```typescript
|
|
2716
|
+
* // Multi-chain usage with same adapter instance
|
|
2717
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
2718
|
+
* privateKey: process.env.PRIVATE_KEY
|
|
2719
|
+
* })
|
|
2720
|
+
*
|
|
2721
|
+
* // Transfer USDC on Ethereum
|
|
2722
|
+
* const preparedEthereum = await adapter.prepare({
|
|
2723
|
+
* address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
2724
|
+
* abi: usdcAbi,
|
|
2725
|
+
* functionName: 'transfer',
|
|
2726
|
+
* args: ['0xrecipient', '1000000']
|
|
2727
|
+
* }, { chain: 'Ethereum' })
|
|
2728
|
+
*
|
|
2729
|
+
* // Transfer USDC on Base using the same adapter
|
|
2730
|
+
* const preparedBase = await adapter.prepare({
|
|
2731
|
+
* address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
2732
|
+
* abi: usdcAbi,
|
|
2733
|
+
* functionName: 'transfer',
|
|
2734
|
+
* args: ['0xrecipient', '1000000']
|
|
2735
|
+
* }, { chain: 'Base' })
|
|
2736
|
+
*
|
|
2737
|
+
* // Execute both transfers
|
|
2738
|
+
* await preparedEthereum.execute()
|
|
2739
|
+
* await preparedBase.execute()
|
|
2740
|
+
* ```
|
|
2741
|
+
*
|
|
2742
|
+
* @example
|
|
2743
|
+
* ```typescript
|
|
2744
|
+
* // Address resolution patterns
|
|
2745
|
+
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
2746
|
+
*
|
|
2747
|
+
* const adapter = await createAdapterFromProvider({
|
|
2748
|
+
* provider: window.ethereum
|
|
2749
|
+
* // Defaults to user-controlled address context
|
|
2750
|
+
* })
|
|
2751
|
+
*
|
|
2752
|
+
* // Address is automatically resolved from the signer
|
|
2753
|
+
* const prepared = await adapter.prepare({
|
|
2754
|
+
* address: '0xcontract',
|
|
2755
|
+
* abi: contractAbi,
|
|
2756
|
+
* functionName: 'approve',
|
|
2757
|
+
* args: ['0xspender', '1000000']
|
|
2758
|
+
* }, {
|
|
2759
|
+
* chain: 'Polygon'
|
|
2760
|
+
* // No need to specify 'address' - comes from signer automatically
|
|
2761
|
+
* })
|
|
2762
|
+
* ```
|
|
2763
|
+
*
|
|
2764
|
+
* @example
|
|
2765
|
+
* ```typescript
|
|
2766
|
+
* // Read-only functions (view/pure) - automatic noop estimation
|
|
2767
|
+
* const prepared = await adapter.prepare({
|
|
2768
|
+
* address: '0xcontract',
|
|
2769
|
+
* abi: parseAbi(['function balanceOf(address account) view returns (uint256)']),
|
|
2770
|
+
* functionName: 'balanceOf',
|
|
2771
|
+
* args: ['0xaccount']
|
|
2772
|
+
* }, { chain: 'Ethereum' })
|
|
2773
|
+
*
|
|
2774
|
+
* // estimate() returns noop for read-only functions
|
|
2775
|
+
* const estimate = await prepared.estimate() // { gas: 0n, fee: '0', gasPrice: 0n }
|
|
2776
|
+
*
|
|
2777
|
+
* // execute() returns the result as a string
|
|
2778
|
+
* const balance = await prepared.execute() // '1000000'
|
|
2779
|
+
* ```
|
|
2780
|
+
*/
|
|
2781
|
+
prepare(params: EvmPreparedChainRequestParams, ctx: OperationContext<TAdapterCapabilities>): Promise<EvmPreparedChainRequest>;
|
|
2782
|
+
/**
|
|
2783
|
+
* Gets the address associated with this adapter.
|
|
2784
|
+
*
|
|
2785
|
+
* @remarks
|
|
2786
|
+
* This method is primarily used internally by the OperationContext resolution system.
|
|
2787
|
+
* In user-facing code, addresses are typically resolved automatically based on the
|
|
2788
|
+
* adapter's addressContext capability.
|
|
2789
|
+
*
|
|
2790
|
+
* **With OperationContext Pattern:**
|
|
2791
|
+
* - The chain parameter is provided automatically by `resolveOperationContext()`
|
|
2792
|
+
* - For `'user-controlled'` adapters: address is derived from the signer/wallet
|
|
2793
|
+
* - For `'developer-controlled'` adapters: address must be provided explicitly in context
|
|
2794
|
+
*
|
|
2795
|
+
* **Implementation Note:**
|
|
2796
|
+
* While the chain parameter is typed as optional for compatibility with the base
|
|
2797
|
+
* adapter interface, it is effectively required and enforced at runtime. This ensures
|
|
2798
|
+
* the adapter is connected to the correct chain before querying the signer.
|
|
2799
|
+
*
|
|
2800
|
+
* @param chain - The chain to use for address resolution (provided by OperationContext)
|
|
2801
|
+
* @returns A promise that resolves to the signer's address
|
|
2802
|
+
* @throws Error when no chain is provided
|
|
2803
|
+
*
|
|
2804
|
+
* @example
|
|
2805
|
+
* ```typescript
|
|
2806
|
+
* import { Ethereum } from '@core/chains'
|
|
2807
|
+
*
|
|
2808
|
+
* // Typically called internally by resolveOperationContext
|
|
2809
|
+
* const address = await adapter.getAddress(Ethereum)
|
|
2810
|
+
* console.log('Wallet address:', address)
|
|
2811
|
+
* ```
|
|
2812
|
+
*
|
|
2813
|
+
* @example
|
|
2814
|
+
* ```typescript
|
|
2815
|
+
* // In practice, address resolution happens automatically
|
|
2816
|
+
* const prepared = await adapter.prepare(params, {
|
|
2817
|
+
* chain: 'Ethereum'
|
|
2818
|
+
* // Address automatically resolved via getAddress() internally
|
|
2819
|
+
* })
|
|
2820
|
+
* ```
|
|
2325
2821
|
*/
|
|
2326
|
-
|
|
2327
|
-
/** Gets the address of the connected wallet. */
|
|
2328
|
-
getAddress(): Promise<string>;
|
|
2329
|
-
/** Gets the current chain definition. */
|
|
2330
|
-
getChain(): Promise<ChainDefinition>;
|
|
2822
|
+
getAddress(chain?: EVMChainDefinition): Promise<string>;
|
|
2331
2823
|
/**
|
|
2332
2824
|
* Waits for a transaction to be mined and confirmed on the blockchain.
|
|
2825
|
+
*
|
|
2826
|
+
* @param txHash - The transaction hash to wait for.
|
|
2827
|
+
* @param config - Optional configuration for confirmations and timeout.
|
|
2828
|
+
* @param chain - The chain definition where the transaction was submitted.
|
|
2829
|
+
* @returns Promise resolving to the transaction receipt details.
|
|
2830
|
+
* @throws Error when transaction is not found or times out.
|
|
2333
2831
|
*/
|
|
2334
|
-
waitForTransaction(txHash: string, config
|
|
2832
|
+
waitForTransaction(txHash: string, config: WaitForTransactionConfig | undefined, chain: EVMChainDefinition): Promise<WaitForTransactionResponse>;
|
|
2335
2833
|
/**
|
|
2336
|
-
*
|
|
2834
|
+
* Fetches the current gas price from the network.
|
|
2835
|
+
*
|
|
2836
|
+
* @param chain - The chain definition to fetch gas price for.
|
|
2837
|
+
* @returns Promise resolving to the current gas price in wei
|
|
2838
|
+
* @throws Error when gas price retrieval fails
|
|
2839
|
+
*/
|
|
2840
|
+
fetchGasPrice(chain: EVMChainDefinition): Promise<bigint>;
|
|
2841
|
+
/**
|
|
2842
|
+
* Signs EIP-712 typed data using the configured signer with OperationContext.
|
|
2843
|
+
*
|
|
2844
|
+
* This method signs structured typed data following the EIP-712 standard, enabling
|
|
2845
|
+
* secure off-chain signatures for permit approvals, meta-transactions, and other
|
|
2846
|
+
* gasless operations. The chain must be specified via the required OperationContext
|
|
2847
|
+
* parameter to ensure signatures are valid for the correct network.
|
|
2848
|
+
*
|
|
2849
|
+
* @remarks
|
|
2850
|
+
* **Operation Flow:**
|
|
2851
|
+
* 1. Validates the typed data structure
|
|
2852
|
+
* 2. Resolves chain from OperationContext and switches if necessary
|
|
2853
|
+
* 3. Resolves signer address based on adapter's addressContext
|
|
2854
|
+
* 4. Signs the typed data using the configured signer
|
|
2855
|
+
* 5. Returns the signature as a hex string
|
|
2856
|
+
*
|
|
2857
|
+
* **Use Cases:**
|
|
2858
|
+
* - ERC-2612 permit approvals (gasless token approvals)
|
|
2859
|
+
* - Meta-transactions and gasless operations
|
|
2860
|
+
* - Off-chain order signing for DEX protocols
|
|
2861
|
+
* - DAO voting signatures
|
|
2862
|
+
*
|
|
2863
|
+
* @typeParam Types - The EIP-712 types definition for the data being signed
|
|
2864
|
+
* @typeParam Message - The message structure being signed
|
|
2865
|
+
* @param typedData - The EIP-712 typed data to sign with full type safety
|
|
2866
|
+
* @param ctx - Required operation context specifying the chain for this operation
|
|
2867
|
+
* @returns Promise resolving to the signature as a hex string
|
|
2868
|
+
* @throws Error when typedData validation fails
|
|
2869
|
+
* @throws Error when no signer is configured
|
|
2870
|
+
* @throws Error when OperationContext resolution fails
|
|
2871
|
+
*
|
|
2872
|
+
* @example
|
|
2873
|
+
* ```typescript
|
|
2874
|
+
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2875
|
+
*
|
|
2876
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
2877
|
+
* privateKey: process.env.PRIVATE_KEY
|
|
2878
|
+
* })
|
|
2879
|
+
*
|
|
2880
|
+
* // Sign ERC-2612 permit (gasless token approval)
|
|
2881
|
+
* const signature = await adapter.signTypedData({
|
|
2882
|
+
* domain: {
|
|
2883
|
+
* name: 'USD Coin',
|
|
2884
|
+
* version: '2',
|
|
2885
|
+
* chainId: 1,
|
|
2886
|
+
* verifyingContract: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
|
|
2887
|
+
* },
|
|
2888
|
+
* types: {
|
|
2889
|
+
* Permit: [
|
|
2890
|
+
* { name: 'owner', type: 'address' },
|
|
2891
|
+
* { name: 'spender', type: 'address' },
|
|
2892
|
+
* { name: 'value', type: 'uint256' },
|
|
2893
|
+
* { name: 'nonce', type: 'uint256' },
|
|
2894
|
+
* { name: 'deadline', type: 'uint256' }
|
|
2895
|
+
* ]
|
|
2896
|
+
* },
|
|
2897
|
+
* primaryType: 'Permit',
|
|
2898
|
+
* message: {
|
|
2899
|
+
* owner: '0xowner',
|
|
2900
|
+
* spender: '0xspender',
|
|
2901
|
+
* value: '1000000',
|
|
2902
|
+
* nonce: '0',
|
|
2903
|
+
* deadline: '1735689600'
|
|
2904
|
+
* }
|
|
2905
|
+
* }, { chain: 'Ethereum' }) // Chain must be specified
|
|
2906
|
+
*
|
|
2907
|
+
* console.log('Signature:', signature)
|
|
2908
|
+
* // '0x...' - can be used for permit approval
|
|
2909
|
+
* ```
|
|
2910
|
+
*
|
|
2911
|
+
* @example
|
|
2912
|
+
* ```typescript
|
|
2913
|
+
* // Multi-chain permit signing with same adapter
|
|
2914
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
2915
|
+
* privateKey: process.env.PRIVATE_KEY
|
|
2916
|
+
* })
|
|
2917
|
+
*
|
|
2918
|
+
* // Sign permit for USDC on Ethereum
|
|
2919
|
+
* const ethSignature = await adapter.signTypedData(permitData, {
|
|
2920
|
+
* chain: 'Ethereum'
|
|
2921
|
+
* })
|
|
2922
|
+
*
|
|
2923
|
+
* // Sign permit for USDC on Base - same adapter!
|
|
2924
|
+
* const baseSignature = await adapter.signTypedData(permitData, {
|
|
2925
|
+
* chain: 'Base'
|
|
2926
|
+
* })
|
|
2927
|
+
* ```
|
|
2928
|
+
*
|
|
2929
|
+
* @example
|
|
2930
|
+
* ```typescript
|
|
2931
|
+
* // Browser wallet usage
|
|
2932
|
+
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
2933
|
+
*
|
|
2934
|
+
* const adapter = await createAdapterFromProvider({
|
|
2935
|
+
* provider: window.ethereum
|
|
2936
|
+
* })
|
|
2937
|
+
*
|
|
2938
|
+
* // User will see signature request in wallet
|
|
2939
|
+
* const signature = await adapter.signTypedData(typedData, {
|
|
2940
|
+
* chain: 'Polygon'
|
|
2941
|
+
* })
|
|
2942
|
+
* ```
|
|
2337
2943
|
*/
|
|
2338
|
-
|
|
2944
|
+
signTypedData<Types extends Record<string, TypedDataField[]>, Message extends Record<string, unknown>>(typedData: TypedData<Types, Message>, ctx: OperationContext<TAdapterCapabilities>): Promise<`0x${string}`>;
|
|
2339
2945
|
/**
|
|
2340
|
-
*
|
|
2946
|
+
* Handle read-only function execution with noop estimation.
|
|
2947
|
+
*
|
|
2948
|
+
* @param params - The EVM prepared chain request parameters.
|
|
2949
|
+
* @param signer - The Ethers signer instance.
|
|
2950
|
+
* @param provider - The Ethers provider instance.
|
|
2951
|
+
* @param walletAddress - The wallet address (prevents race conditions in concurrent requests).
|
|
2952
|
+
* @returns A prepared chain request for read-only function execution.
|
|
2953
|
+
*/
|
|
2954
|
+
private handleReadOnlyFunction;
|
|
2955
|
+
/**
|
|
2956
|
+
* Reads a contract function using Ethers v6.
|
|
2957
|
+
*
|
|
2958
|
+
* @param params - The read contract parameters including address, ABI, function name, and args.
|
|
2959
|
+
* @param chain - The chain definition where the contract is deployed.
|
|
2960
|
+
* @returns Promise resolving to the contract function return value.
|
|
2961
|
+
* @throws Error when contract read fails.
|
|
2341
2962
|
*/
|
|
2342
|
-
|
|
2343
|
-
/** Reads a contract function using Ethers v6. */
|
|
2344
|
-
readContract<TReturnType = unknown>(params: ReadContractParams): Promise<TReturnType>;
|
|
2963
|
+
readContract<TReturnType = unknown>(params: ReadContractParams, chain: EVMChainDefinition): Promise<TReturnType>;
|
|
2345
2964
|
}
|
|
2346
2965
|
|
|
2347
2966
|
/**
|
|
2348
2967
|
* Parameters for creating an {@link EthersAdapter} from a private key.
|
|
2349
2968
|
*
|
|
2350
|
-
* @
|
|
2351
|
-
* @category Types
|
|
2352
|
-
* @description
|
|
2353
|
-
* Defines the configuration required to instantiate an {@link EthersAdapter}
|
|
2354
|
-
* using a raw private key for server-side or programmatic wallet operations.
|
|
2355
|
-
*
|
|
2356
|
-
* This is intended for secure, backend, or automated environments where direct
|
|
2357
|
-
* control of the private key is possible and safe. Do not use this pattern in
|
|
2358
|
-
* browser or client-side code.
|
|
2359
|
-
*
|
|
2360
|
-
* @example
|
|
2361
|
-
* ```typescript
|
|
2362
|
-
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2363
|
-
* import { Blockchain } from '@core/chains'
|
|
2364
|
-
*
|
|
2365
|
-
* // Using a chain identifier (enum, string, or ChainDefinition)
|
|
2366
|
-
* const adapter = createAdapterFromPrivateKey({
|
|
2367
|
-
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
2368
|
-
* defaultChain: Blockchain.Ethereum,
|
|
2369
|
-
* })
|
|
2370
|
-
*
|
|
2371
|
-
* // Advanced: custom provider logic (e.g., for custom endpoints or retry logic)
|
|
2372
|
-
* const adapter2 = createAdapterFromPrivateKey({
|
|
2373
|
-
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
2374
|
-
* defaultChain: 'Ethereum',
|
|
2375
|
-
* getProvider: ({ chain }) => new JsonRpcProvider('https://...'),
|
|
2376
|
-
* })
|
|
2377
|
-
* ```
|
|
2378
|
-
*
|
|
2379
|
-
* @remarks
|
|
2380
|
-
* Supported parameter combinations:
|
|
2381
|
-
* - Provide `privateKey` and `defaultChain` (uses default provider logic).
|
|
2382
|
-
* - Optionally provide a custom `getProvider` function for advanced provider instantiation.
|
|
2383
|
-
*
|
|
2384
|
-
* The `privateKey` must be a valid 32-byte hex string prefixed with `0x`.
|
|
2385
|
-
* The `defaultChain` can be a {@link ChainDefinition}, a supported chain enum, or a string literal.
|
|
2386
|
-
* The `getProvider` function, if supplied, receives an object with a `chain` parameter.
|
|
2969
|
+
* @typeParam TCapabilities - The adapter capabilities type for compile-time address validation
|
|
2387
2970
|
*/
|
|
2388
|
-
interface CreateAdapterFromPrivateKeyParams {
|
|
2389
|
-
/**
|
|
2390
|
-
* The private key for wallet operations.
|
|
2391
|
-
* @remarks
|
|
2392
|
-
* Must be a valid 32-byte hex string prefixed with '0x'. This should be:
|
|
2393
|
-
* - A securely generated private key
|
|
2394
|
-
* - Kept confidential and never exposed in client-side code
|
|
2395
|
-
* - Used only in server-side or secure environments
|
|
2396
|
-
*
|
|
2397
|
-
* The private key will be used to sign transactions and authenticate
|
|
2398
|
-
* with the blockchain network.
|
|
2399
|
-
*/
|
|
2400
|
-
privateKey: `0x${string}`;
|
|
2971
|
+
interface CreateAdapterFromPrivateKeyParams<TCapabilities extends Partial<AdapterCapabilities> = AdapterCapabilities> {
|
|
2401
2972
|
/**
|
|
2402
|
-
* The
|
|
2403
|
-
*
|
|
2404
|
-
*
|
|
2405
|
-
* This determines which EVM-compatible network the adapter will operate on by default.
|
|
2406
|
-
* The adapter will use the canonical RPC URL for the specified chain unless a custom provider is supplied.
|
|
2407
|
-
* Examples: `Blockchain.Ethereum`, `'Ethereum'`, or a `ChainDefinition` object.
|
|
2973
|
+
* The private key to use for wallet derivation.
|
|
2974
|
+
* Must be a valid 32-byte hex string, with or without '0x' prefix.
|
|
2975
|
+
* If the prefix is omitted, it will be added automatically during validation.
|
|
2408
2976
|
*/
|
|
2409
|
-
|
|
2977
|
+
privateKey: string;
|
|
2410
2978
|
/**
|
|
2411
|
-
* Optional function to
|
|
2412
|
-
*
|
|
2413
|
-
* If not provided, a default Provider will be created using the chain's RPC endpoints.
|
|
2414
|
-
* Use this to inject custom provider logic, such as:
|
|
2415
|
-
* - Custom retry or caching strategies
|
|
2416
|
-
* - Enhanced logging or monitoring
|
|
2417
|
-
* - Support for non-standard transports
|
|
2418
|
-
*
|
|
2419
|
-
* @param chain - The chain definition for which to create the provider.
|
|
2420
|
-
* @returns A configured Provider instance.
|
|
2979
|
+
* Optional function to create providers for different chains.
|
|
2980
|
+
* If not provided, a default implementation using JsonRpcProvider will be used.
|
|
2421
2981
|
*/
|
|
2422
2982
|
getProvider?: (params: {
|
|
2423
2983
|
chain: ChainDefinition;
|
|
2424
2984
|
}) => Provider;
|
|
2985
|
+
/**
|
|
2986
|
+
* Optional adapter capabilities configuration.
|
|
2987
|
+
* Defines address control model and supported chains.
|
|
2988
|
+
* If not provided, defaults to user-controlled with all EVM chains supported.
|
|
2989
|
+
*
|
|
2990
|
+
* @example
|
|
2991
|
+
* ```typescript
|
|
2992
|
+
* // Minimal configuration with default capabilities
|
|
2993
|
+
* createAdapterFromPrivateKey({
|
|
2994
|
+
* privateKey: '0x...'
|
|
2995
|
+
* // Capabilities default to:
|
|
2996
|
+
* // { addressContext: 'user-controlled', supportedChains: [all EVM chains] }
|
|
2997
|
+
* })
|
|
2998
|
+
* ```
|
|
2999
|
+
*
|
|
3000
|
+
* @example
|
|
3001
|
+
* ```typescript
|
|
3002
|
+
* // Custom supported chains
|
|
3003
|
+
* createAdapterFromPrivateKey({
|
|
3004
|
+
* privateKey: '0x...',
|
|
3005
|
+
* capabilities: {
|
|
3006
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
3007
|
+
* }
|
|
3008
|
+
* })
|
|
3009
|
+
* ```
|
|
3010
|
+
*/
|
|
3011
|
+
capabilities?: TCapabilities;
|
|
2425
3012
|
}
|
|
2426
3013
|
/**
|
|
2427
|
-
* Creates an EthersAdapter instance from a private key.
|
|
3014
|
+
* Creates an EthersAdapter instance from a private key with automatic type inference.
|
|
2428
3015
|
*
|
|
2429
3016
|
* This function creates an EthersAdapter for server-side or programmatic use
|
|
2430
|
-
* by deriving a wallet from the provided private key
|
|
2431
|
-
*
|
|
2432
|
-
*
|
|
3017
|
+
* by deriving a wallet from the provided private key. It uses lazy initialization
|
|
3018
|
+
* where the wallet is created without a provider and is connected to chain-specific
|
|
3019
|
+
* providers on-demand during operations. This matches the Viem adapter pattern and
|
|
3020
|
+
* enables seamless multi-chain operations with a single adapter instance.
|
|
2433
3021
|
*
|
|
2434
3022
|
* @remarks
|
|
2435
3023
|
* The function performs the following operations:
|
|
2436
3024
|
* 1. Validates the input parameters at runtime
|
|
2437
|
-
* 2.
|
|
2438
|
-
* 3.
|
|
2439
|
-
* 4.
|
|
2440
|
-
* 5. Instantiates a Wallet with the private key and provider
|
|
2441
|
-
* 6. Returns a configured EthersAdapter instance
|
|
3025
|
+
* 2. Creates a Wallet from the private key (without provider - lazy initialization)
|
|
3026
|
+
* 3. Applies smart defaults for capabilities (user-controlled + all EVM chains)
|
|
3027
|
+
* 4. Returns a configured EthersAdapter instance
|
|
2442
3028
|
*
|
|
2443
|
-
*
|
|
2444
|
-
*
|
|
2445
|
-
*
|
|
3029
|
+
* Chain context is provided through OperationContext during individual operations.
|
|
3030
|
+
* The wallet will be connected to a provider when ensureChain() is called in prepare().
|
|
3031
|
+
*
|
|
3032
|
+
* **Default Configuration:**
|
|
3033
|
+
* - `addressContext`: `'user-controlled'` (address derived from private key automatically)
|
|
3034
|
+
* - `supportedChains`: All EVM-compatible chains (~29 networks)
|
|
3035
|
+
* - Lazy initialization: Chain connection deferred until first operation
|
|
2446
3036
|
*
|
|
2447
3037
|
* **Security Warning:** Never use this function in client-side code or expose
|
|
2448
3038
|
* private keys in any way. This function is intended for server-side use only.
|
|
3039
|
+
* Store private keys securely using environment variables or secret management systems.
|
|
2449
3040
|
*
|
|
3041
|
+
* @typeParam TCapabilities - The adapter capabilities type for compile-time address validation
|
|
2450
3042
|
* @param params - Configuration parameters for creating the adapter
|
|
2451
|
-
* @returns A configured EthersAdapter instance
|
|
2452
|
-
* @throws Error when validation fails or wallet
|
|
3043
|
+
* @returns A configured EthersAdapter instance with automatically inferred capabilities
|
|
3044
|
+
* @throws Error when validation fails or wallet derivation fails
|
|
2453
3045
|
*
|
|
2454
3046
|
* @example
|
|
2455
3047
|
* ```typescript
|
|
2456
3048
|
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2457
|
-
* import { Blockchain, Ethereum } from '@core/chains'
|
|
2458
3049
|
*
|
|
2459
|
-
* //
|
|
3050
|
+
* // Both private key formats are supported (with or without '0x' prefix):
|
|
2460
3051
|
* const adapter1 = createAdapterFromPrivateKey({
|
|
2461
|
-
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
2462
|
-
* defaultChain: Ethereum,
|
|
3052
|
+
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' // With prefix
|
|
2463
3053
|
* })
|
|
2464
3054
|
*
|
|
2465
|
-
* // Using Blockchain enum
|
|
2466
3055
|
* const adapter2 = createAdapterFromPrivateKey({
|
|
2467
|
-
* privateKey: '
|
|
2468
|
-
* defaultChain: Blockchain.Ethereum,
|
|
3056
|
+
* privateKey: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' // Without prefix (automatically normalized)
|
|
2469
3057
|
* })
|
|
2470
3058
|
*
|
|
2471
|
-
* //
|
|
2472
|
-
* const
|
|
2473
|
-
*
|
|
2474
|
-
*
|
|
2475
|
-
*
|
|
3059
|
+
* // Chain specified per-operation via OperationContext
|
|
3060
|
+
* const prepared = await adapter1.prepare({
|
|
3061
|
+
* address: '0x...',
|
|
3062
|
+
* abi: contractAbi,
|
|
3063
|
+
* functionName: 'transfer',
|
|
3064
|
+
* args: ['0xto', '1000']
|
|
3065
|
+
* }, { chain: 'Ethereum' })
|
|
2476
3066
|
* ```
|
|
2477
3067
|
*
|
|
2478
3068
|
* @example
|
|
2479
3069
|
* ```typescript
|
|
2480
3070
|
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2481
|
-
* import { JsonRpcProvider } from 'ethers'
|
|
2482
3071
|
*
|
|
2483
|
-
* //
|
|
3072
|
+
* // Multi-chain usage with same adapter instance
|
|
2484
3073
|
* const adapter = createAdapterFromPrivateKey({
|
|
2485
|
-
* privateKey: process.env.PRIVATE_KEY
|
|
2486
|
-
* defaultChain: 'Ethereum',
|
|
2487
|
-
* getProvider: ({ chain }) => new JsonRpcProvider('https://...'),
|
|
3074
|
+
* privateKey: process.env.PRIVATE_KEY as `0x${string}`
|
|
2488
3075
|
* })
|
|
3076
|
+
*
|
|
3077
|
+
* // Transfer USDC on Ethereum
|
|
3078
|
+
* await adapter.prepare(params, { chain: 'Ethereum' })
|
|
3079
|
+
*
|
|
3080
|
+
* // Transfer USDC on Base using the same adapter
|
|
3081
|
+
* await adapter.prepare(params, { chain: 'Base' })
|
|
2489
3082
|
* ```
|
|
2490
3083
|
*
|
|
2491
3084
|
* @example
|
|
2492
3085
|
* ```typescript
|
|
2493
|
-
* // Cross-chain transfer using a single adapter
|
|
2494
3086
|
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
2495
|
-
* import {
|
|
3087
|
+
* import { Ethereum, Base, Polygon } from '@core/chains'
|
|
2496
3088
|
*
|
|
3089
|
+
* // Custom capabilities configuration
|
|
2497
3090
|
* const adapter = createAdapterFromPrivateKey({
|
|
2498
|
-
* privateKey: process.env.PRIVATE_KEY
|
|
2499
|
-
*
|
|
2500
|
-
*
|
|
2501
|
-
*
|
|
2502
|
-
* const kit = new BridgingKit()
|
|
2503
|
-
*
|
|
2504
|
-
* // Use the same adapter for both source and destination
|
|
2505
|
-
* const result = await kit.bridge({
|
|
2506
|
-
* from: { adapter, chain: 'Ethereum' },
|
|
2507
|
-
* to: { adapter, chain: 'Base' },
|
|
2508
|
-
* amount: '100.50'
|
|
3091
|
+
* privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
3092
|
+
* capabilities: {
|
|
3093
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
3094
|
+
* }
|
|
2509
3095
|
* })
|
|
2510
3096
|
* ```
|
|
2511
3097
|
*
|
|
2512
3098
|
* @example
|
|
2513
3099
|
* ```typescript
|
|
2514
3100
|
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
3101
|
+
* import { JsonRpcProvider } from 'ethers'
|
|
2515
3102
|
*
|
|
2516
|
-
* //
|
|
2517
|
-
*
|
|
2518
|
-
*
|
|
2519
|
-
*
|
|
2520
|
-
*
|
|
2521
|
-
*
|
|
2522
|
-
*
|
|
2523
|
-
*
|
|
2524
|
-
*
|
|
2525
|
-
*
|
|
2526
|
-
*
|
|
2527
|
-
* if (error.message.includes('Private key')) {
|
|
2528
|
-
* console.error('Invalid private key format')
|
|
2529
|
-
* } else {
|
|
2530
|
-
* console.error('Failed to create adapter:', error.message)
|
|
3103
|
+
* // Custom provider configuration with explicit chain mapping
|
|
3104
|
+
* const adapter = createAdapterFromPrivateKey({
|
|
3105
|
+
* privateKey: process.env.PRIVATE_KEY as `0x${string}`,
|
|
3106
|
+
* getProvider: ({ chain }) => {
|
|
3107
|
+
* const rpcEndpoints: Record<string, string> = {
|
|
3108
|
+
* 'Ethereum': `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
|
|
3109
|
+
* 'Base': `https://base-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`
|
|
3110
|
+
* }
|
|
3111
|
+
* const endpoint = rpcEndpoints[chain.name]
|
|
3112
|
+
* if (!endpoint) throw new Error(`RPC not configured for ${chain.name}`)
|
|
3113
|
+
* return new JsonRpcProvider(endpoint, chain.chainId)
|
|
2531
3114
|
* }
|
|
2532
|
-
* }
|
|
3115
|
+
* })
|
|
2533
3116
|
* ```
|
|
2534
3117
|
*/
|
|
2535
|
-
declare
|
|
3118
|
+
declare function createAdapterFromPrivateKey<const TCapabilities extends Partial<AdapterCapabilities> = object>(params: CreateAdapterFromPrivateKeyParams<TCapabilities>): EthersAdapter<InferAdapterCapabilities<TCapabilities>>;
|
|
2536
3119
|
|
|
2537
3120
|
/**
|
|
2538
3121
|
* Parameters for creating an {@link EthersAdapter} from an EIP-1193 provider.
|
|
@@ -2541,43 +3124,46 @@ declare const createAdapterFromPrivateKey: (params: CreateAdapterFromPrivateKeyP
|
|
|
2541
3124
|
* @category Types
|
|
2542
3125
|
* @description
|
|
2543
3126
|
* Defines the parameters required to instantiate an {@link EthersAdapter} using an EIP-1193-compatible provider
|
|
2544
|
-
* (such as MetaMask, WalletConnect, or any injected browser wallet)
|
|
3127
|
+
* (such as MetaMask, WalletConnect, or any injected browser wallet).
|
|
2545
3128
|
*
|
|
2546
3129
|
* @example
|
|
2547
3130
|
* ```typescript
|
|
2548
3131
|
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
2549
3132
|
*
|
|
2550
|
-
* // Basic
|
|
3133
|
+
* // Basic browser wallet setup
|
|
2551
3134
|
* const adapter = await createAdapterFromProvider({
|
|
2552
|
-
* provider: window.ethereum
|
|
2553
|
-
*
|
|
3135
|
+
* provider: window.ethereum
|
|
3136
|
+
* // Smart defaults applied:
|
|
3137
|
+
* // - addressContext: 'user-controlled'
|
|
3138
|
+
* // - supportedChains: all EVM chains
|
|
2554
3139
|
* })
|
|
2555
3140
|
* ```
|
|
2556
3141
|
*
|
|
2557
3142
|
* @example
|
|
2558
3143
|
* ```typescript
|
|
2559
3144
|
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
2560
|
-
* import {
|
|
3145
|
+
* import { Ethereum, Base, Polygon } from '@core/chains'
|
|
2561
3146
|
*
|
|
2562
|
-
* // Advanced: custom
|
|
3147
|
+
* // Advanced: custom capabilities
|
|
2563
3148
|
* const adapter = await createAdapterFromProvider({
|
|
2564
3149
|
* provider: window.ethereum,
|
|
2565
|
-
*
|
|
2566
|
-
*
|
|
3150
|
+
* capabilities: {
|
|
3151
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
3152
|
+
* }
|
|
2567
3153
|
* })
|
|
2568
3154
|
* ```
|
|
2569
3155
|
*
|
|
2570
3156
|
* @remarks
|
|
2571
3157
|
* Required parameters:
|
|
2572
3158
|
* - `provider`: A valid EIP-1193 provider (e.g., MetaMask, WalletConnect, etc.).
|
|
2573
|
-
* - `chain`: The blockchain network to use for the adapter. Accepts a chain identifier string, enum, or chain definition.
|
|
2574
3159
|
*
|
|
2575
3160
|
* Optional:
|
|
2576
3161
|
* - `getProvider`: A custom function to instantiate an Ethers Provider for the specified chain.
|
|
2577
3162
|
* Receives an object with a `chain` property of type {@link EVMChainDefinition}.
|
|
3163
|
+
* - `capabilities`: Adapter capabilities defining address control and supported chains.
|
|
2578
3164
|
*
|
|
2579
|
-
*
|
|
2580
|
-
* This enables cross-chain workflows
|
|
3165
|
+
* With OperationContext pattern, chain is specified per-operation rather than at factory creation.
|
|
3166
|
+
* This enables cross-chain workflows with a single adapter instance.
|
|
2581
3167
|
*/
|
|
2582
3168
|
interface CreateAdapterFromProviderParams {
|
|
2583
3169
|
/**
|
|
@@ -2593,13 +3179,6 @@ interface CreateAdapterFromProviderParams {
|
|
|
2593
3179
|
* - `enable()` or equivalent for requesting account access
|
|
2594
3180
|
*/
|
|
2595
3181
|
provider: Eip1193Provider;
|
|
2596
|
-
/**
|
|
2597
|
-
* The blockchain network to use for the adapter.
|
|
2598
|
-
* @remarks
|
|
2599
|
-
* This chain will be used as the intended chain for the adapter.
|
|
2600
|
-
* The adapter will use this chain instead of the wallet's current network.
|
|
2601
|
-
*/
|
|
2602
|
-
chain: ChainIdentifier;
|
|
2603
3182
|
/**
|
|
2604
3183
|
* Optional function to provide a custom Ethers Provider instance.
|
|
2605
3184
|
* @remarks
|
|
@@ -2615,48 +3194,115 @@ interface CreateAdapterFromProviderParams {
|
|
|
2615
3194
|
getProvider?: (params: {
|
|
2616
3195
|
chain: EVMChainDefinition;
|
|
2617
3196
|
}) => Provider;
|
|
3197
|
+
/**
|
|
3198
|
+
* Optional capabilities configuration for the adapter.
|
|
3199
|
+
* @remarks
|
|
3200
|
+
* Defines the adapter's address control model and supported chains.
|
|
3201
|
+
* If not provided, defaults to user-controlled address context with all EVM chains supported.
|
|
3202
|
+
*
|
|
3203
|
+
* - `addressContext`: Determines address control model ('user-controlled' or 'developer-controlled')
|
|
3204
|
+
* - `supportedChains`: Array of supported blockchain networks
|
|
3205
|
+
*
|
|
3206
|
+
* For EIP-1193 provider adapters, typically uses 'user-controlled' since addresses are managed
|
|
3207
|
+
* through the wallet UI and user interaction.
|
|
3208
|
+
*
|
|
3209
|
+
* @example
|
|
3210
|
+
* ```typescript
|
|
3211
|
+
* // Minimal configuration with smart defaults
|
|
3212
|
+
* createAdapterFromProvider({
|
|
3213
|
+
* provider: window.ethereum
|
|
3214
|
+
* // Capabilities default to:
|
|
3215
|
+
* // { addressContext: 'user-controlled', supportedChains: [all EVM chains] }
|
|
3216
|
+
* })
|
|
3217
|
+
* ```
|
|
3218
|
+
*
|
|
3219
|
+
* @example
|
|
3220
|
+
* ```typescript
|
|
3221
|
+
* // Override supported chains only
|
|
3222
|
+
* createAdapterFromProvider({
|
|
3223
|
+
* provider: window.ethereum,
|
|
3224
|
+
* capabilities: {
|
|
3225
|
+
* supportedChains: [Ethereum, Base, Polygon]
|
|
3226
|
+
* // addressContext still defaults to 'user-controlled'
|
|
3227
|
+
* }
|
|
3228
|
+
* })
|
|
3229
|
+
* ```
|
|
3230
|
+
*/
|
|
3231
|
+
capabilities?: Partial<AdapterCapabilities>;
|
|
2618
3232
|
}
|
|
2619
3233
|
/**
|
|
2620
|
-
* Creates an EthersAdapter instance from an EIP-1193 provider.
|
|
3234
|
+
* Creates an EthersAdapter instance from an EIP-1193 provider with smart default capabilities.
|
|
2621
3235
|
*
|
|
2622
3236
|
* This function creates an EthersAdapter for browser or injected wallet use
|
|
2623
|
-
* by connecting to the provided EIP-1193-compatible provider
|
|
2624
|
-
*
|
|
3237
|
+
* by connecting to the provided EIP-1193-compatible provider (such as MetaMask,
|
|
3238
|
+
* WalletConnect, or any browser wallet). The adapter is automatically configured
|
|
3239
|
+
* with user-controlled address context and support for all EVM-compatible chains.
|
|
2625
3240
|
*
|
|
2626
3241
|
* @remarks
|
|
2627
3242
|
* The function performs the following operations:
|
|
2628
3243
|
* 1. Validates the input parameters at runtime
|
|
2629
|
-
* 2. Creates a
|
|
2630
|
-
* 3.
|
|
2631
|
-
* 4.
|
|
2632
|
-
* 5.
|
|
3244
|
+
* 2. Creates a BrowserProvider for the injected provider
|
|
3245
|
+
* 3. Requests account access from the user (wallet prompt appears here)
|
|
3246
|
+
* 4. Retrieves the signer from the connected wallet
|
|
3247
|
+
* 5. Applies smart defaults for capabilities (user-controlled + all EVM chains)
|
|
3248
|
+
* 6. Returns a configured EthersAdapter instance ready for immediate use
|
|
2633
3249
|
*
|
|
2634
3250
|
* The adapter will be ready to use immediately after creation with the
|
|
2635
|
-
* specified provider and signer active.
|
|
2636
|
-
*
|
|
3251
|
+
* specified provider and signer active. Chain context is provided through
|
|
3252
|
+
* OperationContext during individual operations.
|
|
3253
|
+
*
|
|
3254
|
+
* **Smart Defaults:**
|
|
3255
|
+
* - `addressContext`: `'user-controlled'` (addresses managed through wallet UI)
|
|
3256
|
+
* - `supportedChains`: All EVM-compatible chains (~29 networks) for maximum flexibility
|
|
3257
|
+
* - OperationContext support for per-operation chain specification
|
|
2637
3258
|
*
|
|
2638
|
-
* **
|
|
2639
|
-
*
|
|
2640
|
-
* -
|
|
3259
|
+
* **Account Access:**
|
|
3260
|
+
* Note: Unlike Viem, Ethers requires eager signer initialization because:
|
|
3261
|
+
* - Ethers Signer objects are chain-specific and must be recreated during chain switches
|
|
3262
|
+
* - The switchChain utility requires an initialized Signer as input
|
|
3263
|
+
* - This is an architectural difference between Ethers and Viem, not a limitation
|
|
3264
|
+
* The user will be prompted for account access when this factory is called (before adapter is returned).
|
|
2641
3265
|
*
|
|
2642
3266
|
* **Security Note:** This function is intended for use with injected/browser wallets.
|
|
2643
3267
|
* Do not use in server-side code with private keys.
|
|
2644
3268
|
*
|
|
2645
|
-
* @param params - Configuration parameters for creating the adapter
|
|
2646
|
-
* - `provider`: An EIP-1193-compatible provider (e.g., MetaMask, WalletConnect, etc.)
|
|
2647
|
-
* - `chain`: The blockchain network identifier (string, enum, or ChainDefinition)
|
|
2648
|
-
* - `getProvider` (optional): A custom function to create a JsonRpcProvider
|
|
3269
|
+
* @param params - Configuration parameters for creating the adapter
|
|
2649
3270
|
* @returns A configured EthersAdapter instance
|
|
2650
|
-
* @throws Error when validation fails or provider
|
|
3271
|
+
* @throws Error when validation fails, user rejects connection, or provider initialization fails
|
|
3272
|
+
*
|
|
3273
|
+
* @example
|
|
3274
|
+
* ```typescript
|
|
3275
|
+
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
3276
|
+
*
|
|
3277
|
+
* // Minimal browser wallet configuration
|
|
3278
|
+
* const adapter = await createAdapterFromProvider({
|
|
3279
|
+
* provider: window.ethereum
|
|
3280
|
+
* // Smart defaults applied:
|
|
3281
|
+
* // - addressContext: 'user-controlled'
|
|
3282
|
+
* // - supportedChains: all EVM chains (~29 networks)
|
|
3283
|
+
* })
|
|
3284
|
+
*
|
|
3285
|
+
* // Use with OperationContext pattern
|
|
3286
|
+
* const prepared = await adapter.prepare({
|
|
3287
|
+
* address: '0x...',
|
|
3288
|
+
* abi: contractAbi,
|
|
3289
|
+
* functionName: 'transfer',
|
|
3290
|
+
* args: ['0xto', '1000']
|
|
3291
|
+
* }, { chain: 'Ethereum' }) // Chain specified in context
|
|
3292
|
+
* ```
|
|
2651
3293
|
*
|
|
2652
3294
|
* @example
|
|
2653
3295
|
* ```typescript
|
|
2654
3296
|
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
3297
|
+
* import { Ethereum, Base, Polygon } from '@core/chains'
|
|
2655
3298
|
*
|
|
2656
|
-
* //
|
|
3299
|
+
* // Advanced: custom capabilities for production use
|
|
2657
3300
|
* const adapter = await createAdapterFromProvider({
|
|
2658
3301
|
* provider: window.ethereum,
|
|
2659
|
-
*
|
|
3302
|
+
* capabilities: {
|
|
3303
|
+
* supportedChains: [Ethereum, Base, Polygon] // Restrict to specific chains
|
|
3304
|
+
* // addressContext still defaults to 'user-controlled'
|
|
3305
|
+
* }
|
|
2660
3306
|
* })
|
|
2661
3307
|
* ```
|
|
2662
3308
|
*
|
|
@@ -2665,15 +3311,98 @@ interface CreateAdapterFromProviderParams {
|
|
|
2665
3311
|
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
2666
3312
|
* import { JsonRpcProvider } from 'ethers'
|
|
2667
3313
|
*
|
|
2668
|
-
* // Advanced usage with custom provider logic
|
|
3314
|
+
* // Advanced usage with custom provider logic for production
|
|
2669
3315
|
* const adapter = await createAdapterFromProvider({
|
|
2670
3316
|
* provider: window.ethereum,
|
|
2671
|
-
*
|
|
2672
|
-
*
|
|
3317
|
+
* getProvider: ({ chain }) => new JsonRpcProvider(
|
|
3318
|
+
* `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
|
|
3319
|
+
* { name: chain.name, chainId: chain.chainId }
|
|
3320
|
+
* )
|
|
3321
|
+
* })
|
|
3322
|
+
*
|
|
3323
|
+
* // Address is automatically resolved from connected wallet
|
|
3324
|
+
* const prepared = await adapter.prepare(params, {
|
|
3325
|
+
* chain: 'Polygon' // Address comes from wallet UI
|
|
3326
|
+
* })
|
|
3327
|
+
* ```
|
|
3328
|
+
*
|
|
3329
|
+
* @example
|
|
3330
|
+
* ```typescript
|
|
3331
|
+
* // Cross-chain transfer using a single adapter
|
|
3332
|
+
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
3333
|
+
* import { BridgeKit } from '@circle-fin/bridge-kit'
|
|
3334
|
+
*
|
|
3335
|
+
* const adapter = await createAdapterFromProvider({
|
|
3336
|
+
* provider: window.ethereum
|
|
3337
|
+
* })
|
|
3338
|
+
*
|
|
3339
|
+
* const kit = new BridgeKit()
|
|
3340
|
+
*
|
|
3341
|
+
* // Use the same adapter for both source and destination
|
|
3342
|
+
* const result = await kit.bridge({
|
|
3343
|
+
* from: { adapter, chain: 'Ethereum' },
|
|
3344
|
+
* to: { adapter, chain: 'Base' },
|
|
3345
|
+
* amount: '100.50'
|
|
2673
3346
|
* })
|
|
2674
3347
|
* ```
|
|
3348
|
+
*
|
|
3349
|
+
* @example
|
|
3350
|
+
* ```typescript
|
|
3351
|
+
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
3352
|
+
*
|
|
3353
|
+
* // Error handling example - wallet prompt occurs during factory creation
|
|
3354
|
+
* try {
|
|
3355
|
+
* const adapter = await createAdapterFromProvider({
|
|
3356
|
+
* provider: window.ethereum
|
|
3357
|
+
* })
|
|
3358
|
+
*
|
|
3359
|
+
* // Adapter is ready to use immediately
|
|
3360
|
+
* console.log('Adapter connected successfully')
|
|
3361
|
+
* } catch (error) {
|
|
3362
|
+
* if (error.message.includes('User rejected')) {
|
|
3363
|
+
* console.error('User rejected connection request')
|
|
3364
|
+
* } else if (error.message.includes('Failed to initialize')) {
|
|
3365
|
+
* console.error('Could not initialize wallet connection')
|
|
3366
|
+
* } else {
|
|
3367
|
+
* console.error('Failed to create adapter:', error.message)
|
|
3368
|
+
* }
|
|
3369
|
+
* }
|
|
3370
|
+
* ```
|
|
2675
3371
|
*/
|
|
2676
3372
|
declare const createAdapterFromProvider: (params: CreateAdapterFromProviderParams) => Promise<EthersAdapter>;
|
|
2677
3373
|
|
|
2678
|
-
|
|
3374
|
+
/**
|
|
3375
|
+
* Validates adapter capabilities for EthersAdapter.
|
|
3376
|
+
*
|
|
3377
|
+
* This function ensures that the adapter capabilities meet the requirements for the
|
|
3378
|
+
* OperationContext pattern by validating the addressContext property and optionally
|
|
3379
|
+
* checking the supportedChains property for EVM compatibility.
|
|
3380
|
+
*
|
|
3381
|
+
* @param capabilities - The adapter capabilities to validate
|
|
3382
|
+
* @throws ValidationError when capabilities validation fails
|
|
3383
|
+
*
|
|
3384
|
+
* @example
|
|
3385
|
+
* ```typescript
|
|
3386
|
+
* import { validateAdapterCapabilities } from '@circle-fin/adapter-ethers-v6/validation'
|
|
3387
|
+
* import { Ethereum, Base } from '@core/chains'
|
|
3388
|
+
*
|
|
3389
|
+
* // Valid capabilities for user-controlled adapter
|
|
3390
|
+
* const userCapabilities = {
|
|
3391
|
+
* addressContext: 'user-controlled',
|
|
3392
|
+
* supportedChains: [Ethereum, Base]
|
|
3393
|
+
* }
|
|
3394
|
+
*
|
|
3395
|
+
* // Valid capabilities for developer-controlled adapter
|
|
3396
|
+
* const devCapabilities = {
|
|
3397
|
+
* addressContext: 'developer-controlled',
|
|
3398
|
+
* supportedChains: [Ethereum]
|
|
3399
|
+
* }
|
|
3400
|
+
*
|
|
3401
|
+
* validateAdapterCapabilities(userCapabilities) // passes validation
|
|
3402
|
+
* validateAdapterCapabilities(devCapabilities) // passes validation
|
|
3403
|
+
* ```
|
|
3404
|
+
*/
|
|
3405
|
+
declare function validateAdapterCapabilities(capabilities: AdapterCapabilities): void;
|
|
3406
|
+
|
|
3407
|
+
export { Blockchain, EthersAdapter, createAdapterFromPrivateKey, createAdapterFromProvider, validateAdapterCapabilities };
|
|
2679
3408
|
export type { ChainIdentifier, CreateAdapterFromPrivateKeyParams, CreateAdapterFromProviderParams, EthersAdapterOptions };
|