@circle-fin/adapter-ethers-v6 0.0.2-alpha.7 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -13
- package/index.cjs.js +457 -252
- package/index.d.ts +276 -97
- package/index.mjs +396 -194
- package/package.json +6 -4
package/index.mjs
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { JsonRpcProvider, Wallet, BrowserProvider, Interface, Contract } from 'ethers';
|
|
20
|
+
export { JsonRpcProvider } from 'ethers';
|
|
20
21
|
import { z } from 'zod';
|
|
21
22
|
import { hexlify, hexZeroPad } from '@ethersproject/bytes';
|
|
22
23
|
import { getAddress } from '@ethersproject/address';
|
|
@@ -262,6 +263,7 @@ var Blockchain;
|
|
|
262
263
|
Blockchain["Algorand_Testnet"] = "Algorand_Testnet";
|
|
263
264
|
Blockchain["Aptos"] = "Aptos";
|
|
264
265
|
Blockchain["Aptos_Testnet"] = "Aptos_Testnet";
|
|
266
|
+
Blockchain["Arc_Testnet"] = "Arc_Testnet";
|
|
265
267
|
Blockchain["Arbitrum"] = "Arbitrum";
|
|
266
268
|
Blockchain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
|
|
267
269
|
Blockchain["Avalanche"] = "Avalanche";
|
|
@@ -482,6 +484,48 @@ const BRIDGE_CONTRACT_EVM_TESTNET = '0xC5567a5E3370d4DBfB0540025078e283e36A363d'
|
|
|
482
484
|
*/
|
|
483
485
|
const BRIDGE_CONTRACT_EVM_MAINNET = '0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0';
|
|
484
486
|
|
|
487
|
+
/**
|
|
488
|
+
* Arc Testnet chain definition
|
|
489
|
+
* @remarks
|
|
490
|
+
* This represents the test network for the Arc blockchain,
|
|
491
|
+
* Circle's EVM-compatible Layer-1 designed for stablecoin finance
|
|
492
|
+
* and asset tokenization. Arc uses USDC as the native gas token and
|
|
493
|
+
* features the Malachite Byzantine Fault Tolerant (BFT) consensus
|
|
494
|
+
* engine for sub-second finality.
|
|
495
|
+
*/
|
|
496
|
+
const ArcTestnet = defineChain({
|
|
497
|
+
type: 'evm',
|
|
498
|
+
chain: Blockchain.Arc_Testnet,
|
|
499
|
+
name: 'Arc Testnet',
|
|
500
|
+
title: 'ArcTestnet',
|
|
501
|
+
nativeCurrency: {
|
|
502
|
+
name: 'Arc',
|
|
503
|
+
symbol: 'Arc',
|
|
504
|
+
decimals: 18,
|
|
505
|
+
},
|
|
506
|
+
chainId: 5042002,
|
|
507
|
+
isTestnet: true,
|
|
508
|
+
explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
|
|
509
|
+
rpcEndpoints: ['https://rpc.testnet.arc.network/'],
|
|
510
|
+
eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
511
|
+
usdcAddress: '0x3600000000000000000000000000000000000000',
|
|
512
|
+
cctp: {
|
|
513
|
+
domain: 26,
|
|
514
|
+
contracts: {
|
|
515
|
+
v2: {
|
|
516
|
+
type: 'split',
|
|
517
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
518
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
519
|
+
confirmations: 1,
|
|
520
|
+
fastConfirmations: 1,
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
kitContracts: {
|
|
525
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET,
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
|
|
485
529
|
/**
|
|
486
530
|
* Arbitrum Mainnet chain definition
|
|
487
531
|
* @remarks
|
|
@@ -1773,26 +1817,26 @@ const Sonic = defineChain({
|
|
|
1773
1817
|
});
|
|
1774
1818
|
|
|
1775
1819
|
/**
|
|
1776
|
-
* Sonic
|
|
1820
|
+
* Sonic Testnet chain definition
|
|
1777
1821
|
* @remarks
|
|
1778
1822
|
* This represents the official test network for the Sonic blockchain.
|
|
1779
1823
|
*/
|
|
1780
1824
|
const SonicTestnet = defineChain({
|
|
1781
1825
|
type: 'evm',
|
|
1782
1826
|
chain: Blockchain.Sonic_Testnet,
|
|
1783
|
-
name: 'Sonic
|
|
1784
|
-
title: 'Sonic
|
|
1827
|
+
name: 'Sonic Testnet',
|
|
1828
|
+
title: 'Sonic Testnet',
|
|
1785
1829
|
nativeCurrency: {
|
|
1786
1830
|
name: 'Sonic',
|
|
1787
1831
|
symbol: 'S',
|
|
1788
1832
|
decimals: 18,
|
|
1789
1833
|
},
|
|
1790
|
-
chainId:
|
|
1834
|
+
chainId: 14601,
|
|
1791
1835
|
isTestnet: true,
|
|
1792
1836
|
explorerUrl: 'https://testnet.sonicscan.org/tx/{hash}',
|
|
1793
|
-
rpcEndpoints: ['https://rpc.
|
|
1837
|
+
rpcEndpoints: ['https://rpc.testnet.soniclabs.com'],
|
|
1794
1838
|
eurcAddress: null,
|
|
1795
|
-
usdcAddress: '
|
|
1839
|
+
usdcAddress: '0x0BA304580ee7c9a980CF72e55f5Ed2E9fd30Bc51',
|
|
1796
1840
|
cctp: {
|
|
1797
1841
|
domain: 13,
|
|
1798
1842
|
contracts: {
|
|
@@ -2309,6 +2353,7 @@ var Blockchains = /*#__PURE__*/Object.freeze({
|
|
|
2309
2353
|
AptosTestnet: AptosTestnet,
|
|
2310
2354
|
Arbitrum: Arbitrum,
|
|
2311
2355
|
ArbitrumSepolia: ArbitrumSepolia,
|
|
2356
|
+
ArcTestnet: ArcTestnet,
|
|
2312
2357
|
Avalanche: Avalanche,
|
|
2313
2358
|
AvalancheFuji: AvalancheFuji,
|
|
2314
2359
|
Base: Base,
|
|
@@ -2441,6 +2486,11 @@ const baseChainDefinitionSchema = z.object({
|
|
|
2441
2486
|
eurcAddress: z.string().nullable(),
|
|
2442
2487
|
usdcAddress: z.string().nullable(),
|
|
2443
2488
|
cctp: z.any().nullable(), // We'll accept any CCTP config structure
|
|
2489
|
+
kitContracts: z
|
|
2490
|
+
.object({
|
|
2491
|
+
bridge: z.string().optional(),
|
|
2492
|
+
})
|
|
2493
|
+
.optional(),
|
|
2444
2494
|
});
|
|
2445
2495
|
/**
|
|
2446
2496
|
* Zod schema for validating EVM chain definitions specifically.
|
|
@@ -2472,13 +2522,15 @@ const baseChainDefinitionSchema = z.object({
|
|
|
2472
2522
|
* }
|
|
2473
2523
|
* ```
|
|
2474
2524
|
*/
|
|
2475
|
-
const evmChainDefinitionSchema = baseChainDefinitionSchema
|
|
2525
|
+
const evmChainDefinitionSchema = baseChainDefinitionSchema
|
|
2526
|
+
.extend({
|
|
2476
2527
|
type: z.literal('evm'),
|
|
2477
2528
|
chainId: z.number({
|
|
2478
2529
|
required_error: 'EVM chains must have a chainId. Please provide a valid EVM chain ID.',
|
|
2479
2530
|
invalid_type_error: 'EVM chain ID must be a number.',
|
|
2480
2531
|
}),
|
|
2481
|
-
})
|
|
2532
|
+
})
|
|
2533
|
+
.strict(); //// Reject any additional properties not defined in the schema
|
|
2482
2534
|
/**
|
|
2483
2535
|
* Zod schema for validating non-EVM chain definitions.
|
|
2484
2536
|
* This schema extends the base schema with non-EVM specific properties.
|
|
@@ -2498,7 +2550,7 @@ const nonEvmChainDefinitionSchema = baseChainDefinitionSchema
|
|
|
2498
2550
|
'polkadot',
|
|
2499
2551
|
]),
|
|
2500
2552
|
})
|
|
2501
|
-
.strict(); // Reject additional properties
|
|
2553
|
+
.strict(); // Reject any additional properties not defined in the schema
|
|
2502
2554
|
/**
|
|
2503
2555
|
* Discriminated union schema for all chain definitions.
|
|
2504
2556
|
* This schema validates different chain types based on their 'type' field.
|
|
@@ -2980,67 +3032,41 @@ class KitError extends Error {
|
|
|
2980
3032
|
}
|
|
2981
3033
|
|
|
2982
3034
|
/**
|
|
2983
|
-
*
|
|
3035
|
+
* Minimum error code for INPUT type errors.
|
|
3036
|
+
* INPUT errors represent validation failures and invalid parameters.
|
|
3037
|
+
*/
|
|
3038
|
+
/**
|
|
3039
|
+
* Standardized error definitions for INPUT type errors.
|
|
3040
|
+
*
|
|
3041
|
+
* Each entry combines the numeric error code with its corresponding
|
|
3042
|
+
* string name to ensure consistency when creating error instances.
|
|
2984
3043
|
*
|
|
2985
3044
|
* Error codes follow a hierarchical numbering scheme where the first digit
|
|
2986
3045
|
* indicates the error category (1 = INPUT) and subsequent digits provide
|
|
2987
3046
|
* specific error identification within that category.
|
|
2988
3047
|
*
|
|
3048
|
+
*
|
|
2989
3049
|
* @example
|
|
2990
3050
|
* ```typescript
|
|
2991
|
-
* import {
|
|
3051
|
+
* import { InputError } from '@core/errors'
|
|
2992
3052
|
*
|
|
2993
3053
|
* const error = new KitError({
|
|
2994
|
-
*
|
|
2995
|
-
* name: InputErrorName.NETWORK_MISMATCH,
|
|
3054
|
+
* ...InputError.NETWORK_MISMATCH,
|
|
2996
3055
|
* recoverability: 'FATAL',
|
|
2997
3056
|
* message: 'Source and destination networks must be different'
|
|
2998
3057
|
* })
|
|
2999
|
-
* ```
|
|
3000
|
-
*/
|
|
3001
|
-
var InputErrorCode;
|
|
3002
|
-
(function (InputErrorCode) {
|
|
3003
|
-
/** Network type mismatch between chains (mainnet vs testnet) */
|
|
3004
|
-
InputErrorCode[InputErrorCode["NETWORK_MISMATCH"] = 1001] = "NETWORK_MISMATCH";
|
|
3005
|
-
/** Invalid amount format or value (negative, zero, or malformed) */
|
|
3006
|
-
InputErrorCode[InputErrorCode["INVALID_AMOUNT"] = 1002] = "INVALID_AMOUNT";
|
|
3007
|
-
/** Unsupported or invalid bridge route configuration */
|
|
3008
|
-
InputErrorCode[InputErrorCode["UNSUPPORTED_ROUTE"] = 1003] = "UNSUPPORTED_ROUTE";
|
|
3009
|
-
/** Invalid wallet or contract address format */
|
|
3010
|
-
InputErrorCode[InputErrorCode["INVALID_ADDRESS"] = 1004] = "INVALID_ADDRESS";
|
|
3011
|
-
/** Invalid or unsupported chain identifier */
|
|
3012
|
-
InputErrorCode[InputErrorCode["INVALID_CHAIN"] = 1005] = "INVALID_CHAIN";
|
|
3013
|
-
/** General validation failure for complex validation rules */
|
|
3014
|
-
InputErrorCode[InputErrorCode["VALIDATION_FAILED"] = 1098] = "VALIDATION_FAILED";
|
|
3015
|
-
})(InputErrorCode || (InputErrorCode = {}));
|
|
3016
|
-
/**
|
|
3017
|
-
* Standardized error names for INPUT type errors.
|
|
3018
|
-
*
|
|
3019
|
-
* These names correspond 1:1 with InputErrorCode and should always
|
|
3020
|
-
* be used together to ensure consistency across error instances.
|
|
3021
3058
|
*
|
|
3022
|
-
*
|
|
3023
|
-
*
|
|
3024
|
-
*
|
|
3025
|
-
*
|
|
3026
|
-
* // Use matching code and name enums
|
|
3027
|
-
* const error = new KitError({
|
|
3028
|
-
* code: InputErrorCode.NETWORK_MISMATCH,
|
|
3029
|
-
* name: InputErrorName.NETWORK_MISMATCH,
|
|
3030
|
-
* recoverability: 'FATAL',
|
|
3031
|
-
* message: 'Network mismatch detected'
|
|
3032
|
-
* })
|
|
3059
|
+
* // Access code and name individually if needed
|
|
3060
|
+
* console.log(InputError.NETWORK_MISMATCH.code) // 1001
|
|
3061
|
+
* console.log(InputError.NETWORK_MISMATCH.name) // 'INPUT_NETWORK_MISMATCH'
|
|
3033
3062
|
* ```
|
|
3034
3063
|
*/
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
InputErrorName["INVALID_CHAIN"] = "INPUT_INVALID_CHAIN";
|
|
3042
|
-
InputErrorName["VALIDATION_FAILED"] = "INPUT_VALIDATION_FAILED";
|
|
3043
|
-
})(InputErrorName || (InputErrorName = {}));
|
|
3064
|
+
const InputError = {
|
|
3065
|
+
/** Unsupported or invalid bridge route configuration */
|
|
3066
|
+
UNSUPPORTED_ROUTE: {
|
|
3067
|
+
code: 1003,
|
|
3068
|
+
name: 'INPUT_UNSUPPORTED_ROUTE',
|
|
3069
|
+
}};
|
|
3044
3070
|
|
|
3045
3071
|
/**
|
|
3046
3072
|
* Creates error for unsupported bridge route.
|
|
@@ -3062,8 +3088,7 @@ var InputErrorName;
|
|
|
3062
3088
|
*/
|
|
3063
3089
|
function createUnsupportedRouteError(source, destination) {
|
|
3064
3090
|
const errorDetails = {
|
|
3065
|
-
|
|
3066
|
-
name: InputErrorName.UNSUPPORTED_ROUTE,
|
|
3091
|
+
...InputError.UNSUPPORTED_ROUTE,
|
|
3067
3092
|
recoverability: 'FATAL',
|
|
3068
3093
|
message: `Route from ${source} to ${destination} is not supported.`,
|
|
3069
3094
|
cause: {
|
|
@@ -3112,26 +3137,6 @@ class Adapter {
|
|
|
3112
3137
|
* ```
|
|
3113
3138
|
*/
|
|
3114
3139
|
capabilities;
|
|
3115
|
-
/**
|
|
3116
|
-
* Default chain for operations when none is explicitly provided.
|
|
3117
|
-
*
|
|
3118
|
-
* This allows adapters to have sensible defaults for chain operations,
|
|
3119
|
-
* reducing the need for explicit chain specification in every call.
|
|
3120
|
-
*
|
|
3121
|
-
* @remarks
|
|
3122
|
-
* This is optional for backward compatibility and because some adapter types
|
|
3123
|
-
* (like developer-controlled adapters) may not have meaningful defaults.
|
|
3124
|
-
*
|
|
3125
|
-
* @example
|
|
3126
|
-
* ```typescript
|
|
3127
|
-
* // User-controlled adapter with default chain
|
|
3128
|
-
* defaultChain = Ethereum
|
|
3129
|
-
*
|
|
3130
|
-
* // Developer-controlled adapter (no default)
|
|
3131
|
-
* defaultChain = undefined
|
|
3132
|
-
* ```
|
|
3133
|
-
*/
|
|
3134
|
-
defaultChain;
|
|
3135
3140
|
/**
|
|
3136
3141
|
* Registry of available actions for this adapter.
|
|
3137
3142
|
*
|
|
@@ -3203,17 +3208,14 @@ class Adapter {
|
|
|
3203
3208
|
* - **Browser wallet adapters**: Request chain switch via EIP-1193 or equivalent
|
|
3204
3209
|
* - **Multi-entity adapters**: Validate chain support (operations are contextual)
|
|
3205
3210
|
*
|
|
3206
|
-
* @param chain - The target chain for operations.
|
|
3211
|
+
* @param chain - The target chain for operations.
|
|
3207
3212
|
* @returns A promise that resolves when the adapter is operating on the specified chain.
|
|
3208
3213
|
* @throws When the target chain is not supported or chain switching fails.
|
|
3209
3214
|
*
|
|
3210
3215
|
* @remarks
|
|
3211
|
-
* This method
|
|
3212
|
-
*
|
|
3213
|
-
*
|
|
3214
|
-
* **Backward Compatibility**: The default implementation provides basic validation but
|
|
3215
|
-
* doesn't perform actual chain switching. Concrete adapter implementations should override
|
|
3216
|
-
* this method to provide proper chain switching logic.
|
|
3216
|
+
* This method always calls `switchToChain()` to ensure consistency across all adapter types.
|
|
3217
|
+
* The underlying implementations handle idempotent switching efficiently (e.g., browser wallets
|
|
3218
|
+
* gracefully handle switching to the current chain, private key adapters recreate lightweight clients).
|
|
3217
3219
|
*
|
|
3218
3220
|
* @example
|
|
3219
3221
|
* ```typescript
|
|
@@ -3227,25 +3229,9 @@ class Adapter {
|
|
|
3227
3229
|
* await circleWalletsAdapter.ensureChain(Ethereum)
|
|
3228
3230
|
* ```
|
|
3229
3231
|
*/
|
|
3230
|
-
async ensureChain(
|
|
3231
|
-
const targetChain = chain ?? this.defaultChain;
|
|
3232
|
-
if (!targetChain) {
|
|
3233
|
-
return;
|
|
3234
|
-
}
|
|
3232
|
+
async ensureChain(targetChain) {
|
|
3235
3233
|
this.validateChainSupport(targetChain);
|
|
3236
|
-
//
|
|
3237
|
-
if (this.capabilities?.addressContext !== 'developer-controlled') {
|
|
3238
|
-
try {
|
|
3239
|
-
const currentChain = await this.getChain();
|
|
3240
|
-
if (currentChain.chain === targetChain.chain) {
|
|
3241
|
-
return; // Already on the correct chain
|
|
3242
|
-
}
|
|
3243
|
-
}
|
|
3244
|
-
catch {
|
|
3245
|
-
// If getChain() fails, we'll proceed with switching anyway
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
// Delegate actual switching to the concrete implementation
|
|
3234
|
+
// Always delegate to switchToChain - implementations handle idempotent switching
|
|
3249
3235
|
try {
|
|
3250
3236
|
await this.switchToChain(targetChain);
|
|
3251
3237
|
}
|
|
@@ -3808,7 +3794,6 @@ base58StringSchema.refine((value) => value.length >= 86 && value.length <= 88, '
|
|
|
3808
3794
|
const adapterSchema = z.object({
|
|
3809
3795
|
prepare: z.function(),
|
|
3810
3796
|
waitForTransaction: z.function(),
|
|
3811
|
-
getChain: z.function(),
|
|
3812
3797
|
getAddress: z.function(),
|
|
3813
3798
|
});
|
|
3814
3799
|
|
|
@@ -8070,6 +8055,246 @@ class EvmAdapter extends Adapter {
|
|
|
8070
8055
|
}
|
|
8071
8056
|
}
|
|
8072
8057
|
|
|
8058
|
+
// --- Signature Parsing Constants ---
|
|
8059
|
+
const SIGNATURE_BYTE_LENGTH = 65; // Total bytes in an Ethereum signature
|
|
8060
|
+
const HEX_CHARS_PER_BYTE = 2;
|
|
8061
|
+
const SIGNATURE_HEX_LENGTH = SIGNATURE_BYTE_LENGTH * HEX_CHARS_PER_BYTE;
|
|
8062
|
+
const R_HEX_LENGTH = 32 * HEX_CHARS_PER_BYTE; // 32 bytes for 'r'
|
|
8063
|
+
const S_HEX_LENGTH = 32 * HEX_CHARS_PER_BYTE; // 32 bytes for 's'
|
|
8064
|
+
// --- Recovery ID Validation Constants ---
|
|
8065
|
+
/**
|
|
8066
|
+
* Legacy recovery IDs (pre-EIP-155 format):
|
|
8067
|
+
* - 0 or 1 (older clients) or 27, 28 (Ethereum before chain-id inclusion)
|
|
8068
|
+
*/
|
|
8069
|
+
const LEGACY_V_VALUES = new Set([0, 1, 27, 28]);
|
|
8070
|
+
/**
|
|
8071
|
+
* Minimum v value indicating an EIP-155 style signature.
|
|
8072
|
+
* Calculated as 35 + (2 * chainId) + recoveryId (0 or 1).
|
|
8073
|
+
*/
|
|
8074
|
+
const MIN_EIP155_V = 35;
|
|
8075
|
+
/**
|
|
8076
|
+
* parseSignature
|
|
8077
|
+
*
|
|
8078
|
+
* Parse a 65-byte ECDSA signature into its r, s, and v components, expressed in hex.
|
|
8079
|
+
*
|
|
8080
|
+
* Ethereum signatures are structured as:
|
|
8081
|
+
* signature = r (32 bytes) || s (32 bytes) || v (1 byte)
|
|
8082
|
+
*
|
|
8083
|
+
* - r, s: Big-endian hex values (32 bytes each)
|
|
8084
|
+
* - v: Recovery identifier, used by secp256k1 to reconstruct the signer’s public key
|
|
8085
|
+
*
|
|
8086
|
+
* @param signatureHex - Signature as a hex string, optionally prefixed with "0x".
|
|
8087
|
+
* @returns { r, s, v }
|
|
8088
|
+
* - r: Hex string of the R component.
|
|
8089
|
+
* - s: Hex string of the S component.
|
|
8090
|
+
* - v: Numeric recovery ID.
|
|
8091
|
+
*
|
|
8092
|
+
* @throws Error if:
|
|
8093
|
+
* - Input is not valid hex.
|
|
8094
|
+
* - Incorrect length (must be exactly 65 bytes / 130 hex chars).
|
|
8095
|
+
* - v is outside the supported range (Legacy or EIP-155 formula).
|
|
8096
|
+
*
|
|
8097
|
+
* Notes on EIP-155 overload:
|
|
8098
|
+
* EIP-155 repurposes the v field so that:
|
|
8099
|
+
* v = 35 + (2 * chainId) + recoveryId(0 or 1)
|
|
8100
|
+
* Any v value >= 35 indicates the chain-id is encoded, preventing cross-chain replay.
|
|
8101
|
+
* r and s values remain unchanged.
|
|
8102
|
+
*
|
|
8103
|
+
* Example:
|
|
8104
|
+
* ```typescript
|
|
8105
|
+
* const rawSig = '0x6c1b...f02b'
|
|
8106
|
+
* try {
|
|
8107
|
+
* const { r, s, v } = parseSignature(rawSig)
|
|
8108
|
+
* console.log('R:', r)
|
|
8109
|
+
* console.log('S:', s)
|
|
8110
|
+
* console.log('Recovery ID (v):', v)
|
|
8111
|
+
* } catch (err) {
|
|
8112
|
+
* console.error('Signature parse error:', err.message)
|
|
8113
|
+
* }
|
|
8114
|
+
* ```
|
|
8115
|
+
*/
|
|
8116
|
+
function parseSignature(signatureHex) {
|
|
8117
|
+
// 1) Remove optional '0x' prefix
|
|
8118
|
+
const hex = signatureHex.startsWith('0x')
|
|
8119
|
+
? signatureHex.slice(2)
|
|
8120
|
+
: signatureHex;
|
|
8121
|
+
// 2) Validate hex format and length
|
|
8122
|
+
const VALID_HEX_REGEX = /^[0-9a-fA-F]+$/;
|
|
8123
|
+
if (!VALID_HEX_REGEX.test(hex)) {
|
|
8124
|
+
throw new Error('Signature must be a valid hex string (0-9, a-f, A-F).');
|
|
8125
|
+
}
|
|
8126
|
+
if (hex.length !== SIGNATURE_HEX_LENGTH) {
|
|
8127
|
+
throw new Error(`Invalid length: expected ${SIGNATURE_HEX_LENGTH.toString()} hex chars (65 bytes), got ${hex.length.toString()}`);
|
|
8128
|
+
}
|
|
8129
|
+
// 3) Extract components
|
|
8130
|
+
const r = `0x${hex.slice(0, R_HEX_LENGTH)}`;
|
|
8131
|
+
const s = `0x${hex.slice(R_HEX_LENGTH, R_HEX_LENGTH + S_HEX_LENGTH)}`;
|
|
8132
|
+
const vValue = parseInt(hex.slice(R_HEX_LENGTH + S_HEX_LENGTH), 16);
|
|
8133
|
+
// 4) Ensure v is within supported values
|
|
8134
|
+
const isLegacy = LEGACY_V_VALUES.has(vValue);
|
|
8135
|
+
const isEIP155 = vValue >= MIN_EIP155_V;
|
|
8136
|
+
if (!isLegacy && !isEIP155) {
|
|
8137
|
+
throw new Error(`Unsupported v value: ${vValue.toString()}. Must be one of [${[
|
|
8138
|
+
...LEGACY_V_VALUES,
|
|
8139
|
+
].join(', ')}] or >=${MIN_EIP155_V.toString()}`);
|
|
8140
|
+
}
|
|
8141
|
+
return { r: r, s: s, v: vValue };
|
|
8142
|
+
}
|
|
8143
|
+
/**
|
|
8144
|
+
* buildTypedData
|
|
8145
|
+
*
|
|
8146
|
+
* Create an EIP-712 compliant "TypedData" object, encapsulating:
|
|
8147
|
+
* - Domain separator (application/contract identity, chain ID)
|
|
8148
|
+
* - Explicit type definitions (field names and types)
|
|
8149
|
+
* - Primary type name identifying the root object
|
|
8150
|
+
* - Message payload matching the defined schema
|
|
8151
|
+
*
|
|
8152
|
+
* This enforces structured, non-ambiguous signing, and guards against signature replay.
|
|
8153
|
+
*
|
|
8154
|
+
* @typeParam Types - Map of type names to arrays of { name, type } definitions.
|
|
8155
|
+
* @typeParam Msg - Object whose shape matches the primaryType fields.
|
|
8156
|
+
*
|
|
8157
|
+
* @param domain - EIP712Domain, e.g. { name, version, chainId, verifyingContract }.
|
|
8158
|
+
* @param types - Type definitions, e.g.:
|
|
8159
|
+
* {
|
|
8160
|
+
* Mail: [ { name: 'from', type: 'string' }, { name: 'contents', type: 'string' } ],
|
|
8161
|
+
* }
|
|
8162
|
+
* @param primaryType - Root key in types, e.g. 'Mail'.
|
|
8163
|
+
* @param message - The actual values, e.g. { from: 'Alice', contents: 'Hello' }.
|
|
8164
|
+
*
|
|
8165
|
+
* @returns TypedData object ready for use with signing libraries.
|
|
8166
|
+
*
|
|
8167
|
+
* Example:
|
|
8168
|
+
* ```typescript
|
|
8169
|
+
* const typedData = buildTypedData(
|
|
8170
|
+
* { name: 'MyDApp', version: '1', chainId: 1, verifyingContract: '0xabc...' },
|
|
8171
|
+
* { Message: [{ name: 'text', type: 'string' }] },
|
|
8172
|
+
* 'Message',
|
|
8173
|
+
* { text: 'Hello, EIP-712!' }
|
|
8174
|
+
* )
|
|
8175
|
+
* // Pass typedData to ethers.js signer._signTypedData(domain, types, message)
|
|
8176
|
+
* ```
|
|
8177
|
+
*/
|
|
8178
|
+
function buildTypedData(domain, types, primaryType, message) {
|
|
8179
|
+
return { domain, types, primaryType, message };
|
|
8180
|
+
}
|
|
8181
|
+
|
|
8182
|
+
/**
|
|
8183
|
+
* Compute default deadline for permit signatures.
|
|
8184
|
+
*
|
|
8185
|
+
* Returns a timestamp 1 hour (3600 seconds) from the current time,
|
|
8186
|
+
* converted to Unix timestamp format as a bigint. This is commonly
|
|
8187
|
+
* used as the default expiration time for EIP-2612 permit signatures.
|
|
8188
|
+
*
|
|
8189
|
+
* @returns Unix timestamp (in seconds) 1 hour from now as a bigint
|
|
8190
|
+
*
|
|
8191
|
+
* @example
|
|
8192
|
+
* ```typescript
|
|
8193
|
+
* import { computeDefaultDeadline } from '@core/adapter-evm'
|
|
8194
|
+
*
|
|
8195
|
+
* const deadline = computeDefaultDeadline()
|
|
8196
|
+
* console.log(`Permit expires at: ${deadline}`)
|
|
8197
|
+
* // Output: Permit expires at: 1640998800
|
|
8198
|
+
* ```
|
|
8199
|
+
*/
|
|
8200
|
+
function computeDefaultDeadline() {
|
|
8201
|
+
return BigInt(Math.floor(Date.now() / 1000) + 3600);
|
|
8202
|
+
}
|
|
8203
|
+
|
|
8204
|
+
/**
|
|
8205
|
+
* EIP-2612 permit type definition.
|
|
8206
|
+
* Defines the structure for permit signatures according to EIP-2612 specification.
|
|
8207
|
+
*
|
|
8208
|
+
* @see {@link https://eips.ethereum.org/EIPS/eip-2612 | EIP-2612 Specification}
|
|
8209
|
+
*/
|
|
8210
|
+
const EIP2612_TYPES = {
|
|
8211
|
+
Permit: [
|
|
8212
|
+
{ name: 'owner', type: 'address' },
|
|
8213
|
+
{ name: 'spender', type: 'address' },
|
|
8214
|
+
{ name: 'value', type: 'uint256' },
|
|
8215
|
+
{ name: 'nonce', type: 'uint256' },
|
|
8216
|
+
{ name: 'deadline', type: 'uint256' },
|
|
8217
|
+
],
|
|
8218
|
+
};
|
|
8219
|
+
|
|
8220
|
+
/**
|
|
8221
|
+
* Build EIP-2612 typed data for permit signing.
|
|
8222
|
+
*
|
|
8223
|
+
* This function creates the complete EIP-712 typed data structure required
|
|
8224
|
+
* for EIP-2612 permit signatures, including automatic nonce fetching using
|
|
8225
|
+
* the adapter's built-in nonce fetching capability.
|
|
8226
|
+
*
|
|
8227
|
+
* **Address Formatting**: All addresses are automatically formatted with proper
|
|
8228
|
+
* EIP-55 checksumming using the `convertAddress` utility, ensuring compatibility
|
|
8229
|
+
* with strict validation libraries like viem.
|
|
8230
|
+
*
|
|
8231
|
+
* **Nonce Handling**: The nonce can be provided explicitly or will be fetched
|
|
8232
|
+
* automatically using the adapter's `fetchEIP2612Nonce` method, which queries
|
|
8233
|
+
* the token contract's `nonces(owner)` function.
|
|
8234
|
+
*
|
|
8235
|
+
* **Deadline Calculation**: If no deadline is provided, it defaults to 24 hours
|
|
8236
|
+
* from the current time (computed using `computeDefaultDeadline`).
|
|
8237
|
+
*
|
|
8238
|
+
* @param meta - Domain metadata for the token contract
|
|
8239
|
+
* @param adapter - Adapter instance with nonce-fetching capability
|
|
8240
|
+
* @param opts - EIP-2612 permit options including owner, spender, value
|
|
8241
|
+
* @returns Complete EIP-712 typed data ready for signing
|
|
8242
|
+
*
|
|
8243
|
+
* @example
|
|
8244
|
+
* ```typescript
|
|
8245
|
+
* import { buildEIP2612TypedData } from '@core/adapter-evm'
|
|
8246
|
+
*
|
|
8247
|
+
* const typedData = await buildEIP2612TypedData(
|
|
8248
|
+
* {
|
|
8249
|
+
* name: 'USD Coin',
|
|
8250
|
+
* version: '2',
|
|
8251
|
+
* chainId: 1,
|
|
8252
|
+
* verifyingContract: '0xa0b86a33e6441e4d178bb0c14ce0e9ce9c83bdd8'
|
|
8253
|
+
* },
|
|
8254
|
+
* adapter,
|
|
8255
|
+
* {
|
|
8256
|
+
* owner: '0x742d35cc6639c0532fbe9002b3a2265ca4c878f8e',
|
|
8257
|
+
* spender: '0x1234567890123456789012345678901234567890',
|
|
8258
|
+
* value: 1000000n
|
|
8259
|
+
* }
|
|
8260
|
+
* )
|
|
8261
|
+
*
|
|
8262
|
+
* const signature = await adapter.signTypedData(typedData)
|
|
8263
|
+
* ```
|
|
8264
|
+
*/
|
|
8265
|
+
async function buildEIP2612TypedData(meta, adapter, opts, ctx) {
|
|
8266
|
+
// Format addresses to ensure proper EIP-55 checksumming
|
|
8267
|
+
const formattedOwner = convertAddress(opts.owner, 'evm');
|
|
8268
|
+
const formattedSpender = convertAddress(opts.spender, 'evm');
|
|
8269
|
+
const formattedContract = convertAddress(meta.verifyingContract, 'evm');
|
|
8270
|
+
// Fetch nonce if not provided - adapter handles the contract interaction
|
|
8271
|
+
const nonce = opts.nonce ??
|
|
8272
|
+
(await adapter.fetchEIP2612Nonce(formattedContract, formattedOwner, ctx));
|
|
8273
|
+
/*
|
|
8274
|
+
* Calculate deadline if not provided (24 hours from now)
|
|
8275
|
+
* EIP-2612 deadline is a uint256 in the permit struct, so we use bigint for full compatibility
|
|
8276
|
+
* with on-chain values and to avoid overflow/precision issues with large timestamps.
|
|
8277
|
+
* Most real-world deadlines are within JS safe integer range, but using bigint is safest.
|
|
8278
|
+
*/
|
|
8279
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
8280
|
+
const deadline = opts.deadline !== undefined
|
|
8281
|
+
? BigInt(opts.deadline)
|
|
8282
|
+
: computeDefaultDeadline();
|
|
8283
|
+
if (deadline <= now) {
|
|
8284
|
+
throw new Error(`EIP-2612 deadline must be in the future (got ${deadline.toString()}, now ${now.toString()})`);
|
|
8285
|
+
}
|
|
8286
|
+
// Build the message with properly formatted addresses
|
|
8287
|
+
const message = {
|
|
8288
|
+
owner: formattedOwner,
|
|
8289
|
+
spender: formattedSpender,
|
|
8290
|
+
value: opts.value,
|
|
8291
|
+
nonce,
|
|
8292
|
+
deadline,
|
|
8293
|
+
};
|
|
8294
|
+
// Return complete typed data structure with formatted contract address
|
|
8295
|
+
return buildTypedData({ ...meta, verifyingContract: formattedContract }, EIP2612_TYPES, 'Permit', message);
|
|
8296
|
+
}
|
|
8297
|
+
|
|
8073
8298
|
/**
|
|
8074
8299
|
* Checks if a function in an ABI is read-only (view or pure).
|
|
8075
8300
|
*
|
|
@@ -8444,7 +8669,6 @@ const abiSchema = z
|
|
|
8444
8669
|
* - A chainType property set to 'evm'
|
|
8445
8670
|
* - An actionRegistry with registerHandlers method and actionHandlers record
|
|
8446
8671
|
* - A prepare method for creating chain requests
|
|
8447
|
-
* - A getChain method for retrieving chain configuration
|
|
8448
8672
|
*
|
|
8449
8673
|
* @throws \{ValidationError\} If validation fails, with details about which properties failed
|
|
8450
8674
|
*
|
|
@@ -8461,7 +8685,6 @@ const abiSchema = z
|
|
|
8461
8685
|
* }
|
|
8462
8686
|
* },
|
|
8463
8687
|
* prepare: async (request: any) => ({}),
|
|
8464
|
-
* getChain: async () => ({ name: 'Ethereum', type: 'evm' as const })
|
|
8465
8688
|
* }
|
|
8466
8689
|
*
|
|
8467
8690
|
* const result = evmAdapterSchema.safeParse(validAdapter)
|
|
@@ -8563,6 +8786,44 @@ const evmTransactionHashSchema = z
|
|
|
8563
8786
|
.refine((hash) => /^0x[0-9a-fA-F]{64}$/.test(hash), (hash) => ({
|
|
8564
8787
|
message: `Transaction hash "${hash}" contains invalid characters. Only hexadecimal characters (0-9, a-f, A-F) are allowed after '0x'.`,
|
|
8565
8788
|
}));
|
|
8789
|
+
/**
|
|
8790
|
+
* Zod schema for validating EVM private keys.
|
|
8791
|
+
*
|
|
8792
|
+
* This schema validates private key strings to ensure they are properly formatted:
|
|
8793
|
+
* - Accepts private keys with or without '0x' prefix
|
|
8794
|
+
* - Automatically normalizes by adding '0x' prefix if missing
|
|
8795
|
+
* - Validates that the key is exactly 64 hexadecimal characters (32 bytes)
|
|
8796
|
+
* - Ensures only valid hexadecimal characters (0-9, a-f, A-F) are used
|
|
8797
|
+
*
|
|
8798
|
+
* @remarks
|
|
8799
|
+
* This is a shared schema used by both ethers.v6 and viem.v2 adapters to ensure
|
|
8800
|
+
* consistent private key validation across all EVM adapters.
|
|
8801
|
+
*
|
|
8802
|
+
* @throws \{ValidationError\} If validation fails, with details about the issue
|
|
8803
|
+
*
|
|
8804
|
+
* @example
|
|
8805
|
+
* ```typescript
|
|
8806
|
+
* import { evmPrivateKeySchema } from '@core/adapter-evm/validation'
|
|
8807
|
+
*
|
|
8808
|
+
* // Both formats are accepted and normalized
|
|
8809
|
+
* const keyWithPrefix = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
8810
|
+
* const keyWithoutPrefix = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
8811
|
+
*
|
|
8812
|
+
* const result1 = evmPrivateKeySchema.safeParse(keyWithPrefix)
|
|
8813
|
+
* const result2 = evmPrivateKeySchema.safeParse(keyWithoutPrefix)
|
|
8814
|
+
*
|
|
8815
|
+
* // Both succeed and produce the same normalized result with '0x' prefix
|
|
8816
|
+
* ```
|
|
8817
|
+
*/
|
|
8818
|
+
const evmPrivateKeySchema = z
|
|
8819
|
+
.string({
|
|
8820
|
+
required_error: 'Private key is required. Please provide a valid private key.',
|
|
8821
|
+
invalid_type_error: 'Private key must be a string. Please provide a valid private key.',
|
|
8822
|
+
})
|
|
8823
|
+
.transform((val) => (val.startsWith('0x') ? val : `0x${val}`))
|
|
8824
|
+
.pipe(z.string().regex(/^0x[0-9a-fA-F]{64}$/, {
|
|
8825
|
+
message: 'Private key must be a valid 64-character hex string. Please provide a valid private key with or without "0x" prefix.',
|
|
8826
|
+
}));
|
|
8566
8827
|
|
|
8567
8828
|
const assertEvmPreparedChainRequestParamsSymbol = Symbol('assertEvmPreparedChainRequestParams');
|
|
8568
8829
|
/**
|
|
@@ -9331,7 +9592,7 @@ const ethersAdapterOptionsSchema = z.object({
|
|
|
9331
9592
|
* Zod schema for validating parameters to create an EthersAdapter from a private key.
|
|
9332
9593
|
*
|
|
9333
9594
|
* @remarks
|
|
9334
|
-
* - `privateKey`
|
|
9595
|
+
* - `privateKey` can be provided with or without the "0x" prefix. The schema automatically normalizes keys by adding the "0x" prefix if missing before validation.
|
|
9335
9596
|
* - `getProvider` is optional and, if provided, must be a function accepting an object with a `chain` parameter and returning any value.
|
|
9336
9597
|
* - `capabilities` is optional and allows partial overrides with smart defaults.
|
|
9337
9598
|
*
|
|
@@ -9339,27 +9600,22 @@ const ethersAdapterOptionsSchema = z.object({
|
|
|
9339
9600
|
* ```typescript
|
|
9340
9601
|
* import { createAdapterFromPrivateKeyParamsSchema } from '@circle-fin/adapter-ethers-v6/validation'
|
|
9341
9602
|
*
|
|
9342
|
-
*
|
|
9603
|
+
* // Both formats are supported:
|
|
9604
|
+
* const paramsWithPrefix = {
|
|
9343
9605
|
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
9344
9606
|
* }
|
|
9345
9607
|
*
|
|
9346
|
-
* const
|
|
9347
|
-
*
|
|
9348
|
-
* console.log('Parameters are valid')
|
|
9349
|
-
* } else {
|
|
9350
|
-
* console.error('Validation failed:', result.error)
|
|
9608
|
+
* const paramsWithoutPrefix = {
|
|
9609
|
+
* privateKey: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
9351
9610
|
* }
|
|
9611
|
+
*
|
|
9612
|
+
* const result1 = createAdapterFromPrivateKeyParamsSchema.safeParse(paramsWithPrefix)
|
|
9613
|
+
* const result2 = createAdapterFromPrivateKeyParamsSchema.safeParse(paramsWithoutPrefix)
|
|
9614
|
+
* // Both succeed and produce the same normalized result
|
|
9352
9615
|
* ```
|
|
9353
9616
|
*/
|
|
9354
9617
|
const createAdapterFromPrivateKeyParamsSchema = z.object({
|
|
9355
|
-
privateKey:
|
|
9356
|
-
.string({
|
|
9357
|
-
required_error: 'Private key is required. Please provide a valid private key.',
|
|
9358
|
-
invalid_type_error: 'Private key must be a string. Please provide a valid private key.',
|
|
9359
|
-
})
|
|
9360
|
-
.regex(/^0x[0-9a-fA-F]{64}$/, {
|
|
9361
|
-
message: 'Private key must be a 64-character hexadecimal string prefixed with "0x".',
|
|
9362
|
-
}),
|
|
9618
|
+
privateKey: evmPrivateKeySchema,
|
|
9363
9619
|
getProvider: z
|
|
9364
9620
|
.function()
|
|
9365
9621
|
.args(z.object({ chain: z.unknown() }))
|
|
@@ -9468,28 +9724,6 @@ z.object({
|
|
|
9468
9724
|
function validateEthersAdapterOptions(options) {
|
|
9469
9725
|
validate(options, ethersAdapterOptionsSchema, 'EthersAdapterOptions');
|
|
9470
9726
|
}
|
|
9471
|
-
/**
|
|
9472
|
-
* Validates parameters for creating an Ethers adapter from a private key.
|
|
9473
|
-
*
|
|
9474
|
-
* This function validates the parameters used by the createAdapterFromPrivateKey
|
|
9475
|
-
* factory function for the Ethers adapter.
|
|
9476
|
-
*
|
|
9477
|
-
* @param params - The parameters to validate. Must include a `privateKey` string and optionally a `getProvider` function and `capabilities`.
|
|
9478
|
-
* @throws \{ValidationError\} If validation fails.
|
|
9479
|
-
* @example
|
|
9480
|
-
* ```typescript
|
|
9481
|
-
* import { validateCreateAdapterFromPrivateKeyParams } from '@circle-fin/adapter-ethers-v6/validation'
|
|
9482
|
-
*
|
|
9483
|
-
* const params = {
|
|
9484
|
-
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
9485
|
-
* }
|
|
9486
|
-
*
|
|
9487
|
-
* validateCreateAdapterFromPrivateKeyParams(params) // throws if invalid
|
|
9488
|
-
* ```
|
|
9489
|
-
*/
|
|
9490
|
-
function validateCreateAdapterFromPrivateKeyParams(params) {
|
|
9491
|
-
validate(params, createAdapterFromPrivateKeyParamsSchema, 'CreateAdapterFromPrivateKeyParams');
|
|
9492
|
-
}
|
|
9493
9727
|
/**
|
|
9494
9728
|
* Validates parameters for creating an Ethers adapter from an EIP-1193 provider.
|
|
9495
9729
|
*
|
|
@@ -10035,6 +10269,11 @@ class EthersAdapter extends EvmAdapter {
|
|
|
10035
10269
|
* ```
|
|
10036
10270
|
*/
|
|
10037
10271
|
async getAddress(chain) {
|
|
10272
|
+
// Prevent calling getAddress on developer-controlled adapters
|
|
10273
|
+
if (this.capabilities?.addressContext === 'developer-controlled') {
|
|
10274
|
+
throw new Error('Cannot call getAddress() on developer-controlled adapters. ' +
|
|
10275
|
+
'Address must be provided explicitly in the operation context.');
|
|
10276
|
+
}
|
|
10038
10277
|
// Chain parameter should now be provided by resolveOperationContext
|
|
10039
10278
|
if (!chain) {
|
|
10040
10279
|
throw new Error('Chain parameter is required for address resolution. ' +
|
|
@@ -10046,45 +10285,6 @@ class EthersAdapter extends EvmAdapter {
|
|
|
10046
10285
|
const address = await signer.getAddress();
|
|
10047
10286
|
return address;
|
|
10048
10287
|
}
|
|
10049
|
-
/**
|
|
10050
|
-
* Gets the current chain definition.
|
|
10051
|
-
*
|
|
10052
|
-
* TEMP This method is temporary and will be removed once all adapters migrate to the OperationContext pattern.
|
|
10053
|
-
*
|
|
10054
|
-
* **Migration Guide:**
|
|
10055
|
-
*
|
|
10056
|
-
* With the OperationContext pattern, chain information is provided explicitly in each operation
|
|
10057
|
-
* rather than queried from the adapter. This eliminates ambiguity and enables seamless multi-chain
|
|
10058
|
-
* operations with a single adapter instance.
|
|
10059
|
-
*
|
|
10060
|
-
* **Before (Deprecated):**
|
|
10061
|
-
* ```typescript
|
|
10062
|
-
* const chain = await adapter.getChain()
|
|
10063
|
-
* const prepared = await adapter.prepare(params) // Uses cached chain
|
|
10064
|
-
* ```
|
|
10065
|
-
*
|
|
10066
|
-
* **After (OperationContext):**
|
|
10067
|
-
* ```typescript
|
|
10068
|
-
* // Chain specified explicitly per operation
|
|
10069
|
-
* const prepared = await adapter.prepare(params, { chain: 'Ethereum' })
|
|
10070
|
-
*
|
|
10071
|
-
* // Multi-chain operations with same adapter
|
|
10072
|
-
* const ethPrepared = await adapter.prepare(params, { chain: 'Ethereum' })
|
|
10073
|
-
* const basePrepared = await adapter.prepare(params, { chain: 'Base' })
|
|
10074
|
-
* ```
|
|
10075
|
-
*
|
|
10076
|
-
* @returns A promise that resolves to the first supported chain from capabilities
|
|
10077
|
-
* @throws Error when no supported chains are configured
|
|
10078
|
-
*/
|
|
10079
|
-
async getChain() {
|
|
10080
|
-
// Fallback: return first supported chain (deprecated - only for backward compatibility)
|
|
10081
|
-
const firstChain = this.capabilities?.supportedChains?.[0];
|
|
10082
|
-
if (!firstChain) {
|
|
10083
|
-
throw new Error('No supported chains configured. ' +
|
|
10084
|
-
'This method is deprecated - use OperationContext pattern instead.');
|
|
10085
|
-
}
|
|
10086
|
-
return await Promise.resolve(firstChain);
|
|
10087
|
-
}
|
|
10088
10288
|
/**
|
|
10089
10289
|
* Waits for a transaction to be mined and confirmed on the blockchain.
|
|
10090
10290
|
*
|
|
@@ -10359,16 +10559,17 @@ class EthersAdapter extends EvmAdapter {
|
|
|
10359
10559
|
* ```typescript
|
|
10360
10560
|
* import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
|
|
10361
10561
|
*
|
|
10362
|
-
* //
|
|
10363
|
-
* const
|
|
10364
|
-
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
10365
|
-
*
|
|
10366
|
-
*
|
|
10367
|
-
*
|
|
10562
|
+
* // Both private key formats are supported (with or without '0x' prefix):
|
|
10563
|
+
* const adapter1 = createAdapterFromPrivateKey({
|
|
10564
|
+
* privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' // With prefix
|
|
10565
|
+
* })
|
|
10566
|
+
*
|
|
10567
|
+
* const adapter2 = createAdapterFromPrivateKey({
|
|
10568
|
+
* privateKey: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' // Without prefix (automatically normalized)
|
|
10368
10569
|
* })
|
|
10369
10570
|
*
|
|
10370
10571
|
* // Chain specified per-operation via OperationContext
|
|
10371
|
-
* const prepared = await
|
|
10572
|
+
* const prepared = await adapter1.prepare({
|
|
10372
10573
|
* address: '0x...',
|
|
10373
10574
|
* abi: contractAbi,
|
|
10374
10575
|
* functionName: 'transfer',
|
|
@@ -10427,9 +10628,9 @@ class EthersAdapter extends EvmAdapter {
|
|
|
10427
10628
|
* ```
|
|
10428
10629
|
*/
|
|
10429
10630
|
function createAdapterFromPrivateKey(params) {
|
|
10430
|
-
//
|
|
10431
|
-
|
|
10432
|
-
const {
|
|
10631
|
+
// Parse and validate input parameters at runtime (normalizes the private key by adding '0x' prefix if missing)
|
|
10632
|
+
const { privateKey } = createAdapterFromPrivateKeyParamsSchema.parse(params);
|
|
10633
|
+
const { getProvider, capabilities } = params;
|
|
10433
10634
|
// Resolve capabilities with default configuration
|
|
10434
10635
|
const resolvedCapabilities = createAdapterCapabilities('evm', capabilities);
|
|
10435
10636
|
// Validate that capabilities are appropriate for private key adapters
|
|
@@ -10444,6 +10645,7 @@ function createAdapterFromPrivateKey(params) {
|
|
|
10444
10645
|
const getProviderFn = getProvider ?? getDefaultProviderUtil(new Map());
|
|
10445
10646
|
// Create wallet WITHOUT provider (lazy initialization)
|
|
10446
10647
|
// The wallet will be connected to a provider when ensureChain is called
|
|
10648
|
+
// Type assertion safe because we normalized the private key in the schema
|
|
10447
10649
|
const wallet = new Wallet(privateKey);
|
|
10448
10650
|
// Create and return the adapter
|
|
10449
10651
|
return new EthersAdapter({
|
|
@@ -10552,13 +10754,13 @@ function createAdapterFromPrivateKey(params) {
|
|
|
10552
10754
|
* ```typescript
|
|
10553
10755
|
* // Cross-chain transfer using a single adapter
|
|
10554
10756
|
* import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
|
|
10555
|
-
* import {
|
|
10757
|
+
* import { BridgeKit } from '@circle-fin/bridge-kit'
|
|
10556
10758
|
*
|
|
10557
10759
|
* const adapter = await createAdapterFromProvider({
|
|
10558
10760
|
* provider: window.ethereum
|
|
10559
10761
|
* })
|
|
10560
10762
|
*
|
|
10561
|
-
* const kit = new
|
|
10763
|
+
* const kit = new BridgeKit()
|
|
10562
10764
|
*
|
|
10563
10765
|
* // Use the same adapter for both source and destination
|
|
10564
10766
|
* const result = await kit.bridge({
|
|
@@ -10621,5 +10823,5 @@ const createAdapterFromProvider = async (params) => {
|
|
|
10621
10823
|
}, resolvedCapabilities);
|
|
10622
10824
|
};
|
|
10623
10825
|
|
|
10624
|
-
export { EthersAdapter, createAdapterFromPrivateKey, createAdapterFromProvider, validateAdapterCapabilities };
|
|
10826
|
+
export { Blockchain, EthersAdapter, buildEIP2612TypedData, computeDefaultDeadline, createAdapterFromPrivateKey, createAdapterFromProvider, parseSignature, validateAdapterCapabilities };
|
|
10625
10827
|
//# sourceMappingURL=index.mjs.map
|