@circle-fin/app-kit 1.9.0 → 1.10.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 +26 -0
- package/bridge.cjs +622 -26
- package/bridge.d.cts +147 -10
- package/bridge.d.mts +147 -10
- package/bridge.d.ts +147 -10
- package/bridge.mjs +622 -26
- package/chains.cjs +8 -2
- package/chains.d.cts +1 -0
- package/chains.d.mts +1 -0
- package/chains.d.ts +1 -0
- package/chains.mjs +8 -2
- package/context.cjs +1 -0
- package/context.d.cts +152 -12
- package/context.d.mts +152 -12
- package/context.d.ts +152 -12
- package/context.mjs +1 -0
- package/earn.cjs +859 -420
- package/earn.d.cts +521 -94
- package/earn.d.mts +521 -94
- package/earn.d.ts +521 -94
- package/earn.mjs +859 -421
- package/estimateBridge.cjs +622 -26
- package/estimateBridge.d.cts +147 -10
- package/estimateBridge.d.mts +147 -10
- package/estimateBridge.d.ts +147 -10
- package/estimateBridge.mjs +622 -26
- package/estimateSwap.cjs +810 -92
- package/estimateSwap.d.cts +147 -10
- package/estimateSwap.d.mts +147 -10
- package/estimateSwap.d.ts +147 -10
- package/estimateSwap.mjs +810 -92
- package/index.cjs +2450 -645
- package/index.d.cts +1003 -126
- package/index.d.mts +1003 -126
- package/index.d.ts +1003 -126
- package/index.mjs +2450 -645
- package/package.json +6 -6
- package/swap.cjs +810 -92
- package/swap.d.cts +147 -10
- package/swap.d.mts +147 -10
- package/swap.d.ts +147 -10
- package/swap.mjs +810 -92
- package/unifiedBalance.cjs +722 -115
- package/unifiedBalance.d.cts +222 -4
- package/unifiedBalance.d.mts +222 -4
- package/unifiedBalance.d.ts +222 -4
- package/unifiedBalance.mjs +722 -115
package/estimateBridge.cjs
CHANGED
|
@@ -22,9 +22,9 @@ var zod = require('zod');
|
|
|
22
22
|
var pino = require('pino');
|
|
23
23
|
var units = require('@ethersproject/units');
|
|
24
24
|
var bytes = require('@ethersproject/bytes');
|
|
25
|
+
require('@ethersproject/abi');
|
|
25
26
|
var address = require('@ethersproject/address');
|
|
26
27
|
var bs58 = require('bs58');
|
|
27
|
-
require('@ethersproject/abi');
|
|
28
28
|
var web3_js = require('@solana/web3.js');
|
|
29
29
|
require('bn.js');
|
|
30
30
|
require('@coral-xyz/anchor');
|
|
@@ -3101,7 +3101,10 @@ var EarnChain;
|
|
|
3101
3101
|
contracts: {
|
|
3102
3102
|
v1: {
|
|
3103
3103
|
wallet: GATEWAY_WALLET_EVM_TESTNET,
|
|
3104
|
-
minter: GATEWAY_MINTER_EVM_TESTNET
|
|
3104
|
+
minter: GATEWAY_MINTER_EVM_TESTNET,
|
|
3105
|
+
// DepositForHandler the GenericExecutor calls to run a fast cross-chain
|
|
3106
|
+
// deposit into the GatewayWallet above.
|
|
3107
|
+
depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
|
|
3105
3108
|
}
|
|
3106
3109
|
},
|
|
3107
3110
|
forwarderSupported: {
|
|
@@ -6219,7 +6222,10 @@ var Chains = {
|
|
|
6219
6222
|
minter: zod.z.string({
|
|
6220
6223
|
required_error: 'Gateway minter address is required. Please provide a valid contract address.',
|
|
6221
6224
|
invalid_type_error: 'Gateway minter address must be a string.'
|
|
6222
|
-
}).min(1, 'Gateway minter address cannot be empty.')
|
|
6225
|
+
}).min(1, 'Gateway minter address cannot be empty.'),
|
|
6226
|
+
depositForHandler: zod.z.string({
|
|
6227
|
+
invalid_type_error: 'Gateway depositForHandler address must be a string.'
|
|
6228
|
+
}).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
|
|
6223
6229
|
}).strict() // Reject any additional properties not defined in the schema
|
|
6224
6230
|
;
|
|
6225
6231
|
/**
|
|
@@ -6741,21 +6747,31 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
6741
6747
|
* returning the appropriate address based on the requested contract type.
|
|
6742
6748
|
*
|
|
6743
6749
|
* @param chain - The chain definition to resolve the contract address for
|
|
6744
|
-
* @param contractType - The type of contract address to resolve ('tokenMessenger' or '
|
|
6750
|
+
* @param contractType - The type of contract address to resolve ('tokenMessenger', 'messageTransmitter', or 'tokenMessengerWithFees')
|
|
6745
6751
|
* @returns The contract address for the specified contract type
|
|
6746
6752
|
* @throws Error when chain does not support CCTP v2 or has unsupported contract configuration
|
|
6753
|
+
* @throws Error when 'tokenMessengerWithFees' is requested but not configured on the chain
|
|
6747
6754
|
*/ const resolveCCTPV2ContractAddress = (chain, contractType)=>{
|
|
6748
6755
|
// Handle custom bridge contract for tokenMessenger (burn transaction)
|
|
6749
|
-
if (hasCustomContractSupport(chain, 'bridge') && chain.kitContracts?.bridge !== undefined) {
|
|
6756
|
+
if (contractType === 'tokenMessenger' && hasCustomContractSupport(chain, 'bridge') && chain.kitContracts?.bridge !== undefined) {
|
|
6750
6757
|
return chain.kitContracts.bridge;
|
|
6751
6758
|
}
|
|
6752
6759
|
// At this point we know CCTP v2 is supported, so contracts exist
|
|
6753
6760
|
const cctpConfig = chain.cctp;
|
|
6754
6761
|
const contracts = cctpConfig.contracts.v2;
|
|
6762
|
+
// The `TokenMessengerWithFees` wrapper (prepaid FORWARD path) is an optional
|
|
6763
|
+
// deployment carried alongside both split and merged configurations.
|
|
6764
|
+
if (contractType === 'tokenMessengerWithFees') {
|
|
6765
|
+
const wrapper = contracts.tokenMessengerWithFees;
|
|
6766
|
+
if (wrapper === undefined || wrapper === '') {
|
|
6767
|
+
throw new Error(`TokenMessengerWithFees is not configured on chain ${chain.name}. The prepaid FORWARD path is unavailable on this chain.`);
|
|
6768
|
+
}
|
|
6769
|
+
return wrapper;
|
|
6770
|
+
}
|
|
6755
6771
|
// Handle different contract types with explicit type checking
|
|
6756
6772
|
switch(contracts.type){
|
|
6757
6773
|
case 'split':
|
|
6758
|
-
return contracts.tokenMessenger ;
|
|
6774
|
+
return contractType === 'tokenMessenger' ? contracts.tokenMessenger : contracts.messageTransmitter;
|
|
6759
6775
|
case 'merged':
|
|
6760
6776
|
return contracts.contract;
|
|
6761
6777
|
default:
|
|
@@ -9610,7 +9626,7 @@ function resolveOptions(options) {
|
|
|
9610
9626
|
}
|
|
9611
9627
|
|
|
9612
9628
|
var name$2 = "@circle-fin/bridge-kit";
|
|
9613
|
-
var version$3 = "1.12.
|
|
9629
|
+
var version$3 = "1.12.1";
|
|
9614
9630
|
var pkg$3 = {
|
|
9615
9631
|
name: name$2,
|
|
9616
9632
|
version: version$3};
|
|
@@ -12114,6 +12130,144 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
12114
12130
|
return false;
|
|
12115
12131
|
};
|
|
12116
12132
|
|
|
12133
|
+
/**
|
|
12134
|
+
* The zero address, denoting a native-currency fee in a signed quote.
|
|
12135
|
+
*/ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
12136
|
+
/**
|
|
12137
|
+
* Resolve the fee payment channel for a prepaid-FORWARD burn via `TokenMessengerWithFees`.
|
|
12138
|
+
*
|
|
12139
|
+
* Determines the native `msg.value` and the ERC-20 approvals required, honouring
|
|
12140
|
+
* the quote's `feeToken`:
|
|
12141
|
+
* - Native fee (`feeToken` is the zero address): attach exactly `feeTotalAmount`
|
|
12142
|
+
* as `msg.value`; approve only the burn amount.
|
|
12143
|
+
* - ERC-20 fee equal to the burn token (both USDC — the `isBurnTokenFee` case):
|
|
12144
|
+
* approve a single combined `amount + feeTotalAmount` and skip the redundant
|
|
12145
|
+
* second approval.
|
|
12146
|
+
* - ERC-20 fee different from the burn token: approve the burn amount and the fee
|
|
12147
|
+
* amount separately.
|
|
12148
|
+
*
|
|
12149
|
+
* This encodes only balance/allowance intent; it does not fetch balances. The
|
|
12150
|
+
* caller is responsible for a balance preflight against the fresh quote.
|
|
12151
|
+
*
|
|
12152
|
+
* @param params - The fee token, burn token, burn amount, and total fee amount.
|
|
12153
|
+
* @returns The resolved fee payment plan.
|
|
12154
|
+
* @throws KitError if `amount` or `feeTotalAmount` is negative.
|
|
12155
|
+
*
|
|
12156
|
+
* @example
|
|
12157
|
+
* ```typescript
|
|
12158
|
+
* // Native fee
|
|
12159
|
+
* resolveFeePayment({
|
|
12160
|
+
* feeToken: '0x0000000000000000000000000000000000000000',
|
|
12161
|
+
* burnToken: '0xUSDC...',
|
|
12162
|
+
* amount: 1_000_000n,
|
|
12163
|
+
* feeTotalAmount: 3_500_000n,
|
|
12164
|
+
* })
|
|
12165
|
+
* // → { isNativeFee: true, isBurnTokenFee: false, nativeValue: 3_500_000n,
|
|
12166
|
+
* // approvals: [{ token: '0xUSDC...', amount: 1_000_000n }] }
|
|
12167
|
+
* ```
|
|
12168
|
+
*/ const resolveFeePayment = (params)=>{
|
|
12169
|
+
const { feeToken, burnToken, amount, feeTotalAmount } = params;
|
|
12170
|
+
if (typeof amount !== 'bigint' || amount < 0n) {
|
|
12171
|
+
throw createValidationFailedError$1('amount', amount, 'Must be a non-negative bigint');
|
|
12172
|
+
}
|
|
12173
|
+
if (typeof feeTotalAmount !== 'bigint' || feeTotalAmount < 0n) {
|
|
12174
|
+
throw createValidationFailedError$1('feeTotalAmount', feeTotalAmount, 'Must be a non-negative bigint');
|
|
12175
|
+
}
|
|
12176
|
+
const isNativeFee = feeToken.toLowerCase() === ZERO_ADDRESS;
|
|
12177
|
+
const isBurnTokenFee = !isNativeFee && feeToken.toLowerCase() === burnToken.toLowerCase();
|
|
12178
|
+
if (isNativeFee) {
|
|
12179
|
+
return {
|
|
12180
|
+
isNativeFee: true,
|
|
12181
|
+
isBurnTokenFee: false,
|
|
12182
|
+
nativeValue: feeTotalAmount,
|
|
12183
|
+
approvals: [
|
|
12184
|
+
{
|
|
12185
|
+
token: burnToken,
|
|
12186
|
+
amount
|
|
12187
|
+
}
|
|
12188
|
+
]
|
|
12189
|
+
};
|
|
12190
|
+
}
|
|
12191
|
+
if (isBurnTokenFee) {
|
|
12192
|
+
// Fee and burn draw on the same token — a single combined approval covers
|
|
12193
|
+
// both; the redundant second approval is skipped.
|
|
12194
|
+
return {
|
|
12195
|
+
isNativeFee: false,
|
|
12196
|
+
isBurnTokenFee: true,
|
|
12197
|
+
nativeValue: 0n,
|
|
12198
|
+
approvals: [
|
|
12199
|
+
{
|
|
12200
|
+
token: burnToken,
|
|
12201
|
+
amount: amount + feeTotalAmount
|
|
12202
|
+
}
|
|
12203
|
+
]
|
|
12204
|
+
};
|
|
12205
|
+
}
|
|
12206
|
+
return {
|
|
12207
|
+
isNativeFee: false,
|
|
12208
|
+
isBurnTokenFee: false,
|
|
12209
|
+
nativeValue: 0n,
|
|
12210
|
+
approvals: [
|
|
12211
|
+
{
|
|
12212
|
+
token: burnToken,
|
|
12213
|
+
amount
|
|
12214
|
+
},
|
|
12215
|
+
{
|
|
12216
|
+
token: feeToken,
|
|
12217
|
+
amount: feeTotalAmount
|
|
12218
|
+
}
|
|
12219
|
+
]
|
|
12220
|
+
};
|
|
12221
|
+
};
|
|
12222
|
+
|
|
12223
|
+
/**
|
|
12224
|
+
* The ASCII "cctp-forward" magic, hex-encoded (no `0x`), that a forward-friendly
|
|
12225
|
+
* hookData must start with.
|
|
12226
|
+
*/ const CCTP_FORWARD_MAGIC_HEX = Buffer.from(CCTP_FORWARD_MAGIC_PREFIX, 'ascii').toString('hex');
|
|
12227
|
+
/**
|
|
12228
|
+
* Determine whether a hookData blob begins with the `cctp-forward` envelope.
|
|
12229
|
+
*
|
|
12230
|
+
* The prepaid FORWARD path requires the GenericExecutor blob to be wrapped in a
|
|
12231
|
+
* `cctp-forward` frame; without it the wrapper reverts `ForwardFeeWithoutHook`.
|
|
12232
|
+
*
|
|
12233
|
+
* @param hookData - The 0x-prefixed hookData hex string.
|
|
12234
|
+
* @returns True when the hookData starts with the `cctp-forward` magic.
|
|
12235
|
+
*
|
|
12236
|
+
* @example
|
|
12237
|
+
* ```typescript
|
|
12238
|
+
* hasForwardHook('0x636374702d666f7277617264...') // true
|
|
12239
|
+
* hasForwardHook('0xdeadbeef') // false
|
|
12240
|
+
* ```
|
|
12241
|
+
*/ const hasForwardHook = (hookData)=>{
|
|
12242
|
+
if (typeof hookData !== 'string') {
|
|
12243
|
+
return false;
|
|
12244
|
+
}
|
|
12245
|
+
const normalized = (hookData.startsWith('0x') ? hookData.slice(2) : hookData).toLowerCase();
|
|
12246
|
+
return normalized.startsWith(CCTP_FORWARD_MAGIC_HEX);
|
|
12247
|
+
};
|
|
12248
|
+
/**
|
|
12249
|
+
* Assert that a hookData blob is forward-friendly for the prepaid FORWARD path.
|
|
12250
|
+
*
|
|
12251
|
+
* The prepaid FORWARD path always requests a FORWARD fee item, so the wrapper
|
|
12252
|
+
* requires the hookData to start with a `cctp-forward` frame. Validating this
|
|
12253
|
+
* before the burn surfaces the guaranteed `ForwardFeeWithoutHook` revert as a
|
|
12254
|
+
* typed input error instead of an on-chain failure.
|
|
12255
|
+
*
|
|
12256
|
+
* @param hookData - The 0x-prefixed hookData hex string.
|
|
12257
|
+
* @throws KitError (`INPUT_VALIDATION_FAILED`) if the hookData is missing or lacks
|
|
12258
|
+
* the `cctp-forward` frame.
|
|
12259
|
+
*
|
|
12260
|
+
* @example
|
|
12261
|
+
* ```typescript
|
|
12262
|
+
* assertForwardHookData(geForwardHookData) // ok
|
|
12263
|
+
* assertForwardHookData('0xdeadbeef') // throws — would revert ForwardFeeWithoutHook
|
|
12264
|
+
* ```
|
|
12265
|
+
*/ const assertForwardHookData = (hookData)=>{
|
|
12266
|
+
if (!hasForwardHook(hookData)) {
|
|
12267
|
+
throw createValidationFailedError$1('hookData', hookData, 'Prepaid FORWARD burns require a cctp-forward-wrapped hookData; without it the TokenMessengerWithFees wrapper reverts ForwardFeeWithoutHook');
|
|
12268
|
+
}
|
|
12269
|
+
};
|
|
12270
|
+
|
|
12117
12271
|
/**
|
|
12118
12272
|
* Type guard to validate the forwardFee object structure.
|
|
12119
12273
|
*
|
|
@@ -13045,6 +13199,109 @@ const assertCCTPv2BridgeParamsSymbol = Symbol('assertCCTPv2BridgeParams');
|
|
|
13045
13199
|
}
|
|
13046
13200
|
}
|
|
13047
13201
|
|
|
13202
|
+
/**
|
|
13203
|
+
* Assert that `params` is a well-formed {@link BurnWithFeesParams} object.
|
|
13204
|
+
*
|
|
13205
|
+
* Validates the full public-boundary input before any field destructuring,
|
|
13206
|
+
* `BigInt()` coercion, or adapter preparation runs, so malformed JS-caller
|
|
13207
|
+
* inputs always produce typed `KitError` validation failures.
|
|
13208
|
+
*
|
|
13209
|
+
* Checks performed (in order):
|
|
13210
|
+
* - `params` must be a non-null plain object
|
|
13211
|
+
* - `source` — valid CCTP v2 wallet context (via `assertCCTPv2WalletContext`)
|
|
13212
|
+
* - `destinationChain` — present and supports CCTP v2
|
|
13213
|
+
* - source and destination chains must both be testnet or both mainnet
|
|
13214
|
+
* - source and destination chains must differ
|
|
13215
|
+
* - `executor` — non-empty string
|
|
13216
|
+
* - `amount` — bigint or non-empty string coercible to bigint
|
|
13217
|
+
* - `feeTotalAmount` — bigint or non-empty string coercible to bigint
|
|
13218
|
+
* - `feeToken` — valid EVM address (`0x` + 40 hex chars)
|
|
13219
|
+
* - `claim.signedQuote` — valid `0x`-prefixed hex string
|
|
13220
|
+
* - `claim.refundAddress` — valid EVM address
|
|
13221
|
+
* - `hookData` — valid `0x`-prefixed hex string when present
|
|
13222
|
+
*
|
|
13223
|
+
* @param params - The value to validate.
|
|
13224
|
+
* @throws {KitError} If any field is missing or invalid.
|
|
13225
|
+
*
|
|
13226
|
+
* @example
|
|
13227
|
+
* ```typescript
|
|
13228
|
+
* assertBurnWithFeesParams(params)
|
|
13229
|
+
* // params is now typed as BurnWithFeesParams and safe to use
|
|
13230
|
+
* const { source, destinationChain, amount } = params
|
|
13231
|
+
* ```
|
|
13232
|
+
*/ function assertBurnWithFeesParams(params) {
|
|
13233
|
+
if (params === null || typeof params !== 'object' || Array.isArray(params)) {
|
|
13234
|
+
throw createValidationFailedError$1('params', params, 'Must be a non-null plain object');
|
|
13235
|
+
}
|
|
13236
|
+
const p = params;
|
|
13237
|
+
// Source wallet context
|
|
13238
|
+
assertCCTPv2WalletContext(p['source']);
|
|
13239
|
+
const source = p['source'];
|
|
13240
|
+
// destinationChain
|
|
13241
|
+
const destinationChain = p['destinationChain'];
|
|
13242
|
+
if (destinationChain === null || destinationChain === undefined || typeof destinationChain !== 'object') {
|
|
13243
|
+
throw createValidationFailedError$1('destinationChain', destinationChain, 'Must be a chain definition object');
|
|
13244
|
+
}
|
|
13245
|
+
if (!isCCTPV2Supported(destinationChain)) {
|
|
13246
|
+
throw createValidationFailedError$1('destinationChain', destinationChain, 'destinationChain must support CCTP v2');
|
|
13247
|
+
}
|
|
13248
|
+
const dest = destinationChain;
|
|
13249
|
+
// Testnet / mainnet mismatch
|
|
13250
|
+
if (source.chain.isTestnet !== dest.isTestnet) {
|
|
13251
|
+
throw createNetworkMismatchError(source.chain, dest);
|
|
13252
|
+
}
|
|
13253
|
+
// Same-chain guard
|
|
13254
|
+
if (source.chain.name === dest.name) {
|
|
13255
|
+
throw createUnsupportedRouteError(source.chain.name, dest.name);
|
|
13256
|
+
}
|
|
13257
|
+
// executor
|
|
13258
|
+
const executor = p['executor'];
|
|
13259
|
+
if (typeof executor !== 'string' || executor === '') {
|
|
13260
|
+
throw createValidationFailedError$1('executor', executor, 'A GenericExecutor address is required (used for both mintRecipient and destinationCaller)');
|
|
13261
|
+
}
|
|
13262
|
+
// amount
|
|
13263
|
+
const rawAmount = p['amount'];
|
|
13264
|
+
if (typeof rawAmount !== 'bigint' && typeof rawAmount !== 'string' || rawAmount === '') {
|
|
13265
|
+
throw createValidationFailedError$1('amount', rawAmount, 'Must be a bigint or a numeric string');
|
|
13266
|
+
}
|
|
13267
|
+
try {
|
|
13268
|
+
BigInt(rawAmount);
|
|
13269
|
+
} catch {
|
|
13270
|
+
throw createValidationFailedError$1('amount', rawAmount, 'Must be a valid integer value coercible to bigint');
|
|
13271
|
+
}
|
|
13272
|
+
// feeTotalAmount
|
|
13273
|
+
const rawFee = p['feeTotalAmount'];
|
|
13274
|
+
if (typeof rawFee !== 'bigint' && typeof rawFee !== 'string' || rawFee === '') {
|
|
13275
|
+
throw createValidationFailedError$1('feeTotalAmount', rawFee, 'Must be a bigint or a numeric string');
|
|
13276
|
+
}
|
|
13277
|
+
try {
|
|
13278
|
+
BigInt(rawFee);
|
|
13279
|
+
} catch {
|
|
13280
|
+
throw createValidationFailedError$1('feeTotalAmount', rawFee, 'Must be a valid integer value coercible to bigint');
|
|
13281
|
+
}
|
|
13282
|
+
// feeToken
|
|
13283
|
+
if (!evmAddressSchema.safeParse(p['feeToken']).success) {
|
|
13284
|
+
throw createValidationFailedError$1('feeToken', p['feeToken'], 'Must be a valid EVM address (use the zero address for a native fee)');
|
|
13285
|
+
}
|
|
13286
|
+
// claim
|
|
13287
|
+
const rawClaim = p['claim'];
|
|
13288
|
+
if (rawClaim === null || typeof rawClaim !== 'object' || Array.isArray(rawClaim)) {
|
|
13289
|
+
throw createValidationFailedError$1('claim', rawClaim, 'Must be an object with signedQuote and refundAddress');
|
|
13290
|
+
}
|
|
13291
|
+
const claim = rawClaim;
|
|
13292
|
+
if (!hexStringSchema.safeParse(claim['signedQuote']).success) {
|
|
13293
|
+
throw createValidationFailedError$1('claim.signedQuote', claim['signedQuote'], 'Must be a valid hex string starting with 0x');
|
|
13294
|
+
}
|
|
13295
|
+
if (!evmAddressSchema.safeParse(claim['refundAddress']).success) {
|
|
13296
|
+
throw createValidationFailedError$1('claim.refundAddress', claim['refundAddress'], 'Must be a valid EVM address');
|
|
13297
|
+
}
|
|
13298
|
+
// hookData (optional)
|
|
13299
|
+
const hookData = p['hookData'];
|
|
13300
|
+
if (hookData !== undefined && hookData !== '' && !hexStringSchema.safeParse(hookData).success) {
|
|
13301
|
+
throw createValidationFailedError$1('hookData', hookData, 'Must be a valid hex string starting with 0x');
|
|
13302
|
+
}
|
|
13303
|
+
}
|
|
13304
|
+
|
|
13048
13305
|
/**
|
|
13049
13306
|
* CCTP bridge step names that can occur in the bridging flow.
|
|
13050
13307
|
*
|
|
@@ -14253,10 +14510,15 @@ const mockAttestationMessage = {
|
|
|
14253
14510
|
const burnCallData = burnRequest.getCallData();
|
|
14254
14511
|
// batchExecute may throw before submission (wallet declined) but never
|
|
14255
14512
|
// after — post-submission errors are returned as empty receipts.
|
|
14513
|
+
// The sender is threaded for adapters whose execution is routed through a
|
|
14514
|
+
// signing strategy (which has no wallet account to read it from); the
|
|
14515
|
+
// wallet-client path ignores it.
|
|
14256
14516
|
const batchResult = await adapter.batchExecute([
|
|
14257
14517
|
approveCallData,
|
|
14258
14518
|
burnCallData
|
|
14259
|
-
], chain
|
|
14519
|
+
], chain, {
|
|
14520
|
+
fromAddress: params.source.address
|
|
14521
|
+
});
|
|
14260
14522
|
const approveReceipt = batchResult.receipts[0];
|
|
14261
14523
|
const burnReceipt = batchResult.receipts[1];
|
|
14262
14524
|
const approveStep = await buildBatchedStep('approve', approveReceipt, batchResult.batchId, adapter, chain, batchResult.statusCode, batchResult.error);
|
|
@@ -14399,7 +14661,7 @@ const mockAttestationMessage = {
|
|
|
14399
14661
|
return step;
|
|
14400
14662
|
}
|
|
14401
14663
|
|
|
14402
|
-
var version$2 = "1.
|
|
14664
|
+
var version$2 = "1.10.0";
|
|
14403
14665
|
var pkg$2 = {
|
|
14404
14666
|
version: version$2};
|
|
14405
14667
|
|
|
@@ -15554,7 +15816,7 @@ function assertCCTPV2Config(config) {
|
|
|
15554
15816
|
throw new Error(`Failed to resolve operation context: ${error instanceof Error ? error.message : String(error)}`);
|
|
15555
15817
|
}
|
|
15556
15818
|
// Resolve spender address with proper error handling
|
|
15557
|
-
const spenderAddress = resolveCCTPV2ContractAddress(chain);
|
|
15819
|
+
const spenderAddress = resolveCCTPV2ContractAddress(chain, 'tokenMessenger');
|
|
15558
15820
|
// Prepare action parameters
|
|
15559
15821
|
const actionParams = {
|
|
15560
15822
|
amount: BigInt(amount),
|
|
@@ -16034,6 +16296,106 @@ function assertCCTPV2Config(config) {
|
|
|
16034
16296
|
return await source.adapter.prepareAction('cctp.v2.depositForBurn', actionParams, resolvedContext);
|
|
16035
16297
|
}
|
|
16036
16298
|
/**
|
|
16299
|
+
* Prepare a prepaid-FORWARD burn through the `TokenMessengerWithFees` wrapper.
|
|
16300
|
+
*
|
|
16301
|
+
* Builds the source-chain `depositForBurnWithHookAndFees` call for the
|
|
16302
|
+
* GenericExecutor FORWARD path: fees are collected up front on the source chain
|
|
16303
|
+
* against a signed quote, `mintRecipient` and `destinationCaller` are both set to
|
|
16304
|
+
* the GenericExecutor, and the GE `hookData` is passed through unchanged.
|
|
16305
|
+
*
|
|
16306
|
+
* This is the low-level on-chain primitive behind the UBK `fastCrossChainDeposit`
|
|
16307
|
+
* and Bridge Kit `bridge({ deposit })` flows. The `hookData` and signed-quote
|
|
16308
|
+
* `claim` are produced elsewhere and passed in here:
|
|
16309
|
+
* - `hookData`: `buildForwardingHookDataWithPayload(version,
|
|
16310
|
+
* buildDepositForGenericExecutorPayload(...).hookData)` from `@core/utils`.
|
|
16311
|
+
* - `claim.signedQuote` / `feeToken` / `feeTotalAmount`: from `fetchFeeQuote`
|
|
16312
|
+
* (`@circle-fin/provider-fee-v1`), whose FORWARD item must be bound to the
|
|
16313
|
+
* SAME `hookData` and executor `destinationCaller` used here.
|
|
16314
|
+
*
|
|
16315
|
+
* The returned approvals and burn are NOT executed — the caller executes the
|
|
16316
|
+
* approvals first (in order) and then the burn. The fee payment channel matches
|
|
16317
|
+
* the quote's `feeToken`:
|
|
16318
|
+
* - Native fee: exactly `feeTotalAmount` is attached as the burn's `msg.value`;
|
|
16319
|
+
* only the burn amount is approved.
|
|
16320
|
+
* - USDC fee (same token as the burn): a single combined `amount + feeTotalAmount`
|
|
16321
|
+
* approval covers both; the redundant second approval is skipped.
|
|
16322
|
+
*
|
|
16323
|
+
* @typeParam TFromAdapterCapabilities - The source adapter's capabilities.
|
|
16324
|
+
* @param params - The burn amount, executor, hookData, signed-quote claim, and fee.
|
|
16325
|
+
* @returns The prepared approvals, the prepared burn, and the resolved fee plan.
|
|
16326
|
+
* @throws {KitError} If the wallet context is invalid, `destinationChain` does not
|
|
16327
|
+
* support CCTP v2, the executor is missing, `amount` or `feeTotalAmount` is not
|
|
16328
|
+
* a bigint or a numeric string coercible to bigint, the hookData lacks a
|
|
16329
|
+
* `cctp-forward` frame (guaranteed `ForwardFeeWithoutHook`), or the operation
|
|
16330
|
+
* context cannot be resolved.
|
|
16331
|
+
*
|
|
16332
|
+
* @example
|
|
16333
|
+
* ```typescript
|
|
16334
|
+
* const { approvals, burn } = await provider.burnWithFees({
|
|
16335
|
+
* source,
|
|
16336
|
+
* destinationChain: Arc,
|
|
16337
|
+
* amount: 1_000_000n,
|
|
16338
|
+
* executor: genericExecutorAddress,
|
|
16339
|
+
* hookData: geForwardHookData,
|
|
16340
|
+
* claim: { signedQuote: '0x01...', refundAddress: userAddress },
|
|
16341
|
+
* feeToken: '0x0000000000000000000000000000000000000000', // native
|
|
16342
|
+
* feeTotalAmount: 3_500_000n,
|
|
16343
|
+
* })
|
|
16344
|
+
* for (const approval of approvals) await approval.execute()
|
|
16345
|
+
* const txHash = await burn.execute()
|
|
16346
|
+
* ```
|
|
16347
|
+
*/ async burnWithFees(params) {
|
|
16348
|
+
assertBurnWithFeesParams(params);
|
|
16349
|
+
const { source, destinationChain, executor, hookData, claim, feeToken } = params;
|
|
16350
|
+
const amount = BigInt(params.amount);
|
|
16351
|
+
const feeTotalAmount = BigInt(params.feeTotalAmount);
|
|
16352
|
+
// Coupling guard: the prepaid FORWARD path always requests a FORWARD fee item,
|
|
16353
|
+
// so the hookData must carry a cctp-forward frame; otherwise the wrapper
|
|
16354
|
+
// reverts ForwardFeeWithoutHook. Surface it as a typed input error up front.
|
|
16355
|
+
assertForwardHookData(hookData);
|
|
16356
|
+
const burnToken = source.chain.usdcAddress;
|
|
16357
|
+
const feePayment = resolveFeePayment({
|
|
16358
|
+
feeToken,
|
|
16359
|
+
burnToken,
|
|
16360
|
+
amount,
|
|
16361
|
+
feeTotalAmount
|
|
16362
|
+
});
|
|
16363
|
+
// Resolve operation context from the source wallet context.
|
|
16364
|
+
const operationContext = this.extractOperationContext(source);
|
|
16365
|
+
let resolvedContext;
|
|
16366
|
+
try {
|
|
16367
|
+
resolvedContext = await resolveOperationContext(source.adapter, operationContext);
|
|
16368
|
+
} catch (error) {
|
|
16369
|
+
throw createValidationFailedError$1('source.adapter', undefined, `Failed to resolve operation context: ${error instanceof Error ? error.message : String(error)}`);
|
|
16370
|
+
}
|
|
16371
|
+
const context = resolvedContext;
|
|
16372
|
+
const wrapperAddress = resolveCCTPV2ContractAddress(source.chain, 'tokenMessengerWithFees');
|
|
16373
|
+
// Build the ERC-20 approvals to the wrapper (burn token, plus a distinct fee
|
|
16374
|
+
// token only when the fee is not paid in the burn token).
|
|
16375
|
+
const approvals = await Promise.all(feePayment.approvals.map(async (approval)=>source.adapter.prepareAction('token.approve', {
|
|
16376
|
+
tokenAddress: approval.token,
|
|
16377
|
+
delegate: wrapperAddress,
|
|
16378
|
+
amount: approval.amount
|
|
16379
|
+
}, context)));
|
|
16380
|
+
// Build the burn: mintRecipient AND destinationCaller are both the executor.
|
|
16381
|
+
const burn = await source.adapter.prepareAction('cctp.v2.depositForBurnWithFees', {
|
|
16382
|
+
fromChain: source.chain,
|
|
16383
|
+
toChain: destinationChain,
|
|
16384
|
+
amount,
|
|
16385
|
+
mintRecipient: executor,
|
|
16386
|
+
destinationCaller: executor,
|
|
16387
|
+
hookData,
|
|
16388
|
+
claim,
|
|
16389
|
+
feeToken,
|
|
16390
|
+
feeTotalAmount
|
|
16391
|
+
}, context);
|
|
16392
|
+
return {
|
|
16393
|
+
approvals,
|
|
16394
|
+
burn,
|
|
16395
|
+
feePayment
|
|
16396
|
+
};
|
|
16397
|
+
}
|
|
16398
|
+
/**
|
|
16037
16399
|
* Waits for a transaction to be mined and confirmed on the blockchain.
|
|
16038
16400
|
*
|
|
16039
16401
|
* This method should block until the transaction is confirmed on the blockchain.
|
|
@@ -16913,7 +17275,7 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
16913
17275
|
};
|
|
16914
17276
|
|
|
16915
17277
|
var name$1 = "@circle-fin/swap-kit";
|
|
16916
|
-
var version$1 = "1.
|
|
17278
|
+
var version$1 = "1.4.0";
|
|
16917
17279
|
var pkg$1 = {
|
|
16918
17280
|
name: name$1,
|
|
16919
17281
|
version: version$1};
|
|
@@ -16978,7 +17340,10 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
|
|
|
16978
17340
|
}).min(1, 'kitKey must be a non-empty string').optional(),
|
|
16979
17341
|
provider: zod.z.string({
|
|
16980
17342
|
invalid_type_error: 'provider must be a string'
|
|
16981
|
-
}).min(1, 'provider must be a non-empty string').optional()
|
|
17343
|
+
}).min(1, 'provider must be a non-empty string').optional(),
|
|
17344
|
+
batchTransactions: zod.z.boolean({
|
|
17345
|
+
invalid_type_error: 'batchTransactions must be a boolean'
|
|
17346
|
+
}).optional()
|
|
16982
17347
|
});
|
|
16983
17348
|
/**
|
|
16984
17349
|
* Zod schema for adapter context.
|
|
@@ -17417,7 +17782,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
17417
17782
|
/**
|
|
17418
17783
|
* Circle Stablecoin Service API Key.
|
|
17419
17784
|
* Must be a valid API key format.
|
|
17420
|
-
*/ apiKey: apiKeySchema
|
|
17785
|
+
*/ apiKey: apiKeySchema.optional()
|
|
17421
17786
|
}).superRefine(requireCrossChainQuoteToAddress);
|
|
17422
17787
|
/**
|
|
17423
17788
|
* Zod schema for validating CreateSwapRequest parameters.
|
|
@@ -17475,7 +17840,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
17475
17840
|
/**
|
|
17476
17841
|
* Circle Stablecoin Service API Key.
|
|
17477
17842
|
* Must be a valid API key format.
|
|
17478
|
-
*/ apiKey: apiKeySchema
|
|
17843
|
+
*/ apiKey: apiKeySchema.optional()
|
|
17479
17844
|
});
|
|
17480
17845
|
/**
|
|
17481
17846
|
* Zod schema for validating GetSwapStatusResponse data.
|
|
@@ -17511,7 +17876,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
17511
17876
|
toChain: zod.z.string({
|
|
17512
17877
|
invalid_type_error: 'toChain must be a string'
|
|
17513
17878
|
}).min(1, 'toChain must be a non-empty string if provided').optional(),
|
|
17514
|
-
apiKey: apiKeySchema
|
|
17879
|
+
apiKey: apiKeySchema.optional()
|
|
17515
17880
|
});
|
|
17516
17881
|
/**
|
|
17517
17882
|
* Zod schema for validating CreateSwapResponse payloads.
|
|
@@ -17520,13 +17885,15 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
17520
17885
|
required_error: 'fee token is required',
|
|
17521
17886
|
invalid_type_error: 'fee token must be a string'
|
|
17522
17887
|
}).min(1, 'fee token must be a non-empty string'),
|
|
17523
|
-
amount: feeAmountSchema
|
|
17888
|
+
amount: feeAmountSchema,
|
|
17889
|
+
decimals: zod.z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
|
|
17890
|
+
symbol: zod.z.string({
|
|
17891
|
+
invalid_type_error: 'fee token symbol must be a string'
|
|
17892
|
+
}).min(1, 'fee token symbol must be a non-empty string').optional()
|
|
17524
17893
|
});
|
|
17525
17894
|
/**
|
|
17526
17895
|
* Developer fee item schema with basis field.
|
|
17527
|
-
*/ const createSwapDeveloperFeeItemSchema =
|
|
17528
|
-
token: zod.z.string().min(1, 'fee token must be a non-empty string'),
|
|
17529
|
-
amount: feeAmountSchema,
|
|
17896
|
+
*/ const createSwapDeveloperFeeItemSchema = createSwapFeeItemSchema.extend({
|
|
17530
17897
|
basis: zod.z.enum([
|
|
17531
17898
|
'inputAmount',
|
|
17532
17899
|
'estimatedAmount'
|
|
@@ -17618,7 +17985,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
17618
17985
|
addresses: zod.z.array(zod.z.string({
|
|
17619
17986
|
invalid_type_error: 'addresses entries must be strings'
|
|
17620
17987
|
}).min(1, 'addresses entries must be non-empty strings')).min(1, 'addresses must contain at least one entry when provided').max(MAX_RATE_ADDRESSES_PER_REQUEST, `addresses supports at most ${String(MAX_RATE_ADDRESSES_PER_REQUEST)} values per request`).optional(),
|
|
17621
|
-
apiKey: apiKeySchema
|
|
17988
|
+
apiKey: apiKeySchema.optional()
|
|
17622
17989
|
});
|
|
17623
17990
|
/**
|
|
17624
17991
|
* Zod schema for validating GetTokenRatesResponse payloads.
|
|
@@ -18841,7 +19208,7 @@ new Set(Object.values(Blockchain));
|
|
|
18841
19208
|
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
18842
19209
|
|
|
18843
19210
|
var name = "@circle-fin/earn-kit";
|
|
18844
|
-
var version = "1.
|
|
19211
|
+
var version = "1.3.0";
|
|
18845
19212
|
var pkg = {
|
|
18846
19213
|
name: name,
|
|
18847
19214
|
version: version};
|
|
@@ -18971,7 +19338,11 @@ const bridgeFeeTokenSchema = hexAddressSchema;
|
|
|
18971
19338
|
asset: zod.z.string(),
|
|
18972
19339
|
assetAddress: zod.z.string(),
|
|
18973
19340
|
lltv: zod.z.number(),
|
|
18974
|
-
supplyUsd: zod.z.number()
|
|
19341
|
+
supplyUsd: zod.z.number(),
|
|
19342
|
+
// Optional during the expand/contract window (a backend that predates the
|
|
19343
|
+
// field omits the key), mirroring the `.optional()` facets on the base
|
|
19344
|
+
// schema; `null` when the product exposes no per-market allocation (V2).
|
|
19345
|
+
allocationPct: zod.z.number().nullable().optional()
|
|
18975
19346
|
});
|
|
18976
19347
|
/**
|
|
18977
19348
|
* Zod schema for a Morpho vault warning in the API response.
|
|
@@ -18985,7 +19356,74 @@ const bridgeFeeTokenSchema = hexAddressSchema;
|
|
|
18985
19356
|
])
|
|
18986
19357
|
});
|
|
18987
19358
|
/**
|
|
18988
|
-
* Zod schema for
|
|
19359
|
+
* Zod schema for the manager (curator) facet in the API response.
|
|
19360
|
+
*
|
|
19361
|
+
* @internal
|
|
19362
|
+
*/ const managerSchema = zod.z.object({
|
|
19363
|
+
name: zod.z.string(),
|
|
19364
|
+
address: zod.z.string().optional(),
|
|
19365
|
+
// Only 'curator' is emitted today (Morpho V1/V2). Additional manager roles
|
|
19366
|
+
// are added here as the providers that emit them land, rather than shipped
|
|
19367
|
+
// speculatively.
|
|
19368
|
+
type: zod.z.enum([
|
|
19369
|
+
'curator'
|
|
19370
|
+
])
|
|
19371
|
+
});
|
|
19372
|
+
/**
|
|
19373
|
+
* Zod schema for the APY profile facet in the API response.
|
|
19374
|
+
*
|
|
19375
|
+
* @internal
|
|
19376
|
+
*/ const apyProfileSchema = zod.z.object({
|
|
19377
|
+
current: zod.z.number(),
|
|
19378
|
+
native: zod.z.number().nullable(),
|
|
19379
|
+
d7: zod.z.number().nullable(),
|
|
19380
|
+
d30: zod.z.number().nullable(),
|
|
19381
|
+
d90: zod.z.number().nullable(),
|
|
19382
|
+
rewardShare: zod.z.number().nullable(),
|
|
19383
|
+
source: zod.z.string().optional(),
|
|
19384
|
+
asOf: zod.z.string().optional()
|
|
19385
|
+
});
|
|
19386
|
+
/**
|
|
19387
|
+
* Zod schema for the fee split facet in the API response.
|
|
19388
|
+
*
|
|
19389
|
+
* @internal
|
|
19390
|
+
*/ const feeInfoSchema = zod.z.object({
|
|
19391
|
+
performance: zod.z.number().nullable(),
|
|
19392
|
+
management: zod.z.number().nullable()
|
|
19393
|
+
});
|
|
19394
|
+
/**
|
|
19395
|
+
* Zod schema for the liquidity profile facet in the API response.
|
|
19396
|
+
*
|
|
19397
|
+
* `totalSupply` is the outstanding vault share tokens (ERC4626 totalSupply);
|
|
19398
|
+
* it is validated as a raw JSON amount, like `totalDeposits`/`available`.
|
|
19399
|
+
*
|
|
19400
|
+
* @internal
|
|
19401
|
+
*/ const liquidityProfileSchema = zod.z.object({
|
|
19402
|
+
totalDeposits: amountJsonSchema,
|
|
19403
|
+
available: amountJsonSchema,
|
|
19404
|
+
totalSupply: amountJsonSchema,
|
|
19405
|
+
status: zod.z.enum([
|
|
19406
|
+
'active',
|
|
19407
|
+
'low_liquidity'
|
|
19408
|
+
])
|
|
19409
|
+
});
|
|
19410
|
+
/**
|
|
19411
|
+
* Zod schema for the risk signals facet in the API response.
|
|
19412
|
+
*
|
|
19413
|
+
* @internal
|
|
19414
|
+
*/ const riskSignalsSchema = zod.z.object({
|
|
19415
|
+
circleSentinel: zod.z.boolean(),
|
|
19416
|
+
warnings: zod.z.array(vaultWarningSchema).optional(),
|
|
19417
|
+
earnKitWarnings: zod.z.array(zod.z.string()).optional()
|
|
19418
|
+
});
|
|
19419
|
+
/**
|
|
19420
|
+
* Zod schema for the universal earn-opportunity base in the API response.
|
|
19421
|
+
*
|
|
19422
|
+
* Retains every existing deprecated flat field (kept validated through the
|
|
19423
|
+
* expand/contract window so default-strip does not drop them) and adds the
|
|
19424
|
+
* new nested facets. The nested facets are `.optional()` during the
|
|
19425
|
+
* transition so the SDK still validates against a not-yet-fully-deployed
|
|
19426
|
+
* backend; they become required after Expand ships.
|
|
18989
19427
|
*
|
|
18990
19428
|
* @internal
|
|
18991
19429
|
*/ const vaultInfoResponseSchema = zod.z.object({
|
|
@@ -19010,6 +19448,96 @@ const bridgeFeeTokenSchema = hexAddressSchema;
|
|
|
19010
19448
|
warnings: zod.z.array(vaultWarningSchema).optional(),
|
|
19011
19449
|
earnKitWarnings: zod.z.array(zod.z.string()).optional()
|
|
19012
19450
|
});
|
|
19451
|
+
/**
|
|
19452
|
+
* Shared base schema: existing flat fields (kept) plus the new nested
|
|
19453
|
+
* facets and neutral identity. Facets are `.optional()` during the
|
|
19454
|
+
* transition; flip to required once the backend is confirmed emitting.
|
|
19455
|
+
*
|
|
19456
|
+
* @internal
|
|
19457
|
+
*/ const earnBaseSchema = vaultInfoResponseSchema.extend({
|
|
19458
|
+
address: zod.z.string().optional(),
|
|
19459
|
+
asOf: zod.z.string().optional(),
|
|
19460
|
+
manager: managerSchema.nullable().optional(),
|
|
19461
|
+
apyProfile: apyProfileSchema.optional(),
|
|
19462
|
+
fee: feeInfoSchema.optional(),
|
|
19463
|
+
liquidityProfile: liquidityProfileSchema.optional(),
|
|
19464
|
+
riskSignals: riskSignalsSchema.optional()
|
|
19465
|
+
});
|
|
19466
|
+
/**
|
|
19467
|
+
* Zod schema for the `vault` opportunity variant.
|
|
19468
|
+
*
|
|
19469
|
+
* @internal
|
|
19470
|
+
*/ const vaultOpportunitySchema = earnBaseSchema.extend({
|
|
19471
|
+
productType: zod.z.literal('vault'),
|
|
19472
|
+
collateral: zod.z.array(collateralSchema)
|
|
19473
|
+
});
|
|
19474
|
+
/**
|
|
19475
|
+
* Discriminated union over `productType`. Add union members here as new
|
|
19476
|
+
* product types (e.g. `lending_market`, `rwa_token`) land.
|
|
19477
|
+
*
|
|
19478
|
+
* @internal
|
|
19479
|
+
*/ const earnOpportunityVariants = [
|
|
19480
|
+
vaultOpportunitySchema
|
|
19481
|
+
];
|
|
19482
|
+
/** @internal */ const earnOpportunitySchema = zod.z.discriminatedUnion('productType', earnOpportunityVariants);
|
|
19483
|
+
/** Product types this SDK version knows how to parse. */ const knownProductTypes = new Set(earnOpportunityVariants.map((variant)=>variant.shape.productType.value));
|
|
19484
|
+
/**
|
|
19485
|
+
* Tolerant list parser for earn opportunities.
|
|
19486
|
+
*
|
|
19487
|
+
* `z.discriminatedUnion` throws on an unrecognized discriminant and
|
|
19488
|
+
* `z.array` fails the whole array if any element fails. Two migration-window
|
|
19489
|
+
* cases are smoothed over here so neither breaks an already-shipped SDK:
|
|
19490
|
+
*
|
|
19491
|
+
* - A backend that predates `productType` omits it entirely. `'vault'` was the
|
|
19492
|
+
* only opportunity type then, so default a missing discriminant to `'vault'`
|
|
19493
|
+
* rather than dropping every vault the backend returns.
|
|
19494
|
+
* - A future backend adds a *second* `productType` this SDK version does not
|
|
19495
|
+
* know. Drop those elements (a present-but-unrecognized discriminant) instead
|
|
19496
|
+
* of rejecting the whole list.
|
|
19497
|
+
*
|
|
19498
|
+
* Only the drop above is a *tolerant* case. Anything that is not a plain object
|
|
19499
|
+
* with a present-but-unknown string `productType` — `null`, `undefined`,
|
|
19500
|
+
* primitives, or an object whose `productType` is malformed — is passed through
|
|
19501
|
+
* untouched so `z.array(earnOpportunitySchema)` reports it as a normal
|
|
19502
|
+
* validation failure. It is deliberately not silently dropped (which would hide
|
|
19503
|
+
* malformed backend data) and never throws here (an unguarded property read on
|
|
19504
|
+
* a non-object would escape `safeParse` as a raw `TypeError` instead of a
|
|
19505
|
+
* `ZodError`).
|
|
19506
|
+
*
|
|
19507
|
+
* @internal
|
|
19508
|
+
*/ const earnOpportunityListSchema = zod.z.preprocess((raw)=>{
|
|
19509
|
+
if (!Array.isArray(raw)) {
|
|
19510
|
+
return raw;
|
|
19511
|
+
}
|
|
19512
|
+
// Array.isArray narrows `raw` to `any[]`; view it as `unknown[]` so the
|
|
19513
|
+
// map/filter chain stays type-safe and no `any` leaks into the return.
|
|
19514
|
+
const entries = raw;
|
|
19515
|
+
return entries.map((entry)=>{
|
|
19516
|
+
// Only touch plain objects; non-objects fall through to fail validation.
|
|
19517
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
19518
|
+
return entry;
|
|
19519
|
+
}
|
|
19520
|
+
const record = entry;
|
|
19521
|
+
// Older backend predating productType: default to the only type then.
|
|
19522
|
+
return record.productType === undefined ? {
|
|
19523
|
+
...record,
|
|
19524
|
+
productType: 'vault'
|
|
19525
|
+
} : record;
|
|
19526
|
+
}).filter((entry)=>{
|
|
19527
|
+
// Drop ONLY a present-but-unknown string discriminant (a future
|
|
19528
|
+
// productType this SDK version doesn't know). Everything else —
|
|
19529
|
+
// non-objects, a non-string productType — flows through to
|
|
19530
|
+
// z.array(earnOpportunitySchema) and fails/passes validation normally.
|
|
19531
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
19532
|
+
return true;
|
|
19533
|
+
}
|
|
19534
|
+
const productType = entry.productType;
|
|
19535
|
+
if (typeof productType !== 'string') {
|
|
19536
|
+
return true;
|
|
19537
|
+
}
|
|
19538
|
+
return knownProductTypes.has(productType);
|
|
19539
|
+
});
|
|
19540
|
+
}, zod.z.array(earnOpportunitySchema));
|
|
19013
19541
|
// ---------------------------------------------------------------------------
|
|
19014
19542
|
// Position response schema
|
|
19015
19543
|
// ---------------------------------------------------------------------------
|
|
@@ -19139,6 +19667,7 @@ const positionPnlSchema = zod.z.discriminatedUnion('status', [
|
|
|
19139
19667
|
*
|
|
19140
19668
|
* @internal
|
|
19141
19669
|
*/ const depositPayloadSchema = zod.z.object({
|
|
19670
|
+
execId: bridgeDepositExecIdSchema,
|
|
19142
19671
|
executionParams: depositExecutionParamsSchema,
|
|
19143
19672
|
signature: hexSignatureSchema
|
|
19144
19673
|
});
|
|
@@ -19230,6 +19759,21 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19230
19759
|
amount: amountJsonSchema,
|
|
19231
19760
|
vaultAddress: hexAddressSchema
|
|
19232
19761
|
}).passthrough();
|
|
19762
|
+
/** @internal */ const bridgeQuoteExpirySchema = zod.z.discriminatedUnion('mode', [
|
|
19763
|
+
zod.z.object({
|
|
19764
|
+
mode: zod.z.literal('TIMESTAMP'),
|
|
19765
|
+
expiresAt: zod.z.string().datetime({
|
|
19766
|
+
offset: true
|
|
19767
|
+
})
|
|
19768
|
+
}),
|
|
19769
|
+
zod.z.object({
|
|
19770
|
+
mode: zod.z.literal('BLOCK_NUMBER'),
|
|
19771
|
+
expiresAtBlock: zod.z.number().int(),
|
|
19772
|
+
blockEstimatedAt: zod.z.string().datetime({
|
|
19773
|
+
offset: true
|
|
19774
|
+
}).optional()
|
|
19775
|
+
})
|
|
19776
|
+
]).optional().catch(undefined);
|
|
19233
19777
|
/**
|
|
19234
19778
|
* Zod schema for the bridge deposit prepare payload.
|
|
19235
19779
|
*
|
|
@@ -19241,6 +19785,10 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19241
19785
|
execId: bridgeDepositExecIdSchema,
|
|
19242
19786
|
erc3009TypedData: bridgeDepositPreparedBundleSchema,
|
|
19243
19787
|
expiresAt: zod.z.string().datetime(),
|
|
19788
|
+
quoteIssuedAt: zod.z.string().datetime({
|
|
19789
|
+
offset: true
|
|
19790
|
+
}).optional().catch(undefined),
|
|
19791
|
+
quoteExpiry: bridgeQuoteExpirySchema,
|
|
19244
19792
|
review: bridgeDepositPrepareReviewSchema
|
|
19245
19793
|
});
|
|
19246
19794
|
/**
|
|
@@ -19306,6 +19854,7 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19306
19854
|
*
|
|
19307
19855
|
* @internal
|
|
19308
19856
|
*/ const withdrawPayloadSchema = zod.z.object({
|
|
19857
|
+
execId: bridgeDepositExecIdSchema,
|
|
19309
19858
|
executionParams: withdrawExecutionParamsSchema,
|
|
19310
19859
|
signature: hexSignatureSchema
|
|
19311
19860
|
});
|
|
@@ -19319,6 +19868,27 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19319
19868
|
data: withdrawPayloadSchema
|
|
19320
19869
|
});
|
|
19321
19870
|
// ---------------------------------------------------------------------------
|
|
19871
|
+
// Transaction report response schema
|
|
19872
|
+
// ---------------------------------------------------------------------------
|
|
19873
|
+
/**
|
|
19874
|
+
* Zod schema for the transaction report payload inside the API `data` envelope.
|
|
19875
|
+
*
|
|
19876
|
+
* The Earn Service returns an empty payload (`{"data":{}}`) on success, so the
|
|
19877
|
+
* schema accepts any object shape and does not require specific fields.
|
|
19878
|
+
*
|
|
19879
|
+
* @internal
|
|
19880
|
+
*/ const transactionReportPayloadSchema = zod.z.object({}).passthrough();
|
|
19881
|
+
/**
|
|
19882
|
+
* Zod schema for the `POST /v1/earnKit/transactions/report` API response.
|
|
19883
|
+
*
|
|
19884
|
+
* The Earn Service API wraps the transaction report payload in a `data`
|
|
19885
|
+
* envelope.
|
|
19886
|
+
*
|
|
19887
|
+
* @internal
|
|
19888
|
+
*/ zod.z.object({
|
|
19889
|
+
data: transactionReportPayloadSchema
|
|
19890
|
+
});
|
|
19891
|
+
// ---------------------------------------------------------------------------
|
|
19322
19892
|
// Claim rewards response schema
|
|
19323
19893
|
// ---------------------------------------------------------------------------
|
|
19324
19894
|
/**
|
|
@@ -19379,6 +19949,30 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19379
19949
|
token: zod.z.string(),
|
|
19380
19950
|
amount: amountJsonSchema
|
|
19381
19951
|
});
|
|
19952
|
+
/**
|
|
19953
|
+
* Zod schema for a native gas-fee entry in an EarnKit quote response.
|
|
19954
|
+
*
|
|
19955
|
+
* The Earn Service backend estimates gas server-side and returns one entry per
|
|
19956
|
+
* action (`Approve`, `Deposit`, `Withdraw`). A successful estimate carries
|
|
19957
|
+
* `fees` in the SDK `EstimatedGas` shape (`{ gas, gasPrice, fee }`), each a raw
|
|
19958
|
+
* integer string in the chain's native base units. When the backend cannot
|
|
19959
|
+
* estimate an action it returns `fees: null` with an `error` message instead.
|
|
19960
|
+
*
|
|
19961
|
+
* The schema deliberately validates almost nothing beyond the envelope: `name`
|
|
19962
|
+
* is optional and `fees` is entirely unvalidated (`unknown`). ALL validation
|
|
19963
|
+
* of `fees` — that it is an object at all, and that `gas`, `gasPrice`, and
|
|
19964
|
+
* `fee` are parseable integer strings — is deferred to {@link toQuoteGasFees},
|
|
19965
|
+
* which degrades a malformed entry to a `fees: null` soft failure. This is
|
|
19966
|
+
* intentional: gas is best-effort, so a single unparseable gas entry (a wrong
|
|
19967
|
+
* type such as `fees: 123` or `fees: 'bad'`, a missing field, or a non-numeric
|
|
19968
|
+
* `fee`) must never fail Zod validation and reject the entire quote.
|
|
19969
|
+
*
|
|
19970
|
+
* @internal
|
|
19971
|
+
*/ const quoteGasFeeSchema = zod.z.object({
|
|
19972
|
+
name: zod.z.string().optional(),
|
|
19973
|
+
fees: zod.z.unknown(),
|
|
19974
|
+
error: zod.z.string().optional()
|
|
19975
|
+
}).passthrough();
|
|
19382
19976
|
/**
|
|
19383
19977
|
* Zod schema for the inner deposit quote payload.
|
|
19384
19978
|
*
|
|
@@ -19394,7 +19988,8 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19394
19988
|
expectedShares: amountJsonSchema,
|
|
19395
19989
|
sharePrice: zod.z.string(),
|
|
19396
19990
|
currentApy: zod.z.number(),
|
|
19397
|
-
fees: zod.z.array(feeSchema).optional()
|
|
19991
|
+
fees: zod.z.array(feeSchema).optional(),
|
|
19992
|
+
gasFees: zod.z.array(quoteGasFeeSchema).optional()
|
|
19398
19993
|
});
|
|
19399
19994
|
/**
|
|
19400
19995
|
* Zod schema for the `POST /v1/earnKit/deposit/quote` API response.
|
|
@@ -19421,6 +20016,7 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19421
20016
|
sharePrice: zod.z.string(),
|
|
19422
20017
|
maxWithdrawable: amountJsonSchema,
|
|
19423
20018
|
fees: zod.z.array(feeSchema),
|
|
20019
|
+
gasFees: zod.z.array(quoteGasFeeSchema).optional(),
|
|
19424
20020
|
warnings: zod.z.array(zod.z.string()).optional()
|
|
19425
20021
|
});
|
|
19426
20022
|
/**
|
|
@@ -19478,7 +20074,7 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19478
20074
|
*
|
|
19479
20075
|
* @internal
|
|
19480
20076
|
*/ const getVaultsPayloadSchema = zod.z.object({
|
|
19481
|
-
vaults:
|
|
20077
|
+
vaults: earnOpportunityListSchema,
|
|
19482
20078
|
errors: zod.z.array(vaultErrorSchema)
|
|
19483
20079
|
});
|
|
19484
20080
|
/**
|
|
@@ -19508,7 +20104,7 @@ const bridgeDepositPrepareReviewSchema = zod.z.object({
|
|
|
19508
20104
|
*
|
|
19509
20105
|
* @internal
|
|
19510
20106
|
*/ const exploreVaultsPayloadSchema = zod.z.object({
|
|
19511
|
-
vaults:
|
|
20107
|
+
vaults: earnOpportunityListSchema,
|
|
19512
20108
|
pagination: explorePaginationSchema
|
|
19513
20109
|
});
|
|
19514
20110
|
/**
|