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