@circle-fin/app-kit 1.8.0 → 1.9.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/CHANGELOG.md +53 -0
- package/README.md +3 -3
- package/bridge.cjs +469 -231
- package/bridge.d.cts +16 -2
- package/bridge.d.mts +16 -2
- package/bridge.d.ts +16 -2
- package/bridge.mjs +469 -231
- package/chains.cjs +94 -0
- package/chains.d.cts +2 -0
- package/chains.d.mts +2 -0
- package/chains.d.ts +2 -0
- package/chains.mjs +94 -0
- package/context.d.cts +16 -2
- package/context.d.mts +16 -2
- package/context.d.ts +16 -2
- package/earn.cjs +438 -208
- package/earn.d.cts +33 -13
- package/earn.d.mts +33 -13
- package/earn.d.ts +33 -13
- package/earn.mjs +438 -208
- package/estimateBridge.cjs +469 -231
- package/estimateBridge.d.cts +16 -2
- package/estimateBridge.d.mts +16 -2
- package/estimateBridge.d.ts +16 -2
- package/estimateBridge.mjs +469 -231
- package/estimateSwap.cjs +210 -87
- package/estimateSwap.d.cts +16 -2
- package/estimateSwap.d.mts +16 -2
- package/estimateSwap.d.ts +16 -2
- package/estimateSwap.mjs +210 -87
- package/index.cjs +884 -413
- package/index.d.cts +284 -27
- package/index.d.mts +284 -27
- package/index.d.ts +284 -27
- package/index.mjs +884 -413
- package/package.json +12 -6
- package/swap.cjs +210 -87
- package/swap.d.cts +16 -2
- package/swap.d.mts +16 -2
- package/swap.d.ts +16 -2
- package/swap.mjs +210 -87
- package/unifiedBalance.cjs +119 -5
- package/unifiedBalance.d.cts +2 -0
- package/unifiedBalance.d.mts +2 -0
- package/unifiedBalance.d.ts +2 -0
- package/unifiedBalance.mjs +119 -5
package/earn.cjs
CHANGED
|
@@ -843,36 +843,6 @@ class KitError extends Error {
|
|
|
843
843
|
};
|
|
844
844
|
return new KitError(errorDetails);
|
|
845
845
|
}
|
|
846
|
-
/**
|
|
847
|
-
* Creates error for unsupported token on chain.
|
|
848
|
-
*
|
|
849
|
-
* This error is thrown when a token is not supported on the specified chain.
|
|
850
|
-
*
|
|
851
|
-
* @param token - The token symbol (e.g., 'USDC', 'USDT')
|
|
852
|
-
* @param chain - The chain name where the token is unsupported
|
|
853
|
-
* @returns KitError with specific token support details
|
|
854
|
-
*
|
|
855
|
-
* @example
|
|
856
|
-
* ```typescript
|
|
857
|
-
* import { createUnsupportedTokenError } from '@core/errors'
|
|
858
|
-
*
|
|
859
|
-
* throw createUnsupportedTokenError('USDC', 'UnknownChain')
|
|
860
|
-
* // Message: "USDC is not supported on UnknownChain"
|
|
861
|
-
* ```
|
|
862
|
-
*/ function createUnsupportedTokenError(token, chain) {
|
|
863
|
-
const errorDetails = {
|
|
864
|
-
...InputError.UNSUPPORTED_TOKEN,
|
|
865
|
-
recoverability: 'FATAL',
|
|
866
|
-
message: `${token} is not supported on ${chain}.`,
|
|
867
|
-
cause: {
|
|
868
|
-
trace: {
|
|
869
|
-
token,
|
|
870
|
-
chain
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
return new KitError(errorDetails);
|
|
875
|
-
}
|
|
876
846
|
/**
|
|
877
847
|
* Creates error for invalid chain configuration.
|
|
878
848
|
*
|
|
@@ -1799,7 +1769,7 @@ class KitError extends Error {
|
|
|
1799
1769
|
*
|
|
1800
1770
|
* Error code ranges:
|
|
1801
1771
|
* - 1100-1105: INPUT errors — invalid inputs, unsupported configurations
|
|
1802
|
-
* - 8100-
|
|
1772
|
+
* - 8100-8105: SERVICE errors — retryable backend/provider failures
|
|
1803
1773
|
*
|
|
1804
1774
|
* @example
|
|
1805
1775
|
* ```typescript
|
|
@@ -1875,6 +1845,11 @@ class KitError extends Error {
|
|
|
1875
1845
|
code: 8104,
|
|
1876
1846
|
name: 'EARN_PAUSED',
|
|
1877
1847
|
type: 'SERVICE'
|
|
1848
|
+
},
|
|
1849
|
+
/** Position PnL is still reconciling and can be retried. */ POSITION_PNL_PENDING: {
|
|
1850
|
+
code: 8105,
|
|
1851
|
+
name: 'EARN_POSITION_PNL_PENDING',
|
|
1852
|
+
type: 'SERVICE'
|
|
1878
1853
|
}
|
|
1879
1854
|
};
|
|
1880
1855
|
|
|
@@ -1898,11 +1873,11 @@ function getOptionalString(value) {
|
|
|
1898
1873
|
* - vault-not-found, unsupported-chain, unsupported-vault,
|
|
1899
1874
|
* signature-rejected, invalid-id, invalid-batch-size, position-not-registered,
|
|
1900
1875
|
* withdrawal-max-exceeded, insufficient-balance, bridge prepare idempotency
|
|
1901
|
-
* conflicts
|
|
1876
|
+
* conflicts, invalid vault-asset amount precision
|
|
1902
1877
|
*
|
|
1903
1878
|
* SERVICE errors (RETRYABLE) — try again later:
|
|
1904
1879
|
* - signing-failed, provider-error, rewards-fetch-failed,
|
|
1905
|
-
* internal-error, vault-refresh-busy, off-chain-paused,
|
|
1880
|
+
* internal-error, vault-refresh-busy, off-chain-paused, position-PnL-pending,
|
|
1906
1881
|
* bridge failures/status lookup failures
|
|
1907
1882
|
*
|
|
1908
1883
|
* Unrecognized codes fall through to `parseApiError` for HTTP-status-based
|
|
@@ -2082,6 +2057,20 @@ function getOptionalString(value) {
|
|
|
2082
2057
|
recoverability: 'RETRYABLE'
|
|
2083
2058
|
}
|
|
2084
2059
|
],
|
|
2060
|
+
[
|
|
2061
|
+
380415,
|
|
2062
|
+
{
|
|
2063
|
+
errorDef: EarnError.INVALID_INPUT,
|
|
2064
|
+
recoverability: 'FATAL'
|
|
2065
|
+
}
|
|
2066
|
+
],
|
|
2067
|
+
[
|
|
2068
|
+
380416,
|
|
2069
|
+
{
|
|
2070
|
+
errorDef: EarnError.POSITION_PNL_PENDING,
|
|
2071
|
+
recoverability: 'RETRYABLE'
|
|
2072
|
+
}
|
|
2073
|
+
],
|
|
2085
2074
|
// Bridge (380_5XX)
|
|
2086
2075
|
[
|
|
2087
2076
|
380500,
|
|
@@ -2117,6 +2106,13 @@ function getOptionalString(value) {
|
|
|
2117
2106
|
errorDef: EarnError.PROVIDER_ERROR,
|
|
2118
2107
|
recoverability: 'RETRYABLE'
|
|
2119
2108
|
}
|
|
2109
|
+
],
|
|
2110
|
+
[
|
|
2111
|
+
380505,
|
|
2112
|
+
{
|
|
2113
|
+
errorDef: EarnError.PROVIDER_ERROR,
|
|
2114
|
+
recoverability: 'FATAL'
|
|
2115
|
+
}
|
|
2120
2116
|
]
|
|
2121
2117
|
]);
|
|
2122
2118
|
/**
|
|
@@ -2219,6 +2215,8 @@ function getOptionalString(value) {
|
|
|
2219
2215
|
Blockchain["Celo_Alfajores_Testnet"] = "Celo_Alfajores_Testnet";
|
|
2220
2216
|
Blockchain["Codex"] = "Codex";
|
|
2221
2217
|
Blockchain["Codex_Testnet"] = "Codex_Testnet";
|
|
2218
|
+
Blockchain["Cronos"] = "Cronos";
|
|
2219
|
+
Blockchain["Cronos_Testnet"] = "Cronos_Testnet";
|
|
2222
2220
|
Blockchain["Edge"] = "Edge";
|
|
2223
2221
|
Blockchain["Edge_Testnet"] = "Edge_Testnet";
|
|
2224
2222
|
Blockchain["Ethereum"] = "Ethereum";
|
|
@@ -2301,6 +2299,7 @@ var BridgeChain;
|
|
|
2301
2299
|
BridgeChain["Avalanche"] = "Avalanche";
|
|
2302
2300
|
BridgeChain["Base"] = "Base";
|
|
2303
2301
|
BridgeChain["Codex"] = "Codex";
|
|
2302
|
+
BridgeChain["Cronos"] = "Cronos";
|
|
2304
2303
|
BridgeChain["Edge"] = "Edge";
|
|
2305
2304
|
BridgeChain["Ethereum"] = "Ethereum";
|
|
2306
2305
|
BridgeChain["HyperEVM"] = "HyperEVM";
|
|
@@ -2325,6 +2324,7 @@ var BridgeChain;
|
|
|
2325
2324
|
BridgeChain["Avalanche_Fuji"] = "Avalanche_Fuji";
|
|
2326
2325
|
BridgeChain["Base_Sepolia"] = "Base_Sepolia";
|
|
2327
2326
|
BridgeChain["Codex_Testnet"] = "Codex_Testnet";
|
|
2327
|
+
BridgeChain["Cronos_Testnet"] = "Cronos_Testnet";
|
|
2328
2328
|
BridgeChain["Edge_Testnet"] = "Edge_Testnet";
|
|
2329
2329
|
BridgeChain["Ethereum_Sepolia"] = "Ethereum_Sepolia";
|
|
2330
2330
|
BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
|
|
@@ -2576,23 +2576,6 @@ var EarnChain;
|
|
|
2576
2576
|
}
|
|
2577
2577
|
});
|
|
2578
2578
|
|
|
2579
|
-
/**
|
|
2580
|
-
* Standard decimal places for tokens.
|
|
2581
|
-
*
|
|
2582
|
-
* These constants define the decimal precision used by different token types
|
|
2583
|
-
* across the SDK. They are used for amount conversions between human-readable
|
|
2584
|
-
* format and smallest units (base units).
|
|
2585
|
-
*
|
|
2586
|
-
* @remarks
|
|
2587
|
-
* - Most stablecoins (USDC, EURC, USDT, PYUSD) use 6 decimal places
|
|
2588
|
-
* - Some stablecoins (DAI, USDE) and most native tokens (ETH, POL, PLUME) use 18 decimals
|
|
2589
|
-
* - The NATIVE alias uses chain-specific decimals which may vary (e.g., SOL uses 9)
|
|
2590
|
-
*/ /**
|
|
2591
|
-
* Standard decimal places for 6-decimal tokens.
|
|
2592
|
-
*
|
|
2593
|
-
* Used by most stablecoins: USDC, EURC, USDT, PYUSD
|
|
2594
|
-
*/ const TOKEN_DECIMALS_6 = 6;
|
|
2595
|
-
|
|
2596
2579
|
/**
|
|
2597
2580
|
* @packageDocumentation
|
|
2598
2581
|
* @module SwapTokenRegistry
|
|
@@ -3387,6 +3370,96 @@ var EarnChain;
|
|
|
3387
3370
|
}
|
|
3388
3371
|
});
|
|
3389
3372
|
|
|
3373
|
+
/**
|
|
3374
|
+
* Cronos Mainnet chain definition
|
|
3375
|
+
* @remarks
|
|
3376
|
+
* This represents the official production network for the Cronos blockchain.
|
|
3377
|
+
* Cronos is an EVM-compatible blockchain.
|
|
3378
|
+
*/ const Cronos = defineChain({
|
|
3379
|
+
type: 'evm',
|
|
3380
|
+
chain: Blockchain.Cronos,
|
|
3381
|
+
name: 'Cronos',
|
|
3382
|
+
title: 'Cronos Mainnet',
|
|
3383
|
+
nativeCurrency: {
|
|
3384
|
+
name: 'Cronos',
|
|
3385
|
+
symbol: 'CRO',
|
|
3386
|
+
decimals: 18
|
|
3387
|
+
},
|
|
3388
|
+
chainId: 25,
|
|
3389
|
+
isTestnet: false,
|
|
3390
|
+
explorerUrl: 'https://cronoscan.com/tx/{hash}',
|
|
3391
|
+
rpcEndpoints: [
|
|
3392
|
+
'https://evm.cronos.org'
|
|
3393
|
+
],
|
|
3394
|
+
eurcAddress: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
|
|
3395
|
+
usdcAddress: '0x3D7F2C478aAfdB65542BCB44bCeeC05849999d2D',
|
|
3396
|
+
usdtAddress: null,
|
|
3397
|
+
cctp: {
|
|
3398
|
+
domain: 32,
|
|
3399
|
+
contracts: {
|
|
3400
|
+
v2: {
|
|
3401
|
+
type: 'split',
|
|
3402
|
+
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3403
|
+
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3404
|
+
confirmations: 1,
|
|
3405
|
+
fastConfirmations: 1
|
|
3406
|
+
}
|
|
3407
|
+
},
|
|
3408
|
+
forwarderSupported: {
|
|
3409
|
+
source: false,
|
|
3410
|
+
destination: false
|
|
3411
|
+
}
|
|
3412
|
+
},
|
|
3413
|
+
kitContracts: {
|
|
3414
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
3415
|
+
}
|
|
3416
|
+
});
|
|
3417
|
+
|
|
3418
|
+
/**
|
|
3419
|
+
* Cronos Testnet chain definition
|
|
3420
|
+
* @remarks
|
|
3421
|
+
* This represents the official test network for the Cronos blockchain.
|
|
3422
|
+
* Cronos is an EVM-compatible blockchain.
|
|
3423
|
+
*/ const CronosTestnet = defineChain({
|
|
3424
|
+
type: 'evm',
|
|
3425
|
+
chain: Blockchain.Cronos_Testnet,
|
|
3426
|
+
name: 'Cronos Testnet',
|
|
3427
|
+
title: 'Cronos Testnet',
|
|
3428
|
+
nativeCurrency: {
|
|
3429
|
+
name: 'CRO',
|
|
3430
|
+
symbol: 'tCRO',
|
|
3431
|
+
decimals: 18
|
|
3432
|
+
},
|
|
3433
|
+
chainId: 338,
|
|
3434
|
+
isTestnet: true,
|
|
3435
|
+
explorerUrl: 'https://explorer.cronos.org/testnet/tx/{hash}',
|
|
3436
|
+
rpcEndpoints: [
|
|
3437
|
+
'https://evm-t3.cronos.org'
|
|
3438
|
+
],
|
|
3439
|
+
eurcAddress: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
|
|
3440
|
+
usdcAddress: '0xEb33dc5fac03833e132593659e1dE7256aB59794',
|
|
3441
|
+
usdtAddress: null,
|
|
3442
|
+
cctp: {
|
|
3443
|
+
domain: 32,
|
|
3444
|
+
contracts: {
|
|
3445
|
+
v2: {
|
|
3446
|
+
type: 'split',
|
|
3447
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
3448
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
3449
|
+
confirmations: 1,
|
|
3450
|
+
fastConfirmations: 1
|
|
3451
|
+
}
|
|
3452
|
+
},
|
|
3453
|
+
forwarderSupported: {
|
|
3454
|
+
source: false,
|
|
3455
|
+
destination: false
|
|
3456
|
+
}
|
|
3457
|
+
},
|
|
3458
|
+
kitContracts: {
|
|
3459
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET
|
|
3460
|
+
}
|
|
3461
|
+
});
|
|
3462
|
+
|
|
3390
3463
|
/**
|
|
3391
3464
|
* Edge Mainnet chain definition
|
|
3392
3465
|
* @remarks
|
|
@@ -5738,6 +5811,8 @@ var Chains = {
|
|
|
5738
5811
|
CeloAlfajoresTestnet: CeloAlfajoresTestnet,
|
|
5739
5812
|
Codex: Codex,
|
|
5740
5813
|
CodexTestnet: CodexTestnet,
|
|
5814
|
+
Cronos: Cronos,
|
|
5815
|
+
CronosTestnet: CronosTestnet,
|
|
5741
5816
|
Edge: Edge,
|
|
5742
5817
|
EdgeTestnet: EdgeTestnet,
|
|
5743
5818
|
Ethereum: Ethereum,
|
|
@@ -7169,6 +7244,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7169
7244
|
[Blockchain.Base]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
7170
7245
|
[Blockchain.Celo]: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',
|
|
7171
7246
|
[Blockchain.Codex]: '0xd996633a415985DBd7D6D12f4A4343E31f5037cf',
|
|
7247
|
+
[Blockchain.Cronos]: '0x3D7F2C478aAfdB65542BCB44bCeeC05849999d2D',
|
|
7172
7248
|
[Blockchain.Edge]: '0x98d2919b9A214E6Fa5384AC81E6864bA686Ad74c',
|
|
7173
7249
|
[Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
7174
7250
|
[Blockchain.Hedera]: '0.0.456858',
|
|
@@ -7202,6 +7278,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7202
7278
|
[Blockchain.Avalanche_Fuji]: '0x5425890298aed601595a70AB815c96711a31Bc65',
|
|
7203
7279
|
[Blockchain.Base_Sepolia]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
7204
7280
|
[Blockchain.Codex_Testnet]: '0x6d7f141b6819C2c9CC2f818e6ad549E7Ca090F8f',
|
|
7281
|
+
[Blockchain.Cronos_Testnet]: '0xEb33dc5fac03833e132593659e1dE7256aB59794',
|
|
7205
7282
|
[Blockchain.Edge_Testnet]: '0x2d9F7CAD728051AA35Ecdc472a14cf8cDF5CFD6B',
|
|
7206
7283
|
[Blockchain.Ethereum_Sepolia]: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
|
|
7207
7284
|
[Blockchain.Hedera_Testnet]: '0.0.429274',
|
|
@@ -7269,13 +7346,22 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7269
7346
|
symbol: 'EURC',
|
|
7270
7347
|
decimals: 6,
|
|
7271
7348
|
locators: {
|
|
7349
|
+
// =========================================================================
|
|
7350
|
+
// Mainnets
|
|
7351
|
+
// =========================================================================
|
|
7272
7352
|
[Blockchain.Avalanche]: '0xc891EB4cbdEFf6e073e859e987815Ed1505c2ACD',
|
|
7273
7353
|
[Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
7354
|
+
[Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
|
|
7274
7355
|
[Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
|
|
7275
7356
|
[Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
|
|
7276
7357
|
[Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
|
|
7358
|
+
// =========================================================================
|
|
7277
7359
|
// Testnets
|
|
7278
|
-
|
|
7360
|
+
// =========================================================================
|
|
7361
|
+
[Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
7362
|
+
[Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
|
|
7363
|
+
[Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
|
|
7364
|
+
[Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
|
|
7279
7365
|
}
|
|
7280
7366
|
};
|
|
7281
7367
|
|
|
@@ -7485,8 +7571,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7485
7571
|
* cirBTC (Circle Bitcoin) token definition with addresses and metadata.
|
|
7486
7572
|
*
|
|
7487
7573
|
* @remarks
|
|
7488
|
-
* Built-in cirBTC definition for the TokenRegistry.
|
|
7489
|
-
* on Arc Testnet.
|
|
7574
|
+
* Built-in cirBTC definition for the TokenRegistry.
|
|
7490
7575
|
*
|
|
7491
7576
|
* @example
|
|
7492
7577
|
* ```typescript
|
|
@@ -7502,7 +7587,15 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7502
7587
|
symbol: 'cirBTC',
|
|
7503
7588
|
decimals: 8,
|
|
7504
7589
|
locators: {
|
|
7505
|
-
|
|
7590
|
+
// =========================================================================
|
|
7591
|
+
// Mainnets
|
|
7592
|
+
// =========================================================================
|
|
7593
|
+
[Blockchain.Ethereum]: '0x72DFB2E44f59C5AD2bAFE84314E5b99a7cd5075E',
|
|
7594
|
+
// =========================================================================
|
|
7595
|
+
// Testnets
|
|
7596
|
+
// =========================================================================
|
|
7597
|
+
[Blockchain.Arc_Testnet]: '0xf0C4a4CE82A5746AbAAd9425360Ab04fbBA432BF',
|
|
7598
|
+
[Blockchain.Ethereum_Sepolia]: '0x3a3fe695F684Bf9b9e43CF43C2b895Ea5e392bB3'
|
|
7506
7599
|
}
|
|
7507
7600
|
};
|
|
7508
7601
|
|
|
@@ -7941,11 +8034,11 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7941
8034
|
return pkgName.replace('@circle-fin/', '');
|
|
7942
8035
|
}
|
|
7943
8036
|
|
|
7944
|
-
var name$
|
|
7945
|
-
var version$
|
|
7946
|
-
var pkg$
|
|
7947
|
-
name: name$
|
|
7948
|
-
version: version$
|
|
8037
|
+
var name$3 = "@circle-fin/bridge-kit";
|
|
8038
|
+
var version$3 = "1.12.0";
|
|
8039
|
+
var pkg$3 = {
|
|
8040
|
+
name: name$3,
|
|
8041
|
+
version: version$3};
|
|
7949
8042
|
|
|
7950
8043
|
/**
|
|
7951
8044
|
* Schema for validating BridgeKit custom fee policy.
|
|
@@ -8793,16 +8886,16 @@ var TransferSpeed;
|
|
|
8793
8886
|
* @internal
|
|
8794
8887
|
*/ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
|
|
8795
8888
|
|
|
8796
|
-
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$
|
|
8889
|
+
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$3.name);
|
|
8797
8890
|
|
|
8798
8891
|
// Auto-register this kit for user agent tracking
|
|
8799
|
-
registerKit(`${pkg$
|
|
8892
|
+
registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
8800
8893
|
|
|
8801
|
-
var name$
|
|
8802
|
-
var version$
|
|
8803
|
-
var pkg$
|
|
8804
|
-
name: name$
|
|
8805
|
-
version: version$
|
|
8894
|
+
var name$2 = "@circle-fin/swap-kit";
|
|
8895
|
+
var version$2 = "1.3.2";
|
|
8896
|
+
var pkg$2 = {
|
|
8897
|
+
name: name$2,
|
|
8898
|
+
version: version$2};
|
|
8806
8899
|
|
|
8807
8900
|
const chainIdentifierField = zod.z.custom((value)=>chainIdentifierSchema.safeParse(value).success, {
|
|
8808
8901
|
message: 'chain must be a valid chain identifier'
|
|
@@ -12087,17 +12180,20 @@ new Set(Object.values(Blockchain));
|
|
|
12087
12180
|
|
|
12088
12181
|
new Set(Object.values(Blockchain));
|
|
12089
12182
|
|
|
12090
|
-
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$
|
|
12183
|
+
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$2.name);
|
|
12091
12184
|
|
|
12092
12185
|
// Auto-register this kit for user agent tracking
|
|
12093
|
-
registerKit(`${pkg$
|
|
12186
|
+
registerKit(`${pkg$2.name}/${pkg$2.version}`);
|
|
12094
12187
|
|
|
12095
|
-
var name = "@circle-fin/earn-kit";
|
|
12096
|
-
var version = "1.2.
|
|
12097
|
-
var pkg = {
|
|
12098
|
-
name: name,
|
|
12099
|
-
version: version};
|
|
12188
|
+
var name$1 = "@circle-fin/earn-kit";
|
|
12189
|
+
var version$1 = "1.2.2";
|
|
12190
|
+
var pkg$1 = {
|
|
12191
|
+
name: name$1,
|
|
12192
|
+
version: version$1};
|
|
12100
12193
|
|
|
12194
|
+
const EARN_BRIDGE_ERC3009_TOKEN_SYMBOLS = [
|
|
12195
|
+
'USDC'
|
|
12196
|
+
];
|
|
12101
12197
|
/**
|
|
12102
12198
|
* Default base URL for the Earn Service API.
|
|
12103
12199
|
*
|
|
@@ -12142,20 +12238,7 @@ var pkg = {
|
|
|
12142
12238
|
*/ const EARN_BRIDGE_DESTINATION_CHAIN_TO_API = {
|
|
12143
12239
|
[Blockchain.Arc_Testnet]: CHAIN_TO_API[Blockchain.Arc_Testnet]
|
|
12144
12240
|
};
|
|
12145
|
-
|
|
12146
|
-
* Expected EIP-712 domain of the ERC-3009 authorization token per source
|
|
12147
|
-
* chain.
|
|
12148
|
-
*
|
|
12149
|
-
* Cross-chain Earn deposits are USDC-only, but USDC deployments differ on the
|
|
12150
|
-
* EIP-712 domain name: newer deployments use `USDC` while older ones (for
|
|
12151
|
-
* example Arbitrum Sepolia) kept `USD Coin` from the FiatToken V2 upgrade.
|
|
12152
|
-
* These values mirror the bridge service's per-chain domain table and the
|
|
12153
|
-
* on-chain `DOMAIN_SEPARATOR` inputs. Asserted before signing so a tampered
|
|
12154
|
-
* prepare response cannot point the signature at another token. The
|
|
12155
|
-
* `satisfies` check forces a domain entry whenever a source chain is added.
|
|
12156
|
-
*
|
|
12157
|
-
* @internal
|
|
12158
|
-
*/ const EARN_BRIDGE_ERC3009_DOMAINS = {
|
|
12241
|
+
const EARN_BRIDGE_USDC_ERC3009_DOMAINS = {
|
|
12159
12242
|
[Blockchain.Arbitrum_Sepolia]: {
|
|
12160
12243
|
name: 'USD Coin',
|
|
12161
12244
|
version: '2'
|
|
@@ -12169,6 +12252,21 @@ var pkg = {
|
|
|
12169
12252
|
version: '2'
|
|
12170
12253
|
}
|
|
12171
12254
|
};
|
|
12255
|
+
/**
|
|
12256
|
+
* Expected EIP-712 domain of the ERC-3009 authorization token per
|
|
12257
|
+
* cross-chain-supported source token and source chain.
|
|
12258
|
+
*
|
|
12259
|
+
* The bridge service prepares an ERC-3009 payload for the deposited token. We
|
|
12260
|
+
* keep this table as an explicit SDK allowlist because token deployments can
|
|
12261
|
+
* differ by source chain and by domain name/version. These values mirror the
|
|
12262
|
+
* bridge service's per-chain domain table and the on-chain DOMAIN_SEPARATOR
|
|
12263
|
+
* inputs. Asserted before signing so a tampered prepare response cannot point
|
|
12264
|
+
* the signature at another token or unexpected token domain.
|
|
12265
|
+
*
|
|
12266
|
+
* @internal
|
|
12267
|
+
*/ const EARN_BRIDGE_ERC3009_DOMAINS = {
|
|
12268
|
+
USDC: EARN_BRIDGE_USDC_ERC3009_DOMAINS
|
|
12269
|
+
};
|
|
12172
12270
|
/**
|
|
12173
12271
|
* Maximum tolerated remaining lifetime of a prepared ERC-3009 authorization.
|
|
12174
12272
|
*
|
|
@@ -12628,6 +12726,16 @@ const GAS_SAFETY_MULTIPLIER_DENOMINATOR = 10n;
|
|
|
12628
12726
|
return approvalTxHash;
|
|
12629
12727
|
}
|
|
12630
12728
|
|
|
12729
|
+
/** @internal */ function isSameAddress(actual, expected) {
|
|
12730
|
+
return actual.toLowerCase() === expected.toLowerCase();
|
|
12731
|
+
}
|
|
12732
|
+
/** @internal */ function assertDecimalPlaces(field, value, tokenDecimals, reason) {
|
|
12733
|
+
const decimals = value.split('.')[1]?.length ?? 0;
|
|
12734
|
+
if (decimals > tokenDecimals) {
|
|
12735
|
+
throw createValidationFailedError(field, value, reason);
|
|
12736
|
+
}
|
|
12737
|
+
}
|
|
12738
|
+
|
|
12631
12739
|
/**
|
|
12632
12740
|
* Build the `tokenInputs` array forwarded to the adapter contract's
|
|
12633
12741
|
* `execute(executeParams, tokenInputs, signature)` call.
|
|
@@ -12651,15 +12759,17 @@ const GAS_SAFETY_MULTIPLIER_DENOMINATOR = 10n;
|
|
|
12651
12759
|
*
|
|
12652
12760
|
* @example
|
|
12653
12761
|
* ```typescript
|
|
12654
|
-
* const
|
|
12655
|
-
* 'chain.usdcAddress',
|
|
12656
|
-
* chain.usdcAddress,
|
|
12657
|
-
* )
|
|
12658
|
-
*
|
|
12659
|
-
* const tokenInputs = buildEarnTokenInputs(
|
|
12762
|
+
* const approvalToken = resolveEarnApprovalToken(
|
|
12660
12763
|
* executionPayload.executionParams,
|
|
12661
|
-
* approvedToken,
|
|
12662
12764
|
* )
|
|
12765
|
+
*
|
|
12766
|
+
* const tokenInputs =
|
|
12767
|
+
* approvalToken === undefined
|
|
12768
|
+
* ? []
|
|
12769
|
+
* : buildEarnTokenInputs(
|
|
12770
|
+
* executionPayload.executionParams,
|
|
12771
|
+
* approvalToken,
|
|
12772
|
+
* )
|
|
12663
12773
|
* ```
|
|
12664
12774
|
*
|
|
12665
12775
|
* @internal
|
|
@@ -12671,7 +12781,7 @@ const GAS_SAFETY_MULTIPLIER_DENOMINATOR = 10n;
|
|
|
12671
12781
|
return;
|
|
12672
12782
|
}
|
|
12673
12783
|
const { tokenIn } = instruction;
|
|
12674
|
-
if (tokenIn
|
|
12784
|
+
if (!isSameAddress(tokenIn, approvedToken)) {
|
|
12675
12785
|
throw createValidationFailedError(`executionParams.instructions[${index.toString()}].tokenIn`, tokenIn, 'tokenIn must match the token approved for adapter spending');
|
|
12676
12786
|
}
|
|
12677
12787
|
tokenInputs.push({
|
|
@@ -12683,6 +12793,33 @@ const GAS_SAFETY_MULTIPLIER_DENOMINATOR = 10n;
|
|
|
12683
12793
|
});
|
|
12684
12794
|
return tokenInputs;
|
|
12685
12795
|
}
|
|
12796
|
+
/**
|
|
12797
|
+
* Resolve the single token that needs adapter allowance from signed Earn
|
|
12798
|
+
* instructions.
|
|
12799
|
+
*
|
|
12800
|
+
* @param executionParams - Service-signed `ExecutionParams` forwarded to the adapter.
|
|
12801
|
+
* @returns The token requested by positive approval instructions, or `undefined`.
|
|
12802
|
+
* @throws {@link KitError} If positive approval instructions reference multiple tokens.
|
|
12803
|
+
*
|
|
12804
|
+
* @internal
|
|
12805
|
+
*/ function resolveEarnApprovalToken(executionParams) {
|
|
12806
|
+
let approvedToken;
|
|
12807
|
+
executionParams.instructions.forEach((instruction, index)=>{
|
|
12808
|
+
const amount = BigInt(instruction.amountToApprove);
|
|
12809
|
+
if (amount <= 0n) {
|
|
12810
|
+
return;
|
|
12811
|
+
}
|
|
12812
|
+
const { tokenIn } = instruction;
|
|
12813
|
+
if (approvedToken === undefined) {
|
|
12814
|
+
approvedToken = tokenIn;
|
|
12815
|
+
return;
|
|
12816
|
+
}
|
|
12817
|
+
if (!isSameAddress(tokenIn, approvedToken)) {
|
|
12818
|
+
throw createValidationFailedError(`executionParams.instructions[${index.toString()}].tokenIn`, tokenIn, 'tokenIn must match the token approved for adapter spending');
|
|
12819
|
+
}
|
|
12820
|
+
});
|
|
12821
|
+
return approvedToken;
|
|
12822
|
+
}
|
|
12686
12823
|
|
|
12687
12824
|
/**
|
|
12688
12825
|
* Prepare an earn adapter action, execute it, wait for confirmation, and
|
|
@@ -13174,6 +13311,7 @@ const hexSignatureSchema = evmSignatureSchema;
|
|
|
13174
13311
|
const hexAddressSchema = evmAddressSchema;
|
|
13175
13312
|
// '0x' prefix + 32 bytes * 2 hex chars.
|
|
13176
13313
|
const BYTES32_HEX_LENGTH = 66;
|
|
13314
|
+
const bridgeFeeTokenSchema = hexAddressSchema;
|
|
13177
13315
|
/**
|
|
13178
13316
|
* Zod schema for a non-negative uint256-like value.
|
|
13179
13317
|
*
|
|
@@ -13460,14 +13598,12 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13460
13598
|
*
|
|
13461
13599
|
* The bridge prepare path returns one item per collected source fee (e.g.
|
|
13462
13600
|
* `PRE_FINALITY` for the fast-burn fee and `FORWARD` for the destination
|
|
13463
|
-
* forward fee), all denominated in the shared `feeToken`.
|
|
13464
|
-
*
|
|
13465
|
-
* guard parses these to recompute the expected value. Each item's `amount` is
|
|
13466
|
-
* a base-unit decimal string in `feeToken` units.
|
|
13601
|
+
* forward fee), all denominated in the shared `feeToken`. Each item's `amount`
|
|
13602
|
+
* is a base-unit decimal string in `feeToken` units.
|
|
13467
13603
|
*
|
|
13468
13604
|
* @internal
|
|
13469
13605
|
*/ const bridgeFeeQuoteSchema = zod.z.object({
|
|
13470
|
-
feeToken:
|
|
13606
|
+
feeToken: bridgeFeeTokenSchema,
|
|
13471
13607
|
items: zod.z.array(zod.z.object({
|
|
13472
13608
|
type: zod.z.string(),
|
|
13473
13609
|
amount: uint256LikeSchema
|
|
@@ -13483,6 +13619,12 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13483
13619
|
erc3009TypedData: erc3009TypedDataSchema,
|
|
13484
13620
|
feeQuote: bridgeFeeQuoteSchema
|
|
13485
13621
|
}).passthrough();
|
|
13622
|
+
const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
13623
|
+
sourceChain: zod.z.string(),
|
|
13624
|
+
destinationChain: zod.z.string(),
|
|
13625
|
+
amount: amountJsonSchema,
|
|
13626
|
+
vaultAddress: hexAddressSchema
|
|
13627
|
+
}).passthrough();
|
|
13486
13628
|
/**
|
|
13487
13629
|
* Zod schema for the bridge deposit prepare payload.
|
|
13488
13630
|
*
|
|
@@ -13494,7 +13636,7 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13494
13636
|
execId: bridgeDepositExecIdSchema,
|
|
13495
13637
|
erc3009TypedData: bridgeDepositPreparedBundleSchema,
|
|
13496
13638
|
expiresAt: zod.z.string().datetime(),
|
|
13497
|
-
review:
|
|
13639
|
+
review: bridgeDepositPrepareReviewSchema
|
|
13498
13640
|
});
|
|
13499
13641
|
/**
|
|
13500
13642
|
* Zod schema for the `POST /v1/earnKit/bridge/deposit/prepare` API response.
|
|
@@ -13619,10 +13761,11 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13619
13761
|
* Zod schema for a fee entry in an EarnKit API response.
|
|
13620
13762
|
*
|
|
13621
13763
|
* Shared across deposit and withdrawal responses (and reusable for real
|
|
13622
|
-
* charged fees, not just quote estimates). `type` identifies the fee category
|
|
13623
|
-
*
|
|
13624
|
-
* (e.g. `'FORWARD'`, `'PRE_FINALITY'`).
|
|
13625
|
-
* `'
|
|
13764
|
+
* charged fees, not just quote estimates). `type` identifies the fee category.
|
|
13765
|
+
* For cross-chain deposit quotes this is the kits-proxy fee-quote item type
|
|
13766
|
+
* (e.g. `'FORWARD'`, `'PRE_FINALITY'`). For withdrawal quotes, Circle fees use
|
|
13767
|
+
* `type: 'circle'`. `status` qualifies the fee (e.g. `'estimated'` for a
|
|
13768
|
+
* pre-sign cross-chain fee). Both are omitted on plain fees.
|
|
13626
13769
|
*
|
|
13627
13770
|
* @internal
|
|
13628
13771
|
*/ const feeSchema = zod.z.object({
|
|
@@ -13894,6 +14037,60 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13894
14037
|
return claimRewardsQuoteResponseSchema.safeParse(value).success;
|
|
13895
14038
|
}
|
|
13896
14039
|
|
|
14040
|
+
var name = "@circle-fin/provider-earn-service";
|
|
14041
|
+
var version = "1.2.2";
|
|
14042
|
+
var pkg = {
|
|
14043
|
+
name: name,
|
|
14044
|
+
version: version};
|
|
14045
|
+
|
|
14046
|
+
/**
|
|
14047
|
+
* HTTP header name used to report the EarnKit SDK version to the backend.
|
|
14048
|
+
*
|
|
14049
|
+
* @internal
|
|
14050
|
+
*/ const SDK_VERSION_HEADER = 'X-EarnKit-SDK-Version';
|
|
14051
|
+
/**
|
|
14052
|
+
* Resolve the SDK version string from its source components.
|
|
14053
|
+
*
|
|
14054
|
+
* Resolution order:
|
|
14055
|
+
* 1. The registered kit identifier (preferred) — e.g. `@circle-fin/earn-kit/1.1.0`
|
|
14056
|
+
* becomes `earn-kit/1.1.0`.
|
|
14057
|
+
* 2. The provider package itself (fallback when no kit is registered) —
|
|
14058
|
+
* e.g. `provider-earn-service/1.1.0`.
|
|
14059
|
+
* 3. The literal `unknown` when neither source is available.
|
|
14060
|
+
*
|
|
14061
|
+
* Kept as a pure function (no global / module reads) so every branch is
|
|
14062
|
+
* unit-testable.
|
|
14063
|
+
*
|
|
14064
|
+
* @param kitId - The registered kit identifier, or `undefined`.
|
|
14065
|
+
* @param providerName - The provider package name (e.g. `@circle-fin/provider-earn-service`).
|
|
14066
|
+
* @param providerVersion - The provider package version, or `undefined`.
|
|
14067
|
+
* @returns The formatted SDK version string.
|
|
14068
|
+
*
|
|
14069
|
+
* @internal
|
|
14070
|
+
*/ function formatSdkVersion(kitId, providerName, providerVersion) {
|
|
14071
|
+
if (kitId !== undefined && kitId !== '') {
|
|
14072
|
+
// e.g. '@circle-fin/earn-kit/1.1.0' -> 'earn-kit/1.1.0'
|
|
14073
|
+
return resolveKitSdkName(kitId);
|
|
14074
|
+
}
|
|
14075
|
+
{
|
|
14076
|
+
// e.g. '@circle-fin/provider-earn-service' + '1.1.0' -> 'provider-earn-service/1.1.0'
|
|
14077
|
+
return `${resolveKitSdkName(providerName)}/${providerVersion}`;
|
|
14078
|
+
}
|
|
14079
|
+
}
|
|
14080
|
+
/**
|
|
14081
|
+
* Resolve the value for the {@link SDK_VERSION_HEADER} header.
|
|
14082
|
+
*
|
|
14083
|
+
* Reads the kit registered at runtime via {@link createRequestContext} and
|
|
14084
|
+
* falls back to this provider package's own version when no kit is registered.
|
|
14085
|
+
*
|
|
14086
|
+
* @returns The SDK version string, e.g. `earn-kit/1.1.0` or
|
|
14087
|
+
* `provider-earn-service/1.1.0`, or `unknown`.
|
|
14088
|
+
*
|
|
14089
|
+
* @internal
|
|
14090
|
+
*/ function resolveSdkVersionHeader() {
|
|
14091
|
+
return formatSdkVersion(createRequestContext().kit, pkg.name, pkg.version);
|
|
14092
|
+
}
|
|
14093
|
+
|
|
13897
14094
|
/**
|
|
13898
14095
|
* Build an API polling config with optional authorization header,
|
|
13899
14096
|
* and resolve the base URL (configurable for testing).
|
|
@@ -13904,9 +14101,16 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13904
14101
|
* @internal
|
|
13905
14102
|
*/ function buildConfig(serviceConfig) {
|
|
13906
14103
|
const baseUrl = serviceConfig?.baseUrl ?? EARN_SERVICE_BASE_URL;
|
|
14104
|
+
const sdkVersion = resolveSdkVersionHeader();
|
|
13907
14105
|
if (serviceConfig?.kitKey === undefined) {
|
|
13908
14106
|
return {
|
|
13909
|
-
pollingConfig:
|
|
14107
|
+
pollingConfig: {
|
|
14108
|
+
...DEFAULT_CONFIG,
|
|
14109
|
+
headers: {
|
|
14110
|
+
...DEFAULT_CONFIG.headers,
|
|
14111
|
+
[SDK_VERSION_HEADER]: sdkVersion
|
|
14112
|
+
}
|
|
14113
|
+
},
|
|
13910
14114
|
baseUrl
|
|
13911
14115
|
};
|
|
13912
14116
|
}
|
|
@@ -13922,6 +14126,7 @@ const eip712DomainSchema = eip712DomainSchema$1.extend({
|
|
|
13922
14126
|
...DEFAULT_CONFIG,
|
|
13923
14127
|
headers: {
|
|
13924
14128
|
...DEFAULT_CONFIG.headers,
|
|
14129
|
+
[SDK_VERSION_HEADER]: sdkVersion,
|
|
13925
14130
|
Authorization: `Bearer ${serviceConfig.kitKey}`
|
|
13926
14131
|
}
|
|
13927
14132
|
},
|
|
@@ -14222,7 +14427,8 @@ function toPositionInfo(data) {
|
|
|
14222
14427
|
return {
|
|
14223
14428
|
execId: response.data.execId,
|
|
14224
14429
|
preparedBundle,
|
|
14225
|
-
expiresAt: response.data.expiresAt
|
|
14430
|
+
expiresAt: response.data.expiresAt,
|
|
14431
|
+
review: response.data.review
|
|
14226
14432
|
};
|
|
14227
14433
|
} catch (error) {
|
|
14228
14434
|
throw parseEarnApiError(error, {
|
|
@@ -14333,47 +14539,34 @@ const VALID_AFTER_CLOCK_SKEW_SECONDS = 60n;
|
|
|
14333
14539
|
* @throws If any typed-data field does not match the expected bridge deposit intent.
|
|
14334
14540
|
* @internal
|
|
14335
14541
|
*/ function assertBridgeDepositTypedDataMatchesIntent(intent) {
|
|
14336
|
-
const { preparedBundle, sourceChain, sourceAddress, sourceTokenAddress, authorizationRecipient, amount, maxFee, tokenDecimals, nowSeconds = BigInt(Math.floor(Date.now() / 1000)) } = intent;
|
|
14542
|
+
const { preparedBundle, sourceChain, sourceAddress, sourceTokenAddress, expectedDomain, authorizationRecipient, amount, maxFee, tokenDecimals, amountRaw, nowSeconds = BigInt(Math.floor(Date.now() / 1000)) } = intent;
|
|
14337
14543
|
const { domain, message } = preparedBundle.erc3009TypedData;
|
|
14338
|
-
// USDC deployments differ on the EIP-712 domain name per chain, so the
|
|
14339
|
-
// expected domain is looked up for the source chain being signed on.
|
|
14340
|
-
const expectedDomain = EARN_BRIDGE_ERC3009_DOMAINS[sourceChain.chain];
|
|
14341
|
-
if (expectedDomain === undefined) {
|
|
14342
|
-
throw createValidationFailedError('sourceChain.chain', sourceChain.chain, 'no expected ERC-3009 domain is configured for the source chain');
|
|
14343
|
-
}
|
|
14344
|
-
if (domain.name !== expectedDomain.name) {
|
|
14345
|
-
throw createValidationFailedError('preparedBundle.erc3009TypedData.domain.name', domain.name, `domain name must be ${expectedDomain.name}`);
|
|
14346
|
-
}
|
|
14347
|
-
if (domain.version !== expectedDomain.version) {
|
|
14348
|
-
throw createValidationFailedError('preparedBundle.erc3009TypedData.domain.version', domain.version, `domain version must be ${expectedDomain.version}`);
|
|
14349
|
-
}
|
|
14350
14544
|
assertSameAddress('preparedBundle.erc3009TypedData.domain.verifyingContract', domain.verifyingContract, sourceTokenAddress, 'verifyingContract must match the source token contract');
|
|
14351
14545
|
assertSameBigInt('preparedBundle.erc3009TypedData.domain.chainId', domain.chainId, BigInt(sourceChain.chainId), 'chainId must match the source chain');
|
|
14546
|
+
assertSameString('preparedBundle.erc3009TypedData.domain.name', domain.name, expectedDomain.name, 'domain name must match the source token');
|
|
14547
|
+
assertSameString('preparedBundle.erc3009TypedData.domain.version', domain.version, expectedDomain.version, 'domain version must match the source token');
|
|
14352
14548
|
assertSameAddress('preparedBundle.erc3009TypedData.message.from', message.from, sourceAddress, 'from must match the source wallet');
|
|
14353
14549
|
assertSameAddress('preparedBundle.erc3009TypedData.message.to', message.to, authorizationRecipient, 'to must match the configured authorization recipient');
|
|
14354
|
-
//
|
|
14355
|
-
//
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
// token to the source token contract before summing.
|
|
14359
|
-
assertSameAddress('preparedBundle.feeQuote.feeToken', preparedBundle.feeQuote.feeToken, sourceTokenAddress, 'feeQuote.feeToken must match the source token contract');
|
|
14360
|
-
// Recompute the expected value from locally trusted inputs (the caller
|
|
14361
|
-
// principal) plus the bundle's own fee items so the guard accepts fee-bearing
|
|
14362
|
-
// deposits while still rejecting any other value tampering. The fee quote is
|
|
14363
|
-
// service-supplied, so bound it to the caller-accepted quote-derived cap
|
|
14364
|
-
// before including it in the signed value.
|
|
14365
|
-
const principal = Amount.parse(amount, {
|
|
14550
|
+
// Recompute the expected ERC-3009 value from locally trusted inputs. Bridge
|
|
14551
|
+
// source fees are paid in the source ERC-20 and are part of the authorization.
|
|
14552
|
+
assertDecimalPlaces('amount', amount, tokenDecimals, `amount must have at most ${String(tokenDecimals)} decimal places for the cross-chain Earn deposit source token`);
|
|
14553
|
+
const parsedAmount = Amount.parse(amount, {
|
|
14366
14554
|
decimals: tokenDecimals
|
|
14367
14555
|
}).raw;
|
|
14556
|
+
const principal = amountRaw === undefined ? parsedAmount : parseReviewedAmount(amountRaw, parsedAmount);
|
|
14557
|
+
const feeQuote = preparedBundle.feeQuote;
|
|
14368
14558
|
const feeTotal = sumBridgeFeeItems(preparedBundle.feeQuote);
|
|
14559
|
+
assertFeeTokenMatchesSourceToken(feeQuote.feeToken, sourceTokenAddress);
|
|
14560
|
+
const feeDecimals = tokenDecimals;
|
|
14561
|
+
assertDecimalPlaces('maxFee', maxFee, feeDecimals, `maxFee must have at most ${String(feeDecimals)} decimal places for the cross-chain Earn deposit fee token`);
|
|
14369
14562
|
const maxFeeRaw = Amount.parse(maxFee, {
|
|
14370
|
-
decimals:
|
|
14563
|
+
decimals: feeDecimals
|
|
14371
14564
|
}).raw;
|
|
14372
14565
|
if (feeTotal > maxFeeRaw) {
|
|
14373
14566
|
throw createValidationFailedError('preparedBundle.feeQuote.items', feeTotal.toString(), 'fee total must not exceed maxFee in base units');
|
|
14374
14567
|
}
|
|
14375
14568
|
const expectedValue = principal + feeTotal;
|
|
14376
|
-
assertSameBigInt('preparedBundle.erc3009TypedData.message.value', message.value, expectedValue, 'value must match the requested amount plus
|
|
14569
|
+
assertSameBigInt('preparedBundle.erc3009TypedData.message.value', message.value, expectedValue, 'value must match the requested amount plus source-token fees in base units');
|
|
14377
14570
|
const window = checkErc3009ValidityWindow({
|
|
14378
14571
|
validAfter: BigInt(message.validAfter),
|
|
14379
14572
|
validBefore: BigInt(message.validBefore),
|
|
@@ -14447,14 +14640,19 @@ const VALID_AFTER_CLOCK_SKEW_SECONDS = 60n;
|
|
|
14447
14640
|
/**
|
|
14448
14641
|
* Sum the source-collected fee items in a prepared bundle's fee quote.
|
|
14449
14642
|
*
|
|
14450
|
-
* Each item amount is a base-unit value in the shared `feeToken
|
|
14451
|
-
* what the prepare path adds to the principal when building `message.value`.
|
|
14643
|
+
* Each item amount is a base-unit value in the shared `feeToken`.
|
|
14452
14644
|
*
|
|
14453
14645
|
* @param feeQuote - Fee quote parsed from the prepared bundle.
|
|
14454
|
-
* @returns Total fee in
|
|
14646
|
+
* @returns Total fee in fee-token base units (0n when there are no items).
|
|
14455
14647
|
*/ function sumBridgeFeeItems(feeQuote) {
|
|
14456
14648
|
return feeQuote.items.reduce((total, item)=>total + BigInt(item.amount), 0n);
|
|
14457
14649
|
}
|
|
14650
|
+
function assertFeeTokenMatchesSourceToken(feeToken, sourceTokenAddress) {
|
|
14651
|
+
if (isSameAddress(feeToken, sourceTokenAddress)) {
|
|
14652
|
+
return;
|
|
14653
|
+
}
|
|
14654
|
+
throw createValidationFailedError('preparedBundle.feeQuote.feeToken', feeToken, 'fee token must match the cross-chain Earn deposit source token');
|
|
14655
|
+
}
|
|
14458
14656
|
function assertNever(value) {
|
|
14459
14657
|
throw new KitError({
|
|
14460
14658
|
...EarnError.INTERNAL_ERROR,
|
|
@@ -14462,8 +14660,23 @@ function assertNever(value) {
|
|
|
14462
14660
|
message: `Unexpected validity window reason: ${String(value)}`
|
|
14463
14661
|
});
|
|
14464
14662
|
}
|
|
14663
|
+
function parseReviewedAmount(amountRaw, parsedAmount) {
|
|
14664
|
+
let reviewedAmount;
|
|
14665
|
+
try {
|
|
14666
|
+
reviewedAmount = BigInt(amountRaw);
|
|
14667
|
+
} catch {
|
|
14668
|
+
throw createValidationFailedError('prepared.review.amount.raw', amountRaw, 'amount must be a non-negative integer string');
|
|
14669
|
+
}
|
|
14670
|
+
if (reviewedAmount < 0n) {
|
|
14671
|
+
throw createValidationFailedError('prepared.review.amount.raw', amountRaw, 'amount must be a non-negative integer string');
|
|
14672
|
+
}
|
|
14673
|
+
if (reviewedAmount !== parsedAmount) {
|
|
14674
|
+
throw createValidationFailedError('prepared.review.amount.raw', amountRaw, 'review amount must match the requested amount');
|
|
14675
|
+
}
|
|
14676
|
+
return reviewedAmount;
|
|
14677
|
+
}
|
|
14465
14678
|
function assertSameAddress(field, actual, expected, reason) {
|
|
14466
|
-
if (actual
|
|
14679
|
+
if (!isSameAddress(actual, expected)) {
|
|
14467
14680
|
throw createValidationFailedError(field, actual, reason);
|
|
14468
14681
|
}
|
|
14469
14682
|
}
|
|
@@ -14472,6 +14685,11 @@ function assertSameBigInt(field, actual, expected, reason) {
|
|
|
14472
14685
|
throw createValidationFailedError(field, actual, reason);
|
|
14473
14686
|
}
|
|
14474
14687
|
}
|
|
14688
|
+
function assertSameString(field, actual, expected, reason) {
|
|
14689
|
+
if (actual !== expected) {
|
|
14690
|
+
throw createValidationFailedError(field, actual, reason);
|
|
14691
|
+
}
|
|
14692
|
+
}
|
|
14475
14693
|
|
|
14476
14694
|
/**
|
|
14477
14695
|
* Build signed withdrawal instructions via the Earn Service API.
|
|
@@ -14641,9 +14859,15 @@ function toWithdrawalQuoteInfo(data) {
|
|
|
14641
14859
|
symbol: data.asset,
|
|
14642
14860
|
amount: Amount.fromJSON(data.maxWithdrawable)
|
|
14643
14861
|
},
|
|
14644
|
-
fees: data.fees.map((
|
|
14645
|
-
symbol:
|
|
14646
|
-
amount: Amount.fromJSON(
|
|
14862
|
+
fees: data.fees.map(({ token, amount, type, status })=>({
|
|
14863
|
+
symbol: token,
|
|
14864
|
+
amount: Amount.fromJSON(amount),
|
|
14865
|
+
...type !== undefined && {
|
|
14866
|
+
type
|
|
14867
|
+
},
|
|
14868
|
+
...status !== undefined && {
|
|
14869
|
+
status
|
|
14870
|
+
}
|
|
14647
14871
|
})),
|
|
14648
14872
|
gasFees: [],
|
|
14649
14873
|
// Wire format uses `warnings`, but the SDK surface uses
|
|
@@ -14829,6 +15053,9 @@ function toWithdrawalQuoteInfo(data) {
|
|
|
14829
15053
|
'CONFIRMED',
|
|
14830
15054
|
'COMPLETE'
|
|
14831
15055
|
]);
|
|
15056
|
+
// Intentionally built-ins-only: Earn bridge support is limited to SDK-known
|
|
15057
|
+
// token contracts plus the explicit ERC-3009 domain allowlist below.
|
|
15058
|
+
const TOKEN_REGISTRY = createTokenRegistry();
|
|
14832
15059
|
/**
|
|
14833
15060
|
* Build the typed error raised when a cross-chain wait is cancelled via its
|
|
14834
15061
|
* `AbortSignal`. Mirrors `@core/adapter-base`'s `createAbortError` (same
|
|
@@ -15148,24 +15375,20 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15148
15375
|
}
|
|
15149
15376
|
const { address, chain: apiChain, chainDefinition: chain } = await resolveAdapterContext(params.from);
|
|
15150
15377
|
const adapterContractAddress = requireAdapterContract(chain);
|
|
15151
|
-
const rawUsdcAddress = chain.usdcAddress;
|
|
15152
|
-
if (rawUsdcAddress === null) {
|
|
15153
|
-
throw createUnsupportedTokenError('USDC', chain.name);
|
|
15154
|
-
}
|
|
15155
|
-
const usdcAddress = assertHexAddress('chain.usdcAddress', rawUsdcAddress, `USDC address for chain ${chain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15156
15378
|
const { adapter } = params.from;
|
|
15379
|
+
const vaultAddress = assertHexAddress('vaultAddress', params.vaultAddress, 'Vault address must be a 0x-prefixed 20-byte hex address.');
|
|
15157
15380
|
const { executionParams, signature } = await this.runPhase(ctx, 'deposit', 'fetchParams', async ()=>fetchDeposit({
|
|
15158
|
-
vaultAddress
|
|
15381
|
+
vaultAddress,
|
|
15159
15382
|
amount: params.amount,
|
|
15160
15383
|
address,
|
|
15161
15384
|
chain: apiChain,
|
|
15162
15385
|
config
|
|
15163
15386
|
}), ()=>undefined);
|
|
15164
15387
|
validateExecutionDeadline(executionParams);
|
|
15165
|
-
const
|
|
15166
|
-
const
|
|
15388
|
+
const approvalToken = resolveEarnApprovalToken(executionParams);
|
|
15389
|
+
const tokenInputs = approvalToken === undefined ? [] : buildEarnTokenInputs(executionParams, approvalToken);
|
|
15167
15390
|
const requiredAllowance = sumTokenInputAmounts(tokenInputs);
|
|
15168
|
-
if (!options.skipApprove && approvalToken !== undefined) {
|
|
15391
|
+
if (!options.skipApprove && approvalToken !== undefined && requiredAllowance > 0n) {
|
|
15169
15392
|
await this.runPhase(ctx, 'approve', 'approve', async ()=>approveAllowanceIfNeeded({
|
|
15170
15393
|
adapter,
|
|
15171
15394
|
chain,
|
|
@@ -15173,7 +15396,7 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15173
15396
|
delegate: adapterContractAddress,
|
|
15174
15397
|
address,
|
|
15175
15398
|
requiredAllowance,
|
|
15176
|
-
revertMessage: '
|
|
15399
|
+
revertMessage: 'Earn deposit token approval reverted on-chain'
|
|
15177
15400
|
}), (txHash)=>txHash);
|
|
15178
15401
|
}
|
|
15179
15402
|
const { txHash, explorerUrl } = await this.runPhase(ctx, 'deposit', 'execute', async ()=>executeEarnAction({
|
|
@@ -15192,7 +15415,7 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15192
15415
|
kind: 'same-chain',
|
|
15193
15416
|
txHash,
|
|
15194
15417
|
explorerUrl,
|
|
15195
|
-
vaultAddress
|
|
15418
|
+
vaultAddress,
|
|
15196
15419
|
amount: params.amount
|
|
15197
15420
|
};
|
|
15198
15421
|
} catch (error) {
|
|
@@ -15214,13 +15437,6 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15214
15437
|
const sourceAddress = assertHexAddress('from.address', await resolveCrossChainSourceAddress(params.from, sourceChain), `Source address for chain ${sourceChain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15215
15438
|
const destinationAddress = assertHexAddress('to.recipientAddress', params.to.recipientAddress, `Destination address for chain ${destinationChain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15216
15439
|
const vaultAddress = assertHexAddress('vaultAddress', params.vaultAddress, 'Vault address must be a 0x-prefixed 20-byte hex address.');
|
|
15217
|
-
// The signed ERC-3009 value is denominated in USDC's 6 decimals. More
|
|
15218
|
-
// precise inputs would be silently truncated by Amount.parse, so the
|
|
15219
|
-
// result would claim a larger deposit than was actually authorized.
|
|
15220
|
-
const amountDecimals = params.amount.split('.')[1]?.length ?? 0;
|
|
15221
|
-
if (amountDecimals > TOKEN_DECIMALS_6) {
|
|
15222
|
-
throw createValidationFailedError('amount', params.amount, `amount must have at most ${String(TOKEN_DECIMALS_6)} decimal places for cross-chain Earn deposits`);
|
|
15223
|
-
}
|
|
15224
15440
|
const execId = params.idempotencyKey;
|
|
15225
15441
|
const prepared = await this.runPhase(ctx, 'crossChainDeposit', 'prepare', async ()=>fetchBridgeDepositPrepare({
|
|
15226
15442
|
execId,
|
|
@@ -15240,17 +15456,19 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15240
15456
|
// the error trace, instead of ending the event stream unannounced
|
|
15241
15457
|
// after the prepare success event.
|
|
15242
15458
|
assertPreparedBundleMatchesTypedDataNonce(prepared.preparedBundle);
|
|
15459
|
+
const sourceToken = resolvePreparedBridgeSourceToken(prepared.preparedBundle, route.sourceChain);
|
|
15460
|
+
validatePreparedReviewAmountDecimals(prepared.review.amount.decimals, sourceToken.decimals);
|
|
15243
15461
|
assertBridgeDepositTypedDataMatchesIntent({
|
|
15244
15462
|
preparedBundle: prepared.preparedBundle,
|
|
15245
15463
|
sourceChain: route.sourceChain,
|
|
15246
15464
|
sourceAddress,
|
|
15247
|
-
sourceTokenAddress:
|
|
15465
|
+
sourceTokenAddress: sourceToken.address,
|
|
15466
|
+
expectedDomain: sourceToken.erc3009Domain,
|
|
15248
15467
|
authorizationRecipient: route.authorizationRecipient,
|
|
15249
15468
|
amount: params.amount,
|
|
15250
15469
|
maxFee: params.maxFee,
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
tokenDecimals: TOKEN_DECIMALS_6
|
|
15470
|
+
tokenDecimals: sourceToken.decimals,
|
|
15471
|
+
amountRaw: prepared.review.amount.raw
|
|
15254
15472
|
});
|
|
15255
15473
|
return signBridgeDepositAuthorization({
|
|
15256
15474
|
adapter: bridgeSigningAdapter,
|
|
@@ -15473,21 +15691,17 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15473
15691
|
const { adapter, chain, apiChain, address, vaultAddress, amount, config } = params;
|
|
15474
15692
|
try {
|
|
15475
15693
|
const adapterContractAddress = requireAdapterContract(chain);
|
|
15476
|
-
const
|
|
15477
|
-
if (rawUsdcAddress === null) {
|
|
15478
|
-
throw createUnsupportedTokenError('USDC', chain.name);
|
|
15479
|
-
}
|
|
15480
|
-
const usdcAddress = assertHexAddress('chain.usdcAddress', rawUsdcAddress, `USDC address for chain ${chain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15694
|
+
const normalizedVaultAddress = assertHexAddress('vaultAddress', vaultAddress, 'Vault address must be a 0x-prefixed 20-byte hex address.');
|
|
15481
15695
|
const { executionParams, signature } = await fetchDeposit({
|
|
15482
|
-
vaultAddress,
|
|
15696
|
+
vaultAddress: normalizedVaultAddress,
|
|
15483
15697
|
amount,
|
|
15484
15698
|
address,
|
|
15485
15699
|
chain: apiChain,
|
|
15486
15700
|
config
|
|
15487
15701
|
});
|
|
15488
15702
|
validateExecutionDeadline(executionParams);
|
|
15489
|
-
const
|
|
15490
|
-
const
|
|
15703
|
+
const approvalToken = resolveEarnApprovalToken(executionParams);
|
|
15704
|
+
const tokenInputs = approvalToken === undefined ? [] : buildEarnTokenInputs(executionParams, approvalToken);
|
|
15491
15705
|
const requiredAllowance = sumTokenInputAmounts(tokenInputs);
|
|
15492
15706
|
return await estimateEarnQuoteGasFees({
|
|
15493
15707
|
adapter,
|
|
@@ -15500,7 +15714,7 @@ function finishElapsedWait(lastStatus, lastError) {
|
|
|
15500
15714
|
tokenInputs,
|
|
15501
15715
|
signature
|
|
15502
15716
|
},
|
|
15503
|
-
approval: approvalToken !== undefined ? {
|
|
15717
|
+
approval: approvalToken !== undefined && requiredAllowance > 0n ? {
|
|
15504
15718
|
token: approvalToken,
|
|
15505
15719
|
delegate: adapterContractAddress,
|
|
15506
15720
|
requiredAllowance
|
|
@@ -15744,11 +15958,6 @@ function validateCrossChainDepositRoute(sourceChain, destinationChain) {
|
|
|
15744
15958
|
if (destinationApiChain === undefined) {
|
|
15745
15959
|
throw createUnsupportedCrossChainDepositError(destinationChain, 'destination chain is not enabled for cross-chain Earn deposits');
|
|
15746
15960
|
}
|
|
15747
|
-
const sourceTokenAddressRaw = sourceChain.usdcAddress;
|
|
15748
|
-
if (sourceTokenAddressRaw === null) {
|
|
15749
|
-
throw createUnsupportedTokenError('USDC', sourceChain.name);
|
|
15750
|
-
}
|
|
15751
|
-
const sourceTokenAddress = assertHexAddress('sourceChain.usdcAddress', sourceTokenAddressRaw, `USDC address for chain ${sourceChain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15752
15961
|
if (sourceChain.cctp == null) {
|
|
15753
15962
|
throw createBridgeRouteNotConfiguredError(sourceChain, 'source chain does not support CCTP');
|
|
15754
15963
|
}
|
|
@@ -15772,10 +15981,50 @@ function validateCrossChainDepositRoute(sourceChain, destinationChain) {
|
|
|
15772
15981
|
destinationApiChain,
|
|
15773
15982
|
destinationDomain: destinationChain.cctp.domain,
|
|
15774
15983
|
sourceChain,
|
|
15775
|
-
sourceTokenAddress,
|
|
15776
15984
|
authorizationRecipient
|
|
15777
15985
|
};
|
|
15778
15986
|
}
|
|
15987
|
+
function resolvePreparedBridgeSourceToken(preparedBundle, sourceChain) {
|
|
15988
|
+
const sourceTokenAddress = assertHexAddress('preparedBundle.erc3009TypedData.domain.verifyingContract', preparedBundle.erc3009TypedData.domain.verifyingContract, `Source token for chain ${sourceChain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15989
|
+
let sourceToken;
|
|
15990
|
+
try {
|
|
15991
|
+
sourceToken = TOKEN_REGISTRY.resolveByAddress(sourceTokenAddress, sourceChain.chain);
|
|
15992
|
+
} catch {
|
|
15993
|
+
throw createValidationFailedError('preparedBundle.erc3009TypedData.domain.verifyingContract', sourceTokenAddress, `source token ${sourceTokenAddress} is not configured on source chain ${sourceChain.name} for cross-chain Earn deposits`);
|
|
15994
|
+
}
|
|
15995
|
+
const registryAddress = assertHexAddress('sourceToken.locator', sourceToken.locator, `Source token ${sourceToken.symbol ?? sourceTokenAddress} for chain ${sourceChain.name} must be a 0x-prefixed 20-byte hex address.`);
|
|
15996
|
+
if (!isSameAddress(sourceTokenAddress, registryAddress)) {
|
|
15997
|
+
throw createValidationFailedError('preparedBundle.erc3009TypedData.domain.verifyingContract', sourceTokenAddress, `source token must match the configured ${sourceToken.symbol ?? 'token'} address on source chain ${sourceChain.name}`);
|
|
15998
|
+
}
|
|
15999
|
+
const { symbol } = sourceToken;
|
|
16000
|
+
if (symbol === undefined) {
|
|
16001
|
+
throw createValidationFailedError('preparedBundle.erc3009TypedData.domain.verifyingContract', sourceTokenAddress, `source token ${sourceTokenAddress} is not a registered Earn bridge token on source chain ${sourceChain.name}`);
|
|
16002
|
+
}
|
|
16003
|
+
return {
|
|
16004
|
+
address: sourceTokenAddress,
|
|
16005
|
+
erc3009Domain: resolveBridgeErc3009Domain(symbol, sourceChain),
|
|
16006
|
+
decimals: sourceToken.decimals
|
|
16007
|
+
};
|
|
16008
|
+
}
|
|
16009
|
+
function validatePreparedReviewAmountDecimals(reviewedDecimals, tokenDecimals) {
|
|
16010
|
+
if (reviewedDecimals !== tokenDecimals) {
|
|
16011
|
+
throw createValidationFailedError('prepared.review.amount.decimals', reviewedDecimals, `review amount decimals must match the cross-chain Earn deposit source token decimals ${String(tokenDecimals)}`);
|
|
16012
|
+
}
|
|
16013
|
+
}
|
|
16014
|
+
function resolveBridgeErc3009Domain(tokenSymbol, sourceChain) {
|
|
16015
|
+
if (!isEarnBridgeErc3009TokenSymbol(tokenSymbol)) {
|
|
16016
|
+
throw createValidationFailedError('sourceToken.symbol', tokenSymbol, `ERC-3009 domain is not configured for ${tokenSymbol} on source chain ${sourceChain.name}`);
|
|
16017
|
+
}
|
|
16018
|
+
const domainsByChain = EARN_BRIDGE_ERC3009_DOMAINS[tokenSymbol];
|
|
16019
|
+
const domain = domainsByChain[sourceChain.chain];
|
|
16020
|
+
if (domain === undefined) {
|
|
16021
|
+
throw createValidationFailedError('sourceToken.symbol', tokenSymbol, `ERC-3009 domain is not configured for ${tokenSymbol} on source chain ${sourceChain.name}`);
|
|
16022
|
+
}
|
|
16023
|
+
return domain;
|
|
16024
|
+
}
|
|
16025
|
+
function isEarnBridgeErc3009TokenSymbol(tokenSymbol) {
|
|
16026
|
+
return EARN_BRIDGE_ERC3009_TOKEN_SYMBOLS.includes(tokenSymbol);
|
|
16027
|
+
}
|
|
15779
16028
|
function createUnsupportedCrossChainDepositError(chain, reason) {
|
|
15780
16029
|
return new KitError({
|
|
15781
16030
|
...EarnError.UNSUPPORTED_CHAIN,
|
|
@@ -15848,7 +16097,6 @@ function createUnsupportedCrossChainDepositError(chain, reason) {
|
|
|
15848
16097
|
// Untyped callers can pass anything here; without these guards a null
|
|
15849
16098
|
// config crashes with a raw TypeError on `config.providers` instead of
|
|
15850
16099
|
// the structured validation error every other public surface throws.
|
|
15851
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- JS consumers may pass null or a non-object config
|
|
15852
16100
|
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
|
|
15853
16101
|
throw createValidationFailedError('config', config, 'config must be a plain object when provided');
|
|
15854
16102
|
}
|
|
@@ -16215,10 +16463,9 @@ const sourceAdapterContextSchema = zod.z.object({
|
|
|
16215
16463
|
* Schema for validating human-readable decimal amount strings.
|
|
16216
16464
|
*
|
|
16217
16465
|
* Accept positive decimal strings like '100', '100.50', '0.001'. Reject
|
|
16218
|
-
* zero, negative, non-numeric, and non-canonical strings.
|
|
16219
|
-
*
|
|
16220
|
-
*
|
|
16221
|
-
* 7+ decimal-place inputs to the server.
|
|
16466
|
+
* zero, negative, non-numeric, and non-canonical strings. Same-chain
|
|
16467
|
+
* EarnKit vaults can use different asset precisions, so the service enforces
|
|
16468
|
+
* the vault-specific decimal cap after resolving the vault asset.
|
|
16222
16469
|
*
|
|
16223
16470
|
* @internal
|
|
16224
16471
|
*/ const amountSchema = zod.z.string({
|
|
@@ -16227,32 +16474,15 @@ const sourceAdapterContextSchema = zod.z.object({
|
|
|
16227
16474
|
allowZero: false,
|
|
16228
16475
|
regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
|
|
16229
16476
|
attributeName: 'amount',
|
|
16230
|
-
maxDecimals:
|
|
16231
|
-
})(zod.z.string())).refine((value)=>CANONICAL_AMOUNT_REGEX.test(value), AMOUNT_FORMAT_ERROR_MESSAGE);
|
|
16232
|
-
/**
|
|
16233
|
-
* Schema for cross-chain deposit amount strings.
|
|
16234
|
-
*
|
|
16235
|
-
* Cross-chain Earn deposits are USDC-only, and the signed ERC-3009 value is
|
|
16236
|
-
* denominated in USDC's 6 decimals. Reject more precise inputs up front so
|
|
16237
|
-
* the signed value always equals the requested amount instead of a silent
|
|
16238
|
-
* truncation. Non-canonical forms (leading dot, leading zeros) are rejected
|
|
16239
|
-
* too, matching the Earn Service.
|
|
16240
|
-
*
|
|
16241
|
-
* @internal
|
|
16242
|
-
*/ const crossChainAmountSchema = zod.z.string({
|
|
16243
|
-
required_error: 'amount is required'
|
|
16244
|
-
}).min(1, 'amount is required').pipe(createDecimalStringValidator({
|
|
16245
|
-
allowZero: false,
|
|
16246
|
-
regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
|
|
16247
|
-
attributeName: 'amount',
|
|
16248
|
-
maxDecimals: 6
|
|
16477
|
+
maxDecimals: 18
|
|
16249
16478
|
})(zod.z.string())).refine((value)=>CANONICAL_AMOUNT_REGEX.test(value), AMOUNT_FORMAT_ERROR_MESSAGE);
|
|
16250
16479
|
/**
|
|
16251
16480
|
* Schema for cross-chain source fee caps.
|
|
16252
16481
|
*
|
|
16253
|
-
* Cross-chain source fees are denominated in
|
|
16254
|
-
* when the quote contains no source-collected fees; otherwise the cap
|
|
16255
|
-
* the caller-accepted total from a recent quote.
|
|
16482
|
+
* Cross-chain source fees are denominated in the quote's fee token. Zero is
|
|
16483
|
+
* valid when the quote contains no source-collected fees; otherwise the cap
|
|
16484
|
+
* should be the caller-accepted total from a recent quote. The provider
|
|
16485
|
+
* enforces the prepared bundle's fee-token precision before signing.
|
|
16256
16486
|
*
|
|
16257
16487
|
* @internal
|
|
16258
16488
|
*/ const crossChainMaxFeeSchema = zod.z.string({
|
|
@@ -16261,7 +16491,7 @@ const sourceAdapterContextSchema = zod.z.object({
|
|
|
16261
16491
|
allowZero: true,
|
|
16262
16492
|
regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
|
|
16263
16493
|
attributeName: 'maxFee',
|
|
16264
|
-
maxDecimals:
|
|
16494
|
+
maxDecimals: 18
|
|
16265
16495
|
})(zod.z.string())).refine((value)=>CANONICAL_AMOUNT_REGEX.test(value), AMOUNT_FORMAT_ERROR_MESSAGE);
|
|
16266
16496
|
/**
|
|
16267
16497
|
* Build a schema for an optional non-negative decimal filter string.
|
|
@@ -16422,7 +16652,7 @@ const crossChainDepositDestinationSchema = zod.z.object({
|
|
|
16422
16652
|
from: sourceAdapterContextSchema,
|
|
16423
16653
|
to: crossChainDepositDestinationSchema,
|
|
16424
16654
|
vaultAddress: vaultAddressSchema,
|
|
16425
|
-
amount:
|
|
16655
|
+
amount: amountSchema,
|
|
16426
16656
|
maxFee: crossChainMaxFeeSchema,
|
|
16427
16657
|
transferSpeed: zod.z.enum([
|
|
16428
16658
|
'FAST',
|
|
@@ -17846,7 +18076,7 @@ function formatRetryResult(operation, result) {
|
|
|
17846
18076
|
}
|
|
17847
18077
|
|
|
17848
18078
|
// Auto-register this kit for user agent tracking
|
|
17849
|
-
registerKit(`${pkg.name}/${pkg.version}`);
|
|
18079
|
+
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
17850
18080
|
|
|
17851
18081
|
/**
|
|
17852
18082
|
* Create an EarnKit instance for AppKit earn operations.
|