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