@circle-fin/app-kit 1.10.0 → 1.12.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 +73 -0
- package/README.md +56 -25
- package/bridge.cjs +297 -48
- package/bridge.d.cts +891 -2
- package/bridge.d.mts +891 -2
- package/bridge.d.ts +891 -2
- package/bridge.mjs +297 -48
- package/chains.cjs +117 -1
- package/chains.d.cts +96 -2
- package/chains.d.mts +96 -2
- package/chains.d.ts +96 -2
- package/chains.mjs +116 -2
- package/context.cjs +11 -0
- package/context.d.cts +891 -2
- package/context.d.mts +891 -2
- package/context.d.ts +891 -2
- package/context.mjs +11 -0
- package/earn.cjs +2343 -175
- package/earn.d.cts +891 -2
- package/earn.d.mts +891 -2
- package/earn.d.ts +891 -2
- package/earn.mjs +2343 -175
- package/estimateBridge.cjs +297 -48
- package/estimateBridge.d.cts +891 -2
- package/estimateBridge.d.mts +891 -2
- package/estimateBridge.d.ts +891 -2
- package/estimateBridge.mjs +297 -48
- package/estimateSwap.cjs +391 -39
- package/estimateSwap.d.cts +890 -2
- package/estimateSwap.d.mts +890 -2
- package/estimateSwap.d.ts +890 -2
- package/estimateSwap.mjs +391 -39
- package/index.cjs +2591 -315
- package/index.d.cts +2382 -1632
- package/index.d.mts +2382 -1632
- package/index.d.ts +2382 -1632
- package/index.mjs +2590 -316
- package/package.json +7 -6
- package/swap.cjs +391 -39
- package/swap.d.cts +890 -2
- package/swap.d.mts +890 -2
- package/swap.d.ts +890 -2
- package/swap.mjs +391 -39
- package/unifiedBalance.cjs +411 -132
- package/unifiedBalance.d.cts +30 -5
- package/unifiedBalance.d.mts +30 -5
- package/unifiedBalance.d.ts +30 -5
- package/unifiedBalance.mjs +411 -132
package/bridge.mjs
CHANGED
|
@@ -16,6 +16,17 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
// Buffer polyfill setup - executes before any other code
|
|
20
|
+
// Ensures globalThis.Buffer is available for Solana libraries
|
|
21
|
+
import { Buffer } from 'buffer';
|
|
22
|
+
if (typeof globalThis !== 'undefined' && typeof globalThis.Buffer === 'undefined') {
|
|
23
|
+
globalThis.Buffer = Buffer;
|
|
24
|
+
}
|
|
25
|
+
if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
|
|
26
|
+
window.Buffer = Buffer;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
19
30
|
import { z } from 'zod';
|
|
20
31
|
import pino from 'pino';
|
|
21
32
|
import { formatUnits as formatUnits$1, parseUnits as parseUnits$1 } from '@ethersproject/units';
|
|
@@ -27,6 +38,7 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
27
38
|
import 'bn.js';
|
|
28
39
|
import '@coral-xyz/anchor';
|
|
29
40
|
import '@noble/curves/ed25519';
|
|
41
|
+
import 'viem';
|
|
30
42
|
import { keccak256 } from '@ethersproject/keccak256';
|
|
31
43
|
|
|
32
44
|
// Import global type declarations
|
|
@@ -44,6 +56,27 @@ import { keccak256 } from '@ethersproject/keccak256';
|
|
|
44
56
|
* }
|
|
45
57
|
* ```
|
|
46
58
|
*/ const isNodeEnvironment = ()=>typeof process !== 'undefined' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
|
|
59
|
+
/**
|
|
60
|
+
* Return the SDK User-Agent request header only when running in Node.js.
|
|
61
|
+
*
|
|
62
|
+
* Browsers forbid manually setting `User-Agent`, and a custom fallback header
|
|
63
|
+
* can trigger CORS preflight. Non-Node server runtimes also omit this optional
|
|
64
|
+
* attribution header because they cannot set it reliably.
|
|
65
|
+
*
|
|
66
|
+
* @returns A User-Agent header in Node.js, or an empty object otherwise.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { getNodeUserAgentHeader } from '@core/utils'
|
|
71
|
+
*
|
|
72
|
+
* const headers = {
|
|
73
|
+
* 'Content-Type': 'application/json',
|
|
74
|
+
* ...getNodeUserAgentHeader(),
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/ const getNodeUserAgentHeader = ()=>isNodeEnvironment() ? {
|
|
78
|
+
'User-Agent': getUserAgent()
|
|
79
|
+
} : {};
|
|
47
80
|
/**
|
|
48
81
|
* Detect the runtime environment and return a shortened identifier.
|
|
49
82
|
*
|
|
@@ -2523,6 +2556,8 @@ class KitError extends Error {
|
|
|
2523
2556
|
Blockchain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
|
|
2524
2557
|
Blockchain["XDC"] = "XDC";
|
|
2525
2558
|
Blockchain["XDC_Apothem"] = "XDC_Apothem";
|
|
2559
|
+
Blockchain["X_Layer"] = "X_Layer";
|
|
2560
|
+
Blockchain["X_Layer_Testnet"] = "X_Layer_Testnet";
|
|
2526
2561
|
Blockchain["ZKSync_Era"] = "ZKSync_Era";
|
|
2527
2562
|
Blockchain["ZKSync_Sepolia"] = "ZKSync_Sepolia";
|
|
2528
2563
|
})(Blockchain || (Blockchain = {}));
|
|
@@ -2576,6 +2611,7 @@ var BridgeChain;
|
|
|
2576
2611
|
BridgeChain["Unichain"] = "Unichain";
|
|
2577
2612
|
BridgeChain["World_Chain"] = "World_Chain";
|
|
2578
2613
|
BridgeChain["XDC"] = "XDC";
|
|
2614
|
+
BridgeChain["X_Layer"] = "X_Layer";
|
|
2579
2615
|
// Testnet chains with CCTPv2 support
|
|
2580
2616
|
BridgeChain["Arc_Testnet"] = "Arc_Testnet";
|
|
2581
2617
|
BridgeChain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
|
|
@@ -2601,6 +2637,7 @@ var BridgeChain;
|
|
|
2601
2637
|
BridgeChain["Unichain_Sepolia"] = "Unichain_Sepolia";
|
|
2602
2638
|
BridgeChain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
|
|
2603
2639
|
BridgeChain["XDC_Apothem"] = "XDC_Apothem";
|
|
2640
|
+
BridgeChain["X_Layer_Testnet"] = "X_Layer_Testnet";
|
|
2604
2641
|
})(BridgeChain || (BridgeChain = {}));
|
|
2605
2642
|
var UnifiedBalanceChain;
|
|
2606
2643
|
(function(UnifiedBalanceChain) {
|
|
@@ -5138,7 +5175,8 @@ var EarnChain;
|
|
|
5138
5175
|
isTestnet: true,
|
|
5139
5176
|
explorerUrl: 'https://amoy.polygonscan.com/tx/{hash}',
|
|
5140
5177
|
rpcEndpoints: [
|
|
5141
|
-
'https://
|
|
5178
|
+
'https://polygon-amoy-bor-rpc.publicnode.com',
|
|
5179
|
+
'https://polygon-amoy.drpc.org'
|
|
5142
5180
|
],
|
|
5143
5181
|
eurcAddress: null,
|
|
5144
5182
|
usdcAddress: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
|
|
@@ -6003,6 +6041,104 @@ var EarnChain;
|
|
|
6003
6041
|
}
|
|
6004
6042
|
});
|
|
6005
6043
|
|
|
6044
|
+
/**
|
|
6045
|
+
* X Layer Mainnet chain definition
|
|
6046
|
+
* @remarks
|
|
6047
|
+
* This represents the official production network for the X Layer blockchain.
|
|
6048
|
+
* X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
|
|
6049
|
+
* using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
|
|
6050
|
+
* OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
|
|
6051
|
+
*/ const XLayer = defineChain({
|
|
6052
|
+
type: 'evm',
|
|
6053
|
+
chain: Blockchain.X_Layer,
|
|
6054
|
+
name: 'X Layer',
|
|
6055
|
+
title: 'X Layer Mainnet',
|
|
6056
|
+
nativeCurrency: {
|
|
6057
|
+
name: 'OKB',
|
|
6058
|
+
symbol: 'OKB',
|
|
6059
|
+
decimals: 18
|
|
6060
|
+
},
|
|
6061
|
+
chainId: 196,
|
|
6062
|
+
isTestnet: false,
|
|
6063
|
+
explorerUrl: 'https://www.oklink.com/xlayer/tx/{hash}',
|
|
6064
|
+
rpcEndpoints: [
|
|
6065
|
+
'https://xlayerrpc.okx.com'
|
|
6066
|
+
],
|
|
6067
|
+
eurcAddress: null,
|
|
6068
|
+
usdcAddress: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
|
|
6069
|
+
usdtAddress: null,
|
|
6070
|
+
cctp: {
|
|
6071
|
+
domain: 37,
|
|
6072
|
+
contracts: {
|
|
6073
|
+
v2: {
|
|
6074
|
+
type: 'split',
|
|
6075
|
+
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
6076
|
+
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
6077
|
+
confirmations: 65,
|
|
6078
|
+
fastConfirmations: 1
|
|
6079
|
+
}
|
|
6080
|
+
},
|
|
6081
|
+
forwarderSupported: {
|
|
6082
|
+
source: false,
|
|
6083
|
+
destination: false
|
|
6084
|
+
}
|
|
6085
|
+
},
|
|
6086
|
+
kitContracts: {
|
|
6087
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
6088
|
+
}
|
|
6089
|
+
});
|
|
6090
|
+
|
|
6091
|
+
/**
|
|
6092
|
+
* X Layer Testnet chain definition
|
|
6093
|
+
* @remarks
|
|
6094
|
+
* This represents the official test network for the X Layer blockchain.
|
|
6095
|
+
* X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
|
|
6096
|
+
* using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
|
|
6097
|
+
* OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
|
|
6098
|
+
*/ const XLayerTestnet = defineChain({
|
|
6099
|
+
type: 'evm',
|
|
6100
|
+
chain: Blockchain.X_Layer_Testnet,
|
|
6101
|
+
name: 'X Layer Testnet',
|
|
6102
|
+
title: 'X Layer Testnet',
|
|
6103
|
+
nativeCurrency: {
|
|
6104
|
+
name: 'OKB',
|
|
6105
|
+
symbol: 'OKB',
|
|
6106
|
+
decimals: 18
|
|
6107
|
+
},
|
|
6108
|
+
chainId: 1952,
|
|
6109
|
+
isTestnet: true,
|
|
6110
|
+
// Deliberately not oklink.com (used for mainnet): viem's bundled OKLink
|
|
6111
|
+
// testnet URL targets the deprecated pre-rebrand chain ID 195, not this
|
|
6112
|
+
// chain's ID (1952). Verified against the internal chain-expansion-scripts
|
|
6113
|
+
// config (`v2config.sandbox.yml`) — do not "normalize" this to match mainnet.
|
|
6114
|
+
explorerUrl: 'https://web3.okx.com/explorer/x-layer-testnet/tx/{hash}',
|
|
6115
|
+
rpcEndpoints: [
|
|
6116
|
+
'https://testrpc.xlayer.tech'
|
|
6117
|
+
],
|
|
6118
|
+
eurcAddress: null,
|
|
6119
|
+
usdcAddress: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
|
|
6120
|
+
usdtAddress: null,
|
|
6121
|
+
cctp: {
|
|
6122
|
+
domain: 37,
|
|
6123
|
+
contracts: {
|
|
6124
|
+
v2: {
|
|
6125
|
+
type: 'split',
|
|
6126
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
6127
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
6128
|
+
confirmations: 65,
|
|
6129
|
+
fastConfirmations: 1
|
|
6130
|
+
}
|
|
6131
|
+
},
|
|
6132
|
+
forwarderSupported: {
|
|
6133
|
+
source: false,
|
|
6134
|
+
destination: false
|
|
6135
|
+
}
|
|
6136
|
+
},
|
|
6137
|
+
kitContracts: {
|
|
6138
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET
|
|
6139
|
+
}
|
|
6140
|
+
});
|
|
6141
|
+
|
|
6006
6142
|
/**
|
|
6007
6143
|
* ZKSync Era Mainnet chain definition
|
|
6008
6144
|
* @remarks
|
|
@@ -6122,6 +6258,8 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
6122
6258
|
WorldChainSepolia: WorldChainSepolia,
|
|
6123
6259
|
XDC: XDC,
|
|
6124
6260
|
XDCApothem: XDCApothem,
|
|
6261
|
+
XLayer: XLayer,
|
|
6262
|
+
XLayerTestnet: XLayerTestnet,
|
|
6125
6263
|
ZKSyncEra: ZKSyncEra,
|
|
6126
6264
|
ZKSyncEraSepolia: ZKSyncEraSepolia
|
|
6127
6265
|
});
|
|
@@ -7470,13 +7608,12 @@ const swapTokenEnumSchema = z.enum([
|
|
|
7470
7608
|
headers: {
|
|
7471
7609
|
...DEFAULT_CONFIG$1.headers,
|
|
7472
7610
|
...config.headers ?? {},
|
|
7473
|
-
//
|
|
7474
|
-
//
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
}
|
|
7611
|
+
// Browsers forbid setting a user-agent request header, and the custom
|
|
7612
|
+
// fallback header the SDK used instead trips CORS preflight against the
|
|
7613
|
+
// Circle APIs (it isn't in their `Access-Control-Allow-Headers`),
|
|
7614
|
+
// blocking the request. So send the SDK user agent only in Node;
|
|
7615
|
+
// browsers omit it entirely.
|
|
7616
|
+
...getNodeUserAgentHeader()
|
|
7480
7617
|
}
|
|
7481
7618
|
};
|
|
7482
7619
|
let lastError;
|
|
@@ -8177,6 +8314,7 @@ const swapTokenEnumSchema = z.enum([
|
|
|
8177
8314
|
[Blockchain.Unichain]: '0x078D782b760474a361dDA0AF3839290b0EF57AD6',
|
|
8178
8315
|
[Blockchain.World_Chain]: '0x79A02482A880bCE3F13e09Da970dC34db4CD24d1',
|
|
8179
8316
|
[Blockchain.XDC]: '0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1',
|
|
8317
|
+
[Blockchain.X_Layer]: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
|
|
8180
8318
|
[Blockchain.ZKSync_Era]: '0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4',
|
|
8181
8319
|
// =========================================================================
|
|
8182
8320
|
// Testnets (alphabetically sorted)
|
|
@@ -8211,6 +8349,7 @@ const swapTokenEnumSchema = z.enum([
|
|
|
8211
8349
|
[Blockchain.Unichain_Sepolia]: '0x31d0220469e10c4E71834a79b1f276d740d3768F',
|
|
8212
8350
|
[Blockchain.World_Chain_Sepolia]: '0x66145f38cBAC35Ca6F1Dfb4914dF98F1614aeA88',
|
|
8213
8351
|
[Blockchain.XDC_Apothem]: '0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4',
|
|
8352
|
+
[Blockchain.X_Layer_Testnet]: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
|
|
8214
8353
|
[Blockchain.ZKSync_Sepolia]: '0xAe045DE5638162fa134807Cb558E15A3F5A7F853'
|
|
8215
8354
|
}
|
|
8216
8355
|
};
|
|
@@ -9262,6 +9401,7 @@ function resolveOptions(options) {
|
|
|
9262
9401
|
if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
|
|
9263
9402
|
if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
|
|
9264
9403
|
if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
|
|
9404
|
+
if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
|
|
9265
9405
|
if (payload.errorDetails !== undefined) {
|
|
9266
9406
|
const errorDetails = {
|
|
9267
9407
|
...payload.errorDetails.errorCode !== undefined && {
|
|
@@ -9332,18 +9472,15 @@ function resolveOptions(options) {
|
|
|
9332
9472
|
timeoutHandle.unref();
|
|
9333
9473
|
}
|
|
9334
9474
|
try {
|
|
9335
|
-
const isNode = isNodeEnvironment();
|
|
9336
|
-
const userAgent = getUserAgent();
|
|
9337
9475
|
await fetch(getLogsUrl(), {
|
|
9338
9476
|
method: 'POST',
|
|
9339
9477
|
headers: {
|
|
9340
9478
|
'Content-Type': 'application/json',
|
|
9341
|
-
//
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
}
|
|
9479
|
+
// Browsers forbid setting a user-agent request header, and the custom
|
|
9480
|
+
// fallback header the SDK used instead trips CORS preflight (it isn't
|
|
9481
|
+
// in the telemetry endpoint's `Access-Control-Allow-Headers`), so send
|
|
9482
|
+
// it only in Node; browsers omit it entirely.
|
|
9483
|
+
...getNodeUserAgentHeader()
|
|
9347
9484
|
},
|
|
9348
9485
|
body: JSON.stringify(toSafePayload(payload)),
|
|
9349
9486
|
signal: controller.signal
|
|
@@ -9474,7 +9611,7 @@ function resolveOptions(options) {
|
|
|
9474
9611
|
// discards the stack trace, nested `cause`, and any custom Error
|
|
9475
9612
|
// properties — exactly the context an on-call needs when a
|
|
9476
9613
|
// resolver-closure regression triggers this path.
|
|
9477
|
-
console.warn(`[stablecoin-kits telemetry] dropped
|
|
9614
|
+
console.warn(`[stablecoin-kits telemetry] dropped event '${eventType}':`, cause);
|
|
9478
9615
|
} catch {
|
|
9479
9616
|
// console.warn itself throwing is the user's environment; nothing more we
|
|
9480
9617
|
// can do without risking the original operation error.
|
|
@@ -9490,7 +9627,9 @@ function resolveOptions(options) {
|
|
|
9490
9627
|
sdkVersion: config.sdkVersion,
|
|
9491
9628
|
eventType,
|
|
9492
9629
|
timestamp: new Date().toISOString(),
|
|
9493
|
-
errorDetails
|
|
9630
|
+
...errorDetails !== undefined && {
|
|
9631
|
+
errorDetails
|
|
9632
|
+
},
|
|
9494
9633
|
clientContext: buildClientContext(),
|
|
9495
9634
|
...context?.sourceChain != null && {
|
|
9496
9635
|
sourceChain: context.sourceChain
|
|
@@ -9506,6 +9645,9 @@ function resolveOptions(options) {
|
|
|
9506
9645
|
},
|
|
9507
9646
|
...context?.txHash != null && {
|
|
9508
9647
|
txHash: context.txHash
|
|
9648
|
+
},
|
|
9649
|
+
...context?.correlationId != null && {
|
|
9650
|
+
correlationId: context.correlationId
|
|
9509
9651
|
}
|
|
9510
9652
|
};
|
|
9511
9653
|
}
|
|
@@ -9619,7 +9761,7 @@ function resolveOptions(options) {
|
|
|
9619
9761
|
}
|
|
9620
9762
|
|
|
9621
9763
|
var name$2 = "@circle-fin/bridge-kit";
|
|
9622
|
-
var version$3 = "1.
|
|
9764
|
+
var version$3 = "1.13.0";
|
|
9623
9765
|
var pkg$3 = {
|
|
9624
9766
|
name: name$2,
|
|
9625
9767
|
version: version$3};
|
|
@@ -9656,13 +9798,21 @@ const assertCustomFeePolicySymbol = Symbol('assertCustomFeePolicy');
|
|
|
9656
9798
|
computeFee: z.function().returns(z.string().or(z.promise(z.string()))).optional(),
|
|
9657
9799
|
calculateFee: z.function().returns(z.string().or(z.promise(z.string()))).optional(),
|
|
9658
9800
|
resolveFeeRecipientAddress: z.function().returns(z.string().or(z.promise(z.string())))
|
|
9659
|
-
}).strict().
|
|
9801
|
+
}).strict().superRefine((data, ctx)=>{
|
|
9660
9802
|
const hasComputeFee = data.computeFee !== undefined;
|
|
9661
9803
|
const hasCalculateFee = data.calculateFee !== undefined;
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9804
|
+
if (hasComputeFee && hasCalculateFee) {
|
|
9805
|
+
ctx.addIssue({
|
|
9806
|
+
code: z.ZodIssueCode.custom,
|
|
9807
|
+
message: 'Provide either computeFee or calculateFee, not both. Use computeFee (recommended) for human-readable amounts.'
|
|
9808
|
+
});
|
|
9809
|
+
}
|
|
9810
|
+
if (!hasComputeFee && !hasCalculateFee) {
|
|
9811
|
+
ctx.addIssue({
|
|
9812
|
+
code: z.ZodIssueCode.custom,
|
|
9813
|
+
message: 'Provide either computeFee or calculateFee. Use computeFee (recommended) for human-readable amounts.'
|
|
9814
|
+
});
|
|
9815
|
+
}
|
|
9666
9816
|
});
|
|
9667
9817
|
/**
|
|
9668
9818
|
* Assert that the provided value conforms to {@link CustomFeePolicy}.
|
|
@@ -12216,7 +12366,13 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
12216
12366
|
/**
|
|
12217
12367
|
* The ASCII "cctp-forward" magic, hex-encoded (no `0x`), that a forward-friendly
|
|
12218
12368
|
* hookData must start with.
|
|
12219
|
-
|
|
12369
|
+
*
|
|
12370
|
+
* Encoded with `TextEncoder` (a browser-safe Web API) rather than `Buffer.from`
|
|
12371
|
+
* so this module-level constant does not reference the Node `Buffer` global at
|
|
12372
|
+
* import time. App Kit inlines this provider into its bundle without a Buffer polyfill, and a
|
|
12373
|
+
* bare `Buffer` here crashes browser bundles (e.g. Vite) on load — even for apps
|
|
12374
|
+
* that never touch the prepaid FORWARD path. Mirrors `buildForwardingHookData`.
|
|
12375
|
+
*/ const CCTP_FORWARD_MAGIC_HEX = Array.from(new TextEncoder().encode(CCTP_FORWARD_MAGIC_PREFIX)).map((byte)=>byte.toString(16).padStart(2, '0')).join('');
|
|
12220
12376
|
/**
|
|
12221
12377
|
* Determine whether a hookData blob begins with the `cctp-forward` envelope.
|
|
12222
12378
|
*
|
|
@@ -12417,14 +12573,32 @@ const CUSTOM_BURN_GAS_ESTIMATE_EVM = 201_525n // p99 and max are same here: 201_
|
|
|
12417
12573
|
;
|
|
12418
12574
|
const RECEIVE_MESSAGE_GAS_ESTIMATE_EVM = 237_401n // (99p: 163_963n + max: 310_839n) / 2 = 237_401n
|
|
12419
12575
|
;
|
|
12420
|
-
//
|
|
12421
|
-
//
|
|
12422
|
-
//
|
|
12423
|
-
|
|
12576
|
+
// Gas FLOORS, not ceilings — kept separate from the fee-estimate averages
|
|
12577
|
+
// above. `executePreparedChainRequest` submits
|
|
12578
|
+
// max(estimate * buffer, floor), so a chain whose real cost exceeds the floor
|
|
12579
|
+
// is covered by its own estimate, and a chain whose estimator under-reports
|
|
12580
|
+
// (Cronos: returns 30_600 where the EIP-7623 calldata floor is 45_000) is
|
|
12581
|
+
// covered by the floor.
|
|
12582
|
+
//
|
|
12583
|
+
// Two distinct chain surcharges drive these numbers, both measured live:
|
|
12584
|
+
// Sei — ~+51_500 per NEWLY CREATED storage slot (73_595 vs vanilla 22_100);
|
|
12585
|
+
// no flat per-tx surcharge (31_535, identical to Base).
|
|
12586
|
+
// Edge — ~+53_200 flat on EVERY tx (84_751 vs Base 31_535); storage priced
|
|
12587
|
+
// normally. Edge therefore fails warm as well as cold.
|
|
12588
|
+
// A floor must clear the worst COLD cost, since a slot that exists at estimate
|
|
12589
|
+
// time can be consumed before inclusion and cost a full step more on execution.
|
|
12590
|
+
// Each floor is therefore derived from the worst observed estimate *after* the
|
|
12591
|
+
// 1.25x buffer, plus headroom — sizing it below the buffered value would leave
|
|
12592
|
+
// the estimate governing and defeat the point of the floor.
|
|
12593
|
+
//
|
|
12594
|
+
// The `*_GAS_LIMIT_EVM` names are kept despite these being floors: they are
|
|
12595
|
+
// exported, so renaming to `*_GAS_FLOOR_EVM` would be a breaking change for
|
|
12596
|
+
// consumers. Read "LIMIT" here as "the limit we submit", never as a ceiling.
|
|
12597
|
+
const APPROVE_GAS_LIMIT_EVM = 150_000n // buffered worst cold 149_355 (Edge Testnet 119_484 x 1.25) + drift headroom
|
|
12424
12598
|
;
|
|
12425
|
-
const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM =
|
|
12599
|
+
const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM = 500_000n // buffered worst 474_078 (Sei 379_263 x 1.25) + ~26k headroom
|
|
12426
12600
|
;
|
|
12427
|
-
const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839
|
|
12601
|
+
const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839; clears Cronos' calldata floor ~10x
|
|
12428
12602
|
;
|
|
12429
12603
|
/**
|
|
12430
12604
|
* The minimum finality threshold for CCTPv2 transfers.
|
|
@@ -13889,6 +14063,63 @@ function hasPendingState(analysis, result) {
|
|
|
13889
14063
|
return waitForPendingTransaction(pendingStep, adapter, chain);
|
|
13890
14064
|
}
|
|
13891
14065
|
|
|
14066
|
+
/**
|
|
14067
|
+
* Multiplier applied to a successful gas estimate before it is submitted.
|
|
14068
|
+
*
|
|
14069
|
+
* Estimates are exact, not padded: Sei returns 109_739 for an approve that
|
|
14070
|
+
* consumes 107_717 (1.9% headroom). Chains that price storage in large steps
|
|
14071
|
+
* can exceed the estimate if state changes between estimation and inclusion,
|
|
14072
|
+
* so the estimate is padded before use.
|
|
14073
|
+
*
|
|
14074
|
+
* @remarks
|
|
14075
|
+
* This buffer alone does NOT cover Sei's ~51_500 per-new-slot step at approve
|
|
14076
|
+
* scale (25% of ~110_000 is only ~27_500). For approve, the FLOOR is what
|
|
14077
|
+
* covers a slot that exists at estimation time and is consumed before
|
|
14078
|
+
* inclusion — so do not lower `APPROVE_GAS_LIMIT_EVM` on the reasoning that
|
|
14079
|
+
* the estimate covers it. For burn the buffer does cover a step (25% of
|
|
14080
|
+
* ~300_000 exceeds 51_500).
|
|
14081
|
+
*/ const GAS_ESTIMATE_BUFFER_PERCENT = 125n;
|
|
14082
|
+
/**
|
|
14083
|
+
* Resolve the gas limit for an EVM request as `max(estimate * buffer, floor)`.
|
|
14084
|
+
*
|
|
14085
|
+
* Estimates first so chains whose real cost exceeds the floor are covered by
|
|
14086
|
+
* their own measurement, and falls back to the floor whenever estimation is
|
|
14087
|
+
* unavailable or under-reports. Estimation failure is never fatal here: before
|
|
14088
|
+
* floors existed these requests were submitted with a pinned limit and no
|
|
14089
|
+
* estimate at all, so degrading to the floor is never worse than the previous
|
|
14090
|
+
* behaviour.
|
|
14091
|
+
*
|
|
14092
|
+
* @param request - The prepared EVM request to size a gas limit for
|
|
14093
|
+
* @param gasFloor - The minimum gas limit to submit, in gas units
|
|
14094
|
+
* @returns The gas limit to submit, in gas units
|
|
14095
|
+
* @throws Never — estimation failures degrade to `gasFloor`
|
|
14096
|
+
*
|
|
14097
|
+
* @example
|
|
14098
|
+
* ```typescript
|
|
14099
|
+
* const gasLimit = await resolveGasLimit(request, 150_000)
|
|
14100
|
+
* ```
|
|
14101
|
+
*/ const resolveGasLimit = async (request, gasFloor)=>{
|
|
14102
|
+
try {
|
|
14103
|
+
// Deliberately called without a `fallback`: both the viem and ethers
|
|
14104
|
+
// adapters *return* the supplied fallback object when estimation reverts
|
|
14105
|
+
// rather than throwing, which would set the estimate to the floor and then
|
|
14106
|
+
// multiply it by the buffer below. Omitting it routes reverts through the
|
|
14107
|
+
// catch, so a failed estimate degrades to exactly the floor.
|
|
14108
|
+
const estimate = await request.estimate();
|
|
14109
|
+
// The arithmetic stays inside the try on purpose. `EstimatedGas.gas` is
|
|
14110
|
+
// typed `bigint`, but adapters are a public extension point and may be
|
|
14111
|
+
// implemented in plain JS, so a non-bigint `gas` would throw here
|
|
14112
|
+
// ("Cannot mix BigInt and other types"). Guarding it keeps the documented
|
|
14113
|
+
// contract — estimation never aborts a step, it degrades to the floor.
|
|
14114
|
+
const buffered = estimate.gas * GAS_ESTIMATE_BUFFER_PERCENT / 100n;
|
|
14115
|
+
// Convert before comparing: Math.max throws on BigInt operands, and gas
|
|
14116
|
+
// units are far below Number.MAX_SAFE_INTEGER so the narrowing is lossless.
|
|
14117
|
+
return Math.max(Number(buffered), gasFloor);
|
|
14118
|
+
} catch {
|
|
14119
|
+
// Estimation is best-effort; the floor is the known-safe value.
|
|
14120
|
+
return gasFloor;
|
|
14121
|
+
}
|
|
14122
|
+
};
|
|
13892
14123
|
/**
|
|
13893
14124
|
* Executes a prepared chain request and returns the result as a bridge step.
|
|
13894
14125
|
*
|
|
@@ -13902,8 +14133,8 @@ function hasPendingState(analysis, result) {
|
|
|
13902
14133
|
* - `adapter`: The adapter that will execute the transaction
|
|
13903
14134
|
* - `confirmations`: The number of confirmations to wait for (defaults to 1)
|
|
13904
14135
|
* - `timeout`: The timeout for the request in milliseconds
|
|
13905
|
-
* - `
|
|
13906
|
-
*
|
|
14136
|
+
* - `gasFloor`: Optional minimum gas limit (number); the request is submitted
|
|
14137
|
+
* with `max(estimate * 1.25, gasFloor)`. Ignored for non-EVM requests
|
|
13907
14138
|
* @returns The bridge step with the transaction details and explorer URL
|
|
13908
14139
|
* @throws If the transaction execution fails
|
|
13909
14140
|
*
|
|
@@ -13918,7 +14149,7 @@ function hasPendingState(analysis, result) {
|
|
|
13918
14149
|
* })
|
|
13919
14150
|
* console.log('Transaction hash:', step.txHash)
|
|
13920
14151
|
* ```
|
|
13921
|
-
*/ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout,
|
|
14152
|
+
*/ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout, gasFloor }) {
|
|
13922
14153
|
const step = {
|
|
13923
14154
|
name,
|
|
13924
14155
|
state: 'pending'
|
|
@@ -13931,8 +14162,8 @@ function hasPendingState(analysis, result) {
|
|
|
13931
14162
|
step.state = 'noop';
|
|
13932
14163
|
return step;
|
|
13933
14164
|
}
|
|
13934
|
-
const txHash = request.type === 'evm' &&
|
|
13935
|
-
gasLimit
|
|
14165
|
+
const txHash = request.type === 'evm' && gasFloor !== undefined ? await request.execute({
|
|
14166
|
+
gasLimit: await resolveGasLimit(request, gasFloor)
|
|
13936
14167
|
}) : await request.execute();
|
|
13937
14168
|
step.txHash = txHash;
|
|
13938
14169
|
const retryOptions = {
|
|
@@ -14006,7 +14237,7 @@ function hasPendingState(analysis, result) {
|
|
|
14006
14237
|
adapter: params.source.adapter,
|
|
14007
14238
|
chain: params.source.chain,
|
|
14008
14239
|
request: await provider.approve(params.source, approvalAmount),
|
|
14009
|
-
|
|
14240
|
+
gasFloor: Number(APPROVE_GAS_LIMIT_EVM)
|
|
14010
14241
|
});
|
|
14011
14242
|
}
|
|
14012
14243
|
|
|
@@ -14034,7 +14265,7 @@ function hasPendingState(analysis, result) {
|
|
|
14034
14265
|
adapter: params.source.adapter,
|
|
14035
14266
|
chain: params.source.chain,
|
|
14036
14267
|
request: await provider.burn(params),
|
|
14037
|
-
|
|
14268
|
+
gasFloor: Number(DEPOSIT_FOR_BURN_GAS_LIMIT_EVM)
|
|
14038
14269
|
});
|
|
14039
14270
|
}
|
|
14040
14271
|
|
|
@@ -14128,10 +14359,9 @@ function hasPendingState(analysis, result) {
|
|
|
14128
14359
|
request: mintRequest,
|
|
14129
14360
|
// Some chains (e.g. Cronos) enforce an EIP-7623 calldata gas floor that
|
|
14130
14361
|
// eth_estimateGas does not account for, returning a below-floor value
|
|
14131
|
-
// without reverting.
|
|
14132
|
-
//
|
|
14133
|
-
|
|
14134
|
-
gasLimit: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
|
|
14362
|
+
// without reverting. The floor covers those; chains that cost more than the
|
|
14363
|
+
// floor are covered by their own estimate.
|
|
14364
|
+
gasFloor: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
|
|
14135
14365
|
});
|
|
14136
14366
|
// Add forwarded: false for non-relayer mints
|
|
14137
14367
|
return {
|
|
@@ -14654,7 +14884,7 @@ const mockAttestationMessage = {
|
|
|
14654
14884
|
return step;
|
|
14655
14885
|
}
|
|
14656
14886
|
|
|
14657
|
-
var version$2 = "1.10.
|
|
14887
|
+
var version$2 = "1.10.2";
|
|
14658
14888
|
var pkg$2 = {
|
|
14659
14889
|
version: version$2};
|
|
14660
14890
|
|
|
@@ -17252,7 +17482,9 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
17252
17482
|
headers: context.headers
|
|
17253
17483
|
}
|
|
17254
17484
|
});
|
|
17255
|
-
if (
|
|
17485
|
+
if (context.customFeePolicy?.bridge != null) {
|
|
17486
|
+
kit.setCustomFeePolicy(context.customFeePolicy.bridge);
|
|
17487
|
+
} else if (hasBoth) {
|
|
17256
17488
|
kit.setCustomFeePolicy({
|
|
17257
17489
|
calculateFee: async (params)=>{
|
|
17258
17490
|
const feeStr = await getFee('bridge', params);
|
|
@@ -17268,7 +17500,7 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
17268
17500
|
};
|
|
17269
17501
|
|
|
17270
17502
|
var name$1 = "@circle-fin/swap-kit";
|
|
17271
|
-
var version$1 = "1.
|
|
17503
|
+
var version$1 = "1.5.1";
|
|
17272
17504
|
var pkg$1 = {
|
|
17273
17505
|
name: name$1,
|
|
17274
17506
|
version: version$1};
|
|
@@ -18009,6 +18241,16 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
18009
18241
|
required_error: 'estimatedAmount is required',
|
|
18010
18242
|
invalid_type_error: 'estimatedAmount must be a string'
|
|
18011
18243
|
}).min(1, 'estimatedAmount must be a non-empty string'),
|
|
18244
|
+
// Per-swap join key echoed back verbatim on success telemetry. Optional so a
|
|
18245
|
+
// not-yet-upgraded service (no field) still validates during rollout. A
|
|
18246
|
+
// malformed/non-UUID value is coerced to `undefined` (no telemetry id) rather
|
|
18247
|
+
// than throwing: this is a telemetry-only field (stripped from the developer
|
|
18248
|
+
// result, never used for control flow), so it must not be able to abort the
|
|
18249
|
+
// swap via `parseCreateSwapResponse().parse()`. Mirrors the best-effort,
|
|
18250
|
+
// never-throw contract of the rest of the telemetry stack. Implemented with
|
|
18251
|
+
// `preprocess` rather than Zod's `.catch()` because static analysis misreads
|
|
18252
|
+
// `.catch` on the schema chain as an unhandled Promise (S7785).
|
|
18253
|
+
correlationId: z.preprocess((value)=>z.string().uuid().safeParse(value).success ? value : undefined, z.string().optional()),
|
|
18012
18254
|
config: createSwapRequestBaseSchema.shape.config.optional(),
|
|
18013
18255
|
fees: createSwapFeesSchema.optional(),
|
|
18014
18256
|
transaction: createSwapTransactionSchema
|
|
@@ -19201,7 +19443,7 @@ new Set(Object.values(Blockchain));
|
|
|
19201
19443
|
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
19202
19444
|
|
|
19203
19445
|
var name = "@circle-fin/earn-kit";
|
|
19204
|
-
var version = "1.
|
|
19446
|
+
var version = "1.5.0";
|
|
19205
19447
|
var pkg = {
|
|
19206
19448
|
name: name,
|
|
19207
19449
|
version: version};
|
|
@@ -20212,11 +20454,16 @@ const sourceAdapterContextSchema = z.object({
|
|
|
20212
20454
|
*
|
|
20213
20455
|
* Validate the optional Kit Key field using the standard `apiKeySchema`
|
|
20214
20456
|
* format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
|
|
20215
|
-
* operates in permissionless mode.
|
|
20457
|
+
* operates in permissionless mode. `baseUrl` overrides the Earn Service
|
|
20458
|
+
* endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
|
|
20459
|
+
* batched execution. Both are forwarded to the provider, so this `.strict()`
|
|
20460
|
+
* schema must accept them or a valid config object is rejected.
|
|
20216
20461
|
*
|
|
20217
20462
|
* @internal
|
|
20218
20463
|
*/ const earnConfigSchema = z.object({
|
|
20219
|
-
kitKey: apiKeySchema.optional()
|
|
20464
|
+
kitKey: apiKeySchema.optional(),
|
|
20465
|
+
baseUrl: z.string().optional(),
|
|
20466
|
+
batchTransactions: z.boolean().optional()
|
|
20220
20467
|
}).strict();
|
|
20221
20468
|
/**
|
|
20222
20469
|
* Canonical decimal form: a leading digit with no leading zeros (a single
|
|
@@ -20665,6 +20912,8 @@ function hasCrossChainDepositQuoteShape(params) {
|
|
|
20665
20912
|
config: earnConfigSchema.optional()
|
|
20666
20913
|
});
|
|
20667
20914
|
|
|
20915
|
+
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg.name);
|
|
20916
|
+
|
|
20668
20917
|
// Auto-register this kit for user agent tracking
|
|
20669
20918
|
registerKit(`${pkg.name}/${pkg.version}`);
|
|
20670
20919
|
|