@elsoul/erpc-sdk 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +53 -0
- package/README.md +202 -42
- package/dist/index.cjs +1846 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -12
- package/dist/index.d.ts +157 -12
- package/dist/index.js +1846 -121
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var ed25519_js = require('@noble/curves/ed25519.js');
|
|
4
|
+
var sha2_js = require('@noble/hashes/sha2.js');
|
|
5
|
+
var sha3_js = require('@noble/hashes/sha3.js');
|
|
6
|
+
|
|
3
7
|
// src/errors.ts
|
|
4
8
|
var REDACTED = "[REDACTED]";
|
|
5
9
|
var credentialVariants = (credential) => {
|
|
@@ -22,6 +26,16 @@ var directEndpointVariants = (endpoint) => {
|
|
|
22
26
|
const add = (value) => {
|
|
23
27
|
if (value) values.push(value);
|
|
24
28
|
};
|
|
29
|
+
const addPathValue = (value) => {
|
|
30
|
+
add(value);
|
|
31
|
+
try {
|
|
32
|
+
add(decodeURIComponent(value));
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
for (const component of endpoint.pathname.split("/")) {
|
|
37
|
+
if (component) addPathValue(component);
|
|
38
|
+
}
|
|
25
39
|
for (const value of endpoint.searchParams.values()) add(value);
|
|
26
40
|
const rawQuery = endpoint.search.startsWith("?") ? endpoint.search.slice(1) : endpoint.search;
|
|
27
41
|
for (const part of rawQuery.split("&")) {
|
|
@@ -349,13 +363,14 @@ var deepFreeze = (value) => {
|
|
|
349
363
|
}
|
|
350
364
|
return value;
|
|
351
365
|
};
|
|
352
|
-
var TOKEN_CATALOG_VERSION = "1.
|
|
353
|
-
var TOKEN_CATALOG_AS_OF_DATE = "2026-09-
|
|
354
|
-
var TOKEN_CATALOG_CONTENT_DIGEST = "
|
|
366
|
+
var TOKEN_CATALOG_VERSION = "1.1.0";
|
|
367
|
+
var TOKEN_CATALOG_AS_OF_DATE = "2026-09-26";
|
|
368
|
+
var TOKEN_CATALOG_CONTENT_DIGEST = "cca180df1846def0ec98f4e55b84cc46614c60d7a8c4a91c66dc9715c710ba73";
|
|
355
369
|
var TOKEN_CHAIN_IDS = deepFreeze({
|
|
356
370
|
"ethereumMainnet": "eip155:1",
|
|
357
371
|
"solanaMainnet": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
358
|
-
"avalancheCMainnet": "eip155:43114"
|
|
372
|
+
"avalancheCMainnet": "eip155:43114",
|
|
373
|
+
"baseMainnet": "eip155:8453"
|
|
359
374
|
});
|
|
360
375
|
var tokens = deepFreeze({
|
|
361
376
|
"avalancheC": {
|
|
@@ -377,6 +392,11 @@ var tokens = deepFreeze({
|
|
|
377
392
|
"USDT": "deployment-0015",
|
|
378
393
|
"WAVAX": "deployment-0004"
|
|
379
394
|
},
|
|
395
|
+
"base": {
|
|
396
|
+
"ETH": "deployment-0061",
|
|
397
|
+
"EURC": "deployment-0063",
|
|
398
|
+
"USDC": "deployment-0062"
|
|
399
|
+
},
|
|
380
400
|
"ethereum": {
|
|
381
401
|
"AAVE": "deployment-0056",
|
|
382
402
|
"AUSD": "deployment-0034",
|
|
@@ -1790,6 +1810,54 @@ var TOKEN_DEPLOYMENTS = deepFreeze([
|
|
|
1790
1810
|
"status": "active",
|
|
1791
1811
|
"replacedByDeploymentId": null
|
|
1792
1812
|
},
|
|
1813
|
+
{
|
|
1814
|
+
"deploymentId": "deployment-0061",
|
|
1815
|
+
"assetId": "asset-0001",
|
|
1816
|
+
"name": "Ether",
|
|
1817
|
+
"representationKind": "native",
|
|
1818
|
+
"stableCurrency": null,
|
|
1819
|
+
"underlyingAssetId": null,
|
|
1820
|
+
"economicReferenceAssetId": null,
|
|
1821
|
+
"chainId": "eip155:8453",
|
|
1822
|
+
"symbol": "ETH",
|
|
1823
|
+
"decimals": 18,
|
|
1824
|
+
"standard": "native",
|
|
1825
|
+
"address": null,
|
|
1826
|
+
"status": "active",
|
|
1827
|
+
"replacedByDeploymentId": null
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
"deploymentId": "deployment-0062",
|
|
1831
|
+
"assetId": "asset-0007",
|
|
1832
|
+
"name": "USD Coin",
|
|
1833
|
+
"representationKind": "issued",
|
|
1834
|
+
"stableCurrency": "USD",
|
|
1835
|
+
"underlyingAssetId": null,
|
|
1836
|
+
"economicReferenceAssetId": null,
|
|
1837
|
+
"chainId": "eip155:8453",
|
|
1838
|
+
"symbol": "USDC",
|
|
1839
|
+
"decimals": 6,
|
|
1840
|
+
"standard": "erc20",
|
|
1841
|
+
"address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1842
|
+
"status": "active",
|
|
1843
|
+
"replacedByDeploymentId": null
|
|
1844
|
+
},
|
|
1845
|
+
{
|
|
1846
|
+
"deploymentId": "deployment-0063",
|
|
1847
|
+
"assetId": "asset-0008",
|
|
1848
|
+
"name": "Euro Coin",
|
|
1849
|
+
"representationKind": "issued",
|
|
1850
|
+
"stableCurrency": "EUR",
|
|
1851
|
+
"underlyingAssetId": null,
|
|
1852
|
+
"economicReferenceAssetId": null,
|
|
1853
|
+
"chainId": "eip155:8453",
|
|
1854
|
+
"symbol": "EURC",
|
|
1855
|
+
"decimals": 6,
|
|
1856
|
+
"standard": "erc20",
|
|
1857
|
+
"address": "0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42",
|
|
1858
|
+
"status": "active",
|
|
1859
|
+
"replacedByDeploymentId": null
|
|
1860
|
+
},
|
|
1793
1861
|
{
|
|
1794
1862
|
"deploymentId": "discovered-token-054d80a64e1f36a756129763ca2f1e7a140b50b04c83876ff01dd5fd497a74c5",
|
|
1795
1863
|
"assetId": "discovered-token-054d80a64e1f36a756129763ca2f1e7a140b50b04c83876ff01dd5fd497a74c5",
|
|
@@ -1969,6 +2037,9 @@ var TOKEN_ALIASES = deepFreeze([
|
|
|
1969
2037
|
{ namespace: "avalancheC", name: "USDC_E", deploymentId: tokens.avalancheC.USDC_E },
|
|
1970
2038
|
{ namespace: "avalancheC", name: "USDT", deploymentId: tokens.avalancheC.USDT },
|
|
1971
2039
|
{ namespace: "avalancheC", name: "WAVAX", deploymentId: tokens.avalancheC.WAVAX },
|
|
2040
|
+
{ namespace: "base", name: "ETH", deploymentId: tokens.base.ETH },
|
|
2041
|
+
{ namespace: "base", name: "EURC", deploymentId: tokens.base.EURC },
|
|
2042
|
+
{ namespace: "base", name: "USDC", deploymentId: tokens.base.USDC },
|
|
1972
2043
|
{ namespace: "ethereum", name: "AAVE", deploymentId: tokens.ethereum.AAVE },
|
|
1973
2044
|
{ namespace: "ethereum", name: "AUSD", deploymentId: tokens.ethereum.AUSD },
|
|
1974
2045
|
{ namespace: "ethereum", name: "DAI", deploymentId: tokens.ethereum.DAI },
|
|
@@ -2113,13 +2184,13 @@ function isRecord(value) {
|
|
|
2113
2184
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2114
2185
|
}
|
|
2115
2186
|
function isKnownChainId(value) {
|
|
2116
|
-
return value === TOKEN_CHAIN_IDS.ethereumMainnet || value === TOKEN_CHAIN_IDS.solanaMainnet || value === TOKEN_CHAIN_IDS.avalancheCMainnet;
|
|
2187
|
+
return value === TOKEN_CHAIN_IDS.ethereumMainnet || value === TOKEN_CHAIN_IDS.solanaMainnet || value === TOKEN_CHAIN_IDS.avalancheCMainnet || value === TOKEN_CHAIN_IDS.baseMainnet;
|
|
2117
2188
|
}
|
|
2118
2189
|
function isStableCurrency(value) {
|
|
2119
2190
|
return value === "USD" || value === "EUR" || value === "JPY";
|
|
2120
2191
|
}
|
|
2121
2192
|
function isEvmChain(chainId) {
|
|
2122
|
-
return chainId === TOKEN_CHAIN_IDS.ethereumMainnet || chainId === TOKEN_CHAIN_IDS.avalancheCMainnet;
|
|
2193
|
+
return chainId === TOKEN_CHAIN_IDS.ethereumMainnet || chainId === TOKEN_CHAIN_IDS.avalancheCMainnet || chainId === TOKEN_CHAIN_IDS.baseMainnet;
|
|
2123
2194
|
}
|
|
2124
2195
|
function normalizeEvmAddress(address) {
|
|
2125
2196
|
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) return void 0;
|
|
@@ -2479,8 +2550,8 @@ var parseOffering = (value) => {
|
|
|
2479
2550
|
const offering = objectValue(value);
|
|
2480
2551
|
if (offering === null || typeof offering.id !== "string" || typeof offering.kind !== "string" || !resourceKinds.includes(offering.kind) || typeof offering.name !== "string" || typeof offering.description !== "string" || offering.mode !== void 0 && (typeof offering.mode !== "string" || !resourceModes.includes(offering.mode))) return null;
|
|
2481
2552
|
const regions = stringArray(offering.regions);
|
|
2482
|
-
const
|
|
2483
|
-
if (regions === null ||
|
|
2553
|
+
const capabilities2 = stringArray(offering.capabilities);
|
|
2554
|
+
if (regions === null || capabilities2 === null) return null;
|
|
2484
2555
|
const compute = offering.compute === void 0 ? void 0 : objectValue(offering.compute);
|
|
2485
2556
|
if (compute !== void 0 && (compute === null || compute.tenancy !== "virtual-machine" && compute.tenancy !== "bare-metal")) return null;
|
|
2486
2557
|
const solana = offering.solana === void 0 ? void 0 : objectValue(offering.solana);
|
|
@@ -2493,7 +2564,7 @@ var parseOffering = (value) => {
|
|
|
2493
2564
|
name: offering.name,
|
|
2494
2565
|
description: offering.description,
|
|
2495
2566
|
regions,
|
|
2496
|
-
capabilities,
|
|
2567
|
+
capabilities: capabilities2,
|
|
2497
2568
|
...typeof offering.mode === "string" ? { mode: offering.mode } : {},
|
|
2498
2569
|
...compute && (compute.tenancy === "virtual-machine" || compute.tenancy === "bare-metal") ? { compute: { tenancy: compute.tenancy } } : {},
|
|
2499
2570
|
...solana && (solana.transport === "grpc" || solana.transport === "shredstream") ? { solana: { transport: solana.transport } } : {},
|
|
@@ -2533,9 +2604,13 @@ var CloudCatalogClient = class {
|
|
|
2533
2604
|
}
|
|
2534
2605
|
};
|
|
2535
2606
|
|
|
2607
|
+
// src/transport/fetch.ts
|
|
2608
|
+
var wrapFetch = (implementation) => (input, init) => implementation(input, init);
|
|
2609
|
+
|
|
2536
2610
|
// src/config.ts
|
|
2537
2611
|
var DEFAULT_ENDPOINT = "https://edge.erpc.global";
|
|
2538
2612
|
var DEFAULT_AVALANCHE_ENDPOINT = "https://ava-rpc.erpc.global";
|
|
2613
|
+
var DEFAULT_BASE_ENDPOINT = "https://base.erpc.global";
|
|
2539
2614
|
var DEFAULT_ACCOUNT_ENDPOINT = "https://solana-rpc.erpc.global";
|
|
2540
2615
|
var DEFAULT_USER_ENDPOINT = "https://user-api.erpc.global";
|
|
2541
2616
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -2546,7 +2621,7 @@ var requireFetch = (provided) => {
|
|
|
2546
2621
|
"A Fetch API implementation is required in this runtime"
|
|
2547
2622
|
);
|
|
2548
2623
|
}
|
|
2549
|
-
return implementation;
|
|
2624
|
+
return wrapFetch(implementation);
|
|
2550
2625
|
};
|
|
2551
2626
|
var normalizeLegacyEndpoint = (endpoint) => {
|
|
2552
2627
|
endpoint.search = "";
|
|
@@ -2614,6 +2689,15 @@ var resolveRpcEndpoint = (value, namespace) => {
|
|
|
2614
2689
|
...webSocketUrl === void 0 ? {} : { webSocketUrl }
|
|
2615
2690
|
};
|
|
2616
2691
|
};
|
|
2692
|
+
var resolveBaseRpcEndpoint = (value) => {
|
|
2693
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2694
|
+
throw new ErpcConfigError("baseRpc must define an HTTP(S) URL");
|
|
2695
|
+
}
|
|
2696
|
+
const config = value;
|
|
2697
|
+
const httpUrl = parseDirectUrl(config.httpUrl, "baseRpc.httpUrl", "HTTP(S)");
|
|
2698
|
+
const headers = directHeaders(config.headers, "baseRpc");
|
|
2699
|
+
return { headers, httpUrl };
|
|
2700
|
+
};
|
|
2617
2701
|
var resolveConfig = (config) => {
|
|
2618
2702
|
const configuredApiKey = config.apiKey === void 0 ? void 0 : typeof config.apiKey === "string" ? config.apiKey.trim() : (() => {
|
|
2619
2703
|
throw new ErpcConfigError("apiKey must be a string");
|
|
@@ -2621,13 +2705,15 @@ var resolveConfig = (config) => {
|
|
|
2621
2705
|
const solanaRpc = config.solanaRpc === void 0 ? void 0 : resolveRpcEndpoint(config.solanaRpc, "solanaRpc");
|
|
2622
2706
|
const ethereumRpc = config.ethereumRpc === void 0 ? void 0 : resolveRpcEndpoint(config.ethereumRpc, "ethereumRpc");
|
|
2623
2707
|
const avalancheCRpc = config.avalancheCRpc === void 0 ? void 0 : resolveRpcEndpoint(config.avalancheCRpc, "avalancheCRpc");
|
|
2624
|
-
const
|
|
2708
|
+
const baseRpc = config.baseRpc === void 0 ? void 0 : resolveBaseRpcEndpoint(config.baseRpc);
|
|
2709
|
+
const hasDirectRpc = solanaRpc !== void 0 || ethereumRpc !== void 0 || avalancheCRpc !== void 0 || baseRpc !== void 0;
|
|
2625
2710
|
if (!configuredApiKey && !hasDirectRpc) {
|
|
2626
2711
|
throw new ErpcConfigError("apiKey must not be empty");
|
|
2627
2712
|
}
|
|
2628
2713
|
const apiKey = configuredApiKey || void 0;
|
|
2629
2714
|
let endpoint;
|
|
2630
2715
|
let avalancheEndpoint;
|
|
2716
|
+
let baseEndpoint;
|
|
2631
2717
|
let accountEndpoint;
|
|
2632
2718
|
let userEndpoint;
|
|
2633
2719
|
try {
|
|
@@ -2635,6 +2721,9 @@ var resolveConfig = (config) => {
|
|
|
2635
2721
|
avalancheEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2636
2722
|
config.avalancheEndpoint ?? DEFAULT_AVALANCHE_ENDPOINT
|
|
2637
2723
|
));
|
|
2724
|
+
baseEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2725
|
+
config.baseEndpoint ?? DEFAULT_BASE_ENDPOINT
|
|
2726
|
+
));
|
|
2638
2727
|
accountEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2639
2728
|
config.accountEndpoint ?? DEFAULT_ACCOUNT_ENDPOINT
|
|
2640
2729
|
));
|
|
@@ -2648,6 +2737,9 @@ var resolveConfig = (config) => {
|
|
|
2648
2737
|
if (avalancheEndpoint.protocol !== "https:" && avalancheEndpoint.protocol !== "http:") {
|
|
2649
2738
|
throw new ErpcConfigError("avalancheEndpoint must use HTTP or HTTPS");
|
|
2650
2739
|
}
|
|
2740
|
+
if (baseEndpoint.protocol !== "https:" && baseEndpoint.protocol !== "http:") {
|
|
2741
|
+
throw new ErpcConfigError("baseEndpoint must use HTTP or HTTPS");
|
|
2742
|
+
}
|
|
2651
2743
|
if (accountEndpoint.protocol !== "https:" && accountEndpoint.protocol !== "http:") {
|
|
2652
2744
|
throw new ErpcConfigError("accountEndpoint must use HTTP or HTTPS");
|
|
2653
2745
|
}
|
|
@@ -2661,6 +2753,7 @@ var resolveConfig = (config) => {
|
|
|
2661
2753
|
return {
|
|
2662
2754
|
accountEndpoint,
|
|
2663
2755
|
avalancheEndpoint,
|
|
2756
|
+
baseEndpoint,
|
|
2664
2757
|
endpoint,
|
|
2665
2758
|
fetch: requireFetch(config.fetch),
|
|
2666
2759
|
headers: config.headers ?? {},
|
|
@@ -2668,6 +2761,7 @@ var resolveConfig = (config) => {
|
|
|
2668
2761
|
userEndpoint,
|
|
2669
2762
|
...apiKey === void 0 ? {} : { apiKey },
|
|
2670
2763
|
...avalancheCRpc === void 0 ? {} : { avalancheCRpc },
|
|
2764
|
+
...baseRpc === void 0 ? {} : { baseRpc },
|
|
2671
2765
|
...ethereumRpc === void 0 ? {} : { ethereumRpc },
|
|
2672
2766
|
...solanaRpc === void 0 ? {} : { solanaRpc },
|
|
2673
2767
|
...config.webSocket === void 0 ? {} : { webSocket: config.webSocket }
|
|
@@ -3041,6 +3135,19 @@ var createAvalancheClient = (transport, indexTransports, nativeTransport = trans
|
|
|
3041
3135
|
}
|
|
3042
3136
|
});
|
|
3043
3137
|
|
|
3138
|
+
// src/rpc/base.ts
|
|
3139
|
+
var createBaseClient = (transport) => {
|
|
3140
|
+
const ethereumRpc = createEthereumClient(transport).rpc;
|
|
3141
|
+
return {
|
|
3142
|
+
rpc: {
|
|
3143
|
+
endpoint: ethereumRpc.endpoint,
|
|
3144
|
+
eth_chainId: ethereumRpc.eth_chainId,
|
|
3145
|
+
eth_getBalance: ethereumRpc.eth_getBalance,
|
|
3146
|
+
eth_call: ethereumRpc.eth_call
|
|
3147
|
+
}
|
|
3148
|
+
};
|
|
3149
|
+
};
|
|
3150
|
+
|
|
3044
3151
|
// src/rpc/solana.ts
|
|
3045
3152
|
var SOLANA_RPC_METHODS = [
|
|
3046
3153
|
"getAccountInfo",
|
|
@@ -5201,8 +5308,14 @@ var HttpJsonRpcTransport = class {
|
|
|
5201
5308
|
this.#unavailableNamespace = config.unavailableNamespace;
|
|
5202
5309
|
this.maxBatchSize = config.maxBatchSize ?? 256;
|
|
5203
5310
|
const endpoint = new URL(config.endpoint);
|
|
5204
|
-
|
|
5205
|
-
|
|
5311
|
+
if (this.#direct) {
|
|
5312
|
+
endpoint.pathname = "/";
|
|
5313
|
+
endpoint.search = "";
|
|
5314
|
+
endpoint.hash = "";
|
|
5315
|
+
} else {
|
|
5316
|
+
endpoint.search = "";
|
|
5317
|
+
endpoint.hash = "";
|
|
5318
|
+
}
|
|
5206
5319
|
this.endpoint = endpoint.toString();
|
|
5207
5320
|
}
|
|
5208
5321
|
async request(method, params, options = {}) {
|
|
@@ -5473,6 +5586,7 @@ var createErpcClient = (config) => {
|
|
|
5473
5586
|
const solanaTransport = resolved.solanaRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("solana.rpc") : createLegacyHttp(resolved.endpoint) : createDirectHttp(resolved.solanaRpc);
|
|
5474
5587
|
const ethereumTransport = resolved.ethereumRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("ethereum.rpc") : createLegacyHttp(endpointWithPath(resolved.endpoint, "/eth")) : createDirectHttp(resolved.ethereumRpc);
|
|
5475
5588
|
const avalancheTransport = resolved.avalancheCRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("avalanche.rpc") : createLegacyHttp(endpointWithPath(resolved.avalancheEndpoint, "/ava")) : createDirectHttp(resolved.avalancheCRpc);
|
|
5589
|
+
const baseTransport = resolved.baseRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("base") : createLegacyHttp(resolved.baseEndpoint) : createDirectHttp(resolved.baseRpc);
|
|
5476
5590
|
const avalancheNativeTransport = resolved.apiKey === void 0 ? createUnavailableHttp("avalanche.native") : createLegacyHttp(endpointWithPath(resolved.avalancheEndpoint, "/ava"));
|
|
5477
5591
|
const avalancheIndexTransport = (path, namespace) => resolved.apiKey === void 0 ? createUnavailableHttp(namespace) : createLegacyHttp(endpointWithPath(resolved.avalancheEndpoint, path));
|
|
5478
5592
|
const solanaWebSocket = resolved.solanaRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableWebSocket("solana.subscriptions") : createLegacyWebSocket(websocketUrl(resolved.endpoint, resolved.apiKey)) : createDirectWebSocket(resolved.solanaRpc, "solana.subscriptions");
|
|
@@ -5535,6 +5649,7 @@ var createErpcClient = (config) => {
|
|
|
5535
5649
|
solana,
|
|
5536
5650
|
ethereum,
|
|
5537
5651
|
avalanche,
|
|
5652
|
+
base: createBaseClient(baseTransport),
|
|
5538
5653
|
price: new PriceClient(priceTransport),
|
|
5539
5654
|
account: new AccountClient(accountTransport),
|
|
5540
5655
|
swap,
|
|
@@ -5721,7 +5836,7 @@ var requireFetch2 = (provided) => {
|
|
|
5721
5836
|
"A Fetch API implementation is required in this runtime"
|
|
5722
5837
|
);
|
|
5723
5838
|
}
|
|
5724
|
-
return implementation;
|
|
5839
|
+
return wrapFetch(implementation);
|
|
5725
5840
|
};
|
|
5726
5841
|
var cloudEndpoint = (value) => {
|
|
5727
5842
|
let endpoint;
|
|
@@ -5764,9 +5879,1514 @@ var createErpcCloudClient = (config) => {
|
|
|
5764
5879
|
};
|
|
5765
5880
|
|
|
5766
5881
|
// src/generated/bridge_capabilities.ts
|
|
5767
|
-
var BRIDGE_CAPABILITIES_JSON = '[{"bridgeCapabilityId":"bridge-mayan-swift-v2-eurc-eth-sol","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"eip155:1","destinationChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","sourceTokenDeploymentId":"deployment-0011","destinationTokenDeploymentId":"deployment-0013","sourceTokenAddress":"0x1abaea1f7c830bd89acc67ec4af516284b1bc33c","destinationTokenAddress":"HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr","sourceTokenStandard":"erc20","destinationTokenStandard":"spl-token","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"ethereum","destinationProviderChainName":"solana","sourceProviderChainId":1,"destinationProviderChainId":0,"sourceWormholeChainId":2,"destinationWormholeChainId":1,"sourceUsdcDeploymentId":"deployment-0008","sourceUsdcAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","sourceUsdcStandard":"erc20","sourceUsdcDecimals":6,"swiftContract":"0x40ffe85a28dc9993541449464d7529a922142960","forwarderAddress":"0x337685fdab40d39bd02028545a4ffa7d287cc3e2","forwarderFunctionSelector":"0x30dedc57","jupiterProgramAddress":null,"builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","mayan-hosted-source-swap-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer"],"status":"active"},{"bridgeCapabilityId":"bridge-mayan-swift-v2-eurc-sol-eth","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","destinationChainId":"eip155:1","sourceTokenDeploymentId":"deployment-0013","destinationTokenDeploymentId":"deployment-0011","sourceTokenAddress":"HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr","destinationTokenAddress":"0x1abaea1f7c830bd89acc67ec4af516284b1bc33c","sourceTokenStandard":"spl-token","destinationTokenStandard":"erc20","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"solana","destinationProviderChainName":"ethereum","sourceProviderChainId":0,"destinationProviderChainId":1,"sourceWormholeChainId":1,"destinationWormholeChainId":2,"sourceUsdcDeploymentId":"deployment-0010","sourceUsdcAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","sourceUsdcStandard":"spl-token","sourceUsdcDecimals":6,"swiftContract":"mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny","forwarderAddress":null,"forwarderFunctionSelector":null,"jupiterProgramAddress":"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4","builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","mayan-hosted-source-swap-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer","jupiter-v6-source-swap"],"status":"active"}]';
|
|
5768
|
-
var BRIDGE_CAPABILITIES_CONTENT_DIGEST = "
|
|
5769
|
-
var BRIDGE_CAPABILITIES_AS_OF_DATE = "2026-09-
|
|
5882
|
+
var BRIDGE_CAPABILITIES_JSON = '[{"bridgeCapabilityId":"bridge-mayan-swift-v2-eurc-eth-sol","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"eip155:1","destinationChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","sourceTokenDeploymentId":"deployment-0011","destinationTokenDeploymentId":"deployment-0013","sourceTokenAddress":"0x1abaea1f7c830bd89acc67ec4af516284b1bc33c","destinationTokenAddress":"HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr","sourceTokenStandard":"erc20","destinationTokenStandard":"spl-token","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"ethereum","destinationProviderChainName":"solana","sourceProviderChainId":1,"destinationProviderChainId":0,"sourceWormholeChainId":2,"destinationWormholeChainId":1,"sourceUsdcDeploymentId":"deployment-0008","sourceUsdcAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","sourceUsdcStandard":"erc20","sourceUsdcDecimals":6,"swiftContract":"0x40ffe85a28dc9993541449464d7529a922142960","forwarderAddress":"0x337685fdab40d39bd02028545a4ffa7d287cc3e2","forwarderFunctionSelector":"0x30dedc57","jupiterProgramAddress":null,"builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","mayan-hosted-source-swap-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer"],"status":"active"},{"bridgeCapabilityId":"bridge-mayan-swift-v2-eurc-sol-eth","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","destinationChainId":"eip155:1","sourceTokenDeploymentId":"deployment-0013","destinationTokenDeploymentId":"deployment-0011","sourceTokenAddress":"HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr","destinationTokenAddress":"0x1abaea1f7c830bd89acc67ec4af516284b1bc33c","sourceTokenStandard":"spl-token","destinationTokenStandard":"erc20","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"solana","destinationProviderChainName":"ethereum","sourceProviderChainId":0,"destinationProviderChainId":1,"sourceWormholeChainId":1,"destinationWormholeChainId":2,"sourceUsdcDeploymentId":"deployment-0010","sourceUsdcAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","sourceUsdcStandard":"spl-token","sourceUsdcDecimals":6,"swiftContract":"mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny","forwarderAddress":null,"forwarderFunctionSelector":null,"jupiterProgramAddress":"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4","builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","mayan-hosted-source-swap-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer","jupiter-v6-source-swap"],"status":"active"},{"bridgeCapabilityId":"bridge-mayan-swift-v2-usdc-eth-sol","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"eip155:1","destinationChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","sourceTokenDeploymentId":"deployment-0008","destinationTokenDeploymentId":"deployment-0010","sourceTokenAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","destinationTokenAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","sourceTokenStandard":"erc20","destinationTokenStandard":"spl-token","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"ethereum","destinationProviderChainName":"solana","sourceProviderChainId":1,"destinationProviderChainId":0,"sourceWormholeChainId":2,"destinationWormholeChainId":1,"sourceUsdcDeploymentId":"deployment-0008","sourceUsdcAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","sourceUsdcStandard":"erc20","sourceUsdcDecimals":6,"swiftContract":"0x40ffe85a28dc9993541449464d7529a922142960","forwarderAddress":"0x337685fdab40d39bd02028545a4ffa7d287cc3e2","forwarderFunctionSelector":"0xe4269fc4","jupiterProgramAddress":null,"builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer"],"status":"active"},{"bridgeCapabilityId":"bridge-mayan-swift-v2-usdc-sol-eth","providerId":"mayan-swift-v2","capabilityKind":"external-provider-dynamic","sourceChainId":"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","destinationChainId":"eip155:1","sourceTokenDeploymentId":"deployment-0010","destinationTokenDeploymentId":"deployment-0008","sourceTokenAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","destinationTokenAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","sourceTokenStandard":"spl-token","destinationTokenStandard":"erc20","sourceTokenDecimals":6,"destinationTokenDecimals":6,"sourceProviderChainName":"solana","destinationProviderChainName":"ethereum","sourceProviderChainId":0,"destinationProviderChainId":1,"sourceWormholeChainId":1,"destinationWormholeChainId":2,"sourceUsdcDeploymentId":"deployment-0010","sourceUsdcAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","sourceUsdcStandard":"spl-token","sourceUsdcDecimals":6,"swiftContract":"mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny","forwarderAddress":null,"forwarderFunctionSelector":null,"jupiterProgramAddress":null,"builderEndpoint":"https://tx-builder.mayan.finance","explorerEndpoint":"https://explorer-api.mayan.finance/v3","dependencies":["mayan-hosted-quote-api","mayan-hosted-transaction-builder","swift-auction-solvers","relayers","wormhole-guardian-messaging","mayan-explorer-indexer"],"status":"active"}]';
|
|
5883
|
+
var BRIDGE_CAPABILITIES_CONTENT_DIGEST = "691a77498c5ff876dadc437a8265d8288ec51cbc1d44f8beacb746626bf5b98d";
|
|
5884
|
+
var BRIDGE_CAPABILITIES_AS_OF_DATE = "2026-09-17";
|
|
5885
|
+
var ETHEREUM_CHAIN_ID = TOKEN_CHAIN_IDS.ethereumMainnet;
|
|
5886
|
+
var SOLANA_CHAIN_ID = TOKEN_CHAIN_IDS.solanaMainnet;
|
|
5887
|
+
var ETHEREUM_FORWARDER = "0x337685fdab40d39bd02028545a4ffa7d287cc3e2";
|
|
5888
|
+
var ETHEREUM_FORWARDER_PROVIDER = "0x337685fdaB40D39bd02028545a4FfA7D287cC3E2";
|
|
5889
|
+
var SOLANA_SWIFT_PROGRAM = "mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny";
|
|
5890
|
+
var SOLANA_JUPITER_V6 = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
|
|
5891
|
+
var SOLANA_TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
5892
|
+
var SOLANA_ASSOCIATED_TOKEN_PROGRAM = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
5893
|
+
var SOLANA_SYSTEM_PROGRAM = "11111111111111111111111111111111";
|
|
5894
|
+
var SOLANA_SYSVAR_RENT = "SysvarRent111111111111111111111111111111111";
|
|
5895
|
+
var SOLANA_COMPUTE_BUDGET_PROGRAM = "ComputeBudget111111111111111111111111111111";
|
|
5896
|
+
var SOLANA_CPI_PROXY_PROGRAM = "D8C8iW6zmoKg5TRr8nQ7h14TMWqQX8FiBdj2ju5MF3wa";
|
|
5897
|
+
var SOLANA_ANCHOR_EVENT_AUTHORITY = "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf";
|
|
5898
|
+
var SOLANA_FEE_MANAGER_PROGRAM = "5VtQHnhs2pfVEr68qQsbTRwKh4JV5GTu9mBHgHFxpHeQ";
|
|
5899
|
+
var SOLANA_MAINNET_GENESIS_HASH = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
|
|
5900
|
+
var SOLANA_MAYAN_LOOKUP_TABLE = "Ff3yi1meWQQ19VPZMzGg6H8JQQeRudiV7QtVtyzJyoht";
|
|
5901
|
+
var SOLANA_ADDRESS_LOOKUP_TABLE_OWNER = "AddressLookupTab1e1111111111111111111111111";
|
|
5902
|
+
var SOLANA_ROUTE_V2_DISCRIMINATOR = "bb64facc31c4af14";
|
|
5903
|
+
var SOLANA_ROUTE_V2_WHIRLPOOL_TAIL = "000001000000110010270001";
|
|
5904
|
+
var SOLANA_ROUTE_V2_RAYDIUM_TAIL = "0000010000001a10270001";
|
|
5905
|
+
var SOLANA_WHIRLPOOL_PROGRAM = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc";
|
|
5906
|
+
var SOLANA_WHIRLPOOL_POOL = "ArisQNcbjXPJD7RgPRvysatX3xcfHPTbcTkfD8kDoZ9i";
|
|
5907
|
+
var SOLANA_RAYDIUM_CLMM_PROGRAM = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK";
|
|
5908
|
+
var SOLANA_RAYDIUM_CLMM_POOL = "2zVV22uNWdJNmkXpj5vCrMzwHGBoJdsyV7qACh29sK1w";
|
|
5909
|
+
var SOLANA_INIT_ORDER_DISCRIMINATOR = "204c290c27a284db";
|
|
5910
|
+
var EVM_SOURCE_SWAP_SELECTOR = "0x3f0bde25";
|
|
5911
|
+
var SOLANA_MAYAN_SOURCE_SWAP_ENDPOINT = "https://price-api.mayan.finance/v3";
|
|
5912
|
+
var MAYAN_REFERENCE_COMMIT = "c4c98031aaad9264d17630d7b4de0cb18688cf78";
|
|
5913
|
+
var MAYAN_ORACLE_SDK_VERSION = "15_2_2";
|
|
5914
|
+
var MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
5915
|
+
var MAX_JSON_DEPTH = 32;
|
|
5916
|
+
var MAX_ROUTER_CALLDATA_BYTES = 16384;
|
|
5917
|
+
var MAX_SOLANA_SWAP_ACCOUNTS = 64;
|
|
5918
|
+
var MAX_SOLANA_SWAP_DATA_BYTES = 4096;
|
|
5919
|
+
var MAX_LOOKUP_TABLES = 8;
|
|
5920
|
+
var MAX_LOOKUP_TABLE_ADDRESSES = 256;
|
|
5921
|
+
var MAX_SOLANA_TRANSACTION_BYTES = 1232;
|
|
5922
|
+
var UINT64_MAX = (1n << 64n) - 1n;
|
|
5923
|
+
var EVM_ADDRESS2 = /^0x[0-9a-fA-F]{40}$/u;
|
|
5924
|
+
var HEX_BYTES2 = /^0x(?:[0-9a-fA-F]{2})*$/u;
|
|
5925
|
+
var UINT64 = /^(0|[1-9][0-9]*)$/u;
|
|
5926
|
+
var NONCE = /^0x[0-9a-f]{32}$/u;
|
|
5927
|
+
var PLAIN_DECIMAL = /^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/u;
|
|
5928
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
5929
|
+
var capabilities = JSON.parse(BRIDGE_CAPABILITIES_JSON);
|
|
5930
|
+
var concatBytes = (...parts) => {
|
|
5931
|
+
const length = parts.reduce((sum, part) => sum + part.length, 0);
|
|
5932
|
+
const result = new Uint8Array(length);
|
|
5933
|
+
let offset = 0;
|
|
5934
|
+
for (const part of parts) {
|
|
5935
|
+
result.set(part, offset);
|
|
5936
|
+
offset += part.length;
|
|
5937
|
+
}
|
|
5938
|
+
return result;
|
|
5939
|
+
};
|
|
5940
|
+
var bytesToHex = (bytes) => [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
5941
|
+
var hexToBytes = (value) => {
|
|
5942
|
+
const normalized = value.startsWith("0x") ? value.slice(2) : value;
|
|
5943
|
+
if (!/^(?:[0-9a-fA-F]{2})*$/u.test(normalized)) throw new Error("invalid hex");
|
|
5944
|
+
const bytes = new Uint8Array(normalized.length / 2);
|
|
5945
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
5946
|
+
bytes[index] = Number.parseInt(normalized.slice(index * 2, index * 2 + 2), 16);
|
|
5947
|
+
}
|
|
5948
|
+
return bytes;
|
|
5949
|
+
};
|
|
5950
|
+
var sha256Hex = (value) => bytesToHex(sha2_js.sha256(typeof value === "string" ? new TextEncoder().encode(value) : value));
|
|
5951
|
+
var keccakHex = (value) => bytesToHex(sha3_js.keccak_256(value));
|
|
5952
|
+
var stableJson = (value) => {
|
|
5953
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
5954
|
+
if (value !== null && typeof value === "object") {
|
|
5955
|
+
const object = value;
|
|
5956
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object[key])}`).join(",")}}`;
|
|
5957
|
+
}
|
|
5958
|
+
return JSON.stringify(value);
|
|
5959
|
+
};
|
|
5960
|
+
var cloneJson = (value) => JSON.parse(JSON.stringify(value));
|
|
5961
|
+
var assertJsonDepth = (value, depth = 0) => {
|
|
5962
|
+
if (depth > MAX_JSON_DEPTH) throw new Error("json depth");
|
|
5963
|
+
if (Array.isArray(value)) {
|
|
5964
|
+
for (const child of value) assertJsonDepth(child, depth + 1);
|
|
5965
|
+
} else if (value !== null && typeof value === "object") {
|
|
5966
|
+
for (const child of Object.values(value)) assertJsonDepth(child, depth + 1);
|
|
5967
|
+
}
|
|
5968
|
+
};
|
|
5969
|
+
var parseJsonObject = (text) => {
|
|
5970
|
+
if (new TextEncoder().encode(text).length > MAX_RESPONSE_BYTES) throw new Error("response too large");
|
|
5971
|
+
const value = JSON.parse(text);
|
|
5972
|
+
assertJsonDepth(value);
|
|
5973
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("object expected");
|
|
5974
|
+
return value;
|
|
5975
|
+
};
|
|
5976
|
+
var normalizeEvmAddress3 = (value) => {
|
|
5977
|
+
if (typeof value !== "string" || !EVM_ADDRESS2.test(value) || /^0x0{40}$/iu.test(value)) throw new Error("EVM address");
|
|
5978
|
+
return value.toLowerCase();
|
|
5979
|
+
};
|
|
5980
|
+
var base58Decode = (value) => {
|
|
5981
|
+
if (typeof value !== "string" || value.length === 0) throw new Error("base58");
|
|
5982
|
+
let result = 0n;
|
|
5983
|
+
for (const character of value) {
|
|
5984
|
+
const digit = BASE58_ALPHABET.indexOf(character);
|
|
5985
|
+
if (digit < 0) throw new Error("base58");
|
|
5986
|
+
result = result * 58n + BigInt(digit);
|
|
5987
|
+
}
|
|
5988
|
+
const bytes = [];
|
|
5989
|
+
while (result > 0n) {
|
|
5990
|
+
bytes.push(Number(result & 0xffn));
|
|
5991
|
+
result >>= 8n;
|
|
5992
|
+
}
|
|
5993
|
+
bytes.reverse();
|
|
5994
|
+
let leading = 0;
|
|
5995
|
+
while (leading < value.length && value[leading] === "1") leading += 1;
|
|
5996
|
+
return Uint8Array.from([...new Uint8Array(leading), ...bytes]);
|
|
5997
|
+
};
|
|
5998
|
+
var base58Encode = (value) => {
|
|
5999
|
+
let number = 0n;
|
|
6000
|
+
for (const byte of value) number = number * 256n + BigInt(byte);
|
|
6001
|
+
let result = "";
|
|
6002
|
+
while (number > 0n) {
|
|
6003
|
+
const digit = Number(number % 58n);
|
|
6004
|
+
result = BASE58_ALPHABET[digit] + result;
|
|
6005
|
+
number /= 58n;
|
|
6006
|
+
}
|
|
6007
|
+
let leading = 0;
|
|
6008
|
+
while (leading < value.length && value[leading] === 0) leading += 1;
|
|
6009
|
+
return `${"1".repeat(leading)}${result}`;
|
|
6010
|
+
};
|
|
6011
|
+
var canonicalSolanaAddress = (value) => {
|
|
6012
|
+
const bytes = base58Decode(value);
|
|
6013
|
+
if (bytes.length !== 32 || base58Encode(bytes) !== value) throw new Error("Solana address");
|
|
6014
|
+
return value;
|
|
6015
|
+
};
|
|
6016
|
+
var uint64 = (value, positive = false) => {
|
|
6017
|
+
if (typeof value !== "string" || !UINT64.test(value) || value.length > 20) throw new Error("uint64");
|
|
6018
|
+
const parsed = BigInt(value);
|
|
6019
|
+
if (parsed > UINT64_MAX || positive && parsed === 0n) throw new Error("uint64");
|
|
6020
|
+
return parsed;
|
|
6021
|
+
};
|
|
6022
|
+
var wordUint = (value) => {
|
|
6023
|
+
if (value < 0n || value >= 1n << 256n) throw new Error("ABI uint");
|
|
6024
|
+
const result = new Uint8Array(32);
|
|
6025
|
+
let remaining = value;
|
|
6026
|
+
for (let index = 31; index >= 0; index -= 1) {
|
|
6027
|
+
result[index] = Number(remaining & 0xffn);
|
|
6028
|
+
remaining >>= 8n;
|
|
6029
|
+
}
|
|
6030
|
+
return result;
|
|
6031
|
+
};
|
|
6032
|
+
var wordAddress = (value) => {
|
|
6033
|
+
const bytes = hexToBytes(normalizeEvmAddress3(value));
|
|
6034
|
+
return concatBytes(new Uint8Array(12), bytes);
|
|
6035
|
+
};
|
|
6036
|
+
var wordBytes32 = (value) => {
|
|
6037
|
+
if (value.length !== 32) throw new Error("bytes32");
|
|
6038
|
+
return value;
|
|
6039
|
+
};
|
|
6040
|
+
var pad32 = (value) => {
|
|
6041
|
+
const padded = new Uint8Array(Math.ceil(value.length / 32) * 32);
|
|
6042
|
+
padded.set(value);
|
|
6043
|
+
return padded;
|
|
6044
|
+
};
|
|
6045
|
+
var encodeAbiBytes = (value) => concatBytes(wordUint(BigInt(value.length)), pad32(value));
|
|
6046
|
+
var encodeAbiWithDynamics = (head, dynamics) => {
|
|
6047
|
+
const headSize = (head.length + dynamics.length) * 32;
|
|
6048
|
+
let offset = headSize;
|
|
6049
|
+
const offsets = dynamics.map((value) => {
|
|
6050
|
+
const current = offset;
|
|
6051
|
+
offset += 32 + Math.ceil(value.length / 32) * 32;
|
|
6052
|
+
return current;
|
|
6053
|
+
});
|
|
6054
|
+
return concatBytes(
|
|
6055
|
+
...head.map((word) => word),
|
|
6056
|
+
...offsets.map((entry) => wordUint(BigInt(entry))),
|
|
6057
|
+
...dynamics.map(encodeAbiBytes)
|
|
6058
|
+
);
|
|
6059
|
+
};
|
|
6060
|
+
var nativeAddressBytes = (value, chainId) => {
|
|
6061
|
+
if (chainId === ETHEREUM_CHAIN_ID) return wordAddress(value);
|
|
6062
|
+
canonicalSolanaAddress(value);
|
|
6063
|
+
return base58Decode(value);
|
|
6064
|
+
};
|
|
6065
|
+
var routeForQuote = (quote) => {
|
|
6066
|
+
const route = capabilities.find((entry) => entry.sourceChainId === quote.sourceChainId && entry.destinationChainId === quote.destinationChainId && entry.sourceTokenDeploymentId === quote.sourceTokenDeploymentId && entry.destinationTokenDeploymentId === quote.destinationTokenDeploymentId);
|
|
6067
|
+
if (!route) throw new Error("route");
|
|
6068
|
+
return route;
|
|
6069
|
+
};
|
|
6070
|
+
var sourceIsUsdc = (route) => route.bridgeCapabilityId.includes("-usdc-");
|
|
6071
|
+
var providerStandard = (chainId) => chainId === ETHEREUM_CHAIN_ID ? "erc20" : "spl";
|
|
6072
|
+
var assertCatalogToken = (deploymentId, chainId, address, standard) => {
|
|
6073
|
+
const token = getTokenDeployment(deploymentId);
|
|
6074
|
+
if (!token || token.chainId !== chainId || token.address === null || token.standard !== standard || token.decimals !== 6 || token.status !== "active" || (chainId === ETHEREUM_CHAIN_ID ? token.address.toLowerCase() !== address.toLowerCase() : token.address !== address)) throw new Error("token");
|
|
6075
|
+
return token;
|
|
6076
|
+
};
|
|
6077
|
+
var validateLocalRoute = (quote) => {
|
|
6078
|
+
const route = routeForQuote(quote);
|
|
6079
|
+
if (route.providerId !== "mayan-swift-v2" || route.status !== "active") throw new Error("route");
|
|
6080
|
+
assertCatalogToken(route.sourceTokenDeploymentId, route.sourceChainId, route.sourceTokenAddress, route.sourceTokenStandard);
|
|
6081
|
+
assertCatalogToken(route.destinationTokenDeploymentId, route.destinationChainId, route.destinationTokenAddress, route.destinationTokenStandard);
|
|
6082
|
+
assertCatalogToken(route.sourceUsdcDeploymentId, route.sourceChainId, route.sourceUsdcAddress, route.sourceUsdcStandard);
|
|
6083
|
+
if (quote.sourceSwap.required !== !sourceIsUsdc(route)) throw new Error("quote");
|
|
6084
|
+
if (quote.sourceSwap.inputTokenDeploymentId !== route.sourceTokenDeploymentId || quote.sourceSwap.intermediateTokenDeploymentId !== route.sourceUsdcDeploymentId || quote.sourceSwap.intermediateTokenAddress !== route.sourceUsdcAddress || quote.sourceSwap.intermediateTokenStandard !== providerStandard(route.sourceChainId) || quote.sourceSwap.intermediateTokenDecimals !== 6) throw new Error("quote");
|
|
6085
|
+
if (sourceIsUsdc(route)) {
|
|
6086
|
+
if (quote.sourceSwap.routerKind !== null || quote.sourceSwap.routerAddress !== null) throw new Error("quote");
|
|
6087
|
+
if (JSON.stringify(quote.dependencies) !== JSON.stringify(route.dependencies)) throw new Error("quote");
|
|
6088
|
+
} else if (route.sourceChainId === ETHEREUM_CHAIN_ID && (quote.sourceSwap.routerKind !== "provider-selected-evm" || quote.sourceSwap.routerAddress === null) || route.sourceChainId === SOLANA_CHAIN_ID && (quote.sourceSwap.routerKind !== "jupiter-v6" || quote.sourceSwap.routerAddress !== SOLANA_JUPITER_V6) || JSON.stringify(quote.dependencies) !== JSON.stringify(route.dependencies)) throw new Error("quote");
|
|
6089
|
+
const raw = parseJsonObject(quote.rawSignedQuoteJson);
|
|
6090
|
+
if (raw.swiftWrapAndLock !== void 0 && raw.swiftWrapAndLock !== false) throw new Error("quote");
|
|
6091
|
+
if (!sourceIsUsdc(route) && route.sourceChainId === ETHEREUM_CHAIN_ID) {
|
|
6092
|
+
if (raw.evmSwapRouterAddress !== void 0 && !rawAddressEquals(raw.evmSwapRouterAddress, quote.sourceSwap.routerAddress ?? "")) throw new Error("quote");
|
|
6093
|
+
if (raw.evmSwapRouterCalldata !== void 0 && (typeof raw.evmSwapRouterCalldata !== "string" || !HEX_BYTES2.test(raw.evmSwapRouterCalldata) || raw.evmSwapRouterCalldata === "0x" || hexToBytes(raw.evmSwapRouterCalldata).length > MAX_ROUTER_CALLDATA_BYTES)) throw new Error("quote");
|
|
6094
|
+
}
|
|
6095
|
+
const mode = raw.swiftAuctionMode;
|
|
6096
|
+
if (mode !== 2 && mode !== 3) throw new Error("quote");
|
|
6097
|
+
if (mode !== (sourceIsUsdc(route) ? 3 : 2)) throw new Error("quote");
|
|
6098
|
+
if (mode === 3 && (raw.expectedAmountOutBaseUnits !== raw.minAmountOutBaseUnits || raw.minAmountOutBaseUnits !== raw.minReceivedBaseUnits)) throw new Error("quote");
|
|
6099
|
+
const forbidden = ["customPayload", "memoHex", "referrer", "referrerAddress", "swiftRefundAddress", "permit", "approval", "approvalBatch", "separateSwapTx", "jito", "extraInstructions"];
|
|
6100
|
+
for (const key of forbidden) if (Object.hasOwn(raw, key) && raw[key] !== null && raw[key] !== false && raw[key] !== "") throw new Error("quote");
|
|
6101
|
+
return route;
|
|
6102
|
+
};
|
|
6103
|
+
var extractRawNumberLexeme = (raw, key) => {
|
|
6104
|
+
const expression = new RegExp(`"${key}"\\s*:\\s*([^,}\\s]+)`, "gu");
|
|
6105
|
+
const matches = [...raw.matchAll(expression)];
|
|
6106
|
+
const match = matches[0];
|
|
6107
|
+
if (matches.length !== 1 || match === void 0 || match[1] === void 0) throw new Error("number");
|
|
6108
|
+
return match[1];
|
|
6109
|
+
};
|
|
6110
|
+
var parsePlainDecimal = (value) => {
|
|
6111
|
+
if (!PLAIN_DECIMAL.test(value)) throw new Error("decimal");
|
|
6112
|
+
const separator = value.indexOf(".");
|
|
6113
|
+
const integerPart = separator === -1 ? value : value.slice(0, separator);
|
|
6114
|
+
const fractionalPart = separator === -1 ? "" : value.slice(separator + 1);
|
|
6115
|
+
const integer = BigInt(integerPart);
|
|
6116
|
+
const keptFraction = fractionalPart.slice(0, 6).padEnd(6, "0");
|
|
6117
|
+
const result = integer * 1000000n + BigInt(keptFraction || "0");
|
|
6118
|
+
if (result <= 0n || result > UINT64_MAX) throw new Error("decimal");
|
|
6119
|
+
return { source: value, integer: result, scale: fractionalPart.length };
|
|
6120
|
+
};
|
|
6121
|
+
var binary64RoundedDecimalUnits = (value) => {
|
|
6122
|
+
const number = Number(value);
|
|
6123
|
+
if (!Number.isFinite(number) || number <= 0 || number === 0) throw new Error("decimal");
|
|
6124
|
+
const bits = new DataView(new ArrayBuffer(8));
|
|
6125
|
+
bits.setFloat64(0, number, false);
|
|
6126
|
+
const high = BigInt(bits.getUint32(0, false));
|
|
6127
|
+
const low = BigInt(bits.getUint32(4, false));
|
|
6128
|
+
const encoded = high << 32n | low;
|
|
6129
|
+
const exponent = Number(encoded >> 52n & 0x7ffn);
|
|
6130
|
+
const fraction = encoded & (1n << 52n) - 1n;
|
|
6131
|
+
const mantissa = exponent === 0 ? fraction : 1n << 52n | fraction;
|
|
6132
|
+
const binaryExponent = exponent === 0 ? -1074 : exponent - 1023 - 52;
|
|
6133
|
+
let numerator = mantissa * 10000000n;
|
|
6134
|
+
let denominator = 1n;
|
|
6135
|
+
if (binaryExponent >= 0) numerator <<= BigInt(binaryExponent);
|
|
6136
|
+
else denominator <<= BigInt(-binaryExponent);
|
|
6137
|
+
let rounded = numerator / denominator;
|
|
6138
|
+
const remainder = numerator % denominator;
|
|
6139
|
+
if (remainder * 2n >= denominator) rounded += 1n;
|
|
6140
|
+
const result = rounded / 10n;
|
|
6141
|
+
if (result <= 0n || result > UINT64_MAX) throw new Error("decimal");
|
|
6142
|
+
return result;
|
|
6143
|
+
};
|
|
6144
|
+
var exactIntermediateAmount = (raw, direct, amountIn) => {
|
|
6145
|
+
const decimal = parsePlainDecimal(raw);
|
|
6146
|
+
const exact = decimal.integer;
|
|
6147
|
+
if (direct) {
|
|
6148
|
+
if (exact !== uint64(amountIn, true)) throw new Error("decimal");
|
|
6149
|
+
return exact.toString();
|
|
6150
|
+
}
|
|
6151
|
+
if (binary64RoundedDecimalUnits(raw) !== exact) throw new Error("decimal");
|
|
6152
|
+
return exact.toString();
|
|
6153
|
+
};
|
|
6154
|
+
var validateDestinationMinimumCompatibility = (raw, canonical) => {
|
|
6155
|
+
const units = uint64(canonical, true);
|
|
6156
|
+
const lexeme = extractRawNumberLexeme(raw, "minAmountOut");
|
|
6157
|
+
if (parsePlainDecimal(lexeme).integer !== units || binary64RoundedDecimalUnits(lexeme) !== units) {
|
|
6158
|
+
throw new Error("destination minimum");
|
|
6159
|
+
}
|
|
6160
|
+
};
|
|
6161
|
+
var rawUint64 = (raw, key, required = true) => {
|
|
6162
|
+
const value = raw[key];
|
|
6163
|
+
if (value === void 0 && !required) return 0n;
|
|
6164
|
+
return uint64(value, false);
|
|
6165
|
+
};
|
|
6166
|
+
var rawAddressEquals = (value, expected) => typeof value === "string" && (EVM_ADDRESS2.test(expected) ? value.toLowerCase() === expected.toLowerCase() : value === expected);
|
|
6167
|
+
var isOnCurveZip215 = (bytes) => {
|
|
6168
|
+
try {
|
|
6169
|
+
ed25519_js.ed25519.Point.fromBytes(bytes, true);
|
|
6170
|
+
return true;
|
|
6171
|
+
} catch {
|
|
6172
|
+
return false;
|
|
6173
|
+
}
|
|
6174
|
+
};
|
|
6175
|
+
var findProgramAddress = (seeds, programId) => {
|
|
6176
|
+
if (seeds.length > 16 || seeds.some((seed) => seed.length > 32)) throw new Error("PDA seeds");
|
|
6177
|
+
const program = base58Decode(programId);
|
|
6178
|
+
if (program.length !== 32) throw new Error("PDA program");
|
|
6179
|
+
const suffix = new TextEncoder().encode("ProgramDerivedAddress");
|
|
6180
|
+
for (let bump = 255; bump >= 0; bump -= 1) {
|
|
6181
|
+
const candidate = sha2_js.sha256(concatBytes(...seeds, Uint8Array.from([bump]), program, suffix));
|
|
6182
|
+
if (!isOnCurveZip215(candidate)) return { address: base58Encode(candidate), bump };
|
|
6183
|
+
}
|
|
6184
|
+
throw new Error("PDA unavailable");
|
|
6185
|
+
};
|
|
6186
|
+
var associatedTokenAddress = (owner, mint, allowOwnerOffCurve) => {
|
|
6187
|
+
const ownerBytes = base58Decode(owner);
|
|
6188
|
+
const mintBytes = base58Decode(mint);
|
|
6189
|
+
if (ownerBytes.length !== 32 || mintBytes.length !== 32) throw new Error("ATA address");
|
|
6190
|
+
if (!allowOwnerOffCurve && isOnCurveZip215(ownerBytes) === false) throw new Error("ATA owner");
|
|
6191
|
+
return findProgramAddress(
|
|
6192
|
+
[ownerBytes, base58Decode(SOLANA_TOKEN_PROGRAM), mintBytes],
|
|
6193
|
+
SOLANA_ASSOCIATED_TOKEN_PROGRAM
|
|
6194
|
+
).address;
|
|
6195
|
+
};
|
|
6196
|
+
var parseSourceQuote = (quote, route) => {
|
|
6197
|
+
const raw = parseJsonObject(quote.rawSignedQuoteJson);
|
|
6198
|
+
const minimumLexeme = extractRawNumberLexeme(quote.rawSignedQuoteJson, "minMiddleAmount");
|
|
6199
|
+
const modeValue = raw.swiftAuctionMode;
|
|
6200
|
+
if (modeValue !== 2 && modeValue !== 3) throw new Error("mode");
|
|
6201
|
+
const mode = modeValue === 2 || modeValue === 3 ? modeValue : sourceIsUsdc(route) ? 3 : 2;
|
|
6202
|
+
if (mode !== (sourceIsUsdc(route) ? 3 : 2)) throw new Error("mode");
|
|
6203
|
+
if (mode === 3 && (raw.expectedAmountOutBaseUnits !== raw.minAmountOutBaseUnits || raw.minAmountOutBaseUnits !== raw.minReceivedBaseUnits)) throw new Error("guaranteed output");
|
|
6204
|
+
const minimumIntermediateAmount = exactIntermediateAmount(minimumLexeme, sourceIsUsdc(route), quote.amountIn);
|
|
6205
|
+
if (quote.sourceSwap.providerMinimumAmount !== minimumLexeme) throw new Error("provider minimum");
|
|
6206
|
+
if (!sourceIsUsdc(route)) {
|
|
6207
|
+
const numeric = Number(minimumLexeme);
|
|
6208
|
+
if (!Number.isFinite(numeric) || numeric <= 0) throw new Error("number");
|
|
6209
|
+
}
|
|
6210
|
+
return {
|
|
6211
|
+
raw,
|
|
6212
|
+
minimumIntermediateAmount,
|
|
6213
|
+
mode,
|
|
6214
|
+
cancelFee: rawUint64(raw, "cancelRelayerFee64"),
|
|
6215
|
+
refundFee: rawUint64(raw, "refundRelayerFee64"),
|
|
6216
|
+
submitFee: rawUint64(raw, "submitRelayerFee64")
|
|
6217
|
+
};
|
|
6218
|
+
};
|
|
6219
|
+
var swiftRandom = (quoteId, orderNonce) => concatBytes(hexToBytes(quoteId), hexToBytes(orderNonce));
|
|
6220
|
+
var writeUint16Be = (value) => {
|
|
6221
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > 65535) throw new Error("uint16");
|
|
6222
|
+
return Uint8Array.from([value >>> 8 & 255, value & 255]);
|
|
6223
|
+
};
|
|
6224
|
+
var writeUint64Be = (value) => {
|
|
6225
|
+
if (value < 0n || value > UINT64_MAX) throw new Error("uint64");
|
|
6226
|
+
const result = new Uint8Array(8);
|
|
6227
|
+
let current = value;
|
|
6228
|
+
for (let index = 7; index >= 0; index -= 1) {
|
|
6229
|
+
result[index] = Number(current & 0xffn);
|
|
6230
|
+
current >>= 8n;
|
|
6231
|
+
}
|
|
6232
|
+
return result;
|
|
6233
|
+
};
|
|
6234
|
+
var writeUint64Le = (value) => {
|
|
6235
|
+
const result = writeUint64Be(value);
|
|
6236
|
+
return Uint8Array.from([...result].reverse());
|
|
6237
|
+
};
|
|
6238
|
+
var writeUint16Le = (value) => {
|
|
6239
|
+
const result = writeUint16Be(value);
|
|
6240
|
+
return Uint8Array.from([result[1], result[0]]);
|
|
6241
|
+
};
|
|
6242
|
+
var zero32 = () => new Uint8Array(32);
|
|
6243
|
+
var orderPreimage = (quote, route, swapperAddress, destinationAddress, orderNonce, minimumIntermediateAmount, cancelFee, refundFee, mode) => {
|
|
6244
|
+
const destinationMinimum = uint64(quote.minimumAmountOut, true);
|
|
6245
|
+
const parts = [
|
|
6246
|
+
Uint8Array.from([1]),
|
|
6247
|
+
nativeAddressBytes(swapperAddress, route.sourceChainId),
|
|
6248
|
+
writeUint16Be(route.sourceWormholeChainId),
|
|
6249
|
+
nativeAddressBytes(route.sourceUsdcAddress, route.sourceChainId),
|
|
6250
|
+
nativeAddressBytes(destinationAddress, route.destinationChainId),
|
|
6251
|
+
writeUint16Be(route.destinationWormholeChainId),
|
|
6252
|
+
nativeAddressBytes(route.destinationTokenAddress, route.destinationChainId),
|
|
6253
|
+
writeUint64Be(destinationMinimum),
|
|
6254
|
+
writeUint64Be(0n),
|
|
6255
|
+
writeUint64Be(cancelFee),
|
|
6256
|
+
writeUint64Be(refundFee),
|
|
6257
|
+
writeUint64Be(uint64(quote.deadline, true)),
|
|
6258
|
+
zero32(),
|
|
6259
|
+
Uint8Array.from([0, 0, mode]),
|
|
6260
|
+
swiftRandom(quote.quoteId, orderNonce),
|
|
6261
|
+
zero32()
|
|
6262
|
+
];
|
|
6263
|
+
const result = concatBytes(...parts);
|
|
6264
|
+
if (result.length !== 272) throw new Error("order preimage");
|
|
6265
|
+
return result;
|
|
6266
|
+
};
|
|
6267
|
+
var hashOrder = (quote, route, swapperAddress, destinationAddress, orderNonce, minimumIntermediateAmount, cancelFee, refundFee, mode) => `0x${keccakHex(orderPreimage(quote, route, swapperAddress, destinationAddress, orderNonce, minimumIntermediateAmount, cancelFee, refundFee, mode))}`;
|
|
6268
|
+
var quoteBindingHash = (route, quote, rawQuoteSha256, orderNonce, swapperAddress, destinationAddress) => sha256Hex(stableJson({
|
|
6269
|
+
capabilityId: route.bridgeCapabilityId,
|
|
6270
|
+
destinationAddress,
|
|
6271
|
+
destinationChainId: route.destinationChainId,
|
|
6272
|
+
destinationTokenDeploymentId: route.destinationTokenDeploymentId,
|
|
6273
|
+
orderNonce,
|
|
6274
|
+
quoteId: quote.quoteId,
|
|
6275
|
+
rawQuoteSha256,
|
|
6276
|
+
sourceChainId: route.sourceChainId,
|
|
6277
|
+
sourceTokenDeploymentId: route.sourceTokenDeploymentId,
|
|
6278
|
+
swapperAddress
|
|
6279
|
+
}));
|
|
6280
|
+
var sourceSwapHashProjection = (sourceSwap) => {
|
|
6281
|
+
if (sourceSwap.kind === "none") return sourceSwap;
|
|
6282
|
+
if (sourceSwap.kind === "evm-router") {
|
|
6283
|
+
const { rawProviderSourceSwapJson: _raw2, ...value2 } = sourceSwap;
|
|
6284
|
+
return value2;
|
|
6285
|
+
}
|
|
6286
|
+
const { rawProviderSourceSwapJson: _raw, ...value } = sourceSwap;
|
|
6287
|
+
return value;
|
|
6288
|
+
};
|
|
6289
|
+
var planHash = (binding, sourceSwap) => sha256Hex(stableJson({ quoteBindingHash: binding, sourceSwap: sourceSwapHashProjection(sourceSwap) }));
|
|
6290
|
+
var endpointUrl = (value) => {
|
|
6291
|
+
const source = value === void 0 ? SOLANA_MAYAN_SOURCE_SWAP_ENDPOINT : value;
|
|
6292
|
+
if (typeof source !== "string" || source.length === 0 || source.trim() !== source) throw new Error("endpoint");
|
|
6293
|
+
let endpoint;
|
|
6294
|
+
try {
|
|
6295
|
+
endpoint = new URL(source);
|
|
6296
|
+
} catch {
|
|
6297
|
+
throw new Error("endpoint");
|
|
6298
|
+
}
|
|
6299
|
+
if (endpoint.username || endpoint.password || endpoint.search || endpoint.hash || endpoint.protocol !== "https:" && !(endpoint.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]", "::1"].includes(endpoint.hostname))) throw new Error("endpoint");
|
|
6300
|
+
endpoint.pathname = endpoint.pathname.replace(/\/+$/u, "") || "/";
|
|
6301
|
+
return endpoint;
|
|
6302
|
+
};
|
|
6303
|
+
var sourceSwapUrl = (endpoint, chain, params) => {
|
|
6304
|
+
const result = new URL(endpoint);
|
|
6305
|
+
const basePath = result.pathname.replace(/\/+$/u, "");
|
|
6306
|
+
result.pathname = `${basePath}/get-swap/${chain}`.replace(/\/{2,}/gu, "/");
|
|
6307
|
+
for (const [key, value] of params) result.searchParams.append(key, String(value));
|
|
6308
|
+
return result;
|
|
6309
|
+
};
|
|
6310
|
+
var SourceResponseInvalidError = class extends Error {
|
|
6311
|
+
constructor() {
|
|
6312
|
+
super("invalid source response");
|
|
6313
|
+
this.name = "SourceResponseInvalidError";
|
|
6314
|
+
}
|
|
6315
|
+
};
|
|
6316
|
+
var disposeResponseBody = (response) => {
|
|
6317
|
+
if (response.body === null) return;
|
|
6318
|
+
try {
|
|
6319
|
+
const reader = response.body.getReader();
|
|
6320
|
+
void reader.cancel().catch(() => void 0);
|
|
6321
|
+
reader.releaseLock();
|
|
6322
|
+
} catch {
|
|
6323
|
+
}
|
|
6324
|
+
};
|
|
6325
|
+
var readSourceResponseText = async (response, signal) => {
|
|
6326
|
+
const declaredLength = response.headers.get("content-length");
|
|
6327
|
+
if (declaredLength !== null && /^\d+$/u.test(declaredLength) && Number(declaredLength) > MAX_RESPONSE_BYTES) {
|
|
6328
|
+
disposeResponseBody(response);
|
|
6329
|
+
throw new SourceResponseInvalidError();
|
|
6330
|
+
}
|
|
6331
|
+
if (response.body === null) return "";
|
|
6332
|
+
const reader = response.body.getReader();
|
|
6333
|
+
const chunks = [];
|
|
6334
|
+
let total = 0;
|
|
6335
|
+
let complete = false;
|
|
6336
|
+
let abortListener;
|
|
6337
|
+
try {
|
|
6338
|
+
while (true) {
|
|
6339
|
+
if (signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
6340
|
+
const abortPromise = new Promise((_resolve, reject) => {
|
|
6341
|
+
abortListener = () => reject(new DOMException("aborted", "AbortError"));
|
|
6342
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
6343
|
+
});
|
|
6344
|
+
let result;
|
|
6345
|
+
try {
|
|
6346
|
+
result = await Promise.race([reader.read(), abortPromise]);
|
|
6347
|
+
} finally {
|
|
6348
|
+
if (abortListener !== void 0) signal.removeEventListener("abort", abortListener);
|
|
6349
|
+
abortListener = void 0;
|
|
6350
|
+
}
|
|
6351
|
+
if (result.done) {
|
|
6352
|
+
complete = true;
|
|
6353
|
+
break;
|
|
6354
|
+
}
|
|
6355
|
+
if (!(result.value instanceof Uint8Array)) throw new SourceResponseInvalidError();
|
|
6356
|
+
total += result.value.byteLength;
|
|
6357
|
+
if (total > MAX_RESPONSE_BYTES) throw new SourceResponseInvalidError();
|
|
6358
|
+
chunks.push(result.value);
|
|
6359
|
+
}
|
|
6360
|
+
} finally {
|
|
6361
|
+
if (!complete) {
|
|
6362
|
+
try {
|
|
6363
|
+
await reader.cancel();
|
|
6364
|
+
} catch {
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
reader.releaseLock();
|
|
6368
|
+
}
|
|
6369
|
+
const bytes = new Uint8Array(total);
|
|
6370
|
+
let offset = 0;
|
|
6371
|
+
for (const chunk of chunks) {
|
|
6372
|
+
bytes.set(chunk, offset);
|
|
6373
|
+
offset += chunk.byteLength;
|
|
6374
|
+
}
|
|
6375
|
+
try {
|
|
6376
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
6377
|
+
} catch {
|
|
6378
|
+
throw new SourceResponseInvalidError();
|
|
6379
|
+
}
|
|
6380
|
+
};
|
|
6381
|
+
var fetchSourceSwap = async (runtime, url, options) => {
|
|
6382
|
+
const controller = new AbortController();
|
|
6383
|
+
let timedOut = false;
|
|
6384
|
+
const timeout = setTimeout(() => {
|
|
6385
|
+
timedOut = true;
|
|
6386
|
+
controller.abort();
|
|
6387
|
+
}, runtime.timeoutMs);
|
|
6388
|
+
const abort = () => controller.abort();
|
|
6389
|
+
if (options?.signal?.aborted) controller.abort();
|
|
6390
|
+
else options?.signal?.addEventListener("abort", abort, { once: true });
|
|
6391
|
+
try {
|
|
6392
|
+
const response = await runtime.fetch(url, {
|
|
6393
|
+
method: "GET",
|
|
6394
|
+
headers: { accept: "application/json" },
|
|
6395
|
+
credentials: "omit",
|
|
6396
|
+
redirect: "manual",
|
|
6397
|
+
signal: controller.signal
|
|
6398
|
+
});
|
|
6399
|
+
if (!response.ok) {
|
|
6400
|
+
disposeResponseBody(response);
|
|
6401
|
+
runtime.fail("BRIDGE_PROVIDER_HTTP");
|
|
6402
|
+
}
|
|
6403
|
+
const text = await readSourceResponseText(response, controller.signal);
|
|
6404
|
+
let root;
|
|
6405
|
+
try {
|
|
6406
|
+
root = parseJsonObject(text);
|
|
6407
|
+
} catch {
|
|
6408
|
+
runtime.fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6409
|
+
}
|
|
6410
|
+
return { text, root };
|
|
6411
|
+
} catch (error) {
|
|
6412
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
6413
|
+
if (error instanceof SourceResponseInvalidError) runtime.fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6414
|
+
if (runtime.fail && timedOut) runtime.fail("BRIDGE_TIMEOUT");
|
|
6415
|
+
if (options?.signal?.aborted) runtime.fail("BRIDGE_ABORTED");
|
|
6416
|
+
if (error instanceof ErpcHttpError) runtime.fail("BRIDGE_PROVIDER_HTTP");
|
|
6417
|
+
runtime.fail("BRIDGE_PROVIDER_TRANSPORT");
|
|
6418
|
+
} finally {
|
|
6419
|
+
clearTimeout(timeout);
|
|
6420
|
+
options?.signal?.removeEventListener("abort", abort);
|
|
6421
|
+
}
|
|
6422
|
+
};
|
|
6423
|
+
var base64Decode = (value, maximumBytes = MAX_SOLANA_SWAP_DATA_BYTES) => {
|
|
6424
|
+
if (typeof value !== "string" || value.length > Math.ceil(maximumBytes * 4 / 3) + 4 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value)) throw new Error("base64");
|
|
6425
|
+
const bytes = Uint8Array.from(Buffer.from(value, "base64"));
|
|
6426
|
+
if (bytes.length > maximumBytes || Buffer.from(bytes).toString("base64") !== value) throw new Error("base64");
|
|
6427
|
+
return bytes;
|
|
6428
|
+
};
|
|
6429
|
+
var instructionFromRaw = (value) => {
|
|
6430
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("instruction");
|
|
6431
|
+
const source = value;
|
|
6432
|
+
if (Object.keys(source).sort().join(",") !== "accounts,data,programId") throw new Error("instruction");
|
|
6433
|
+
const programId = canonicalSolanaAddress(source.programId);
|
|
6434
|
+
if (!Array.isArray(source.accounts) || source.accounts.length > MAX_SOLANA_SWAP_ACCOUNTS) throw new Error("instruction");
|
|
6435
|
+
const accounts = source.accounts.map((entry) => {
|
|
6436
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new Error("account");
|
|
6437
|
+
const account = entry;
|
|
6438
|
+
if (Object.keys(account).sort().join(",") !== "isSigner,isWritable,pubkey" || typeof account.isSigner !== "boolean" || typeof account.isWritable !== "boolean") throw new Error("account");
|
|
6439
|
+
return {
|
|
6440
|
+
pubkey: canonicalSolanaAddress(account.pubkey),
|
|
6441
|
+
isSigner: account.isSigner,
|
|
6442
|
+
isWritable: account.isWritable
|
|
6443
|
+
};
|
|
6444
|
+
});
|
|
6445
|
+
const dataBase64 = source.data;
|
|
6446
|
+
base64Decode(dataBase64);
|
|
6447
|
+
return { programId, accounts, dataBase64 };
|
|
6448
|
+
};
|
|
6449
|
+
var encodeInstructionData = (value) => base64Decode(value);
|
|
6450
|
+
var accountAt = (instruction, index) => {
|
|
6451
|
+
const value = instruction.accounts[index];
|
|
6452
|
+
if (!value) throw new Error("account");
|
|
6453
|
+
return value;
|
|
6454
|
+
};
|
|
6455
|
+
var assertAccount = (account, pubkey, isSigner, isWritable) => {
|
|
6456
|
+
if (account.pubkey !== pubkey || account.isSigner !== isSigner || account.isWritable !== isWritable) {
|
|
6457
|
+
throw new Error("account");
|
|
6458
|
+
}
|
|
6459
|
+
};
|
|
6460
|
+
var validateComputeInstructions = (instructions) => {
|
|
6461
|
+
if (instructions.length > 2) throw new Error("compute");
|
|
6462
|
+
const tags = /* @__PURE__ */ new Set();
|
|
6463
|
+
for (const instruction of instructions) {
|
|
6464
|
+
if (instruction.programId !== SOLANA_COMPUTE_BUDGET_PROGRAM || instruction.accounts.length !== 0) throw new Error("compute");
|
|
6465
|
+
const data = encodeInstructionData(instruction.dataBase64);
|
|
6466
|
+
const tag = data[0];
|
|
6467
|
+
if (tag !== 2 && tag !== 3 || tags.has(tag)) throw new Error("compute");
|
|
6468
|
+
tags.add(tag);
|
|
6469
|
+
if (tag === 2) {
|
|
6470
|
+
if (data.length !== 5 || new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(1, true) > 14e5) throw new Error("compute");
|
|
6471
|
+
} else if (data.length !== 9 || new DataView(data.buffer, data.byteOffset, data.byteLength).getBigUint64(1, true) > 100000n) {
|
|
6472
|
+
throw new Error("compute");
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
};
|
|
6476
|
+
var validateAtaSetup = (instructions, swapperAddress, stateAddress, sourceUsdcAddress) => {
|
|
6477
|
+
if (instructions.length === 0 || instructions.length > 2) throw new Error("setup");
|
|
6478
|
+
const tokenProgram = SOLANA_TOKEN_PROGRAM;
|
|
6479
|
+
const owners = /* @__PURE__ */ new Set();
|
|
6480
|
+
for (const instruction of instructions) {
|
|
6481
|
+
if (instruction.programId !== SOLANA_ASSOCIATED_TOKEN_PROGRAM || instruction.accounts.length !== 6) throw new Error("setup");
|
|
6482
|
+
const payer = accountAt(instruction, 0);
|
|
6483
|
+
assertAccount(payer, swapperAddress, true, true);
|
|
6484
|
+
const owner = accountAt(instruction, 2).pubkey;
|
|
6485
|
+
if (owner !== swapperAddress && owner !== stateAddress) throw new Error("setup");
|
|
6486
|
+
if (owners.has(owner)) throw new Error("setup");
|
|
6487
|
+
owners.add(owner);
|
|
6488
|
+
const expectedAta = associatedTokenAddress(owner, sourceUsdcAddress, owner === stateAddress);
|
|
6489
|
+
assertAccount(accountAt(instruction, 2), owner, false, false);
|
|
6490
|
+
assertAccount(accountAt(instruction, 1), expectedAta, false, true);
|
|
6491
|
+
assertAccount(accountAt(instruction, 3), sourceUsdcAddress, false, false);
|
|
6492
|
+
assertAccount(accountAt(instruction, 4), SOLANA_SYSTEM_PROGRAM, false, false);
|
|
6493
|
+
assertAccount(accountAt(instruction, 5), tokenProgram, false, false);
|
|
6494
|
+
const data = encodeInstructionData(instruction.dataBase64);
|
|
6495
|
+
if (data.length !== 0 && (data.length !== 1 || data[0] !== 1)) throw new Error("setup");
|
|
6496
|
+
}
|
|
6497
|
+
if (!owners.has(stateAddress)) throw new Error("setup");
|
|
6498
|
+
};
|
|
6499
|
+
var validateJupiterInstruction = (instruction, route, quote, stateTokenAccount, swapperAddress, minimumIntermediateAmount, sourceSwapRaw) => {
|
|
6500
|
+
if (instruction.programId !== SOLANA_JUPITER_V6 || instruction.accounts.length < 8 || instruction.accounts.length > MAX_SOLANA_SWAP_ACCOUNTS) throw new Error("jupiter");
|
|
6501
|
+
const data = encodeInstructionData(instruction.dataBase64);
|
|
6502
|
+
if (bytesToHex(data.slice(0, 8)) !== SOLANA_ROUTE_V2_DISCRIMINATOR) throw new Error("jupiter");
|
|
6503
|
+
const quoteResponse = sourceSwapRaw.quoteResponse;
|
|
6504
|
+
if (quoteResponse === null || typeof quoteResponse !== "object" || Array.isArray(quoteResponse)) throw new Error("jupiter");
|
|
6505
|
+
const quoteResponseRaw = quoteResponse.raw;
|
|
6506
|
+
if (quoteResponseRaw === null || typeof quoteResponseRaw !== "object" || Array.isArray(quoteResponseRaw)) throw new Error("jupiter");
|
|
6507
|
+
const routePlan = quoteResponseRaw.routePlan;
|
|
6508
|
+
if (!Array.isArray(routePlan) || routePlan.length !== 1) throw new Error("jupiter");
|
|
6509
|
+
const swapInfo = routePlan[0]?.swapInfo;
|
|
6510
|
+
if (swapInfo === null || typeof swapInfo !== "object" || Array.isArray(swapInfo)) throw new Error("jupiter");
|
|
6511
|
+
const swapInfoRecord = swapInfo;
|
|
6512
|
+
const quoteResponseRecord = quoteResponse;
|
|
6513
|
+
const quoteResponseRawRecord = quoteResponseRaw;
|
|
6514
|
+
if (!rawAddressEquals(quoteResponseRecord.inputMint, route.sourceTokenAddress) || !rawAddressEquals(quoteResponseRecord.outputMint, route.sourceUsdcAddress) || !rawAddressEquals(quoteResponseRawRecord.inputMint, route.sourceTokenAddress) || !rawAddressEquals(quoteResponseRawRecord.outputMint, route.sourceUsdcAddress) || !rawAddressEquals(swapInfoRecord.inputMint, route.sourceTokenAddress) || !rawAddressEquals(swapInfoRecord.outputMint, route.sourceUsdcAddress) || typeof swapInfoRecord.inAmount !== "string" || typeof swapInfoRecord.outAmount !== "string" || uint64(swapInfoRecord.inAmount, true) !== uint64(quote.amountIn, true) || uint64(swapInfoRecord.outAmount, true) < uint64(minimumIntermediateAmount, true)) throw new Error("jupiter");
|
|
6515
|
+
const label = swapInfo.label;
|
|
6516
|
+
const expectedTail = label === "Whirlpool" ? SOLANA_ROUTE_V2_WHIRLPOOL_TAIL : label === "Raydium CLMM" ? SOLANA_ROUTE_V2_RAYDIUM_TAIL : null;
|
|
6517
|
+
if (expectedTail === null || data.length !== 28 + expectedTail.length / 2 || bytesToHex(data.slice(28)) !== expectedTail) throw new Error("jupiter");
|
|
6518
|
+
const expectedAccountCount = label === "Whirlpool" ? 22 : 25;
|
|
6519
|
+
const expectedAccounts = label === "Whirlpool" ? [
|
|
6520
|
+
[swapperAddress, true, false],
|
|
6521
|
+
[associatedTokenAddress(swapperAddress, route.sourceTokenAddress, false), false, true],
|
|
6522
|
+
[associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false), false, true],
|
|
6523
|
+
[route.sourceTokenAddress, false, false],
|
|
6524
|
+
[route.sourceUsdcAddress, false, false],
|
|
6525
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6526
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6527
|
+
[stateTokenAccount, false, true],
|
|
6528
|
+
[SOLANA_ANCHOR_EVENT_AUTHORITY, false, false],
|
|
6529
|
+
[SOLANA_JUPITER_V6, false, false],
|
|
6530
|
+
[SOLANA_WHIRLPOOL_PROGRAM, false, false],
|
|
6531
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6532
|
+
[swapperAddress, false, false],
|
|
6533
|
+
[SOLANA_WHIRLPOOL_POOL, false, true],
|
|
6534
|
+
[associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false), false, true],
|
|
6535
|
+
["6i68TM44UYSawGAS4Bx1vX31Af7QNZaRNBLUbc4r8exB", false, true],
|
|
6536
|
+
[associatedTokenAddress(swapperAddress, route.sourceTokenAddress, false), false, true],
|
|
6537
|
+
["8aq9zUXe37KLtXSaEYt7oq65oNAJiu1my2kRNMRPhTD5", false, true],
|
|
6538
|
+
["7qscKXFXCd1WQinZJvSDLsGLTTEwjmd88a871pz2V3Ja", false, true],
|
|
6539
|
+
["CaohZGaBaLmXyFQ4cLc83wGZTET7Mt9xMtUqR9EGaMHF", false, true],
|
|
6540
|
+
["7Mr4WYMiGPAXkyt9ePsHHmV6ust3U6dHwBmyfMRiHPA7", false, true],
|
|
6541
|
+
["9BjNZYSCZ3ac3XUYVKte4YYtmBGd7ATKfRshTGN99NxQ", false, false]
|
|
6542
|
+
] : [
|
|
6543
|
+
[swapperAddress, true, false],
|
|
6544
|
+
[associatedTokenAddress(swapperAddress, route.sourceTokenAddress, false), false, true],
|
|
6545
|
+
[associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false), false, true],
|
|
6546
|
+
[route.sourceTokenAddress, false, false],
|
|
6547
|
+
[route.sourceUsdcAddress, false, false],
|
|
6548
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6549
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6550
|
+
[stateTokenAccount, false, true],
|
|
6551
|
+
[SOLANA_ANCHOR_EVENT_AUTHORITY, false, false],
|
|
6552
|
+
[SOLANA_JUPITER_V6, false, false],
|
|
6553
|
+
[SOLANA_RAYDIUM_CLMM_PROGRAM, false, false],
|
|
6554
|
+
[swapperAddress, false, false],
|
|
6555
|
+
["9iFER3bpjf1PTTCQCfTRu17EJgvsxo9pVyA9QWwEuX4x", false, false],
|
|
6556
|
+
[SOLANA_RAYDIUM_CLMM_POOL, false, true],
|
|
6557
|
+
[associatedTokenAddress(swapperAddress, route.sourceTokenAddress, false), false, true],
|
|
6558
|
+
[associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false), false, true],
|
|
6559
|
+
["GFwsANMCPK8W3WhqTnwVP8JiwHaAr3cNDe5TJqgHHSPe", false, true],
|
|
6560
|
+
["ECw2X1TYbsrqFgdiYApNpn2ggznbj8pL5tREpY9Fb8jY", false, true],
|
|
6561
|
+
["2UQncszfVU7igwDiGN3jq2sUKzziLxDZqNsJEXzEob5x", false, true],
|
|
6562
|
+
[SOLANA_TOKEN_PROGRAM, false, false],
|
|
6563
|
+
["BVvv13QAQjPYKTWrpX7wQbhBAu3pbWwTb8P9SAqgRNKQ", false, true],
|
|
6564
|
+
["4HSR9WBSHgw7n5V8WGYYhLW8g92RPSrgnf2CHzbeQrrr", false, true],
|
|
6565
|
+
["HssFpWsQcNbJXBro1NVWCFAYEh8jp6NJV2nyFhE1zMGj", false, true],
|
|
6566
|
+
["DKcmVcrXuiF5FZre6h8GqurR2sKChUGBakxdTX7dSDw9", false, true],
|
|
6567
|
+
[SOLANA_JUPITER_V6, false, false]
|
|
6568
|
+
];
|
|
6569
|
+
const expectedPool = label === "Whirlpool" ? SOLANA_WHIRLPOOL_POOL : SOLANA_RAYDIUM_CLMM_POOL;
|
|
6570
|
+
if (instruction.accounts.length !== expectedAccountCount || expectedAccounts.length !== instruction.accounts.length) throw new Error("jupiter");
|
|
6571
|
+
for (const [index, [pubkey, isSigner, isWritable]] of expectedAccounts.entries()) {
|
|
6572
|
+
assertAccount(accountAt(instruction, index), pubkey, isSigner, isWritable);
|
|
6573
|
+
}
|
|
6574
|
+
if (typeof swapInfoRecord.ammKey !== "string" || swapInfoRecord.ammKey !== expectedPool) throw new Error("jupiter");
|
|
6575
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
6576
|
+
const inputAmount = view.getBigUint64(8, true);
|
|
6577
|
+
const quotedOutput = view.getBigUint64(16, true);
|
|
6578
|
+
const slippageBps = view.getUint16(24, true);
|
|
6579
|
+
const platformBps = view.getUint16(26, true);
|
|
6580
|
+
if (inputAmount !== uint64(quote.amountIn, true) || quotedOutput < uint64(minimumIntermediateAmount, true) || platformBps !== 0 || slippageBps > 1e4) throw new Error("jupiter");
|
|
6581
|
+
};
|
|
6582
|
+
var wrapInCpiProxy = (instruction) => ({
|
|
6583
|
+
programId: SOLANA_CPI_PROXY_PROGRAM,
|
|
6584
|
+
accounts: [
|
|
6585
|
+
{ pubkey: instruction.programId, isSigner: false, isWritable: false },
|
|
6586
|
+
...instruction.accounts
|
|
6587
|
+
],
|
|
6588
|
+
dataBase64: instruction.dataBase64
|
|
6589
|
+
});
|
|
6590
|
+
var makeAtaInstruction = (swapperAddress, owner, mint, allowOwnerOffCurve) => ({
|
|
6591
|
+
programId: SOLANA_ASSOCIATED_TOKEN_PROGRAM,
|
|
6592
|
+
accounts: [
|
|
6593
|
+
{ pubkey: swapperAddress, isSigner: true, isWritable: true },
|
|
6594
|
+
{ pubkey: associatedTokenAddress(owner, mint, allowOwnerOffCurve), isSigner: false, isWritable: true },
|
|
6595
|
+
{ pubkey: owner, isSigner: false, isWritable: false },
|
|
6596
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
6597
|
+
{ pubkey: SOLANA_SYSTEM_PROGRAM, isSigner: false, isWritable: false },
|
|
6598
|
+
{ pubkey: SOLANA_TOKEN_PROGRAM, isSigner: false, isWritable: false },
|
|
6599
|
+
{ pubkey: SOLANA_SYSVAR_RENT, isSigner: false, isWritable: false }
|
|
6600
|
+
],
|
|
6601
|
+
dataBase64: "AQ=="
|
|
6602
|
+
});
|
|
6603
|
+
var makeSplTransferInstruction = (source, destination, owner, amount) => ({
|
|
6604
|
+
programId: SOLANA_TOKEN_PROGRAM,
|
|
6605
|
+
accounts: [
|
|
6606
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
6607
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
6608
|
+
{ pubkey: owner, isSigner: true, isWritable: false }
|
|
6609
|
+
],
|
|
6610
|
+
dataBase64: Buffer.from(Uint8Array.from([3, ...writeUint64Le(amount)])).toString("base64")
|
|
6611
|
+
});
|
|
6612
|
+
var makeComputeUnitPriceInstruction = (microLamports) => ({
|
|
6613
|
+
programId: SOLANA_COMPUTE_BUDGET_PROGRAM,
|
|
6614
|
+
accounts: [],
|
|
6615
|
+
dataBase64: Buffer.from(Uint8Array.from([3, ...writeUint64Le(microLamports)])).toString("base64")
|
|
6616
|
+
});
|
|
6617
|
+
var makeSwiftInitInstruction = (quote, route, swapperAddress, destinationAddress, stateAddress, stateTokenAccount, minimumIntermediateAmount, cancelFee, refundFee, submitFee, mode, orderNonce) => {
|
|
6618
|
+
const relayerAccount = associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false);
|
|
6619
|
+
const data = new Uint8Array(198);
|
|
6620
|
+
data.set(hexToBytes(`0x${SOLANA_INIT_ORDER_DISCRIMINATOR}`), 0);
|
|
6621
|
+
data.set(writeUint64Le(uint64(minimumIntermediateAmount, true)), 8);
|
|
6622
|
+
data[16] = 0;
|
|
6623
|
+
data.set(writeUint64Le(submitFee), 17);
|
|
6624
|
+
data.set(nativeAddressBytes(destinationAddress, route.destinationChainId), 25);
|
|
6625
|
+
data.set(writeUint16Le(route.destinationWormholeChainId), 57);
|
|
6626
|
+
data.set(nativeAddressBytes(route.destinationTokenAddress, route.destinationChainId), 59);
|
|
6627
|
+
data.set(writeUint64Le(uint64(quote.minimumAmountOut, true)), 91);
|
|
6628
|
+
data.set(writeUint64Le(0n), 99);
|
|
6629
|
+
data.set(writeUint64Le(cancelFee), 107);
|
|
6630
|
+
data.set(writeUint64Le(refundFee), 115);
|
|
6631
|
+
data.set(writeUint64Le(uint64(quote.deadline, true)), 123);
|
|
6632
|
+
data.set(zero32(), 131);
|
|
6633
|
+
data[163] = 0;
|
|
6634
|
+
data[164] = 0;
|
|
6635
|
+
data[165] = mode;
|
|
6636
|
+
data.set(swiftRandom(quote.quoteId, orderNonce), 166);
|
|
6637
|
+
const accounts = [
|
|
6638
|
+
{ pubkey: swapperAddress, isSigner: false, isWritable: false },
|
|
6639
|
+
{ pubkey: swapperAddress, isSigner: true, isWritable: true },
|
|
6640
|
+
{ pubkey: stateAddress, isSigner: false, isWritable: true },
|
|
6641
|
+
{ pubkey: stateTokenAccount, isSigner: false, isWritable: true },
|
|
6642
|
+
{ pubkey: relayerAccount, isSigner: false, isWritable: true },
|
|
6643
|
+
{ pubkey: SOLANA_SWIFT_PROGRAM, isSigner: false, isWritable: false },
|
|
6644
|
+
{ pubkey: route.sourceUsdcAddress, isSigner: false, isWritable: false },
|
|
6645
|
+
{ pubkey: SOLANA_FEE_MANAGER_PROGRAM, isSigner: false, isWritable: false },
|
|
6646
|
+
{ pubkey: SOLANA_TOKEN_PROGRAM, isSigner: false, isWritable: false },
|
|
6647
|
+
{ pubkey: SOLANA_SYSTEM_PROGRAM, isSigner: false, isWritable: false }
|
|
6648
|
+
];
|
|
6649
|
+
return {
|
|
6650
|
+
programId: SOLANA_SWIFT_PROGRAM,
|
|
6651
|
+
accounts,
|
|
6652
|
+
dataBase64: Buffer.from(data).toString("base64")
|
|
6653
|
+
};
|
|
6654
|
+
};
|
|
6655
|
+
var encodeShortVec = (value) => {
|
|
6656
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > 65535) throw new Error("shortvec");
|
|
6657
|
+
const bytes = [];
|
|
6658
|
+
let current = value;
|
|
6659
|
+
do {
|
|
6660
|
+
let element = current & 127;
|
|
6661
|
+
current >>>= 7;
|
|
6662
|
+
if (current !== 0) element |= 128;
|
|
6663
|
+
bytes.push(element);
|
|
6664
|
+
} while (current !== 0);
|
|
6665
|
+
return Uint8Array.from(bytes);
|
|
6666
|
+
};
|
|
6667
|
+
var compileSolanaV0 = (payer, recentBlockhash, instructions, lookupTables) => {
|
|
6668
|
+
const keyMeta = /* @__PURE__ */ new Map();
|
|
6669
|
+
const getOrInsert = (address) => {
|
|
6670
|
+
const existing = keyMeta.get(address);
|
|
6671
|
+
if (existing) return existing;
|
|
6672
|
+
const value = { signer: false, writable: false, invoked: false };
|
|
6673
|
+
keyMeta.set(address, value);
|
|
6674
|
+
return value;
|
|
6675
|
+
};
|
|
6676
|
+
const payerMeta = getOrInsert(payer);
|
|
6677
|
+
payerMeta.signer = true;
|
|
6678
|
+
payerMeta.writable = true;
|
|
6679
|
+
for (const instruction of instructions) {
|
|
6680
|
+
getOrInsert(instruction.programId).invoked = true;
|
|
6681
|
+
for (const account of instruction.accounts) {
|
|
6682
|
+
const meta = getOrInsert(account.pubkey);
|
|
6683
|
+
meta.signer ||= account.isSigner;
|
|
6684
|
+
meta.writable ||= account.isWritable;
|
|
6685
|
+
}
|
|
6686
|
+
}
|
|
6687
|
+
const lookupTableLookups = [];
|
|
6688
|
+
const writableLookupKeys = [];
|
|
6689
|
+
const readonlyLookupKeys = [];
|
|
6690
|
+
for (const table of lookupTables) {
|
|
6691
|
+
const writableIndexes = [];
|
|
6692
|
+
const readonlyIndexes = [];
|
|
6693
|
+
for (const [address, meta] of [...keyMeta.entries()]) {
|
|
6694
|
+
if (meta.signer || meta.invoked || !meta.writable) continue;
|
|
6695
|
+
const index = table.addresses.indexOf(address);
|
|
6696
|
+
if (index >= 0) {
|
|
6697
|
+
if (index > 255) throw new Error("ALT index");
|
|
6698
|
+
writableIndexes.push(index);
|
|
6699
|
+
writableLookupKeys.push(address);
|
|
6700
|
+
keyMeta.delete(address);
|
|
6701
|
+
}
|
|
6702
|
+
}
|
|
6703
|
+
for (const [address, meta] of [...keyMeta.entries()]) {
|
|
6704
|
+
if (meta.signer || meta.invoked || meta.writable) continue;
|
|
6705
|
+
const index = table.addresses.indexOf(address);
|
|
6706
|
+
if (index >= 0) {
|
|
6707
|
+
if (index > 255) throw new Error("ALT index");
|
|
6708
|
+
readonlyIndexes.push(index);
|
|
6709
|
+
readonlyLookupKeys.push(address);
|
|
6710
|
+
keyMeta.delete(address);
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
if (writableIndexes.length > 0 || readonlyIndexes.length > 0) {
|
|
6714
|
+
lookupTableLookups.push({ accountKey: table.address, writableIndexes, readonlyIndexes });
|
|
6715
|
+
}
|
|
6716
|
+
}
|
|
6717
|
+
if (keyMeta.size > 256 || lookupTableLookups.length > MAX_LOOKUP_TABLES) throw new Error("account keys");
|
|
6718
|
+
const entries = [...keyMeta.entries()];
|
|
6719
|
+
const writableSigners = entries.filter(([, meta]) => meta.signer && meta.writable);
|
|
6720
|
+
const readonlySigners = entries.filter(([, meta]) => meta.signer && !meta.writable);
|
|
6721
|
+
const writableNonSigners = entries.filter(([, meta]) => !meta.signer && meta.writable);
|
|
6722
|
+
const readonlyNonSigners = entries.filter(([, meta]) => !meta.signer && !meta.writable);
|
|
6723
|
+
if (writableSigners.length !== 1 || readonlySigners.length !== 0 || writableSigners[0]?.[0] !== payer) throw new Error("payer");
|
|
6724
|
+
const staticKeys = [
|
|
6725
|
+
...writableSigners.map(([address]) => address),
|
|
6726
|
+
...readonlySigners.map(([address]) => address),
|
|
6727
|
+
...writableNonSigners.map(([address]) => address),
|
|
6728
|
+
...readonlyNonSigners.map(([address]) => address)
|
|
6729
|
+
];
|
|
6730
|
+
const allKeys = [...staticKeys, ...writableLookupKeys, ...readonlyLookupKeys];
|
|
6731
|
+
if (allKeys.length > 256) throw new Error("account index");
|
|
6732
|
+
const keyIndexes = new Map(allKeys.map((address, index) => [address, index]));
|
|
6733
|
+
const compiled = instructions.map((instruction) => {
|
|
6734
|
+
const programIdIndex = keyIndexes.get(instruction.programId);
|
|
6735
|
+
if (programIdIndex === void 0) throw new Error("program index");
|
|
6736
|
+
const accountKeyIndexes = instruction.accounts.map((account) => {
|
|
6737
|
+
const index = keyIndexes.get(account.pubkey);
|
|
6738
|
+
if (index === void 0) throw new Error("account index");
|
|
6739
|
+
return index;
|
|
6740
|
+
});
|
|
6741
|
+
return { programIdIndex, accountKeyIndexes, data: encodeInstructionData(instruction.dataBase64) };
|
|
6742
|
+
});
|
|
6743
|
+
const header = Uint8Array.from([
|
|
6744
|
+
writableSigners.length + readonlySigners.length,
|
|
6745
|
+
readonlySigners.length,
|
|
6746
|
+
readonlyNonSigners.length
|
|
6747
|
+
]);
|
|
6748
|
+
const compiledInstructionBytes = concatBytes(
|
|
6749
|
+
encodeShortVec(compiled.length),
|
|
6750
|
+
...compiled.map((instruction) => concatBytes(
|
|
6751
|
+
Uint8Array.from([instruction.programIdIndex]),
|
|
6752
|
+
encodeShortVec(instruction.accountKeyIndexes.length),
|
|
6753
|
+
Uint8Array.from(instruction.accountKeyIndexes),
|
|
6754
|
+
encodeShortVec(instruction.data.length),
|
|
6755
|
+
instruction.data
|
|
6756
|
+
))
|
|
6757
|
+
);
|
|
6758
|
+
const lookupBytes = concatBytes(
|
|
6759
|
+
encodeShortVec(lookupTableLookups.length),
|
|
6760
|
+
...lookupTableLookups.map((lookup) => concatBytes(
|
|
6761
|
+
base58Decode(lookup.accountKey),
|
|
6762
|
+
encodeShortVec(lookup.writableIndexes.length),
|
|
6763
|
+
Uint8Array.from(lookup.writableIndexes),
|
|
6764
|
+
encodeShortVec(lookup.readonlyIndexes.length),
|
|
6765
|
+
Uint8Array.from(lookup.readonlyIndexes)
|
|
6766
|
+
))
|
|
6767
|
+
);
|
|
6768
|
+
const message = concatBytes(
|
|
6769
|
+
Uint8Array.from([128]),
|
|
6770
|
+
header,
|
|
6771
|
+
encodeShortVec(staticKeys.length),
|
|
6772
|
+
...staticKeys.map((address) => base58Decode(address)),
|
|
6773
|
+
base58Decode(canonicalSolanaAddress(recentBlockhash)),
|
|
6774
|
+
compiledInstructionBytes,
|
|
6775
|
+
lookupBytes
|
|
6776
|
+
);
|
|
6777
|
+
const requiredSignatures = writableSigners.length + readonlySigners.length;
|
|
6778
|
+
const transaction = concatBytes(
|
|
6779
|
+
encodeShortVec(requiredSignatures),
|
|
6780
|
+
new Uint8Array(requiredSignatures * 64),
|
|
6781
|
+
message
|
|
6782
|
+
);
|
|
6783
|
+
if (transaction.length > MAX_SOLANA_TRANSACTION_BYTES) throw new Error("transaction size");
|
|
6784
|
+
return {
|
|
6785
|
+
transactionBase64: Buffer.from(transaction).toString("base64"),
|
|
6786
|
+
lookupTableLookups
|
|
6787
|
+
};
|
|
6788
|
+
};
|
|
6789
|
+
var validateSourceSwapEnvelope = (quote, route, raw, stateAddress, stateTokenAccount, swapperAddress, minimumIntermediateAmount) => {
|
|
6790
|
+
const direct = sourceIsUsdc(route);
|
|
6791
|
+
if (direct) throw new Error("direct source swap");
|
|
6792
|
+
if (route.sourceChainId === ETHEREUM_CHAIN_ID) {
|
|
6793
|
+
if (Object.keys(raw).sort().join(",") !== "swapRouterAddress,swapRouterCalldata") throw new Error("source swap");
|
|
6794
|
+
const routerAddress = normalizeEvmAddress3(raw.swapRouterAddress);
|
|
6795
|
+
if (quote.sourceSwap.routerAddress !== routerAddress || quote.sourceSwap.routerKind !== "provider-selected-evm") throw new Error("source swap");
|
|
6796
|
+
if (typeof raw.swapRouterCalldata !== "string" || !HEX_BYTES2.test(raw.swapRouterCalldata) || raw.swapRouterCalldata === "0x" || !raw.swapRouterCalldata.toLowerCase().startsWith(EVM_SOURCE_SWAP_SELECTOR) || hexToBytes(raw.swapRouterCalldata).length > MAX_ROUTER_CALLDATA_BYTES) throw new Error("source swap");
|
|
6797
|
+
return {
|
|
6798
|
+
kind: "evm-router",
|
|
6799
|
+
routerAddress,
|
|
6800
|
+
calldata: raw.swapRouterCalldata.toLowerCase(),
|
|
6801
|
+
rawResponseSha256: "",
|
|
6802
|
+
rawProviderSourceSwapJson: ""
|
|
6803
|
+
};
|
|
6804
|
+
}
|
|
6805
|
+
if (Object.hasOwn(raw, "tokenLedgerInstruction") && raw.tokenLedgerInstruction !== null) throw new Error("source swap");
|
|
6806
|
+
if (!Array.isArray(raw.computeBudgetInstructions) || !Array.isArray(raw.setupInstructions) || raw.swapInstruction === void 0 || raw.swapInstruction === null) throw new Error("source swap");
|
|
6807
|
+
if (raw.cleanupInstruction !== null && raw.cleanupInstruction !== void 0) throw new Error("source swap");
|
|
6808
|
+
if (!Array.isArray(raw.otherInstructions) || raw.otherInstructions.length !== 0) throw new Error("source swap");
|
|
6809
|
+
if (raw.simulationError !== null && raw.simulationError !== void 0) throw new Error("source swap");
|
|
6810
|
+
if (raw.separateSwapTx !== void 0 && raw.separateSwapTx !== false) throw new Error("source swap");
|
|
6811
|
+
if (raw.jito !== void 0 && raw.jito !== false && raw.jito !== null) throw new Error("source swap");
|
|
6812
|
+
const compute = raw.computeBudgetInstructions.map(instructionFromRaw);
|
|
6813
|
+
const setup = raw.setupInstructions.map(instructionFromRaw);
|
|
6814
|
+
const swap = instructionFromRaw(raw.swapInstruction);
|
|
6815
|
+
validateComputeInstructions(compute);
|
|
6816
|
+
validateAtaSetup(setup, swapperAddress, stateAddress, route.sourceUsdcAddress);
|
|
6817
|
+
validateJupiterInstruction(swap, route, quote, stateTokenAccount, swapperAddress, minimumIntermediateAmount, raw);
|
|
6818
|
+
const providerAlts = raw.addressLookupTableAddresses;
|
|
6819
|
+
if (!Array.isArray(providerAlts) || providerAlts.length > MAX_LOOKUP_TABLES || providerAlts.some((address) => {
|
|
6820
|
+
try {
|
|
6821
|
+
canonicalSolanaAddress(address);
|
|
6822
|
+
return false;
|
|
6823
|
+
} catch {
|
|
6824
|
+
return true;
|
|
6825
|
+
}
|
|
6826
|
+
})) throw new Error("source swap");
|
|
6827
|
+
const addressLookupTableAddresses = providerAlts;
|
|
6828
|
+
if (raw.prioritizationFeeLamports !== void 0 && (typeof raw.prioritizationFeeLamports !== "number" || !Number.isSafeInteger(raw.prioritizationFeeLamports) || raw.prioritizationFeeLamports < 0)) throw new Error("source swap");
|
|
6829
|
+
if (raw.computeUnitLimit !== void 0 && (typeof raw.computeUnitLimit !== "number" || !Number.isSafeInteger(raw.computeUnitLimit) || raw.computeUnitLimit > 14e5)) throw new Error("source swap");
|
|
6830
|
+
return {
|
|
6831
|
+
kind: "solana-jupiter-v6",
|
|
6832
|
+
instructions: [...compute, ...setup, swap],
|
|
6833
|
+
addressLookupTableAddresses,
|
|
6834
|
+
rawResponseSha256: "",
|
|
6835
|
+
rawProviderSourceSwapJson: ""
|
|
6836
|
+
};
|
|
6837
|
+
};
|
|
6838
|
+
var preparePlan = (context, runtime, options) => {
|
|
6839
|
+
const snapshot = cloneJson(context);
|
|
6840
|
+
return (async () => {
|
|
6841
|
+
const context2 = {
|
|
6842
|
+
...snapshot,
|
|
6843
|
+
quote: runtime.validateQuote(snapshot.quote, "BRIDGE_LOCAL_PLAN_INVALID")
|
|
6844
|
+
};
|
|
6845
|
+
let route;
|
|
6846
|
+
let rawQuote;
|
|
6847
|
+
let swapperAddress;
|
|
6848
|
+
let destinationAddress;
|
|
6849
|
+
let orderNonce;
|
|
6850
|
+
try {
|
|
6851
|
+
if (context2 === null || typeof context2 !== "object" || Array.isArray(context2)) throw new Error("context");
|
|
6852
|
+
const keys = Object.keys(context2).sort().join(",");
|
|
6853
|
+
if (keys !== "destinationAddress,orderNonce,quote,swapperAddress") throw new Error("context");
|
|
6854
|
+
route = validateLocalRoute(context2.quote);
|
|
6855
|
+
rawQuote = parseSourceQuote(context2.quote, route);
|
|
6856
|
+
swapperAddress = route.sourceChainId === ETHEREUM_CHAIN_ID ? normalizeEvmAddress3(context2.swapperAddress) : canonicalSolanaAddress(context2.swapperAddress);
|
|
6857
|
+
destinationAddress = route.destinationChainId === ETHEREUM_CHAIN_ID ? normalizeEvmAddress3(context2.destinationAddress) : canonicalSolanaAddress(context2.destinationAddress);
|
|
6858
|
+
orderNonce = context2.orderNonce;
|
|
6859
|
+
if (typeof orderNonce !== "string" || !NONCE.test(orderNonce)) throw new Error("nonce");
|
|
6860
|
+
validateDestinationMinimumCompatibility(context2.quote.rawSignedQuoteJson, context2.quote.minimumAmountOut);
|
|
6861
|
+
if (Math.floor(Date.now() / 1e3) + runtime.minimumQuoteValiditySeconds > Number(uint64(context2.quote.deadline, true))) runtime.fail("BRIDGE_QUOTE_EXPIRED");
|
|
6862
|
+
} catch (error) {
|
|
6863
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
6864
|
+
runtime.fail("BRIDGE_LOCAL_PLAN_INVALID");
|
|
6865
|
+
}
|
|
6866
|
+
const rawQuoteSha256 = sha256Hex(context2.quote.rawSignedQuoteJson);
|
|
6867
|
+
const orderHash = hashOrder(context2.quote, route, swapperAddress, destinationAddress, orderNonce, rawQuote.minimumIntermediateAmount, rawQuote.cancelFee, rawQuote.refundFee, rawQuote.mode);
|
|
6868
|
+
const binding = quoteBindingHash(route, context2.quote, rawQuoteSha256, orderNonce, swapperAddress, destinationAddress);
|
|
6869
|
+
let sourceSwap;
|
|
6870
|
+
if (sourceIsUsdc(route)) {
|
|
6871
|
+
sourceSwap = { kind: "none" };
|
|
6872
|
+
} else {
|
|
6873
|
+
const endpoint = endpointUrl(runtime.localBuild?.sourceSwapEndpoint);
|
|
6874
|
+
const sourceChain = route.sourceChainId === ETHEREUM_CHAIN_ID ? "evm" : "solana";
|
|
6875
|
+
let url;
|
|
6876
|
+
if (sourceChain === "evm") {
|
|
6877
|
+
url = sourceSwapUrl(endpoint, sourceChain, [
|
|
6878
|
+
["forwarderAddress", ETHEREUM_FORWARDER_PROVIDER],
|
|
6879
|
+
["slippageBps", context2.quote.slippageBps],
|
|
6880
|
+
["fromToken", String(rawQuote.raw.fromToken.contract)],
|
|
6881
|
+
["middleToken", route.sourceUsdcAddress],
|
|
6882
|
+
["chainName", route.sourceProviderChainName],
|
|
6883
|
+
["amountIn64", context2.quote.amountIn],
|
|
6884
|
+
["sdkVersion", MAYAN_ORACLE_SDK_VERSION]
|
|
6885
|
+
]);
|
|
6886
|
+
} else {
|
|
6887
|
+
const state = findProgramAddress([
|
|
6888
|
+
new TextEncoder().encode("STATE_SOURCE"),
|
|
6889
|
+
hexToBytes(orderHash),
|
|
6890
|
+
writeUint16Le(2)
|
|
6891
|
+
], SOLANA_SWIFT_PROGRAM);
|
|
6892
|
+
const sourceMinimum = extractRawNumberLexeme(context2.quote.rawSignedQuoteJson, "minMiddleAmount");
|
|
6893
|
+
url = sourceSwapUrl(endpoint, sourceChain, [
|
|
6894
|
+
["minMiddleAmount", Number(sourceMinimum)],
|
|
6895
|
+
["middleToken", route.sourceUsdcAddress],
|
|
6896
|
+
["userWallet", swapperAddress],
|
|
6897
|
+
["slippageBps", context2.quote.slippageBps],
|
|
6898
|
+
["fromToken", route.sourceTokenAddress],
|
|
6899
|
+
["amountIn64", context2.quote.amountIn],
|
|
6900
|
+
["depositMode", "SWIFT"],
|
|
6901
|
+
["fillMaxAccounts", false],
|
|
6902
|
+
["chainName", route.sourceProviderChainName],
|
|
6903
|
+
["userLedger", state.address],
|
|
6904
|
+
["sdkVersion", MAYAN_ORACLE_SDK_VERSION]
|
|
6905
|
+
]);
|
|
6906
|
+
}
|
|
6907
|
+
try {
|
|
6908
|
+
const response = await fetchSourceSwap(runtime, url, options);
|
|
6909
|
+
const state = route.sourceChainId === SOLANA_CHAIN_ID ? findProgramAddress([new TextEncoder().encode("STATE_SOURCE"), hexToBytes(orderHash), writeUint16Le(2)], SOLANA_SWIFT_PROGRAM).address : "";
|
|
6910
|
+
const stateTokenAccount = route.sourceChainId === SOLANA_CHAIN_ID ? associatedTokenAddress(state, route.sourceUsdcAddress, true) : "";
|
|
6911
|
+
sourceSwap = validateSourceSwapEnvelope(context2.quote, route, response.root, state, stateTokenAccount, swapperAddress, rawQuote.minimumIntermediateAmount);
|
|
6912
|
+
if (sourceSwap.kind === "none") throw new Error("source swap");
|
|
6913
|
+
sourceSwap = {
|
|
6914
|
+
...sourceSwap,
|
|
6915
|
+
rawResponseSha256: sha256Hex(response.text),
|
|
6916
|
+
rawProviderSourceSwapJson: response.text
|
|
6917
|
+
};
|
|
6918
|
+
} catch (error) {
|
|
6919
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
6920
|
+
runtime.fail("BRIDGE_LOCAL_PLAN_INVALID");
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
const plan = {
|
|
6924
|
+
planKind: "mayan-swift-v2-local-source-swap",
|
|
6925
|
+
providerId: "mayan-swift-v2",
|
|
6926
|
+
capabilityId: route.bridgeCapabilityId,
|
|
6927
|
+
sourceChainId: route.sourceChainId,
|
|
6928
|
+
destinationChainId: route.destinationChainId,
|
|
6929
|
+
sourceTokenDeploymentId: route.sourceTokenDeploymentId,
|
|
6930
|
+
destinationTokenDeploymentId: route.destinationTokenDeploymentId,
|
|
6931
|
+
quoteId: context2.quote.quoteId,
|
|
6932
|
+
rawQuoteSha256,
|
|
6933
|
+
orderNonce,
|
|
6934
|
+
swapperAddress,
|
|
6935
|
+
destinationAddress,
|
|
6936
|
+
orderHash,
|
|
6937
|
+
quoteBindingHash: binding,
|
|
6938
|
+
minimumIntermediateAmount: rawQuote.minimumIntermediateAmount,
|
|
6939
|
+
sourceSwap,
|
|
6940
|
+
planHash: planHash(binding, sourceSwap)
|
|
6941
|
+
};
|
|
6942
|
+
return plan;
|
|
6943
|
+
})();
|
|
6944
|
+
};
|
|
6945
|
+
var sourceRpcError = (runtime, error) => {
|
|
6946
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
6947
|
+
if (error instanceof ErpcInvalidResponseError || error instanceof ErpcJsonRpcError) {
|
|
6948
|
+
return runtime.fail("BRIDGE_SOURCE_RPC_INVALID_RESPONSE");
|
|
6949
|
+
}
|
|
6950
|
+
if (error instanceof ErpcAbortedError) return runtime.fail("BRIDGE_ABORTED");
|
|
6951
|
+
if (error instanceof ErpcTimeoutError) return runtime.fail("BRIDGE_TIMEOUT");
|
|
6952
|
+
if (error instanceof ErpcHttpError || error instanceof ErpcTransportError) {
|
|
6953
|
+
return runtime.fail("BRIDGE_SOURCE_RPC_TRANSPORT");
|
|
6954
|
+
}
|
|
6955
|
+
if (error instanceof ErpcConfigError) return runtime.fail("BRIDGE_LOCAL_BUILD_INVALID");
|
|
6956
|
+
return runtime.fail("BRIDGE_SOURCE_RPC_INVALID_RESPONSE");
|
|
6957
|
+
};
|
|
6958
|
+
var directRpc = (endpoint, runtime, code, chain) => {
|
|
6959
|
+
if (endpoint === void 0 || endpoint === null) runtime.fail(code);
|
|
6960
|
+
if (endpoint === null || typeof endpoint !== "object" || Array.isArray(endpoint)) runtime.fail("BRIDGE_LOCAL_BUILD_INVALID");
|
|
6961
|
+
const rpcFetch = async (input, init) => {
|
|
6962
|
+
const requestBody = init?.body;
|
|
6963
|
+
if (typeof requestBody !== "string") return runtime.fetch(input, init);
|
|
6964
|
+
let request;
|
|
6965
|
+
try {
|
|
6966
|
+
const parsed2 = JSON.parse(requestBody);
|
|
6967
|
+
if (parsed2 === null || typeof parsed2 !== "object" || Array.isArray(parsed2)) return runtime.fetch(input, init);
|
|
6968
|
+
request = parsed2;
|
|
6969
|
+
} catch {
|
|
6970
|
+
return runtime.fetch(input, init);
|
|
6971
|
+
}
|
|
6972
|
+
const requestId = request.id;
|
|
6973
|
+
request.id = 1;
|
|
6974
|
+
const response = await runtime.fetch(input, { ...init, body: JSON.stringify(request) });
|
|
6975
|
+
let responseBody;
|
|
6976
|
+
try {
|
|
6977
|
+
const signal = init?.signal ?? new AbortController().signal;
|
|
6978
|
+
responseBody = await readSourceResponseText(response, signal);
|
|
6979
|
+
} catch (error) {
|
|
6980
|
+
if (error instanceof SourceResponseInvalidError) {
|
|
6981
|
+
return new Response("null", {
|
|
6982
|
+
status: response.status,
|
|
6983
|
+
statusText: response.statusText,
|
|
6984
|
+
headers: response.headers
|
|
6985
|
+
});
|
|
6986
|
+
}
|
|
6987
|
+
throw error;
|
|
6988
|
+
}
|
|
6989
|
+
if (!response.ok) {
|
|
6990
|
+
return new Response(responseBody, {
|
|
6991
|
+
status: response.status,
|
|
6992
|
+
statusText: response.statusText,
|
|
6993
|
+
headers: response.headers
|
|
6994
|
+
});
|
|
6995
|
+
}
|
|
6996
|
+
let parsed;
|
|
6997
|
+
try {
|
|
6998
|
+
parsed = parseJsonObject(responseBody);
|
|
6999
|
+
} catch {
|
|
7000
|
+
return new Response("null", {
|
|
7001
|
+
status: response.status,
|
|
7002
|
+
statusText: response.statusText,
|
|
7003
|
+
headers: response.headers
|
|
7004
|
+
});
|
|
7005
|
+
}
|
|
7006
|
+
if (parsed.jsonrpc !== "2.0" || typeof parsed.id !== "number" || !Number.isSafeInteger(parsed.id) || parsed.id !== 1) {
|
|
7007
|
+
return new Response("null", {
|
|
7008
|
+
status: response.status,
|
|
7009
|
+
statusText: response.statusText,
|
|
7010
|
+
headers: response.headers
|
|
7011
|
+
});
|
|
7012
|
+
}
|
|
7013
|
+
parsed.id = requestId;
|
|
7014
|
+
responseBody = JSON.stringify(parsed);
|
|
7015
|
+
return new Response(responseBody, {
|
|
7016
|
+
status: response.status,
|
|
7017
|
+
statusText: response.statusText,
|
|
7018
|
+
headers: response.headers
|
|
7019
|
+
});
|
|
7020
|
+
};
|
|
7021
|
+
return createErpcClient({
|
|
7022
|
+
...chain === "ethereum" ? { ethereumRpc: endpoint } : { solanaRpc: endpoint },
|
|
7023
|
+
fetch: rpcFetch,
|
|
7024
|
+
timeoutMs: runtime.timeoutMs
|
|
7025
|
+
});
|
|
7026
|
+
};
|
|
7027
|
+
var parseRpcAccount = (value) => {
|
|
7028
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("account");
|
|
7029
|
+
const account = value;
|
|
7030
|
+
if (!Array.isArray(account.data) || account.data.length !== 2 || typeof account.data[0] !== "string" || account.data[1] !== "base64" || typeof account.owner !== "string" || account.executable !== false) throw new Error("account");
|
|
7031
|
+
const data = base64Decode(account.data[0], 16384);
|
|
7032
|
+
return { data, owner: canonicalSolanaAddress(account.owner) };
|
|
7033
|
+
};
|
|
7034
|
+
var decodeLookupTable = (address, account, accountContextSlot) => {
|
|
7035
|
+
if (account.owner !== SOLANA_ADDRESS_LOOKUP_TABLE_OWNER || account.data.length < 56 || (account.data.length - 56) % 32 !== 0) throw new Error("ALT");
|
|
7036
|
+
const view = new DataView(account.data.buffer, account.data.byteOffset, account.data.byteLength);
|
|
7037
|
+
if (view.getUint32(0, true) !== 1) throw new Error("ALT");
|
|
7038
|
+
const deactivationSlot = view.getBigUint64(4, true);
|
|
7039
|
+
if (deactivationSlot !== UINT64_MAX) throw new Error("ALT");
|
|
7040
|
+
const lastExtendedSlot = view.getBigUint64(12, true);
|
|
7041
|
+
if (lastExtendedSlot > BigInt(accountContextSlot)) throw new Error("ALT");
|
|
7042
|
+
const lastExtendedStartIndex = account.data[20];
|
|
7043
|
+
const authorityOption = account.data[21];
|
|
7044
|
+
if (lastExtendedStartIndex === void 0 || authorityOption === void 0 || authorityOption !== 0 && authorityOption !== 1) throw new Error("ALT");
|
|
7045
|
+
for (let index = 54; index < 56; index += 1) {
|
|
7046
|
+
if (account.data[index] !== 0) throw new Error("ALT");
|
|
7047
|
+
}
|
|
7048
|
+
if (authorityOption === 0) {
|
|
7049
|
+
for (let index = 22; index < 54; index += 1) {
|
|
7050
|
+
if (account.data[index] !== 0) throw new Error("ALT");
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
const addresses = [];
|
|
7054
|
+
for (let offset = 56; offset < account.data.length; offset += 32) addresses.push(base58Encode(account.data.slice(offset, offset + 32)));
|
|
7055
|
+
if (addresses.length > MAX_LOOKUP_TABLE_ADDRESSES || lastExtendedStartIndex > addresses.length) throw new Error("ALT");
|
|
7056
|
+
const activeCount = lastExtendedSlot === BigInt(accountContextSlot) ? lastExtendedStartIndex : addresses.length;
|
|
7057
|
+
return { address, addresses: addresses.slice(0, activeCount) };
|
|
7058
|
+
};
|
|
7059
|
+
var fetchSourceRpc = async (route, plan, runtime, options) => {
|
|
7060
|
+
const endpoint = route.sourceChainId === ETHEREUM_CHAIN_ID ? runtime.localBuild?.ethereumRpc : runtime.localBuild?.solanaRpc;
|
|
7061
|
+
let erpc;
|
|
7062
|
+
try {
|
|
7063
|
+
erpc = directRpc(endpoint, runtime, "BRIDGE_LOCAL_RPC_REQUIRED", route.sourceChainId === ETHEREUM_CHAIN_ID ? "ethereum" : "solana");
|
|
7064
|
+
} catch (error) {
|
|
7065
|
+
return sourceRpcError(runtime, error);
|
|
7066
|
+
}
|
|
7067
|
+
const rpcOptions = options?.signal === void 0 ? void 0 : { signal: options.signal };
|
|
7068
|
+
try {
|
|
7069
|
+
if (route.sourceChainId === ETHEREUM_CHAIN_ID) {
|
|
7070
|
+
const rpcChainId = await erpc.ethereum.rpc.eth_chainId().send(rpcOptions);
|
|
7071
|
+
if (rpcChainId.toLowerCase() !== "0x1") throw new Error("chain");
|
|
7072
|
+
const codeAddresses = [ETHEREUM_FORWARDER, route.swiftContract];
|
|
7073
|
+
if (plan.sourceSwap.kind === "evm-router") codeAddresses.push(plan.sourceSwap.routerAddress);
|
|
7074
|
+
const code = [];
|
|
7075
|
+
for (const address of codeAddresses) {
|
|
7076
|
+
const bytecode = await erpc.ethereum.rpc.eth_getCode(address, "latest").send(rpcOptions);
|
|
7077
|
+
if (typeof bytecode !== "string" || !HEX_BYTES2.test(bytecode) || bytecode === "0x") throw new Error("code");
|
|
7078
|
+
code.push({ address: normalizeEvmAddress3(address), keccak256: `0x${keccakHex(hexToBytes(bytecode))}` });
|
|
7079
|
+
}
|
|
7080
|
+
return {
|
|
7081
|
+
erpc,
|
|
7082
|
+
evidence: { kind: "evm", rpcChainId: "0x1", code },
|
|
7083
|
+
lookupTables: [],
|
|
7084
|
+
recentBlockhash: null
|
|
7085
|
+
};
|
|
7086
|
+
}
|
|
7087
|
+
const genesisHash = await erpc.solana.rpc.getGenesisHash().send(rpcOptions);
|
|
7088
|
+
if (genesisHash !== SOLANA_MAINNET_GENESIS_HASH) throw new Error("genesis");
|
|
7089
|
+
const blockhashResult = await erpc.solana.rpc.getLatestBlockhash({ commitment: "confirmed" }).send(rpcOptions);
|
|
7090
|
+
if (blockhashResult === null || typeof blockhashResult !== "object" || Array.isArray(blockhashResult)) throw new Error("blockhash");
|
|
7091
|
+
const blockhashWrapper = blockhashResult;
|
|
7092
|
+
const blockhashContext = blockhashWrapper.context;
|
|
7093
|
+
const blockhashValue = blockhashWrapper.value;
|
|
7094
|
+
if (blockhashContext === null || typeof blockhashContext !== "object" || Array.isArray(blockhashContext) || blockhashValue === null || typeof blockhashValue !== "object" || Array.isArray(blockhashValue)) throw new Error("blockhash");
|
|
7095
|
+
const blockhashSlot = blockhashContext.slot;
|
|
7096
|
+
const recentBlockhash = blockhashValue.blockhash;
|
|
7097
|
+
const lastValidBlockHeight = blockhashValue.lastValidBlockHeight;
|
|
7098
|
+
if (typeof blockhashSlot !== "number" || !Number.isSafeInteger(blockhashSlot) || blockhashSlot < 0 || typeof recentBlockhash !== "string" || typeof lastValidBlockHeight !== "number" || !Number.isSafeInteger(lastValidBlockHeight) || lastValidBlockHeight < 0 || !canonicalSolanaAddress(recentBlockhash)) throw new Error("blockhash");
|
|
7099
|
+
const providerAlts = plan.sourceSwap.kind === "solana-jupiter-v6" ? plan.sourceSwap.addressLookupTableAddresses : [];
|
|
7100
|
+
const altAddresses = [.../* @__PURE__ */ new Set([SOLANA_MAYAN_LOOKUP_TABLE, ...providerAlts])];
|
|
7101
|
+
if (altAddresses.length > MAX_LOOKUP_TABLES) throw new Error("ALT");
|
|
7102
|
+
const accountsResult = await erpc.solana.rpc.getMultipleAccounts(
|
|
7103
|
+
altAddresses,
|
|
7104
|
+
{ encoding: "base64", commitment: "confirmed", minContextSlot: blockhashSlot }
|
|
7105
|
+
).send(rpcOptions);
|
|
7106
|
+
if (accountsResult === null || typeof accountsResult !== "object" || Array.isArray(accountsResult)) throw new Error("accounts");
|
|
7107
|
+
const accountsWrapper = accountsResult;
|
|
7108
|
+
const accountContext = accountsWrapper.context;
|
|
7109
|
+
const accountValues = accountsWrapper.value;
|
|
7110
|
+
if (accountContext === null || typeof accountContext !== "object" || Array.isArray(accountContext) || !Array.isArray(accountValues)) throw new Error("accounts");
|
|
7111
|
+
const accountSlot = accountContext.slot;
|
|
7112
|
+
if (typeof accountSlot !== "number" || !Number.isSafeInteger(accountSlot) || accountSlot < 0 || typeof blockhashSlot !== "number" || accountSlot < blockhashSlot || accountValues.length !== altAddresses.length) throw new Error("accounts");
|
|
7113
|
+
const lookupTables = altAddresses.map((address, index) => decodeLookupTable(address, parseRpcAccount(accountValues[index]), accountSlot));
|
|
7114
|
+
return {
|
|
7115
|
+
erpc,
|
|
7116
|
+
evidence: {
|
|
7117
|
+
kind: "solana",
|
|
7118
|
+
genesisHash,
|
|
7119
|
+
blockhashContextSlot: String(blockhashSlot),
|
|
7120
|
+
accountContextSlot: String(accountSlot),
|
|
7121
|
+
recentBlockhash,
|
|
7122
|
+
lastValidBlockHeight: String(lastValidBlockHeight),
|
|
7123
|
+
lookupTables: lookupTables.map((table) => ({ address: table.address, dataSha256: sha256Hex(parseRpcAccount(accountValues[altAddresses.indexOf(table.address)]).data) }))
|
|
7124
|
+
},
|
|
7125
|
+
lookupTables,
|
|
7126
|
+
recentBlockhash
|
|
7127
|
+
};
|
|
7128
|
+
} catch (error) {
|
|
7129
|
+
erpc.close();
|
|
7130
|
+
return sourceRpcError(runtime, error);
|
|
7131
|
+
}
|
|
7132
|
+
};
|
|
7133
|
+
var exactKeys = (value, expected) => {
|
|
7134
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
7135
|
+
const actual = Object.keys(value).sort();
|
|
7136
|
+
const wanted = [...expected].sort();
|
|
7137
|
+
return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
|
|
7138
|
+
};
|
|
7139
|
+
var validatePlan = (request, route, rawQuote, plan, rawQuoteSha256, orderHash, binding, swapperAddress, destinationAddress) => {
|
|
7140
|
+
if (!exactKeys(plan, [
|
|
7141
|
+
"planKind",
|
|
7142
|
+
"providerId",
|
|
7143
|
+
"capabilityId",
|
|
7144
|
+
"sourceChainId",
|
|
7145
|
+
"destinationChainId",
|
|
7146
|
+
"sourceTokenDeploymentId",
|
|
7147
|
+
"destinationTokenDeploymentId",
|
|
7148
|
+
"quoteId",
|
|
7149
|
+
"rawQuoteSha256",
|
|
7150
|
+
"orderNonce",
|
|
7151
|
+
"swapperAddress",
|
|
7152
|
+
"destinationAddress",
|
|
7153
|
+
"orderHash",
|
|
7154
|
+
"quoteBindingHash",
|
|
7155
|
+
"minimumIntermediateAmount",
|
|
7156
|
+
"sourceSwap",
|
|
7157
|
+
"planHash"
|
|
7158
|
+
])) throw new Error("plan");
|
|
7159
|
+
if (plan.planKind !== "mayan-swift-v2-local-source-swap" || plan.providerId !== "mayan-swift-v2" || plan.capabilityId !== route.bridgeCapabilityId || plan.sourceChainId !== route.sourceChainId || plan.destinationChainId !== route.destinationChainId || plan.sourceTokenDeploymentId !== route.sourceTokenDeploymentId || plan.destinationTokenDeploymentId !== route.destinationTokenDeploymentId || plan.quoteId !== request.quote.quoteId || plan.rawQuoteSha256 !== rawQuoteSha256 || plan.orderNonce !== request.orderNonce || plan.swapperAddress !== swapperAddress || plan.destinationAddress !== destinationAddress || plan.orderHash !== orderHash || plan.quoteBindingHash !== binding || plan.minimumIntermediateAmount !== rawQuote.minimumIntermediateAmount) throw new Error("plan");
|
|
7160
|
+
let normalizedSwap;
|
|
7161
|
+
if (sourceIsUsdc(route)) {
|
|
7162
|
+
if (!exactKeys(plan.sourceSwap, ["kind"]) || plan.sourceSwap.kind !== "none") throw new Error("plan");
|
|
7163
|
+
normalizedSwap = { kind: "none" };
|
|
7164
|
+
} else {
|
|
7165
|
+
const state = route.sourceChainId === SOLANA_CHAIN_ID ? findProgramAddress([new TextEncoder().encode("STATE_SOURCE"), hexToBytes(orderHash), writeUint16Le(2)], SOLANA_SWIFT_PROGRAM).address : "";
|
|
7166
|
+
const stateTokenAccount = route.sourceChainId === SOLANA_CHAIN_ID ? associatedTokenAddress(state, route.sourceUsdcAddress, true) : "";
|
|
7167
|
+
if (plan.sourceSwap.kind === "none") throw new Error("plan");
|
|
7168
|
+
const sourceRaw = parseJsonObject(plan.sourceSwap.rawProviderSourceSwapJson);
|
|
7169
|
+
if (plan.sourceSwap.rawResponseSha256 !== sha256Hex(plan.sourceSwap.rawProviderSourceSwapJson)) throw new Error("plan");
|
|
7170
|
+
const expected = validateSourceSwapEnvelope(request.quote, route, sourceRaw, state, stateTokenAccount, swapperAddress, rawQuote.minimumIntermediateAmount);
|
|
7171
|
+
if (stableJson(expected) !== stableJson({ ...plan.sourceSwap, rawResponseSha256: "", rawProviderSourceSwapJson: "" })) throw new Error("plan");
|
|
7172
|
+
normalizedSwap = plan.sourceSwap;
|
|
7173
|
+
}
|
|
7174
|
+
if (plan.planHash !== planHash(binding, normalizedSwap)) throw new Error("plan");
|
|
7175
|
+
return plan;
|
|
7176
|
+
};
|
|
7177
|
+
var localBuildDependencies = (route) => [
|
|
7178
|
+
...route.dependencies.filter((dependency) => dependency !== "mayan-hosted-transaction-builder"),
|
|
7179
|
+
route.sourceChainId === ETHEREUM_CHAIN_ID ? "configured-ethereum-rpc" : "configured-solana-rpc"
|
|
7180
|
+
];
|
|
7181
|
+
var buildEvmOrderCall = (quote, route, plan, swapperAddress, destinationAddress, minimumIntermediateAmount, cancelFee, refundFee, mode, orderNonce) => {
|
|
7182
|
+
const orderWords = [
|
|
7183
|
+
wordUint(1n),
|
|
7184
|
+
wordBytes32(nativeAddressBytes(swapperAddress, route.sourceChainId)),
|
|
7185
|
+
wordBytes32(nativeAddressBytes(destinationAddress, route.destinationChainId)),
|
|
7186
|
+
wordUint(BigInt(route.destinationWormholeChainId)),
|
|
7187
|
+
wordBytes32(zero32()),
|
|
7188
|
+
wordBytes32(nativeAddressBytes(route.destinationTokenAddress, route.destinationChainId)),
|
|
7189
|
+
wordUint(uint64(quote.minimumAmountOut, true)),
|
|
7190
|
+
wordUint(0n),
|
|
7191
|
+
wordUint(cancelFee),
|
|
7192
|
+
wordUint(refundFee),
|
|
7193
|
+
wordUint(uint64(quote.deadline, true)),
|
|
7194
|
+
wordUint(0n),
|
|
7195
|
+
wordUint(BigInt(mode)),
|
|
7196
|
+
wordBytes32(swiftRandom(quote.quoteId, orderNonce))
|
|
7197
|
+
];
|
|
7198
|
+
const swiftCallData = `0xa3a30834${bytesToHex(encodeAbiWithDynamics([
|
|
7199
|
+
wordAddress(route.sourceUsdcAddress),
|
|
7200
|
+
wordUint(uint64(quote.amountIn, true)),
|
|
7201
|
+
...orderWords
|
|
7202
|
+
], [new Uint8Array()]))}`;
|
|
7203
|
+
if (plan.sourceSwap.kind === "none") {
|
|
7204
|
+
return `0xe4269fc4${bytesToHex(encodeAbiWithDynamics([
|
|
7205
|
+
wordAddress(route.sourceUsdcAddress),
|
|
7206
|
+
wordUint(uint64(quote.amountIn, true)),
|
|
7207
|
+
...[wordUint(0n), wordUint(0n), wordUint(0n), wordBytes32(zero32()), wordBytes32(zero32())],
|
|
7208
|
+
wordAddress(route.swiftContract)
|
|
7209
|
+
], [hexToBytes(swiftCallData)]))}`;
|
|
7210
|
+
}
|
|
7211
|
+
if (plan.sourceSwap.kind !== "evm-router") throw new Error("plan");
|
|
7212
|
+
const routerData = hexToBytes(plan.sourceSwap.calldata);
|
|
7213
|
+
const routerOffset = 13 * 32;
|
|
7214
|
+
const swiftOffset = routerOffset + 32 + Math.ceil(routerData.length / 32) * 32;
|
|
7215
|
+
const head = [
|
|
7216
|
+
wordAddress(route.sourceTokenAddress),
|
|
7217
|
+
wordUint(uint64(quote.amountIn, true)),
|
|
7218
|
+
wordUint(0n),
|
|
7219
|
+
wordUint(0n),
|
|
7220
|
+
wordUint(0n),
|
|
7221
|
+
wordBytes32(zero32()),
|
|
7222
|
+
wordBytes32(zero32()),
|
|
7223
|
+
wordAddress(plan.sourceSwap.routerAddress),
|
|
7224
|
+
wordUint(BigInt(routerOffset)),
|
|
7225
|
+
wordAddress(route.sourceUsdcAddress),
|
|
7226
|
+
wordUint(uint64(minimumIntermediateAmount, true)),
|
|
7227
|
+
wordAddress(route.swiftContract),
|
|
7228
|
+
wordUint(BigInt(swiftOffset))
|
|
7229
|
+
];
|
|
7230
|
+
return `0x30dedc57${bytesToHex(concatBytes(
|
|
7231
|
+
...head,
|
|
7232
|
+
encodeAbiBytes(routerData),
|
|
7233
|
+
encodeAbiBytes(hexToBytes(swiftCallData))
|
|
7234
|
+
))}`;
|
|
7235
|
+
};
|
|
7236
|
+
var buildSolanaInstructions = (quote, route, plan, swapperAddress, destinationAddress, minimumIntermediateAmount, cancelFee, refundFee, submitFee, mode, orderNonce, raw) => {
|
|
7237
|
+
const state = findProgramAddress([
|
|
7238
|
+
new TextEncoder().encode("STATE_SOURCE"),
|
|
7239
|
+
hexToBytes(hashOrder(quote, route, swapperAddress, destinationAddress, orderNonce, minimumIntermediateAmount, cancelFee, refundFee, mode)),
|
|
7240
|
+
writeUint16Le(2)
|
|
7241
|
+
], SOLANA_SWIFT_PROGRAM).address;
|
|
7242
|
+
const stateTokenAccount = associatedTokenAddress(state, route.sourceUsdcAddress, true);
|
|
7243
|
+
const init = makeSwiftInitInstruction(
|
|
7244
|
+
quote,
|
|
7245
|
+
route,
|
|
7246
|
+
swapperAddress,
|
|
7247
|
+
destinationAddress,
|
|
7248
|
+
state,
|
|
7249
|
+
stateTokenAccount,
|
|
7250
|
+
minimumIntermediateAmount,
|
|
7251
|
+
cancelFee,
|
|
7252
|
+
refundFee,
|
|
7253
|
+
submitFee,
|
|
7254
|
+
mode,
|
|
7255
|
+
orderNonce
|
|
7256
|
+
);
|
|
7257
|
+
if (sourceIsUsdc(route)) {
|
|
7258
|
+
const instructions = [];
|
|
7259
|
+
const suggestedPriorityFee = raw.suggestedPriorityFee;
|
|
7260
|
+
if (typeof suggestedPriorityFee === "number" && Number.isSafeInteger(suggestedPriorityFee) && suggestedPriorityFee > 0) {
|
|
7261
|
+
if (suggestedPriorityFee > 1e5) throw new Error("compute");
|
|
7262
|
+
instructions.push(makeComputeUnitPriceInstruction(BigInt(suggestedPriorityFee)));
|
|
7263
|
+
}
|
|
7264
|
+
instructions.push(wrapInCpiProxy(makeAtaInstruction(swapperAddress, state, route.sourceUsdcAddress, true)));
|
|
7265
|
+
instructions.push(wrapInCpiProxy(makeSplTransferInstruction(
|
|
7266
|
+
associatedTokenAddress(swapperAddress, route.sourceUsdcAddress, false),
|
|
7267
|
+
stateTokenAccount,
|
|
7268
|
+
swapperAddress,
|
|
7269
|
+
uint64(quote.amountIn, true)
|
|
7270
|
+
)));
|
|
7271
|
+
instructions.push(wrapInCpiProxy(init));
|
|
7272
|
+
return instructions;
|
|
7273
|
+
}
|
|
7274
|
+
if (plan.sourceSwap.kind !== "solana-jupiter-v6") throw new Error("plan");
|
|
7275
|
+
const computeCount = plan.sourceSwap.instructions.filter((instruction) => instruction.programId === SOLANA_COMPUTE_BUDGET_PROGRAM).length;
|
|
7276
|
+
const compute = plan.sourceSwap.instructions.slice(0, computeCount);
|
|
7277
|
+
const remainder = plan.sourceSwap.instructions.slice(computeCount);
|
|
7278
|
+
const swapIndex = remainder.findIndex((instruction) => instruction.programId === SOLANA_JUPITER_V6);
|
|
7279
|
+
if (swapIndex < 1) throw new Error("source swap");
|
|
7280
|
+
const setup = remainder.slice(0, swapIndex);
|
|
7281
|
+
const swap = remainder[swapIndex];
|
|
7282
|
+
if (!swap || remainder.slice(swapIndex + 1).length !== 0) throw new Error("source swap");
|
|
7283
|
+
return [
|
|
7284
|
+
...compute,
|
|
7285
|
+
...setup.map(wrapInCpiProxy),
|
|
7286
|
+
swap,
|
|
7287
|
+
wrapInCpiProxy(init)
|
|
7288
|
+
];
|
|
7289
|
+
};
|
|
7290
|
+
var buildLocalPlan = (context, runtime, options) => {
|
|
7291
|
+
const snapshot = cloneJson(context);
|
|
7292
|
+
return (async () => {
|
|
7293
|
+
const context2 = {
|
|
7294
|
+
...snapshot,
|
|
7295
|
+
quote: runtime.validateQuote(snapshot.quote, "BRIDGE_LOCAL_BUILD_INVALID")
|
|
7296
|
+
};
|
|
7297
|
+
let route;
|
|
7298
|
+
let rawQuote;
|
|
7299
|
+
let swapperAddress;
|
|
7300
|
+
let destinationAddress;
|
|
7301
|
+
try {
|
|
7302
|
+
if (context2 === null || typeof context2 !== "object" || Array.isArray(context2)) throw new Error("context");
|
|
7303
|
+
const keys = Object.keys(context2).sort().join(",");
|
|
7304
|
+
if (keys !== "destinationAddress,orderNonce,quote,sourceSwapPlan,swapperAddress") throw new Error("context");
|
|
7305
|
+
route = validateLocalRoute(context2.quote);
|
|
7306
|
+
rawQuote = parseSourceQuote(context2.quote, route);
|
|
7307
|
+
swapperAddress = route.sourceChainId === ETHEREUM_CHAIN_ID ? normalizeEvmAddress3(context2.swapperAddress) : canonicalSolanaAddress(context2.swapperAddress);
|
|
7308
|
+
destinationAddress = route.destinationChainId === ETHEREUM_CHAIN_ID ? normalizeEvmAddress3(context2.destinationAddress) : canonicalSolanaAddress(context2.destinationAddress);
|
|
7309
|
+
if (typeof context2.orderNonce !== "string" || !NONCE.test(context2.orderNonce)) throw new Error("nonce");
|
|
7310
|
+
validateDestinationMinimumCompatibility(context2.quote.rawSignedQuoteJson, context2.quote.minimumAmountOut);
|
|
7311
|
+
if (Math.floor(Date.now() / 1e3) + runtime.minimumQuoteValiditySeconds > Number(uint64(context2.quote.deadline, true))) runtime.fail("BRIDGE_QUOTE_EXPIRED");
|
|
7312
|
+
} catch (error) {
|
|
7313
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
7314
|
+
runtime.fail("BRIDGE_LOCAL_BUILD_INVALID");
|
|
7315
|
+
}
|
|
7316
|
+
const rawQuoteSha256 = sha256Hex(context2.quote.rawSignedQuoteJson);
|
|
7317
|
+
const orderHash = hashOrder(context2.quote, route, swapperAddress, destinationAddress, context2.orderNonce, rawQuote.minimumIntermediateAmount, rawQuote.cancelFee, rawQuote.refundFee, rawQuote.mode);
|
|
7318
|
+
const binding = quoteBindingHash(route, context2.quote, rawQuoteSha256, context2.orderNonce, swapperAddress, destinationAddress);
|
|
7319
|
+
try {
|
|
7320
|
+
const plan = validatePlan(context2, route, rawQuote, context2.sourceSwapPlan, rawQuoteSha256, orderHash, binding, swapperAddress, destinationAddress);
|
|
7321
|
+
const rpc = await fetchSourceRpc(route, plan, runtime, options);
|
|
7322
|
+
try {
|
|
7323
|
+
let transaction;
|
|
7324
|
+
if (route.sourceChainId === ETHEREUM_CHAIN_ID) {
|
|
7325
|
+
const data = buildEvmOrderCall(context2.quote, route, plan, swapperAddress, destinationAddress, rawQuote.minimumIntermediateAmount, rawQuote.cancelFee, rawQuote.refundFee, rawQuote.mode, context2.orderNonce);
|
|
7326
|
+
transaction = {
|
|
7327
|
+
kind: "evm-unsigned-transaction",
|
|
7328
|
+
chainId: ETHEREUM_CHAIN_ID,
|
|
7329
|
+
from: swapperAddress,
|
|
7330
|
+
to: ETHEREUM_FORWARDER,
|
|
7331
|
+
data,
|
|
7332
|
+
value: "0"
|
|
7333
|
+
};
|
|
7334
|
+
} else {
|
|
7335
|
+
const instructions = buildSolanaInstructions(context2.quote, route, plan, swapperAddress, destinationAddress, rawQuote.minimumIntermediateAmount, rawQuote.cancelFee, rawQuote.refundFee, rawQuote.submitFee, rawQuote.mode, context2.orderNonce, rawQuote.raw);
|
|
7336
|
+
if (rpc.recentBlockhash === null) throw new Error("blockhash");
|
|
7337
|
+
const compiled = compileSolanaV0(swapperAddress, rpc.recentBlockhash, instructions, rpc.lookupTables);
|
|
7338
|
+
transaction = {
|
|
7339
|
+
kind: "solana-v0-unsigned-transaction",
|
|
7340
|
+
chainId: SOLANA_CHAIN_ID,
|
|
7341
|
+
feePayer: swapperAddress,
|
|
7342
|
+
transactionBase64: compiled.transactionBase64
|
|
7343
|
+
};
|
|
7344
|
+
}
|
|
7345
|
+
const allowance = route.sourceChainId === ETHEREUM_CHAIN_ID ? {
|
|
7346
|
+
tokenDeploymentId: route.sourceTokenDeploymentId,
|
|
7347
|
+
tokenAddress: route.sourceTokenAddress,
|
|
7348
|
+
owner: swapperAddress,
|
|
7349
|
+
spender: ETHEREUM_FORWARDER,
|
|
7350
|
+
requiredAmount: context2.quote.amountIn
|
|
7351
|
+
} : null;
|
|
7352
|
+
return {
|
|
7353
|
+
buildKind: "mayan-swift-v2-local-unsigned",
|
|
7354
|
+
providerId: "mayan-swift-v2",
|
|
7355
|
+
capabilityId: route.bridgeCapabilityId,
|
|
7356
|
+
quote: cloneJson(context2.quote),
|
|
7357
|
+
sourceChainId: route.sourceChainId,
|
|
7358
|
+
destinationChainId: route.destinationChainId,
|
|
7359
|
+
sourceSwapPlan: cloneJson(plan),
|
|
7360
|
+
transaction,
|
|
7361
|
+
allowance,
|
|
7362
|
+
construction: {
|
|
7363
|
+
mode: "local",
|
|
7364
|
+
referenceCommit: MAYAN_REFERENCE_COMMIT,
|
|
7365
|
+
orderNonce: context2.orderNonce,
|
|
7366
|
+
orderHash,
|
|
7367
|
+
minimumIntermediateAmount: rawQuote.minimumIntermediateAmount,
|
|
7368
|
+
effectiveDependencies: localBuildDependencies(route),
|
|
7369
|
+
sourceRpcEvidence: rpc.evidence
|
|
7370
|
+
},
|
|
7371
|
+
validation: {
|
|
7372
|
+
level: "local-structural",
|
|
7373
|
+
quoteSignatureLocallyVerified: false,
|
|
7374
|
+
planBindingLocallyVerified: true,
|
|
7375
|
+
transactionBytesLocallyConstructed: true,
|
|
7376
|
+
settlementLocallyVerified: false
|
|
7377
|
+
}
|
|
7378
|
+
};
|
|
7379
|
+
} finally {
|
|
7380
|
+
rpc.erpc.close();
|
|
7381
|
+
}
|
|
7382
|
+
} catch (error) {
|
|
7383
|
+
if (error instanceof Error && error.name === "BridgeError") throw error;
|
|
7384
|
+
runtime.fail("BRIDGE_LOCAL_BUILD_INVALID");
|
|
7385
|
+
}
|
|
7386
|
+
})();
|
|
7387
|
+
};
|
|
7388
|
+
var prepareSourceSwap = (context, runtime, options) => preparePlan(context, runtime, options);
|
|
7389
|
+
var buildLocalUnsigned = (request, runtime, options) => buildLocalPlan(request, runtime, options);
|
|
5770
7390
|
|
|
5771
7391
|
// src/bridge.ts
|
|
5772
7392
|
var BRIDGE_ERROR_MESSAGES = Object.freeze({
|
|
@@ -5780,6 +7400,11 @@ var BRIDGE_ERROR_MESSAGES = Object.freeze({
|
|
|
5780
7400
|
BRIDGE_QUOTE_EXPIRED: "Bridge quote is expired",
|
|
5781
7401
|
BRIDGE_QUOTE_MISMATCH: "Bridge quote does not match the request",
|
|
5782
7402
|
BRIDGE_BUILD_INVALID: "Bridge provider build is invalid",
|
|
7403
|
+
BRIDGE_LOCAL_RPC_REQUIRED: "Bridge local source RPC is required",
|
|
7404
|
+
BRIDGE_SOURCE_RPC_TRANSPORT: "Bridge source RPC transport failed",
|
|
7405
|
+
BRIDGE_SOURCE_RPC_INVALID_RESPONSE: "Bridge source RPC response is invalid",
|
|
7406
|
+
BRIDGE_LOCAL_PLAN_INVALID: "Bridge local source-swap plan is invalid",
|
|
7407
|
+
BRIDGE_LOCAL_BUILD_INVALID: "Bridge local unsigned build is invalid",
|
|
5783
7408
|
BRIDGE_STATUS_NOT_FOUND: "Bridge status was not found",
|
|
5784
7409
|
BRIDGE_TIMEOUT: "Bridge provider request timed out",
|
|
5785
7410
|
BRIDGE_ABORTED: "Bridge provider request was aborted"
|
|
@@ -5794,8 +7419,8 @@ var BridgeError = class extends Error {
|
|
|
5794
7419
|
if (status !== void 0) this.status = status;
|
|
5795
7420
|
}
|
|
5796
7421
|
};
|
|
5797
|
-
var
|
|
5798
|
-
var
|
|
7422
|
+
var ETHEREUM_CHAIN_ID2 = TOKEN_CHAIN_IDS.ethereumMainnet;
|
|
7423
|
+
var SOLANA_CHAIN_ID2 = TOKEN_CHAIN_IDS.solanaMainnet;
|
|
5799
7424
|
var ETHEREUM_NAME = "ethereum";
|
|
5800
7425
|
var SOLANA_NAME = "solana";
|
|
5801
7426
|
var ETHEREUM_PROVIDER_CHAIN_ID = 1;
|
|
@@ -5811,26 +7436,28 @@ var SOLANA_EURC_ADDRESS = "HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr";
|
|
|
5811
7436
|
var ETHEREUM_USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48";
|
|
5812
7437
|
var SOLANA_USDC_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
5813
7438
|
var ETHEREUM_SWIFT_CONTRACT = "0x40ffe85a28dc9993541449464d7529a922142960";
|
|
5814
|
-
var
|
|
5815
|
-
var
|
|
5816
|
-
var
|
|
5817
|
-
var
|
|
7439
|
+
var SOLANA_SWIFT_PROGRAM2 = "mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny";
|
|
7440
|
+
var ETHEREUM_FORWARDER2 = "0x337685fdab40d39bd02028545a4ffa7d287cc3e2";
|
|
7441
|
+
var SOLANA_JUPITER_V62 = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
|
|
7442
|
+
var ETHEREUM_EURC_FORWARDER_SELECTOR = "0x30dedc57";
|
|
7443
|
+
var ETHEREUM_USDC_FORWARDER_SELECTOR = "0xe4269fc4";
|
|
7444
|
+
var MAYAN_USDC_MINT = "A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM";
|
|
5818
7445
|
var DEFAULT_BUILDER_ENDPOINT = "https://tx-builder.mayan.finance";
|
|
5819
7446
|
var DEFAULT_EXPLORER_ENDPOINT = "https://explorer-api.mayan.finance/v3";
|
|
5820
7447
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
5821
|
-
var
|
|
7448
|
+
var MAX_RESPONSE_BYTES2 = 1024 * 1024;
|
|
5822
7449
|
var MAX_RAW_QUOTE_BYTES = 256 * 1024;
|
|
5823
|
-
var
|
|
7450
|
+
var MAX_JSON_DEPTH2 = 32;
|
|
5824
7451
|
var MAX_QUOTES = 16;
|
|
5825
|
-
var
|
|
7452
|
+
var UINT64_MAX2 = (1n << 64n) - 1n;
|
|
5826
7453
|
var CANONICAL_UINT64 = /^(0|[1-9][0-9]*)$/u;
|
|
5827
7454
|
var POSITIVE_UINT64 = /^[1-9][0-9]*$/u;
|
|
5828
|
-
var
|
|
7455
|
+
var EVM_ADDRESS3 = /^0x[0-9a-fA-F]{40}$/u;
|
|
5829
7456
|
var EVM_HASH = /^0x[0-9a-fA-F]{64}$/u;
|
|
5830
7457
|
var EVM_SIGNATURE = /^0x[0-9a-fA-F]{130}$/u;
|
|
5831
|
-
var
|
|
7458
|
+
var HEX_BYTES3 = /^0x[0-9a-fA-F]*$/u;
|
|
5832
7459
|
var BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
|
|
5833
|
-
var
|
|
7460
|
+
var BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
5834
7461
|
var DEPENDENCIES = Object.freeze([
|
|
5835
7462
|
"mayan-hosted-quote-api",
|
|
5836
7463
|
"mayan-hosted-transaction-builder",
|
|
@@ -5840,6 +7467,14 @@ var DEPENDENCIES = Object.freeze([
|
|
|
5840
7467
|
"wormhole-guardian-messaging",
|
|
5841
7468
|
"mayan-explorer-indexer"
|
|
5842
7469
|
]);
|
|
7470
|
+
var DIRECT_USDC_DEPENDENCIES = Object.freeze([
|
|
7471
|
+
"mayan-hosted-quote-api",
|
|
7472
|
+
"mayan-hosted-transaction-builder",
|
|
7473
|
+
"swift-auction-solvers",
|
|
7474
|
+
"relayers",
|
|
7475
|
+
"wormhole-guardian-messaging",
|
|
7476
|
+
"mayan-explorer-indexer"
|
|
7477
|
+
]);
|
|
5843
7478
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5844
7479
|
var deepFreeze6 = (value) => {
|
|
5845
7480
|
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -5863,9 +7498,9 @@ var requireString = (value, code, nonempty = true) => {
|
|
|
5863
7498
|
if (typeof value !== "string" || nonempty && value.length === 0) fail(code);
|
|
5864
7499
|
return value;
|
|
5865
7500
|
};
|
|
5866
|
-
var
|
|
7501
|
+
var normalizeEvmAddress4 = (value, code) => {
|
|
5867
7502
|
const address = requireString(value, code);
|
|
5868
|
-
if (!
|
|
7503
|
+
if (!EVM_ADDRESS3.test(address) || /^0x0{40}$/iu.test(address)) fail(code);
|
|
5869
7504
|
return address.toLowerCase();
|
|
5870
7505
|
};
|
|
5871
7506
|
var normalizePositiveUint64 = (value, code) => {
|
|
@@ -5878,7 +7513,7 @@ var normalizePositiveUint64 = (value, code) => {
|
|
|
5878
7513
|
return fail(code);
|
|
5879
7514
|
}
|
|
5880
7515
|
const valueParsed = parsed;
|
|
5881
|
-
if (valueParsed <= 0n || valueParsed >
|
|
7516
|
+
if (valueParsed <= 0n || valueParsed > UINT64_MAX2) fail(code);
|
|
5882
7517
|
return { source, value: valueParsed };
|
|
5883
7518
|
};
|
|
5884
7519
|
var normalizeCanonicalUint64 = (value, code) => {
|
|
@@ -5891,7 +7526,7 @@ var normalizeCanonicalUint64 = (value, code) => {
|
|
|
5891
7526
|
return fail(code);
|
|
5892
7527
|
}
|
|
5893
7528
|
const valueParsed = parsed;
|
|
5894
|
-
if (valueParsed >
|
|
7529
|
+
if (valueParsed > UINT64_MAX2) fail(code);
|
|
5895
7530
|
return { source, value: valueParsed };
|
|
5896
7531
|
};
|
|
5897
7532
|
var normalizeSlippage = (value, code) => {
|
|
@@ -5900,18 +7535,22 @@ var normalizeSlippage = (value, code) => {
|
|
|
5900
7535
|
}
|
|
5901
7536
|
return value;
|
|
5902
7537
|
};
|
|
5903
|
-
var providerAddressEquals = (value, expected) => typeof value === "string" && (
|
|
5904
|
-
var catalogTokenMatches = (token, expected) => token?.deploymentId === expected.deploymentId && token.chainId === expected.chainId && token.address !== null && (expected.chainId ===
|
|
5905
|
-
var directionFacts = (sourceChainId, destinationChainId) => {
|
|
5906
|
-
if (sourceChainId ===
|
|
7538
|
+
var providerAddressEquals = (value, expected) => typeof value === "string" && (EVM_ADDRESS3.test(value) ? value.toLowerCase() === expected.toLowerCase() : value === expected);
|
|
7539
|
+
var catalogTokenMatches = (token, expected) => token?.deploymentId === expected.deploymentId && token.chainId === expected.chainId && token.address !== null && (expected.chainId === ETHEREUM_CHAIN_ID2 ? token.address.toLowerCase() === expected.address.toLowerCase() : token.address === expected.address) && token.standard === expected.standard && token.decimals === expected.decimals && token.status === "active";
|
|
7540
|
+
var directionFacts = (sourceChainId, destinationChainId, sourceTokenDeploymentId, destinationTokenDeploymentId) => {
|
|
7541
|
+
if (sourceChainId === ETHEREUM_CHAIN_ID2 && destinationChainId === SOLANA_CHAIN_ID2) {
|
|
7542
|
+
const isEurc = sourceTokenDeploymentId === ETHEREUM_EURC_DEPLOYMENT_ID && destinationTokenDeploymentId === SOLANA_EURC_DEPLOYMENT_ID;
|
|
7543
|
+
const isUsdc = sourceTokenDeploymentId === ETHEREUM_USDC_DEPLOYMENT_ID && destinationTokenDeploymentId === SOLANA_USDC_DEPLOYMENT_ID;
|
|
7544
|
+
if (!isEurc && !isUsdc) return fail("BRIDGE_UNSUPPORTED_ROUTE");
|
|
5907
7545
|
return {
|
|
5908
7546
|
sourceChainId,
|
|
5909
7547
|
destinationChainId,
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
7548
|
+
asset: isEurc ? "eurc" : "usdc",
|
|
7549
|
+
bridgeCapabilityId: isEurc ? "bridge-mayan-swift-v2-eurc-eth-sol" : "bridge-mayan-swift-v2-usdc-eth-sol",
|
|
7550
|
+
sourceTokenDeploymentId,
|
|
7551
|
+
destinationTokenDeploymentId,
|
|
7552
|
+
sourceTokenAddress: isEurc ? ETHEREUM_EURC_ADDRESS : ETHEREUM_USDC_ADDRESS,
|
|
7553
|
+
destinationTokenAddress: isEurc ? SOLANA_EURC_ADDRESS : SOLANA_USDC_ADDRESS,
|
|
5915
7554
|
sourceTokenStandard: "erc20",
|
|
5916
7555
|
destinationTokenStandard: "spl-token",
|
|
5917
7556
|
sourceProviderChainId: ETHEREUM_PROVIDER_CHAIN_ID,
|
|
@@ -5920,23 +7559,31 @@ var directionFacts = (sourceChainId, destinationChainId) => {
|
|
|
5920
7559
|
destinationWormholeChainId: SOLANA_WORMHOLE_CHAIN_ID,
|
|
5921
7560
|
sourceName: ETHEREUM_NAME,
|
|
5922
7561
|
destinationName: SOLANA_NAME,
|
|
5923
|
-
|
|
5924
|
-
|
|
7562
|
+
sourceTokenName: isEurc ? "EuroC" : "USD Coin",
|
|
7563
|
+
destinationTokenName: isEurc ? "EuroC" : "USD Coin",
|
|
7564
|
+
sourceTokenMint: isEurc ? "" : MAYAN_USDC_MINT,
|
|
7565
|
+
destinationTokenMint: isEurc ? SOLANA_EURC_ADDRESS : SOLANA_USDC_ADDRESS,
|
|
5925
7566
|
sourceUsdcDeploymentId: ETHEREUM_USDC_DEPLOYMENT_ID,
|
|
5926
7567
|
sourceUsdcAddress: ETHEREUM_USDC_ADDRESS,
|
|
5927
7568
|
sourceUsdcStandard: "erc20",
|
|
5928
|
-
swiftContract: ETHEREUM_SWIFT_CONTRACT
|
|
7569
|
+
swiftContract: ETHEREUM_SWIFT_CONTRACT,
|
|
7570
|
+
forwarderAddress: ETHEREUM_FORWARDER2,
|
|
7571
|
+
forwarderFunctionSelector: isUsdc ? ETHEREUM_USDC_FORWARDER_SELECTOR : ETHEREUM_EURC_FORWARDER_SELECTOR
|
|
5929
7572
|
};
|
|
5930
7573
|
}
|
|
5931
|
-
if (sourceChainId ===
|
|
7574
|
+
if (sourceChainId === SOLANA_CHAIN_ID2 && destinationChainId === ETHEREUM_CHAIN_ID2) {
|
|
7575
|
+
const isEurc = sourceTokenDeploymentId === SOLANA_EURC_DEPLOYMENT_ID && destinationTokenDeploymentId === ETHEREUM_EURC_DEPLOYMENT_ID;
|
|
7576
|
+
const isUsdc = sourceTokenDeploymentId === SOLANA_USDC_DEPLOYMENT_ID && destinationTokenDeploymentId === ETHEREUM_USDC_DEPLOYMENT_ID;
|
|
7577
|
+
if (!isEurc && !isUsdc) return fail("BRIDGE_UNSUPPORTED_ROUTE");
|
|
5932
7578
|
return {
|
|
5933
7579
|
sourceChainId,
|
|
5934
7580
|
destinationChainId,
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
7581
|
+
asset: isEurc ? "eurc" : "usdc",
|
|
7582
|
+
bridgeCapabilityId: isEurc ? "bridge-mayan-swift-v2-eurc-sol-eth" : "bridge-mayan-swift-v2-usdc-sol-eth",
|
|
7583
|
+
sourceTokenDeploymentId,
|
|
7584
|
+
destinationTokenDeploymentId,
|
|
7585
|
+
sourceTokenAddress: isEurc ? SOLANA_EURC_ADDRESS : SOLANA_USDC_ADDRESS,
|
|
7586
|
+
destinationTokenAddress: isEurc ? ETHEREUM_EURC_ADDRESS : ETHEREUM_USDC_ADDRESS,
|
|
5940
7587
|
sourceTokenStandard: "spl-token",
|
|
5941
7588
|
destinationTokenStandard: "erc20",
|
|
5942
7589
|
sourceProviderChainId: SOLANA_PROVIDER_CHAIN_ID,
|
|
@@ -5945,12 +7592,16 @@ var directionFacts = (sourceChainId, destinationChainId) => {
|
|
|
5945
7592
|
destinationWormholeChainId: ETHEREUM_WORMHOLE_CHAIN_ID,
|
|
5946
7593
|
sourceName: SOLANA_NAME,
|
|
5947
7594
|
destinationName: ETHEREUM_NAME,
|
|
5948
|
-
|
|
5949
|
-
|
|
7595
|
+
sourceTokenName: isEurc ? "EuroC" : "USD Coin",
|
|
7596
|
+
destinationTokenName: isEurc ? "EuroC" : "USD Coin",
|
|
7597
|
+
sourceTokenMint: isEurc ? SOLANA_EURC_ADDRESS : SOLANA_USDC_ADDRESS,
|
|
7598
|
+
destinationTokenMint: isEurc ? "" : MAYAN_USDC_MINT,
|
|
5950
7599
|
sourceUsdcDeploymentId: SOLANA_USDC_DEPLOYMENT_ID,
|
|
5951
7600
|
sourceUsdcAddress: SOLANA_USDC_ADDRESS,
|
|
5952
7601
|
sourceUsdcStandard: "spl-token",
|
|
5953
|
-
swiftContract:
|
|
7602
|
+
swiftContract: SOLANA_SWIFT_PROGRAM2,
|
|
7603
|
+
forwarderAddress: null,
|
|
7604
|
+
forwarderFunctionSelector: null
|
|
5954
7605
|
};
|
|
5955
7606
|
}
|
|
5956
7607
|
return fail("BRIDGE_UNSUPPORTED_ROUTE");
|
|
@@ -6014,12 +7665,12 @@ var validateCapability = (capability, facts) => {
|
|
|
6014
7665
|
sourceUsdcStandard: facts.sourceUsdcStandard,
|
|
6015
7666
|
sourceUsdcDecimals: 6,
|
|
6016
7667
|
swiftContract: facts.swiftContract,
|
|
6017
|
-
forwarderAddress: facts.sourceChainId ===
|
|
6018
|
-
forwarderFunctionSelector: facts.sourceChainId ===
|
|
6019
|
-
jupiterProgramAddress: facts.sourceChainId ===
|
|
7668
|
+
forwarderAddress: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? ETHEREUM_FORWARDER2 : null,
|
|
7669
|
+
forwarderFunctionSelector: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? facts.asset === "usdc" ? ETHEREUM_USDC_FORWARDER_SELECTOR : ETHEREUM_EURC_FORWARDER_SELECTOR : null,
|
|
7670
|
+
jupiterProgramAddress: facts.sourceChainId === SOLANA_CHAIN_ID2 && facts.asset === "eurc" ? SOLANA_JUPITER_V62 : null,
|
|
6020
7671
|
builderEndpoint: DEFAULT_BUILDER_ENDPOINT,
|
|
6021
7672
|
explorerEndpoint: DEFAULT_EXPLORER_ENDPOINT,
|
|
6022
|
-
dependencies: facts.sourceChainId ===
|
|
7673
|
+
dependencies: facts.asset === "usdc" ? [...DIRECT_USDC_DEPENDENCIES] : facts.sourceChainId === SOLANA_CHAIN_ID2 ? [...DEPENDENCIES, "jupiter-v6-source-swap"] : [...DEPENDENCIES],
|
|
6023
7674
|
status: "active"
|
|
6024
7675
|
};
|
|
6025
7676
|
const actualKeys = Object.keys(capability).sort();
|
|
@@ -6060,10 +7711,12 @@ var validateBridgeRoute = (request) => {
|
|
|
6060
7711
|
);
|
|
6061
7712
|
const amountIn = normalizePositiveUint64(value.amountIn, "BRIDGE_INVALID_ARGUMENT");
|
|
6062
7713
|
const slippageBps = normalizeSlippage(value.slippageBps, "BRIDGE_INVALID_ARGUMENT");
|
|
6063
|
-
const facts = directionFacts(
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
7714
|
+
const facts = directionFacts(
|
|
7715
|
+
sourceChainId,
|
|
7716
|
+
destinationChainId,
|
|
7717
|
+
sourceTokenDeploymentId,
|
|
7718
|
+
destinationTokenDeploymentId
|
|
7719
|
+
);
|
|
6067
7720
|
validateCatalogDirection(facts);
|
|
6068
7721
|
const capability = findCapability(facts);
|
|
6069
7722
|
validateCapability(capability, facts);
|
|
@@ -6095,7 +7748,7 @@ var StrictJsonParser = class {
|
|
|
6095
7748
|
return value;
|
|
6096
7749
|
}
|
|
6097
7750
|
#value(depth) {
|
|
6098
|
-
if (depth >
|
|
7751
|
+
if (depth > MAX_JSON_DEPTH2) this.#invalid();
|
|
6099
7752
|
const start = this.#index;
|
|
6100
7753
|
const character = this.#source[this.#index];
|
|
6101
7754
|
if (character === "{") return this.#object(start, depth);
|
|
@@ -6307,7 +7960,7 @@ var decodeResponseBody = async (response, controlled, external) => {
|
|
|
6307
7960
|
const contentLength = response.headers.get("content-length");
|
|
6308
7961
|
if (contentLength !== null && /^\d+$/u.test(contentLength)) {
|
|
6309
7962
|
try {
|
|
6310
|
-
if (BigInt(contentLength) > BigInt(
|
|
7963
|
+
if (BigInt(contentLength) > BigInt(MAX_RESPONSE_BYTES2)) {
|
|
6311
7964
|
fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6312
7965
|
}
|
|
6313
7966
|
} catch {
|
|
@@ -6348,7 +8001,7 @@ var decodeResponseBody = async (response, controlled, external) => {
|
|
|
6348
8001
|
const chunk = result.value;
|
|
6349
8002
|
if (!(chunk instanceof Uint8Array)) return fail("BRIDGE_PROVIDER_TRANSPORT");
|
|
6350
8003
|
totalBytes += chunk.byteLength;
|
|
6351
|
-
if (totalBytes >
|
|
8004
|
+
if (totalBytes > MAX_RESPONSE_BYTES2) {
|
|
6352
8005
|
fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6353
8006
|
}
|
|
6354
8007
|
chunks.push(chunk);
|
|
@@ -6383,7 +8036,8 @@ var CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6383
8036
|
"allowUnauthenticatedBuild",
|
|
6384
8037
|
"minimumQuoteValiditySeconds",
|
|
6385
8038
|
"timeoutMs",
|
|
6386
|
-
"fetch"
|
|
8039
|
+
"fetch",
|
|
8040
|
+
"localBuild"
|
|
6387
8041
|
]);
|
|
6388
8042
|
var endpointWithPath2 = (base, path) => new URL(path.replace(/^\/+/, ""), `${base.toString().replace(/\/+$/u, "")}/`);
|
|
6389
8043
|
var normalizeProviderEndpoint = (value, fallback, label) => {
|
|
@@ -6455,6 +8109,15 @@ var normalizeBridgeConfig = (config) => {
|
|
|
6455
8109
|
const timeoutMs = timeoutMsValue;
|
|
6456
8110
|
const implementation = value.fetch ?? globalThis.fetch;
|
|
6457
8111
|
if (typeof implementation !== "function") fail("BRIDGE_INVALID_ARGUMENT");
|
|
8112
|
+
let localBuild;
|
|
8113
|
+
if (value.localBuild !== void 0) {
|
|
8114
|
+
const localBuildValue = requireRecord(value.localBuild, "BRIDGE_INVALID_ARGUMENT");
|
|
8115
|
+
const localBuildKeys = /* @__PURE__ */ new Set(["sourceSwapEndpoint", "ethereumRpc", "solanaRpc"]);
|
|
8116
|
+
if (Object.keys(localBuildValue).some((key) => !localBuildKeys.has(key))) {
|
|
8117
|
+
fail("BRIDGE_INVALID_ARGUMENT");
|
|
8118
|
+
}
|
|
8119
|
+
localBuild = localBuildValue;
|
|
8120
|
+
}
|
|
6458
8121
|
return Object.freeze({
|
|
6459
8122
|
builderEndpoint,
|
|
6460
8123
|
explorerEndpoint,
|
|
@@ -6462,7 +8125,8 @@ var normalizeBridgeConfig = (config) => {
|
|
|
6462
8125
|
allowUnauthenticatedBuild,
|
|
6463
8126
|
minimumQuoteValiditySeconds,
|
|
6464
8127
|
timeoutMs,
|
|
6465
|
-
fetch: implementation
|
|
8128
|
+
fetch: wrapFetch(implementation),
|
|
8129
|
+
...localBuild === void 0 ? {} : { localBuild }
|
|
6466
8130
|
});
|
|
6467
8131
|
};
|
|
6468
8132
|
var requestSignal = (timeoutMs, external) => {
|
|
@@ -6572,18 +8236,18 @@ var encodeBase58 = (bytes) => {
|
|
|
6572
8236
|
}
|
|
6573
8237
|
let result = "1".repeat(zeroes);
|
|
6574
8238
|
for (let index = digits.length - 1; index >= 0; index -= 1) {
|
|
6575
|
-
result +=
|
|
8239
|
+
result += BASE58_ALPHABET2[digits[index] ?? 0] ?? "";
|
|
6576
8240
|
}
|
|
6577
8241
|
return result === "" ? "1" : result;
|
|
6578
8242
|
};
|
|
6579
8243
|
var decodeBase58 = (value, expectedBytes, code) => {
|
|
6580
8244
|
const text = requireString(value, code);
|
|
6581
|
-
if (text.length > expectedBytes * 2 || [...text].some((char) => !
|
|
8245
|
+
if (text.length > expectedBytes * 2 || [...text].some((char) => !BASE58_ALPHABET2.includes(char))) {
|
|
6582
8246
|
fail(code);
|
|
6583
8247
|
}
|
|
6584
8248
|
const bytes = [0];
|
|
6585
8249
|
for (const char of text) {
|
|
6586
|
-
const digit =
|
|
8250
|
+
const digit = BASE58_ALPHABET2.indexOf(char);
|
|
6587
8251
|
let carry = digit;
|
|
6588
8252
|
for (let index = 0; index < bytes.length; index += 1) {
|
|
6589
8253
|
const current = (bytes[index] ?? 0) * 58 + carry;
|
|
@@ -6727,7 +8391,7 @@ var providerInteger = (node, key) => {
|
|
|
6727
8391
|
var providerAddress = (node, key, expected) => {
|
|
6728
8392
|
const value = providerString(node, key);
|
|
6729
8393
|
if (!providerAddressEquals(value, expected)) providerInvalid();
|
|
6730
|
-
return
|
|
8394
|
+
return EVM_ADDRESS3.test(value) ? value.toLowerCase() : value;
|
|
6731
8395
|
};
|
|
6732
8396
|
var providerUint64 = (node, key, positive) => {
|
|
6733
8397
|
const value = providerString(node, key);
|
|
@@ -6746,14 +8410,14 @@ var providerToken = (node, expected) => {
|
|
|
6746
8410
|
if (mint !== expected.mint) providerInvalid();
|
|
6747
8411
|
const realOrigin = providerString(node, "realOriginContractAddress");
|
|
6748
8412
|
if (!providerAddressEquals(realOrigin, expected.address)) providerInvalid();
|
|
6749
|
-
if (providerString(node, "name") !==
|
|
8413
|
+
if (providerString(node, "name") !== expected.name) providerInvalid();
|
|
6750
8414
|
if (providerString(node, "standard") !== expected.standard) providerInvalid();
|
|
6751
8415
|
if (providerInteger(node, "chainId") !== expected.chainId) providerInvalid();
|
|
6752
8416
|
if (providerInteger(node, "wChainId") !== expected.wormholeChainId) providerInvalid();
|
|
6753
8417
|
if (providerInteger(node, "realOriginChainId") !== expected.wormholeChainId) providerInvalid();
|
|
6754
8418
|
if (providerInteger(node, "decimals") !== 6) providerInvalid();
|
|
6755
8419
|
};
|
|
6756
|
-
var quoteProviderStandard = (facts) => facts.sourceChainId ===
|
|
8420
|
+
var quoteProviderStandard = (facts) => facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl";
|
|
6757
8421
|
var ensureQuoteDeadline = (deadlineValue, margin) => {
|
|
6758
8422
|
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
6759
8423
|
if (!Number.isSafeInteger(Number(now)) || deadlineValue < now + BigInt(margin)) {
|
|
@@ -6785,17 +8449,19 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6785
8449
|
const destinationToken = requiredNode(node, "toToken");
|
|
6786
8450
|
providerToken(sourceToken, {
|
|
6787
8451
|
address: facts.sourceTokenAddress,
|
|
6788
|
-
standard: facts.sourceChainId ===
|
|
8452
|
+
standard: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl",
|
|
6789
8453
|
chainId: facts.sourceProviderChainId,
|
|
6790
8454
|
wormholeChainId: facts.sourceWormholeChainId,
|
|
6791
|
-
mint: facts.
|
|
8455
|
+
mint: facts.sourceTokenMint,
|
|
8456
|
+
name: facts.sourceTokenName
|
|
6792
8457
|
});
|
|
6793
8458
|
providerToken(destinationToken, {
|
|
6794
8459
|
address: facts.destinationTokenAddress,
|
|
6795
|
-
standard: facts.destinationChainId ===
|
|
8460
|
+
standard: facts.destinationChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl",
|
|
6796
8461
|
chainId: facts.destinationProviderChainId,
|
|
6797
8462
|
wormholeChainId: facts.destinationWormholeChainId,
|
|
6798
|
-
mint: facts.
|
|
8463
|
+
mint: facts.destinationTokenMint,
|
|
8464
|
+
name: facts.destinationTokenName
|
|
6799
8465
|
});
|
|
6800
8466
|
const sourceUsdcStandard = quoteProviderStandard(facts);
|
|
6801
8467
|
if (providerAddress(node, "swiftInputContract", facts.sourceUsdcAddress) !== facts.sourceUsdcAddress) {
|
|
@@ -6812,23 +8478,27 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6812
8478
|
}
|
|
6813
8479
|
let routerAddress;
|
|
6814
8480
|
let routerKind;
|
|
6815
|
-
|
|
6816
|
-
|
|
8481
|
+
const evmRouter = objectValue5(node, "evmSwapRouterAddress");
|
|
8482
|
+
if (facts.asset === "usdc") {
|
|
8483
|
+
if (evmRouter !== void 0 && evmRouter !== null) providerInvalid();
|
|
8484
|
+
routerAddress = null;
|
|
8485
|
+
routerKind = null;
|
|
8486
|
+
} else if (facts.sourceChainId === ETHEREUM_CHAIN_ID2) {
|
|
8487
|
+
routerAddress = normalizeEvmAddress4(
|
|
6817
8488
|
providerString(node, "evmSwapRouterAddress"),
|
|
6818
8489
|
"BRIDGE_PROVIDER_INVALID_RESPONSE"
|
|
6819
8490
|
);
|
|
6820
8491
|
routerKind = "provider-selected-evm";
|
|
6821
8492
|
} else {
|
|
6822
|
-
routerAddress =
|
|
8493
|
+
routerAddress = SOLANA_JUPITER_V62;
|
|
6823
8494
|
routerKind = "jupiter-v6";
|
|
6824
|
-
const evmRouter = objectValue5(node, "evmSwapRouterAddress");
|
|
6825
8495
|
if (evmRouter !== void 0 && evmRouter !== null) providerInvalid();
|
|
6826
8496
|
}
|
|
6827
8497
|
const quoteId = providerString(node, "quoteId");
|
|
6828
8498
|
if (!/^0x[0-9a-fA-F]{32}$/u.test(quoteId)) providerInvalid();
|
|
6829
8499
|
const signature = providerString(node, "signature");
|
|
6830
8500
|
if (!EVM_SIGNATURE.test(signature)) providerInvalid();
|
|
6831
|
-
const dependencies = facts.sourceChainId ===
|
|
8501
|
+
const dependencies = facts.asset === "usdc" ? [...DIRECT_USDC_DEPENDENCIES] : facts.sourceChainId === SOLANA_CHAIN_ID2 ? [...DEPENDENCIES, "jupiter-v6-source-swap"] : [...DEPENDENCIES];
|
|
6832
8502
|
const quote = {
|
|
6833
8503
|
quoteKind: "mayan-swift-v2",
|
|
6834
8504
|
providerId: "mayan-swift-v2",
|
|
@@ -6845,8 +8515,8 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6845
8515
|
quoteId: quoteId.toLowerCase(),
|
|
6846
8516
|
providerSignature: signature.toLowerCase(),
|
|
6847
8517
|
sourceSwap: {
|
|
6848
|
-
required:
|
|
6849
|
-
inputTokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8518
|
+
required: facts.asset === "eurc",
|
|
8519
|
+
inputTokenDeploymentId: facts.asset === "usdc" ? facts.sourceUsdcDeploymentId : facts.sourceTokenDeploymentId,
|
|
6850
8520
|
intermediateTokenDeploymentId: facts.sourceUsdcDeploymentId,
|
|
6851
8521
|
intermediateTokenAddress: facts.sourceUsdcAddress,
|
|
6852
8522
|
intermediateTokenStandard: sourceUsdcStandard,
|
|
@@ -6903,10 +8573,10 @@ var exactObjectKeys = (value, expected, code) => {
|
|
|
6903
8573
|
fail(code);
|
|
6904
8574
|
}
|
|
6905
8575
|
};
|
|
6906
|
-
var
|
|
6907
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
8576
|
+
var stableJson2 = (value) => {
|
|
8577
|
+
if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
|
|
6908
8578
|
if (isRecord4(value)) {
|
|
6909
|
-
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${
|
|
8579
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson2(value[key])}`).join(",")}}`;
|
|
6910
8580
|
}
|
|
6911
8581
|
return JSON.stringify(value);
|
|
6912
8582
|
};
|
|
@@ -6923,8 +8593,23 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6923
8593
|
if (value.quoteKind !== "mayan-swift-v2" || value.providerId !== "mayan-swift-v2") fail(code);
|
|
6924
8594
|
const sourceChainId = requireString(value.sourceChainId, code);
|
|
6925
8595
|
const destinationChainId = requireString(value.destinationChainId, code);
|
|
6926
|
-
const
|
|
6927
|
-
|
|
8596
|
+
const sourceTokenDeploymentId = requireString(value.sourceTokenDeploymentId, code);
|
|
8597
|
+
const destinationTokenDeploymentId = requireString(value.destinationTokenDeploymentId, code);
|
|
8598
|
+
let facts;
|
|
8599
|
+
try {
|
|
8600
|
+
facts = directionFacts(
|
|
8601
|
+
sourceChainId,
|
|
8602
|
+
destinationChainId,
|
|
8603
|
+
sourceTokenDeploymentId,
|
|
8604
|
+
destinationTokenDeploymentId
|
|
8605
|
+
);
|
|
8606
|
+
} catch (error) {
|
|
8607
|
+
if (error instanceof BridgeError && error.code === "BRIDGE_UNSUPPORTED_ROUTE") {
|
|
8608
|
+
return fail(code);
|
|
8609
|
+
}
|
|
8610
|
+
throw error;
|
|
8611
|
+
}
|
|
8612
|
+
if (sourceTokenDeploymentId !== facts.sourceTokenDeploymentId || destinationTokenDeploymentId !== facts.destinationTokenDeploymentId) fail(code);
|
|
6928
8613
|
const amountIn = normalizePositiveUint64(value.amountIn, code);
|
|
6929
8614
|
const expectedAmountOut = normalizePositiveUint64(value.expectedAmountOut, code);
|
|
6930
8615
|
const minimumAmountOut = normalizePositiveUint64(value.minimumAmountOut, code);
|
|
@@ -6939,29 +8624,33 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6939
8624
|
if (!EVM_SIGNATURE.test(signature)) fail(code);
|
|
6940
8625
|
const sourceSwap = requireRecord(value.sourceSwap, code);
|
|
6941
8626
|
exactObjectKeys(sourceSwap, SOURCE_SWAP_KEYS, code);
|
|
6942
|
-
if (sourceSwap.required !==
|
|
6943
|
-
if (sourceSwap.inputTokenDeploymentId !== facts.sourceTokenDeploymentId || sourceSwap.intermediateTokenDeploymentId !== facts.sourceUsdcDeploymentId) fail(code);
|
|
8627
|
+
if (sourceSwap.required !== (facts.asset === "eurc")) fail(code);
|
|
8628
|
+
if (sourceSwap.inputTokenDeploymentId !== (facts.asset === "usdc" ? facts.sourceUsdcDeploymentId : facts.sourceTokenDeploymentId) || sourceSwap.intermediateTokenDeploymentId !== facts.sourceUsdcDeploymentId) fail(code);
|
|
6944
8629
|
if (sourceSwap.intermediateTokenAddress !== facts.sourceUsdcAddress) fail(code);
|
|
6945
|
-
const
|
|
6946
|
-
if (sourceSwap.intermediateTokenStandard !==
|
|
8630
|
+
const providerStandard2 = quoteProviderStandard(facts);
|
|
8631
|
+
if (sourceSwap.intermediateTokenStandard !== providerStandard2 || sourceSwap.intermediateTokenDecimals !== 6) fail(code);
|
|
6947
8632
|
const providerMinimumAmount = sourceSwap.providerMinimumAmount;
|
|
6948
8633
|
if (typeof providerMinimumAmount !== "string" || providerMinimumAmount.length === 0) fail(code);
|
|
6949
8634
|
let normalizedRouterAddress;
|
|
6950
8635
|
let normalizedRouterKind;
|
|
6951
|
-
if (facts.
|
|
8636
|
+
if (facts.asset === "usdc") {
|
|
8637
|
+
if (sourceSwap.routerKind !== null || sourceSwap.routerAddress !== null) fail(code);
|
|
8638
|
+
normalizedRouterAddress = null;
|
|
8639
|
+
normalizedRouterKind = null;
|
|
8640
|
+
} else if (facts.sourceChainId === ETHEREUM_CHAIN_ID2) {
|
|
6952
8641
|
const routerAddress = sourceSwap.routerAddress;
|
|
6953
|
-
if (sourceSwap.routerKind !== "provider-selected-evm" || typeof routerAddress !== "string" || !
|
|
8642
|
+
if (sourceSwap.routerKind !== "provider-selected-evm" || typeof routerAddress !== "string" || !EVM_ADDRESS3.test(routerAddress) || /^0x0{40}$/iu.test(routerAddress)) return fail(code);
|
|
6954
8643
|
normalizedRouterAddress = routerAddress.toLowerCase();
|
|
6955
8644
|
normalizedRouterKind = "provider-selected-evm";
|
|
6956
|
-
} else if (sourceSwap.routerKind !== "jupiter-v6" || sourceSwap.routerAddress !==
|
|
8645
|
+
} else if (sourceSwap.routerKind !== "jupiter-v6" || sourceSwap.routerAddress !== SOLANA_JUPITER_V62) {
|
|
6957
8646
|
return fail(code);
|
|
6958
8647
|
} else {
|
|
6959
|
-
normalizedRouterAddress =
|
|
8648
|
+
normalizedRouterAddress = SOLANA_JUPITER_V62;
|
|
6960
8649
|
normalizedRouterKind = "jupiter-v6";
|
|
6961
8650
|
}
|
|
6962
8651
|
if (!Array.isArray(value.dependencies)) fail(code);
|
|
6963
|
-
const wantedDependencies = facts.sourceChainId ===
|
|
6964
|
-
if (
|
|
8652
|
+
const wantedDependencies = facts.asset === "usdc" ? [...DIRECT_USDC_DEPENDENCIES] : facts.sourceChainId === SOLANA_CHAIN_ID2 ? [...DEPENDENCIES, "jupiter-v6-source-swap"] : [...DEPENDENCIES];
|
|
8653
|
+
if (stableJson2(value.dependencies) !== stableJson2(wantedDependencies)) fail(code);
|
|
6965
8654
|
const rawSignedQuoteJson = requireString(value.rawSignedQuoteJson, code);
|
|
6966
8655
|
if (byteLength(rawSignedQuoteJson) > MAX_RAW_QUOTE_BYTES) fail(code);
|
|
6967
8656
|
return {
|
|
@@ -6980,11 +8669,11 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6980
8669
|
quoteId: quoteId.toLowerCase(),
|
|
6981
8670
|
providerSignature: signature.toLowerCase(),
|
|
6982
8671
|
sourceSwap: {
|
|
6983
|
-
required:
|
|
6984
|
-
inputTokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8672
|
+
required: facts.asset === "eurc",
|
|
8673
|
+
inputTokenDeploymentId: facts.asset === "usdc" ? facts.sourceUsdcDeploymentId : facts.sourceTokenDeploymentId,
|
|
6985
8674
|
intermediateTokenDeploymentId: facts.sourceUsdcDeploymentId,
|
|
6986
8675
|
intermediateTokenAddress: facts.sourceUsdcAddress,
|
|
6987
|
-
intermediateTokenStandard:
|
|
8676
|
+
intermediateTokenStandard: providerStandard2,
|
|
6988
8677
|
intermediateTokenDecimals: 6,
|
|
6989
8678
|
providerMinimumAmount,
|
|
6990
8679
|
routerKind: normalizedRouterKind,
|
|
@@ -7065,7 +8754,7 @@ var buildRequestSnapshot = (value) => {
|
|
|
7065
8754
|
};
|
|
7066
8755
|
};
|
|
7067
8756
|
var normalizeChainAddress = (value, chainId, code) => {
|
|
7068
|
-
if (chainId ===
|
|
8757
|
+
if (chainId === ETHEREUM_CHAIN_ID2) return normalizeEvmAddress4(value, code);
|
|
7069
8758
|
const address = requireString(value, code);
|
|
7070
8759
|
decodeBase58(address, 32, code);
|
|
7071
8760
|
return address;
|
|
@@ -7080,9 +8769,9 @@ var isCanonicalSolanaAddress = (value) => {
|
|
|
7080
8769
|
}
|
|
7081
8770
|
};
|
|
7082
8771
|
var rejectAddressFromOtherChain = (value, expectedChainId) => {
|
|
7083
|
-
const isEvm = typeof value === "string" &&
|
|
8772
|
+
const isEvm = typeof value === "string" && EVM_ADDRESS3.test(value) && !/^0x0{40}$/iu.test(value);
|
|
7084
8773
|
const isSolana = isCanonicalSolanaAddress(value);
|
|
7085
|
-
if (expectedChainId ===
|
|
8774
|
+
if (expectedChainId === ETHEREUM_CHAIN_ID2 && isSolana || expectedChainId === SOLANA_CHAIN_ID2 && isEvm) {
|
|
7086
8775
|
fail("BRIDGE_QUOTE_MISMATCH");
|
|
7087
8776
|
}
|
|
7088
8777
|
};
|
|
@@ -7097,7 +8786,7 @@ var buildRouteFromQuote = (quote) => {
|
|
|
7097
8786
|
if (error instanceof BridgeError) throw error;
|
|
7098
8787
|
return fail("BRIDGE_QUOTE_MISMATCH");
|
|
7099
8788
|
}
|
|
7100
|
-
if (
|
|
8789
|
+
if (stableJson2(quote) !== stableJson2(normalizedQuote)) fail("BRIDGE_QUOTE_MISMATCH");
|
|
7101
8790
|
const route = validateBridgeRoute({
|
|
7102
8791
|
sourceChainId: normalizedQuote.sourceChainId,
|
|
7103
8792
|
destinationChainId: normalizedQuote.destinationChainId,
|
|
@@ -7132,7 +8821,9 @@ var validateRawQuoteForBuild = (quote, route, config) => {
|
|
|
7132
8821
|
if (error instanceof BridgeError && error.code === "BRIDGE_QUOTE_EXPIRED") throw error;
|
|
7133
8822
|
return fail("BRIDGE_QUOTE_MISMATCH");
|
|
7134
8823
|
}
|
|
7135
|
-
if (
|
|
8824
|
+
if (stableJson2(rebuilt.quote) !== stableJson2(quote)) {
|
|
8825
|
+
fail("BRIDGE_QUOTE_MISMATCH");
|
|
8826
|
+
}
|
|
7136
8827
|
return deepFreeze6(quote);
|
|
7137
8828
|
};
|
|
7138
8829
|
var numericZero = (value) => {
|
|
@@ -7141,26 +8832,29 @@ var numericZero = (value) => {
|
|
|
7141
8832
|
if (value === "0") return true;
|
|
7142
8833
|
return /^0x0+$/iu.test(value);
|
|
7143
8834
|
};
|
|
7144
|
-
var validateEvmBuildResult = (wrapper, swapperAddress) => {
|
|
8835
|
+
var validateEvmBuildResult = (wrapper, swapperAddress, facts) => {
|
|
8836
|
+
const forwarderAddress = facts.forwarderAddress ?? providerInvalid();
|
|
8837
|
+
const forwarderFunctionSelector = facts.forwarderFunctionSelector ?? providerInvalid();
|
|
7145
8838
|
if (providerString(wrapper, "chainCategory") !== "evm") providerInvalid();
|
|
7146
8839
|
if (providerString(wrapper, "quoteType") !== "SWIFT") providerInvalid();
|
|
7147
8840
|
if (providerBoolean(wrapper, "gasless")) providerInvalid();
|
|
7148
8841
|
const transaction = requiredNode(wrapper, "transaction");
|
|
7149
8842
|
if (!isRecord4(transaction.value)) providerInvalid();
|
|
7150
8843
|
const to = providerString(transaction, "to");
|
|
7151
|
-
if (!providerAddressEquals(to,
|
|
8844
|
+
if (!providerAddressEquals(to, forwarderAddress)) providerInvalid();
|
|
7152
8845
|
const chainId = providerInteger(transaction, "chainId");
|
|
7153
8846
|
if (chainId !== ETHEREUM_PROVIDER_CHAIN_ID) providerInvalid();
|
|
7154
8847
|
if (!numericZero(objectValue5(transaction, "value"))) providerInvalid();
|
|
7155
8848
|
const data = providerString(transaction, "data").toLowerCase();
|
|
7156
|
-
|
|
8849
|
+
const minimumWords = facts.asset === "usdc" ? 10 : 13;
|
|
8850
|
+
if (!HEX_BYTES3.test(data) || data.length % 2 !== 0 || !data.startsWith(forwarderFunctionSelector) || data.length < 2 + 8 + minimumWords * 64) {
|
|
7157
8851
|
providerInvalid();
|
|
7158
8852
|
}
|
|
7159
8853
|
return {
|
|
7160
8854
|
kind: "evm-unsigned-transaction",
|
|
7161
8855
|
chainId: "eip155:1",
|
|
7162
8856
|
from: swapperAddress,
|
|
7163
|
-
to:
|
|
8857
|
+
to: forwarderAddress,
|
|
7164
8858
|
data,
|
|
7165
8859
|
value: "0"
|
|
7166
8860
|
};
|
|
@@ -7174,7 +8868,7 @@ var validateSolanaBuildResult = (wrapper, swapperAddress) => {
|
|
|
7174
8868
|
const encoded = validateSolanaTransaction(transaction.value, swapperAddress);
|
|
7175
8869
|
return {
|
|
7176
8870
|
kind: "solana-v0-unsigned-transaction",
|
|
7177
|
-
chainId:
|
|
8871
|
+
chainId: SOLANA_CHAIN_ID2,
|
|
7178
8872
|
feePayer: swapperAddress,
|
|
7179
8873
|
transactionBase64: encoded
|
|
7180
8874
|
};
|
|
@@ -7195,7 +8889,7 @@ var validateBuildResponse = (response, quote, facts, swapperAddress) => {
|
|
|
7195
8889
|
}
|
|
7196
8890
|
let transaction;
|
|
7197
8891
|
try {
|
|
7198
|
-
transaction = facts.sourceChainId ===
|
|
8892
|
+
transaction = facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? validateEvmBuildResult(wrapper, swapperAddress, facts) : validateSolanaBuildResult(wrapper, swapperAddress);
|
|
7199
8893
|
} catch (error) {
|
|
7200
8894
|
if (error instanceof BridgeError) {
|
|
7201
8895
|
if (error.code === "BRIDGE_BUILD_INVALID") throw error;
|
|
@@ -7210,11 +8904,11 @@ var validateBuildResponse = (response, quote, facts, swapperAddress) => {
|
|
|
7210
8904
|
sourceChainId: quote.sourceChainId,
|
|
7211
8905
|
destinationChainId: quote.destinationChainId,
|
|
7212
8906
|
transaction,
|
|
7213
|
-
allowance: facts.sourceChainId ===
|
|
7214
|
-
tokenDeploymentId:
|
|
7215
|
-
tokenAddress:
|
|
8907
|
+
allowance: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? {
|
|
8908
|
+
tokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8909
|
+
tokenAddress: facts.sourceTokenAddress,
|
|
7216
8910
|
owner: swapperAddress,
|
|
7217
|
-
spender:
|
|
8911
|
+
spender: facts.forwarderAddress,
|
|
7218
8912
|
requiredAmount: quote.amountIn
|
|
7219
8913
|
} : null,
|
|
7220
8914
|
validation: {
|
|
@@ -7240,14 +8934,14 @@ var statusRequestSnapshot = (value) => {
|
|
|
7240
8934
|
};
|
|
7241
8935
|
var normalizeStatusRequest = (value) => {
|
|
7242
8936
|
const request = statusRequestSnapshot(value);
|
|
7243
|
-
if (request.sourceChainId ===
|
|
8937
|
+
if (request.sourceChainId === ETHEREUM_CHAIN_ID2) {
|
|
7244
8938
|
if (!EVM_HASH.test(request.sourceTransactionHash)) fail("BRIDGE_INVALID_ARGUMENT");
|
|
7245
8939
|
return {
|
|
7246
8940
|
sourceChainId: request.sourceChainId,
|
|
7247
8941
|
sourceTransactionHash: request.sourceTransactionHash.toLowerCase()
|
|
7248
8942
|
};
|
|
7249
8943
|
}
|
|
7250
|
-
if (request.sourceChainId ===
|
|
8944
|
+
if (request.sourceChainId === SOLANA_CHAIN_ID2) {
|
|
7251
8945
|
decodeBase58(request.sourceTransactionHash, 64, "BRIDGE_INVALID_ARGUMENT");
|
|
7252
8946
|
return request;
|
|
7253
8947
|
}
|
|
@@ -7283,7 +8977,7 @@ var buildBody = (quote, sourceChainId, swapperAddress, destinationAddress, refun
|
|
|
7283
8977
|
swapperAddress,
|
|
7284
8978
|
destinationAddress
|
|
7285
8979
|
};
|
|
7286
|
-
if (sourceChainId ===
|
|
8980
|
+
if (sourceChainId === ETHEREUM_CHAIN_ID2) params.signerChainId = 1;
|
|
7287
8981
|
if (refundAddress !== void 0) params.swiftRefundAddress = refundAddress;
|
|
7288
8982
|
return `{"quote":${quote.rawSignedQuoteJson},"params":${JSON.stringify(params)}}`;
|
|
7289
8983
|
};
|
|
@@ -7363,6 +9057,37 @@ var MayanSwiftV2BridgeClient = class {
|
|
|
7363
9057
|
const parsed = await providerJson(response, "status");
|
|
7364
9058
|
return statusFromResponse(parsed, normalized);
|
|
7365
9059
|
}
|
|
9060
|
+
async prepareSourceSwap(context, options) {
|
|
9061
|
+
return prepareSourceSwap(context, this.#localRuntime(), options);
|
|
9062
|
+
}
|
|
9063
|
+
async buildLocalUnsigned(request, options) {
|
|
9064
|
+
return buildLocalUnsigned(request, this.#localRuntime(), options);
|
|
9065
|
+
}
|
|
9066
|
+
#localRuntime() {
|
|
9067
|
+
return {
|
|
9068
|
+
localBuild: this.#config.localBuild,
|
|
9069
|
+
fetch: this.#config.fetch,
|
|
9070
|
+
timeoutMs: this.#config.timeoutMs,
|
|
9071
|
+
minimumQuoteValiditySeconds: this.#config.minimumQuoteValiditySeconds,
|
|
9072
|
+
validateQuote: (quote, invalidCode) => {
|
|
9073
|
+
try {
|
|
9074
|
+
const { route, normalizedQuote } = buildRouteFromQuote(quote);
|
|
9075
|
+
const validationQuote = /[ \t\r\n]$/u.test(normalizedQuote.rawSignedQuoteJson) ? {
|
|
9076
|
+
...normalizedQuote,
|
|
9077
|
+
rawSignedQuoteJson: normalizedQuote.rawSignedQuoteJson.replace(/[ \t\r\n]+$/gu, "")
|
|
9078
|
+
} : normalizedQuote;
|
|
9079
|
+
validateRawQuoteForBuild(validationQuote, route, this.#config);
|
|
9080
|
+
return quote;
|
|
9081
|
+
} catch (error) {
|
|
9082
|
+
if (error instanceof BridgeError && error.code === "BRIDGE_QUOTE_EXPIRED") {
|
|
9083
|
+
throw error;
|
|
9084
|
+
}
|
|
9085
|
+
return fail(invalidCode);
|
|
9086
|
+
}
|
|
9087
|
+
},
|
|
9088
|
+
fail
|
|
9089
|
+
};
|
|
9090
|
+
}
|
|
7366
9091
|
close() {
|
|
7367
9092
|
}
|
|
7368
9093
|
};
|
|
@@ -7385,6 +9110,7 @@ exports.CloudCreditClient = CloudCreditClient;
|
|
|
7385
9110
|
exports.CloudResourcesClient = CloudResourcesClient;
|
|
7386
9111
|
exports.DEFAULT_ACCOUNT_ENDPOINT = DEFAULT_ACCOUNT_ENDPOINT;
|
|
7387
9112
|
exports.DEFAULT_AVALANCHE_ENDPOINT = DEFAULT_AVALANCHE_ENDPOINT;
|
|
9113
|
+
exports.DEFAULT_BASE_ENDPOINT = DEFAULT_BASE_ENDPOINT;
|
|
7388
9114
|
exports.DEFAULT_ENDPOINT = DEFAULT_ENDPOINT;
|
|
7389
9115
|
exports.DEFAULT_TIMEOUT_MS = DEFAULT_TIMEOUT_MS;
|
|
7390
9116
|
exports.DEFAULT_USER_ENDPOINT = DEFAULT_USER_ENDPOINT;
|