@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.cjs
CHANGED
|
@@ -18,6 +18,17 @@
|
|
|
18
18
|
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
21
|
+
// Buffer polyfill setup - executes before any other code
|
|
22
|
+
// Ensures globalThis.Buffer is available for Solana libraries
|
|
23
|
+
const { Buffer } = require('buffer');
|
|
24
|
+
if (typeof globalThis !== 'undefined' && typeof globalThis.Buffer === 'undefined') {
|
|
25
|
+
globalThis.Buffer = Buffer;
|
|
26
|
+
}
|
|
27
|
+
if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
|
|
28
|
+
window.Buffer = Buffer;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
21
32
|
var zod = require('zod');
|
|
22
33
|
var pino = require('pino');
|
|
23
34
|
var units = require('@ethersproject/units');
|
|
@@ -29,6 +40,7 @@ var web3_js = require('@solana/web3.js');
|
|
|
29
40
|
require('bn.js');
|
|
30
41
|
require('@coral-xyz/anchor');
|
|
31
42
|
require('@noble/curves/ed25519');
|
|
43
|
+
require('viem');
|
|
32
44
|
var keccak256 = require('@ethersproject/keccak256');
|
|
33
45
|
|
|
34
46
|
function _interopDefault (e) { return e && e.__esModule ? e.default : e; }
|
|
@@ -51,6 +63,27 @@ var bs58__default = /*#__PURE__*/_interopDefault(bs58);
|
|
|
51
63
|
* }
|
|
52
64
|
* ```
|
|
53
65
|
*/ const isNodeEnvironment = ()=>typeof process !== 'undefined' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
|
|
66
|
+
/**
|
|
67
|
+
* Return the SDK User-Agent request header only when running in Node.js.
|
|
68
|
+
*
|
|
69
|
+
* Browsers forbid manually setting `User-Agent`, and a custom fallback header
|
|
70
|
+
* can trigger CORS preflight. Non-Node server runtimes also omit this optional
|
|
71
|
+
* attribution header because they cannot set it reliably.
|
|
72
|
+
*
|
|
73
|
+
* @returns A User-Agent header in Node.js, or an empty object otherwise.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { getNodeUserAgentHeader } from '@core/utils'
|
|
78
|
+
*
|
|
79
|
+
* const headers = {
|
|
80
|
+
* 'Content-Type': 'application/json',
|
|
81
|
+
* ...getNodeUserAgentHeader(),
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/ const getNodeUserAgentHeader = ()=>isNodeEnvironment() ? {
|
|
85
|
+
'User-Agent': getUserAgent()
|
|
86
|
+
} : {};
|
|
54
87
|
/**
|
|
55
88
|
* Detect the runtime environment and return a shortened identifier.
|
|
56
89
|
*
|
|
@@ -2530,6 +2563,8 @@ class KitError extends Error {
|
|
|
2530
2563
|
Blockchain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
|
|
2531
2564
|
Blockchain["XDC"] = "XDC";
|
|
2532
2565
|
Blockchain["XDC_Apothem"] = "XDC_Apothem";
|
|
2566
|
+
Blockchain["X_Layer"] = "X_Layer";
|
|
2567
|
+
Blockchain["X_Layer_Testnet"] = "X_Layer_Testnet";
|
|
2533
2568
|
Blockchain["ZKSync_Era"] = "ZKSync_Era";
|
|
2534
2569
|
Blockchain["ZKSync_Sepolia"] = "ZKSync_Sepolia";
|
|
2535
2570
|
})(Blockchain || (Blockchain = {}));
|
|
@@ -2583,6 +2618,7 @@ var BridgeChain;
|
|
|
2583
2618
|
BridgeChain["Unichain"] = "Unichain";
|
|
2584
2619
|
BridgeChain["World_Chain"] = "World_Chain";
|
|
2585
2620
|
BridgeChain["XDC"] = "XDC";
|
|
2621
|
+
BridgeChain["X_Layer"] = "X_Layer";
|
|
2586
2622
|
// Testnet chains with CCTPv2 support
|
|
2587
2623
|
BridgeChain["Arc_Testnet"] = "Arc_Testnet";
|
|
2588
2624
|
BridgeChain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
|
|
@@ -2608,6 +2644,7 @@ var BridgeChain;
|
|
|
2608
2644
|
BridgeChain["Unichain_Sepolia"] = "Unichain_Sepolia";
|
|
2609
2645
|
BridgeChain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
|
|
2610
2646
|
BridgeChain["XDC_Apothem"] = "XDC_Apothem";
|
|
2647
|
+
BridgeChain["X_Layer_Testnet"] = "X_Layer_Testnet";
|
|
2611
2648
|
})(BridgeChain || (BridgeChain = {}));
|
|
2612
2649
|
var UnifiedBalanceChain;
|
|
2613
2650
|
(function(UnifiedBalanceChain) {
|
|
@@ -5145,7 +5182,8 @@ var EarnChain;
|
|
|
5145
5182
|
isTestnet: true,
|
|
5146
5183
|
explorerUrl: 'https://amoy.polygonscan.com/tx/{hash}',
|
|
5147
5184
|
rpcEndpoints: [
|
|
5148
|
-
'https://
|
|
5185
|
+
'https://polygon-amoy-bor-rpc.publicnode.com',
|
|
5186
|
+
'https://polygon-amoy.drpc.org'
|
|
5149
5187
|
],
|
|
5150
5188
|
eurcAddress: null,
|
|
5151
5189
|
usdcAddress: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
|
|
@@ -6010,6 +6048,104 @@ var EarnChain;
|
|
|
6010
6048
|
}
|
|
6011
6049
|
});
|
|
6012
6050
|
|
|
6051
|
+
/**
|
|
6052
|
+
* X Layer Mainnet chain definition
|
|
6053
|
+
* @remarks
|
|
6054
|
+
* This represents the official production network for the X Layer blockchain.
|
|
6055
|
+
* X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
|
|
6056
|
+
* using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
|
|
6057
|
+
* OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
|
|
6058
|
+
*/ const XLayer = defineChain({
|
|
6059
|
+
type: 'evm',
|
|
6060
|
+
chain: Blockchain.X_Layer,
|
|
6061
|
+
name: 'X Layer',
|
|
6062
|
+
title: 'X Layer Mainnet',
|
|
6063
|
+
nativeCurrency: {
|
|
6064
|
+
name: 'OKB',
|
|
6065
|
+
symbol: 'OKB',
|
|
6066
|
+
decimals: 18
|
|
6067
|
+
},
|
|
6068
|
+
chainId: 196,
|
|
6069
|
+
isTestnet: false,
|
|
6070
|
+
explorerUrl: 'https://www.oklink.com/xlayer/tx/{hash}',
|
|
6071
|
+
rpcEndpoints: [
|
|
6072
|
+
'https://xlayerrpc.okx.com'
|
|
6073
|
+
],
|
|
6074
|
+
eurcAddress: null,
|
|
6075
|
+
usdcAddress: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
|
|
6076
|
+
usdtAddress: null,
|
|
6077
|
+
cctp: {
|
|
6078
|
+
domain: 37,
|
|
6079
|
+
contracts: {
|
|
6080
|
+
v2: {
|
|
6081
|
+
type: 'split',
|
|
6082
|
+
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
6083
|
+
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
6084
|
+
confirmations: 65,
|
|
6085
|
+
fastConfirmations: 1
|
|
6086
|
+
}
|
|
6087
|
+
},
|
|
6088
|
+
forwarderSupported: {
|
|
6089
|
+
source: false,
|
|
6090
|
+
destination: false
|
|
6091
|
+
}
|
|
6092
|
+
},
|
|
6093
|
+
kitContracts: {
|
|
6094
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
6095
|
+
}
|
|
6096
|
+
});
|
|
6097
|
+
|
|
6098
|
+
/**
|
|
6099
|
+
* X Layer Testnet chain definition
|
|
6100
|
+
* @remarks
|
|
6101
|
+
* This represents the official test network for the X Layer blockchain.
|
|
6102
|
+
* X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
|
|
6103
|
+
* using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
|
|
6104
|
+
* OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
|
|
6105
|
+
*/ const XLayerTestnet = defineChain({
|
|
6106
|
+
type: 'evm',
|
|
6107
|
+
chain: Blockchain.X_Layer_Testnet,
|
|
6108
|
+
name: 'X Layer Testnet',
|
|
6109
|
+
title: 'X Layer Testnet',
|
|
6110
|
+
nativeCurrency: {
|
|
6111
|
+
name: 'OKB',
|
|
6112
|
+
symbol: 'OKB',
|
|
6113
|
+
decimals: 18
|
|
6114
|
+
},
|
|
6115
|
+
chainId: 1952,
|
|
6116
|
+
isTestnet: true,
|
|
6117
|
+
// Deliberately not oklink.com (used for mainnet): viem's bundled OKLink
|
|
6118
|
+
// testnet URL targets the deprecated pre-rebrand chain ID 195, not this
|
|
6119
|
+
// chain's ID (1952). Verified against the internal chain-expansion-scripts
|
|
6120
|
+
// config (`v2config.sandbox.yml`) — do not "normalize" this to match mainnet.
|
|
6121
|
+
explorerUrl: 'https://web3.okx.com/explorer/x-layer-testnet/tx/{hash}',
|
|
6122
|
+
rpcEndpoints: [
|
|
6123
|
+
'https://testrpc.xlayer.tech'
|
|
6124
|
+
],
|
|
6125
|
+
eurcAddress: null,
|
|
6126
|
+
usdcAddress: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
|
|
6127
|
+
usdtAddress: null,
|
|
6128
|
+
cctp: {
|
|
6129
|
+
domain: 37,
|
|
6130
|
+
contracts: {
|
|
6131
|
+
v2: {
|
|
6132
|
+
type: 'split',
|
|
6133
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
6134
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
6135
|
+
confirmations: 65,
|
|
6136
|
+
fastConfirmations: 1
|
|
6137
|
+
}
|
|
6138
|
+
},
|
|
6139
|
+
forwarderSupported: {
|
|
6140
|
+
source: false,
|
|
6141
|
+
destination: false
|
|
6142
|
+
}
|
|
6143
|
+
},
|
|
6144
|
+
kitContracts: {
|
|
6145
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET
|
|
6146
|
+
}
|
|
6147
|
+
});
|
|
6148
|
+
|
|
6013
6149
|
/**
|
|
6014
6150
|
* ZKSync Era Mainnet chain definition
|
|
6015
6151
|
* @remarks
|
|
@@ -6129,6 +6265,8 @@ var Chains = {
|
|
|
6129
6265
|
WorldChainSepolia: WorldChainSepolia,
|
|
6130
6266
|
XDC: XDC,
|
|
6131
6267
|
XDCApothem: XDCApothem,
|
|
6268
|
+
XLayer: XLayer,
|
|
6269
|
+
XLayerTestnet: XLayerTestnet,
|
|
6132
6270
|
ZKSyncEra: ZKSyncEra,
|
|
6133
6271
|
ZKSyncEraSepolia: ZKSyncEraSepolia
|
|
6134
6272
|
};
|
|
@@ -7477,13 +7615,12 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
7477
7615
|
headers: {
|
|
7478
7616
|
...DEFAULT_CONFIG$1.headers,
|
|
7479
7617
|
...config.headers ?? {},
|
|
7480
|
-
//
|
|
7481
|
-
//
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
}
|
|
7618
|
+
// Browsers forbid setting a user-agent request header, and the custom
|
|
7619
|
+
// fallback header the SDK used instead trips CORS preflight against the
|
|
7620
|
+
// Circle APIs (it isn't in their `Access-Control-Allow-Headers`),
|
|
7621
|
+
// blocking the request. So send the SDK user agent only in Node;
|
|
7622
|
+
// browsers omit it entirely.
|
|
7623
|
+
...getNodeUserAgentHeader()
|
|
7487
7624
|
}
|
|
7488
7625
|
};
|
|
7489
7626
|
let lastError;
|
|
@@ -8184,6 +8321,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
8184
8321
|
[Blockchain.Unichain]: '0x078D782b760474a361dDA0AF3839290b0EF57AD6',
|
|
8185
8322
|
[Blockchain.World_Chain]: '0x79A02482A880bCE3F13e09Da970dC34db4CD24d1',
|
|
8186
8323
|
[Blockchain.XDC]: '0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1',
|
|
8324
|
+
[Blockchain.X_Layer]: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
|
|
8187
8325
|
[Blockchain.ZKSync_Era]: '0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4',
|
|
8188
8326
|
// =========================================================================
|
|
8189
8327
|
// Testnets (alphabetically sorted)
|
|
@@ -8218,6 +8356,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
8218
8356
|
[Blockchain.Unichain_Sepolia]: '0x31d0220469e10c4E71834a79b1f276d740d3768F',
|
|
8219
8357
|
[Blockchain.World_Chain_Sepolia]: '0x66145f38cBAC35Ca6F1Dfb4914dF98F1614aeA88',
|
|
8220
8358
|
[Blockchain.XDC_Apothem]: '0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4',
|
|
8359
|
+
[Blockchain.X_Layer_Testnet]: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
|
|
8221
8360
|
[Blockchain.ZKSync_Sepolia]: '0xAe045DE5638162fa134807Cb558E15A3F5A7F853'
|
|
8222
8361
|
}
|
|
8223
8362
|
};
|
|
@@ -9269,6 +9408,7 @@ function resolveOptions(options) {
|
|
|
9269
9408
|
if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
|
|
9270
9409
|
if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
|
|
9271
9410
|
if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
|
|
9411
|
+
if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
|
|
9272
9412
|
if (payload.errorDetails !== undefined) {
|
|
9273
9413
|
const errorDetails = {
|
|
9274
9414
|
...payload.errorDetails.errorCode !== undefined && {
|
|
@@ -9339,18 +9479,15 @@ function resolveOptions(options) {
|
|
|
9339
9479
|
timeoutHandle.unref();
|
|
9340
9480
|
}
|
|
9341
9481
|
try {
|
|
9342
|
-
const isNode = isNodeEnvironment();
|
|
9343
|
-
const userAgent = getUserAgent();
|
|
9344
9482
|
await fetch(getLogsUrl(), {
|
|
9345
9483
|
method: 'POST',
|
|
9346
9484
|
headers: {
|
|
9347
9485
|
'Content-Type': 'application/json',
|
|
9348
|
-
//
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
}
|
|
9486
|
+
// Browsers forbid setting a user-agent request header, and the custom
|
|
9487
|
+
// fallback header the SDK used instead trips CORS preflight (it isn't
|
|
9488
|
+
// in the telemetry endpoint's `Access-Control-Allow-Headers`), so send
|
|
9489
|
+
// it only in Node; browsers omit it entirely.
|
|
9490
|
+
...getNodeUserAgentHeader()
|
|
9354
9491
|
},
|
|
9355
9492
|
body: JSON.stringify(toSafePayload(payload)),
|
|
9356
9493
|
signal: controller.signal
|
|
@@ -9481,7 +9618,7 @@ function resolveOptions(options) {
|
|
|
9481
9618
|
// discards the stack trace, nested `cause`, and any custom Error
|
|
9482
9619
|
// properties — exactly the context an on-call needs when a
|
|
9483
9620
|
// resolver-closure regression triggers this path.
|
|
9484
|
-
console.warn(`[stablecoin-kits telemetry] dropped
|
|
9621
|
+
console.warn(`[stablecoin-kits telemetry] dropped event '${eventType}':`, cause);
|
|
9485
9622
|
} catch {
|
|
9486
9623
|
// console.warn itself throwing is the user's environment; nothing more we
|
|
9487
9624
|
// can do without risking the original operation error.
|
|
@@ -9497,7 +9634,9 @@ function resolveOptions(options) {
|
|
|
9497
9634
|
sdkVersion: config.sdkVersion,
|
|
9498
9635
|
eventType,
|
|
9499
9636
|
timestamp: new Date().toISOString(),
|
|
9500
|
-
errorDetails
|
|
9637
|
+
...errorDetails !== undefined && {
|
|
9638
|
+
errorDetails
|
|
9639
|
+
},
|
|
9501
9640
|
clientContext: buildClientContext(),
|
|
9502
9641
|
...context?.sourceChain != null && {
|
|
9503
9642
|
sourceChain: context.sourceChain
|
|
@@ -9513,6 +9652,9 @@ function resolveOptions(options) {
|
|
|
9513
9652
|
},
|
|
9514
9653
|
...context?.txHash != null && {
|
|
9515
9654
|
txHash: context.txHash
|
|
9655
|
+
},
|
|
9656
|
+
...context?.correlationId != null && {
|
|
9657
|
+
correlationId: context.correlationId
|
|
9516
9658
|
}
|
|
9517
9659
|
};
|
|
9518
9660
|
}
|
|
@@ -9626,7 +9768,7 @@ function resolveOptions(options) {
|
|
|
9626
9768
|
}
|
|
9627
9769
|
|
|
9628
9770
|
var name$2 = "@circle-fin/bridge-kit";
|
|
9629
|
-
var version$3 = "1.
|
|
9771
|
+
var version$3 = "1.13.0";
|
|
9630
9772
|
var pkg$3 = {
|
|
9631
9773
|
name: name$2,
|
|
9632
9774
|
version: version$3};
|
|
@@ -9663,13 +9805,21 @@ const assertCustomFeePolicySymbol = Symbol('assertCustomFeePolicy');
|
|
|
9663
9805
|
computeFee: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string()))).optional(),
|
|
9664
9806
|
calculateFee: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string()))).optional(),
|
|
9665
9807
|
resolveFeeRecipientAddress: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string())))
|
|
9666
|
-
}).strict().
|
|
9808
|
+
}).strict().superRefine((data, ctx)=>{
|
|
9667
9809
|
const hasComputeFee = data.computeFee !== undefined;
|
|
9668
9810
|
const hasCalculateFee = data.calculateFee !== undefined;
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9811
|
+
if (hasComputeFee && hasCalculateFee) {
|
|
9812
|
+
ctx.addIssue({
|
|
9813
|
+
code: zod.z.ZodIssueCode.custom,
|
|
9814
|
+
message: 'Provide either computeFee or calculateFee, not both. Use computeFee (recommended) for human-readable amounts.'
|
|
9815
|
+
});
|
|
9816
|
+
}
|
|
9817
|
+
if (!hasComputeFee && !hasCalculateFee) {
|
|
9818
|
+
ctx.addIssue({
|
|
9819
|
+
code: zod.z.ZodIssueCode.custom,
|
|
9820
|
+
message: 'Provide either computeFee or calculateFee. Use computeFee (recommended) for human-readable amounts.'
|
|
9821
|
+
});
|
|
9822
|
+
}
|
|
9673
9823
|
});
|
|
9674
9824
|
/**
|
|
9675
9825
|
* Assert that the provided value conforms to {@link CustomFeePolicy}.
|
|
@@ -12223,7 +12373,13 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
12223
12373
|
/**
|
|
12224
12374
|
* The ASCII "cctp-forward" magic, hex-encoded (no `0x`), that a forward-friendly
|
|
12225
12375
|
* hookData must start with.
|
|
12226
|
-
|
|
12376
|
+
*
|
|
12377
|
+
* Encoded with `TextEncoder` (a browser-safe Web API) rather than `Buffer.from`
|
|
12378
|
+
* so this module-level constant does not reference the Node `Buffer` global at
|
|
12379
|
+
* import time. App Kit inlines this provider into its bundle without a Buffer polyfill, and a
|
|
12380
|
+
* bare `Buffer` here crashes browser bundles (e.g. Vite) on load — even for apps
|
|
12381
|
+
* that never touch the prepaid FORWARD path. Mirrors `buildForwardingHookData`.
|
|
12382
|
+
*/ const CCTP_FORWARD_MAGIC_HEX = Array.from(new TextEncoder().encode(CCTP_FORWARD_MAGIC_PREFIX)).map((byte)=>byte.toString(16).padStart(2, '0')).join('');
|
|
12227
12383
|
/**
|
|
12228
12384
|
* Determine whether a hookData blob begins with the `cctp-forward` envelope.
|
|
12229
12385
|
*
|
|
@@ -12424,14 +12580,32 @@ const CUSTOM_BURN_GAS_ESTIMATE_EVM = 201_525n // p99 and max are same here: 201_
|
|
|
12424
12580
|
;
|
|
12425
12581
|
const RECEIVE_MESSAGE_GAS_ESTIMATE_EVM = 237_401n // (99p: 163_963n + max: 310_839n) / 2 = 237_401n
|
|
12426
12582
|
;
|
|
12427
|
-
//
|
|
12428
|
-
//
|
|
12429
|
-
//
|
|
12430
|
-
|
|
12583
|
+
// Gas FLOORS, not ceilings — kept separate from the fee-estimate averages
|
|
12584
|
+
// above. `executePreparedChainRequest` submits
|
|
12585
|
+
// max(estimate * buffer, floor), so a chain whose real cost exceeds the floor
|
|
12586
|
+
// is covered by its own estimate, and a chain whose estimator under-reports
|
|
12587
|
+
// (Cronos: returns 30_600 where the EIP-7623 calldata floor is 45_000) is
|
|
12588
|
+
// covered by the floor.
|
|
12589
|
+
//
|
|
12590
|
+
// Two distinct chain surcharges drive these numbers, both measured live:
|
|
12591
|
+
// Sei — ~+51_500 per NEWLY CREATED storage slot (73_595 vs vanilla 22_100);
|
|
12592
|
+
// no flat per-tx surcharge (31_535, identical to Base).
|
|
12593
|
+
// Edge — ~+53_200 flat on EVERY tx (84_751 vs Base 31_535); storage priced
|
|
12594
|
+
// normally. Edge therefore fails warm as well as cold.
|
|
12595
|
+
// A floor must clear the worst COLD cost, since a slot that exists at estimate
|
|
12596
|
+
// time can be consumed before inclusion and cost a full step more on execution.
|
|
12597
|
+
// Each floor is therefore derived from the worst observed estimate *after* the
|
|
12598
|
+
// 1.25x buffer, plus headroom — sizing it below the buffered value would leave
|
|
12599
|
+
// the estimate governing and defeat the point of the floor.
|
|
12600
|
+
//
|
|
12601
|
+
// The `*_GAS_LIMIT_EVM` names are kept despite these being floors: they are
|
|
12602
|
+
// exported, so renaming to `*_GAS_FLOOR_EVM` would be a breaking change for
|
|
12603
|
+
// consumers. Read "LIMIT" here as "the limit we submit", never as a ceiling.
|
|
12604
|
+
const APPROVE_GAS_LIMIT_EVM = 150_000n // buffered worst cold 149_355 (Edge Testnet 119_484 x 1.25) + drift headroom
|
|
12431
12605
|
;
|
|
12432
|
-
const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM =
|
|
12606
|
+
const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM = 500_000n // buffered worst 474_078 (Sei 379_263 x 1.25) + ~26k headroom
|
|
12433
12607
|
;
|
|
12434
|
-
const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839
|
|
12608
|
+
const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839; clears Cronos' calldata floor ~10x
|
|
12435
12609
|
;
|
|
12436
12610
|
/**
|
|
12437
12611
|
* The minimum finality threshold for CCTPv2 transfers.
|
|
@@ -13896,6 +14070,63 @@ function hasPendingState(analysis, result) {
|
|
|
13896
14070
|
return waitForPendingTransaction(pendingStep, adapter, chain);
|
|
13897
14071
|
}
|
|
13898
14072
|
|
|
14073
|
+
/**
|
|
14074
|
+
* Multiplier applied to a successful gas estimate before it is submitted.
|
|
14075
|
+
*
|
|
14076
|
+
* Estimates are exact, not padded: Sei returns 109_739 for an approve that
|
|
14077
|
+
* consumes 107_717 (1.9% headroom). Chains that price storage in large steps
|
|
14078
|
+
* can exceed the estimate if state changes between estimation and inclusion,
|
|
14079
|
+
* so the estimate is padded before use.
|
|
14080
|
+
*
|
|
14081
|
+
* @remarks
|
|
14082
|
+
* This buffer alone does NOT cover Sei's ~51_500 per-new-slot step at approve
|
|
14083
|
+
* scale (25% of ~110_000 is only ~27_500). For approve, the FLOOR is what
|
|
14084
|
+
* covers a slot that exists at estimation time and is consumed before
|
|
14085
|
+
* inclusion — so do not lower `APPROVE_GAS_LIMIT_EVM` on the reasoning that
|
|
14086
|
+
* the estimate covers it. For burn the buffer does cover a step (25% of
|
|
14087
|
+
* ~300_000 exceeds 51_500).
|
|
14088
|
+
*/ const GAS_ESTIMATE_BUFFER_PERCENT = 125n;
|
|
14089
|
+
/**
|
|
14090
|
+
* Resolve the gas limit for an EVM request as `max(estimate * buffer, floor)`.
|
|
14091
|
+
*
|
|
14092
|
+
* Estimates first so chains whose real cost exceeds the floor are covered by
|
|
14093
|
+
* their own measurement, and falls back to the floor whenever estimation is
|
|
14094
|
+
* unavailable or under-reports. Estimation failure is never fatal here: before
|
|
14095
|
+
* floors existed these requests were submitted with a pinned limit and no
|
|
14096
|
+
* estimate at all, so degrading to the floor is never worse than the previous
|
|
14097
|
+
* behaviour.
|
|
14098
|
+
*
|
|
14099
|
+
* @param request - The prepared EVM request to size a gas limit for
|
|
14100
|
+
* @param gasFloor - The minimum gas limit to submit, in gas units
|
|
14101
|
+
* @returns The gas limit to submit, in gas units
|
|
14102
|
+
* @throws Never — estimation failures degrade to `gasFloor`
|
|
14103
|
+
*
|
|
14104
|
+
* @example
|
|
14105
|
+
* ```typescript
|
|
14106
|
+
* const gasLimit = await resolveGasLimit(request, 150_000)
|
|
14107
|
+
* ```
|
|
14108
|
+
*/ const resolveGasLimit = async (request, gasFloor)=>{
|
|
14109
|
+
try {
|
|
14110
|
+
// Deliberately called without a `fallback`: both the viem and ethers
|
|
14111
|
+
// adapters *return* the supplied fallback object when estimation reverts
|
|
14112
|
+
// rather than throwing, which would set the estimate to the floor and then
|
|
14113
|
+
// multiply it by the buffer below. Omitting it routes reverts through the
|
|
14114
|
+
// catch, so a failed estimate degrades to exactly the floor.
|
|
14115
|
+
const estimate = await request.estimate();
|
|
14116
|
+
// The arithmetic stays inside the try on purpose. `EstimatedGas.gas` is
|
|
14117
|
+
// typed `bigint`, but adapters are a public extension point and may be
|
|
14118
|
+
// implemented in plain JS, so a non-bigint `gas` would throw here
|
|
14119
|
+
// ("Cannot mix BigInt and other types"). Guarding it keeps the documented
|
|
14120
|
+
// contract — estimation never aborts a step, it degrades to the floor.
|
|
14121
|
+
const buffered = estimate.gas * GAS_ESTIMATE_BUFFER_PERCENT / 100n;
|
|
14122
|
+
// Convert before comparing: Math.max throws on BigInt operands, and gas
|
|
14123
|
+
// units are far below Number.MAX_SAFE_INTEGER so the narrowing is lossless.
|
|
14124
|
+
return Math.max(Number(buffered), gasFloor);
|
|
14125
|
+
} catch {
|
|
14126
|
+
// Estimation is best-effort; the floor is the known-safe value.
|
|
14127
|
+
return gasFloor;
|
|
14128
|
+
}
|
|
14129
|
+
};
|
|
13899
14130
|
/**
|
|
13900
14131
|
* Executes a prepared chain request and returns the result as a bridge step.
|
|
13901
14132
|
*
|
|
@@ -13909,8 +14140,8 @@ function hasPendingState(analysis, result) {
|
|
|
13909
14140
|
* - `adapter`: The adapter that will execute the transaction
|
|
13910
14141
|
* - `confirmations`: The number of confirmations to wait for (defaults to 1)
|
|
13911
14142
|
* - `timeout`: The timeout for the request in milliseconds
|
|
13912
|
-
* - `
|
|
13913
|
-
*
|
|
14143
|
+
* - `gasFloor`: Optional minimum gas limit (number); the request is submitted
|
|
14144
|
+
* with `max(estimate * 1.25, gasFloor)`. Ignored for non-EVM requests
|
|
13914
14145
|
* @returns The bridge step with the transaction details and explorer URL
|
|
13915
14146
|
* @throws If the transaction execution fails
|
|
13916
14147
|
*
|
|
@@ -13925,7 +14156,7 @@ function hasPendingState(analysis, result) {
|
|
|
13925
14156
|
* })
|
|
13926
14157
|
* console.log('Transaction hash:', step.txHash)
|
|
13927
14158
|
* ```
|
|
13928
|
-
*/ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout,
|
|
14159
|
+
*/ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout, gasFloor }) {
|
|
13929
14160
|
const step = {
|
|
13930
14161
|
name,
|
|
13931
14162
|
state: 'pending'
|
|
@@ -13938,8 +14169,8 @@ function hasPendingState(analysis, result) {
|
|
|
13938
14169
|
step.state = 'noop';
|
|
13939
14170
|
return step;
|
|
13940
14171
|
}
|
|
13941
|
-
const txHash = request.type === 'evm' &&
|
|
13942
|
-
gasLimit
|
|
14172
|
+
const txHash = request.type === 'evm' && gasFloor !== undefined ? await request.execute({
|
|
14173
|
+
gasLimit: await resolveGasLimit(request, gasFloor)
|
|
13943
14174
|
}) : await request.execute();
|
|
13944
14175
|
step.txHash = txHash;
|
|
13945
14176
|
const retryOptions = {
|
|
@@ -14013,7 +14244,7 @@ function hasPendingState(analysis, result) {
|
|
|
14013
14244
|
adapter: params.source.adapter,
|
|
14014
14245
|
chain: params.source.chain,
|
|
14015
14246
|
request: await provider.approve(params.source, approvalAmount),
|
|
14016
|
-
|
|
14247
|
+
gasFloor: Number(APPROVE_GAS_LIMIT_EVM)
|
|
14017
14248
|
});
|
|
14018
14249
|
}
|
|
14019
14250
|
|
|
@@ -14041,7 +14272,7 @@ function hasPendingState(analysis, result) {
|
|
|
14041
14272
|
adapter: params.source.adapter,
|
|
14042
14273
|
chain: params.source.chain,
|
|
14043
14274
|
request: await provider.burn(params),
|
|
14044
|
-
|
|
14275
|
+
gasFloor: Number(DEPOSIT_FOR_BURN_GAS_LIMIT_EVM)
|
|
14045
14276
|
});
|
|
14046
14277
|
}
|
|
14047
14278
|
|
|
@@ -14135,10 +14366,9 @@ function hasPendingState(analysis, result) {
|
|
|
14135
14366
|
request: mintRequest,
|
|
14136
14367
|
// Some chains (e.g. Cronos) enforce an EIP-7623 calldata gas floor that
|
|
14137
14368
|
// eth_estimateGas does not account for, returning a below-floor value
|
|
14138
|
-
// without reverting.
|
|
14139
|
-
//
|
|
14140
|
-
|
|
14141
|
-
gasLimit: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
|
|
14369
|
+
// without reverting. The floor covers those; chains that cost more than the
|
|
14370
|
+
// floor are covered by their own estimate.
|
|
14371
|
+
gasFloor: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
|
|
14142
14372
|
});
|
|
14143
14373
|
// Add forwarded: false for non-relayer mints
|
|
14144
14374
|
return {
|
|
@@ -14661,7 +14891,7 @@ const mockAttestationMessage = {
|
|
|
14661
14891
|
return step;
|
|
14662
14892
|
}
|
|
14663
14893
|
|
|
14664
|
-
var version$2 = "1.10.
|
|
14894
|
+
var version$2 = "1.10.2";
|
|
14665
14895
|
var pkg$2 = {
|
|
14666
14896
|
version: version$2};
|
|
14667
14897
|
|
|
@@ -17259,7 +17489,9 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
17259
17489
|
headers: context.headers
|
|
17260
17490
|
}
|
|
17261
17491
|
});
|
|
17262
|
-
if (
|
|
17492
|
+
if (context.customFeePolicy?.bridge != null) {
|
|
17493
|
+
kit.setCustomFeePolicy(context.customFeePolicy.bridge);
|
|
17494
|
+
} else if (hasBoth) {
|
|
17263
17495
|
kit.setCustomFeePolicy({
|
|
17264
17496
|
calculateFee: async (params)=>{
|
|
17265
17497
|
const feeStr = await getFee('bridge', params);
|
|
@@ -17275,7 +17507,7 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
17275
17507
|
};
|
|
17276
17508
|
|
|
17277
17509
|
var name$1 = "@circle-fin/swap-kit";
|
|
17278
|
-
var version$1 = "1.
|
|
17510
|
+
var version$1 = "1.5.1";
|
|
17279
17511
|
var pkg$1 = {
|
|
17280
17512
|
name: name$1,
|
|
17281
17513
|
version: version$1};
|
|
@@ -18016,6 +18248,16 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
18016
18248
|
required_error: 'estimatedAmount is required',
|
|
18017
18249
|
invalid_type_error: 'estimatedAmount must be a string'
|
|
18018
18250
|
}).min(1, 'estimatedAmount must be a non-empty string'),
|
|
18251
|
+
// Per-swap join key echoed back verbatim on success telemetry. Optional so a
|
|
18252
|
+
// not-yet-upgraded service (no field) still validates during rollout. A
|
|
18253
|
+
// malformed/non-UUID value is coerced to `undefined` (no telemetry id) rather
|
|
18254
|
+
// than throwing: this is a telemetry-only field (stripped from the developer
|
|
18255
|
+
// result, never used for control flow), so it must not be able to abort the
|
|
18256
|
+
// swap via `parseCreateSwapResponse().parse()`. Mirrors the best-effort,
|
|
18257
|
+
// never-throw contract of the rest of the telemetry stack. Implemented with
|
|
18258
|
+
// `preprocess` rather than Zod's `.catch()` because static analysis misreads
|
|
18259
|
+
// `.catch` on the schema chain as an unhandled Promise (S7785).
|
|
18260
|
+
correlationId: zod.z.preprocess((value)=>zod.z.string().uuid().safeParse(value).success ? value : undefined, zod.z.string().optional()),
|
|
18019
18261
|
config: createSwapRequestBaseSchema.shape.config.optional(),
|
|
18020
18262
|
fees: createSwapFeesSchema.optional(),
|
|
18021
18263
|
transaction: createSwapTransactionSchema
|
|
@@ -19208,7 +19450,7 @@ new Set(Object.values(Blockchain));
|
|
|
19208
19450
|
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
19209
19451
|
|
|
19210
19452
|
var name = "@circle-fin/earn-kit";
|
|
19211
|
-
var version = "1.
|
|
19453
|
+
var version = "1.5.0";
|
|
19212
19454
|
var pkg = {
|
|
19213
19455
|
name: name,
|
|
19214
19456
|
version: version};
|
|
@@ -20219,11 +20461,16 @@ const sourceAdapterContextSchema = zod.z.object({
|
|
|
20219
20461
|
*
|
|
20220
20462
|
* Validate the optional Kit Key field using the standard `apiKeySchema`
|
|
20221
20463
|
* format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
|
|
20222
|
-
* operates in permissionless mode.
|
|
20464
|
+
* operates in permissionless mode. `baseUrl` overrides the Earn Service
|
|
20465
|
+
* endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
|
|
20466
|
+
* batched execution. Both are forwarded to the provider, so this `.strict()`
|
|
20467
|
+
* schema must accept them or a valid config object is rejected.
|
|
20223
20468
|
*
|
|
20224
20469
|
* @internal
|
|
20225
20470
|
*/ const earnConfigSchema = zod.z.object({
|
|
20226
|
-
kitKey: apiKeySchema.optional()
|
|
20471
|
+
kitKey: apiKeySchema.optional(),
|
|
20472
|
+
baseUrl: zod.z.string().optional(),
|
|
20473
|
+
batchTransactions: zod.z.boolean().optional()
|
|
20227
20474
|
}).strict();
|
|
20228
20475
|
/**
|
|
20229
20476
|
* Canonical decimal form: a leading digit with no leading zeros (a single
|
|
@@ -20672,6 +20919,8 @@ function hasCrossChainDepositQuoteShape(params) {
|
|
|
20672
20919
|
config: earnConfigSchema.optional()
|
|
20673
20920
|
});
|
|
20674
20921
|
|
|
20922
|
+
/** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg.name);
|
|
20923
|
+
|
|
20675
20924
|
// Auto-register this kit for user agent tracking
|
|
20676
20925
|
registerKit(`${pkg.name}/${pkg.version}`);
|
|
20677
20926
|
|