@elsoul/erpc-sdk 0.8.1 → 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 +1841 -118
- 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 +1841 -119
- 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 } } : {},
|
|
@@ -2537,6 +2608,7 @@ var wrapFetch = (implementation) => (input, init) => implementation(input, init)
|
|
|
2537
2608
|
// src/config.ts
|
|
2538
2609
|
var DEFAULT_ENDPOINT = "https://edge.erpc.global";
|
|
2539
2610
|
var DEFAULT_AVALANCHE_ENDPOINT = "https://ava-rpc.erpc.global";
|
|
2611
|
+
var DEFAULT_BASE_ENDPOINT = "https://base.erpc.global";
|
|
2540
2612
|
var DEFAULT_ACCOUNT_ENDPOINT = "https://solana-rpc.erpc.global";
|
|
2541
2613
|
var DEFAULT_USER_ENDPOINT = "https://user-api.erpc.global";
|
|
2542
2614
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -2615,6 +2687,15 @@ var resolveRpcEndpoint = (value, namespace) => {
|
|
|
2615
2687
|
...webSocketUrl === void 0 ? {} : { webSocketUrl }
|
|
2616
2688
|
};
|
|
2617
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
|
+
};
|
|
2618
2699
|
var resolveConfig = (config) => {
|
|
2619
2700
|
const configuredApiKey = config.apiKey === void 0 ? void 0 : typeof config.apiKey === "string" ? config.apiKey.trim() : (() => {
|
|
2620
2701
|
throw new ErpcConfigError("apiKey must be a string");
|
|
@@ -2622,13 +2703,15 @@ var resolveConfig = (config) => {
|
|
|
2622
2703
|
const solanaRpc = config.solanaRpc === void 0 ? void 0 : resolveRpcEndpoint(config.solanaRpc, "solanaRpc");
|
|
2623
2704
|
const ethereumRpc = config.ethereumRpc === void 0 ? void 0 : resolveRpcEndpoint(config.ethereumRpc, "ethereumRpc");
|
|
2624
2705
|
const avalancheCRpc = config.avalancheCRpc === void 0 ? void 0 : resolveRpcEndpoint(config.avalancheCRpc, "avalancheCRpc");
|
|
2625
|
-
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;
|
|
2626
2708
|
if (!configuredApiKey && !hasDirectRpc) {
|
|
2627
2709
|
throw new ErpcConfigError("apiKey must not be empty");
|
|
2628
2710
|
}
|
|
2629
2711
|
const apiKey = configuredApiKey || void 0;
|
|
2630
2712
|
let endpoint;
|
|
2631
2713
|
let avalancheEndpoint;
|
|
2714
|
+
let baseEndpoint;
|
|
2632
2715
|
let accountEndpoint;
|
|
2633
2716
|
let userEndpoint;
|
|
2634
2717
|
try {
|
|
@@ -2636,6 +2719,9 @@ var resolveConfig = (config) => {
|
|
|
2636
2719
|
avalancheEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2637
2720
|
config.avalancheEndpoint ?? DEFAULT_AVALANCHE_ENDPOINT
|
|
2638
2721
|
));
|
|
2722
|
+
baseEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2723
|
+
config.baseEndpoint ?? DEFAULT_BASE_ENDPOINT
|
|
2724
|
+
));
|
|
2639
2725
|
accountEndpoint = normalizeLegacyEndpoint(new URL(
|
|
2640
2726
|
config.accountEndpoint ?? DEFAULT_ACCOUNT_ENDPOINT
|
|
2641
2727
|
));
|
|
@@ -2649,6 +2735,9 @@ var resolveConfig = (config) => {
|
|
|
2649
2735
|
if (avalancheEndpoint.protocol !== "https:" && avalancheEndpoint.protocol !== "http:") {
|
|
2650
2736
|
throw new ErpcConfigError("avalancheEndpoint must use HTTP or HTTPS");
|
|
2651
2737
|
}
|
|
2738
|
+
if (baseEndpoint.protocol !== "https:" && baseEndpoint.protocol !== "http:") {
|
|
2739
|
+
throw new ErpcConfigError("baseEndpoint must use HTTP or HTTPS");
|
|
2740
|
+
}
|
|
2652
2741
|
if (accountEndpoint.protocol !== "https:" && accountEndpoint.protocol !== "http:") {
|
|
2653
2742
|
throw new ErpcConfigError("accountEndpoint must use HTTP or HTTPS");
|
|
2654
2743
|
}
|
|
@@ -2662,6 +2751,7 @@ var resolveConfig = (config) => {
|
|
|
2662
2751
|
return {
|
|
2663
2752
|
accountEndpoint,
|
|
2664
2753
|
avalancheEndpoint,
|
|
2754
|
+
baseEndpoint,
|
|
2665
2755
|
endpoint,
|
|
2666
2756
|
fetch: requireFetch(config.fetch),
|
|
2667
2757
|
headers: config.headers ?? {},
|
|
@@ -2669,6 +2759,7 @@ var resolveConfig = (config) => {
|
|
|
2669
2759
|
userEndpoint,
|
|
2670
2760
|
...apiKey === void 0 ? {} : { apiKey },
|
|
2671
2761
|
...avalancheCRpc === void 0 ? {} : { avalancheCRpc },
|
|
2762
|
+
...baseRpc === void 0 ? {} : { baseRpc },
|
|
2672
2763
|
...ethereumRpc === void 0 ? {} : { ethereumRpc },
|
|
2673
2764
|
...solanaRpc === void 0 ? {} : { solanaRpc },
|
|
2674
2765
|
...config.webSocket === void 0 ? {} : { webSocket: config.webSocket }
|
|
@@ -3042,6 +3133,19 @@ var createAvalancheClient = (transport, indexTransports, nativeTransport = trans
|
|
|
3042
3133
|
}
|
|
3043
3134
|
});
|
|
3044
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
|
+
|
|
3045
3149
|
// src/rpc/solana.ts
|
|
3046
3150
|
var SOLANA_RPC_METHODS = [
|
|
3047
3151
|
"getAccountInfo",
|
|
@@ -5202,8 +5306,14 @@ var HttpJsonRpcTransport = class {
|
|
|
5202
5306
|
this.#unavailableNamespace = config.unavailableNamespace;
|
|
5203
5307
|
this.maxBatchSize = config.maxBatchSize ?? 256;
|
|
5204
5308
|
const endpoint = new URL(config.endpoint);
|
|
5205
|
-
|
|
5206
|
-
|
|
5309
|
+
if (this.#direct) {
|
|
5310
|
+
endpoint.pathname = "/";
|
|
5311
|
+
endpoint.search = "";
|
|
5312
|
+
endpoint.hash = "";
|
|
5313
|
+
} else {
|
|
5314
|
+
endpoint.search = "";
|
|
5315
|
+
endpoint.hash = "";
|
|
5316
|
+
}
|
|
5207
5317
|
this.endpoint = endpoint.toString();
|
|
5208
5318
|
}
|
|
5209
5319
|
async request(method, params, options = {}) {
|
|
@@ -5474,6 +5584,7 @@ var createErpcClient = (config) => {
|
|
|
5474
5584
|
const solanaTransport = resolved.solanaRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("solana.rpc") : createLegacyHttp(resolved.endpoint) : createDirectHttp(resolved.solanaRpc);
|
|
5475
5585
|
const ethereumTransport = resolved.ethereumRpc === void 0 ? resolved.apiKey === void 0 ? createUnavailableHttp("ethereum.rpc") : createLegacyHttp(endpointWithPath(resolved.endpoint, "/eth")) : createDirectHttp(resolved.ethereumRpc);
|
|
5476
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);
|
|
5477
5588
|
const avalancheNativeTransport = resolved.apiKey === void 0 ? createUnavailableHttp("avalanche.native") : createLegacyHttp(endpointWithPath(resolved.avalancheEndpoint, "/ava"));
|
|
5478
5589
|
const avalancheIndexTransport = (path, namespace) => resolved.apiKey === void 0 ? createUnavailableHttp(namespace) : createLegacyHttp(endpointWithPath(resolved.avalancheEndpoint, path));
|
|
5479
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");
|
|
@@ -5536,6 +5647,7 @@ var createErpcClient = (config) => {
|
|
|
5536
5647
|
solana,
|
|
5537
5648
|
ethereum,
|
|
5538
5649
|
avalanche,
|
|
5650
|
+
base: createBaseClient(baseTransport),
|
|
5539
5651
|
price: new PriceClient(priceTransport),
|
|
5540
5652
|
account: new AccountClient(accountTransport),
|
|
5541
5653
|
swap,
|
|
@@ -5765,9 +5877,1514 @@ var createErpcCloudClient = (config) => {
|
|
|
5765
5877
|
};
|
|
5766
5878
|
|
|
5767
5879
|
// src/generated/bridge_capabilities.ts
|
|
5768
|
-
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"}]';
|
|
5769
|
-
var BRIDGE_CAPABILITIES_CONTENT_DIGEST = "
|
|
5770
|
-
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);
|
|
5771
7388
|
|
|
5772
7389
|
// src/bridge.ts
|
|
5773
7390
|
var BRIDGE_ERROR_MESSAGES = Object.freeze({
|
|
@@ -5781,6 +7398,11 @@ var BRIDGE_ERROR_MESSAGES = Object.freeze({
|
|
|
5781
7398
|
BRIDGE_QUOTE_EXPIRED: "Bridge quote is expired",
|
|
5782
7399
|
BRIDGE_QUOTE_MISMATCH: "Bridge quote does not match the request",
|
|
5783
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",
|
|
5784
7406
|
BRIDGE_STATUS_NOT_FOUND: "Bridge status was not found",
|
|
5785
7407
|
BRIDGE_TIMEOUT: "Bridge provider request timed out",
|
|
5786
7408
|
BRIDGE_ABORTED: "Bridge provider request was aborted"
|
|
@@ -5795,8 +7417,8 @@ var BridgeError = class extends Error {
|
|
|
5795
7417
|
if (status !== void 0) this.status = status;
|
|
5796
7418
|
}
|
|
5797
7419
|
};
|
|
5798
|
-
var
|
|
5799
|
-
var
|
|
7420
|
+
var ETHEREUM_CHAIN_ID2 = TOKEN_CHAIN_IDS.ethereumMainnet;
|
|
7421
|
+
var SOLANA_CHAIN_ID2 = TOKEN_CHAIN_IDS.solanaMainnet;
|
|
5800
7422
|
var ETHEREUM_NAME = "ethereum";
|
|
5801
7423
|
var SOLANA_NAME = "solana";
|
|
5802
7424
|
var ETHEREUM_PROVIDER_CHAIN_ID = 1;
|
|
@@ -5812,26 +7434,28 @@ var SOLANA_EURC_ADDRESS = "HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr";
|
|
|
5812
7434
|
var ETHEREUM_USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48";
|
|
5813
7435
|
var SOLANA_USDC_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
5814
7436
|
var ETHEREUM_SWIFT_CONTRACT = "0x40ffe85a28dc9993541449464d7529a922142960";
|
|
5815
|
-
var
|
|
5816
|
-
var
|
|
5817
|
-
var
|
|
5818
|
-
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";
|
|
5819
7443
|
var DEFAULT_BUILDER_ENDPOINT = "https://tx-builder.mayan.finance";
|
|
5820
7444
|
var DEFAULT_EXPLORER_ENDPOINT = "https://explorer-api.mayan.finance/v3";
|
|
5821
7445
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
5822
|
-
var
|
|
7446
|
+
var MAX_RESPONSE_BYTES2 = 1024 * 1024;
|
|
5823
7447
|
var MAX_RAW_QUOTE_BYTES = 256 * 1024;
|
|
5824
|
-
var
|
|
7448
|
+
var MAX_JSON_DEPTH2 = 32;
|
|
5825
7449
|
var MAX_QUOTES = 16;
|
|
5826
|
-
var
|
|
7450
|
+
var UINT64_MAX2 = (1n << 64n) - 1n;
|
|
5827
7451
|
var CANONICAL_UINT64 = /^(0|[1-9][0-9]*)$/u;
|
|
5828
7452
|
var POSITIVE_UINT64 = /^[1-9][0-9]*$/u;
|
|
5829
|
-
var
|
|
7453
|
+
var EVM_ADDRESS3 = /^0x[0-9a-fA-F]{40}$/u;
|
|
5830
7454
|
var EVM_HASH = /^0x[0-9a-fA-F]{64}$/u;
|
|
5831
7455
|
var EVM_SIGNATURE = /^0x[0-9a-fA-F]{130}$/u;
|
|
5832
|
-
var
|
|
7456
|
+
var HEX_BYTES3 = /^0x[0-9a-fA-F]*$/u;
|
|
5833
7457
|
var BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
|
|
5834
|
-
var
|
|
7458
|
+
var BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
5835
7459
|
var DEPENDENCIES = Object.freeze([
|
|
5836
7460
|
"mayan-hosted-quote-api",
|
|
5837
7461
|
"mayan-hosted-transaction-builder",
|
|
@@ -5841,6 +7465,14 @@ var DEPENDENCIES = Object.freeze([
|
|
|
5841
7465
|
"wormhole-guardian-messaging",
|
|
5842
7466
|
"mayan-explorer-indexer"
|
|
5843
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
|
+
]);
|
|
5844
7476
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5845
7477
|
var deepFreeze6 = (value) => {
|
|
5846
7478
|
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -5864,9 +7496,9 @@ var requireString = (value, code, nonempty = true) => {
|
|
|
5864
7496
|
if (typeof value !== "string" || nonempty && value.length === 0) fail(code);
|
|
5865
7497
|
return value;
|
|
5866
7498
|
};
|
|
5867
|
-
var
|
|
7499
|
+
var normalizeEvmAddress4 = (value, code) => {
|
|
5868
7500
|
const address = requireString(value, code);
|
|
5869
|
-
if (!
|
|
7501
|
+
if (!EVM_ADDRESS3.test(address) || /^0x0{40}$/iu.test(address)) fail(code);
|
|
5870
7502
|
return address.toLowerCase();
|
|
5871
7503
|
};
|
|
5872
7504
|
var normalizePositiveUint64 = (value, code) => {
|
|
@@ -5879,7 +7511,7 @@ var normalizePositiveUint64 = (value, code) => {
|
|
|
5879
7511
|
return fail(code);
|
|
5880
7512
|
}
|
|
5881
7513
|
const valueParsed = parsed;
|
|
5882
|
-
if (valueParsed <= 0n || valueParsed >
|
|
7514
|
+
if (valueParsed <= 0n || valueParsed > UINT64_MAX2) fail(code);
|
|
5883
7515
|
return { source, value: valueParsed };
|
|
5884
7516
|
};
|
|
5885
7517
|
var normalizeCanonicalUint64 = (value, code) => {
|
|
@@ -5892,7 +7524,7 @@ var normalizeCanonicalUint64 = (value, code) => {
|
|
|
5892
7524
|
return fail(code);
|
|
5893
7525
|
}
|
|
5894
7526
|
const valueParsed = parsed;
|
|
5895
|
-
if (valueParsed >
|
|
7527
|
+
if (valueParsed > UINT64_MAX2) fail(code);
|
|
5896
7528
|
return { source, value: valueParsed };
|
|
5897
7529
|
};
|
|
5898
7530
|
var normalizeSlippage = (value, code) => {
|
|
@@ -5901,18 +7533,22 @@ var normalizeSlippage = (value, code) => {
|
|
|
5901
7533
|
}
|
|
5902
7534
|
return value;
|
|
5903
7535
|
};
|
|
5904
|
-
var providerAddressEquals = (value, expected) => typeof value === "string" && (
|
|
5905
|
-
var catalogTokenMatches = (token, expected) => token?.deploymentId === expected.deploymentId && token.chainId === expected.chainId && token.address !== null && (expected.chainId ===
|
|
5906
|
-
var directionFacts = (sourceChainId, destinationChainId) => {
|
|
5907
|
-
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");
|
|
5908
7543
|
return {
|
|
5909
7544
|
sourceChainId,
|
|
5910
7545
|
destinationChainId,
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
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,
|
|
5916
7552
|
sourceTokenStandard: "erc20",
|
|
5917
7553
|
destinationTokenStandard: "spl-token",
|
|
5918
7554
|
sourceProviderChainId: ETHEREUM_PROVIDER_CHAIN_ID,
|
|
@@ -5921,23 +7557,31 @@ var directionFacts = (sourceChainId, destinationChainId) => {
|
|
|
5921
7557
|
destinationWormholeChainId: SOLANA_WORMHOLE_CHAIN_ID,
|
|
5922
7558
|
sourceName: ETHEREUM_NAME,
|
|
5923
7559
|
destinationName: SOLANA_NAME,
|
|
5924
|
-
|
|
5925
|
-
|
|
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,
|
|
5926
7564
|
sourceUsdcDeploymentId: ETHEREUM_USDC_DEPLOYMENT_ID,
|
|
5927
7565
|
sourceUsdcAddress: ETHEREUM_USDC_ADDRESS,
|
|
5928
7566
|
sourceUsdcStandard: "erc20",
|
|
5929
|
-
swiftContract: ETHEREUM_SWIFT_CONTRACT
|
|
7567
|
+
swiftContract: ETHEREUM_SWIFT_CONTRACT,
|
|
7568
|
+
forwarderAddress: ETHEREUM_FORWARDER2,
|
|
7569
|
+
forwarderFunctionSelector: isUsdc ? ETHEREUM_USDC_FORWARDER_SELECTOR : ETHEREUM_EURC_FORWARDER_SELECTOR
|
|
5930
7570
|
};
|
|
5931
7571
|
}
|
|
5932
|
-
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");
|
|
5933
7576
|
return {
|
|
5934
7577
|
sourceChainId,
|
|
5935
7578
|
destinationChainId,
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
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,
|
|
5941
7585
|
sourceTokenStandard: "spl-token",
|
|
5942
7586
|
destinationTokenStandard: "erc20",
|
|
5943
7587
|
sourceProviderChainId: SOLANA_PROVIDER_CHAIN_ID,
|
|
@@ -5946,12 +7590,16 @@ var directionFacts = (sourceChainId, destinationChainId) => {
|
|
|
5946
7590
|
destinationWormholeChainId: ETHEREUM_WORMHOLE_CHAIN_ID,
|
|
5947
7591
|
sourceName: SOLANA_NAME,
|
|
5948
7592
|
destinationName: ETHEREUM_NAME,
|
|
5949
|
-
|
|
5950
|
-
|
|
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,
|
|
5951
7597
|
sourceUsdcDeploymentId: SOLANA_USDC_DEPLOYMENT_ID,
|
|
5952
7598
|
sourceUsdcAddress: SOLANA_USDC_ADDRESS,
|
|
5953
7599
|
sourceUsdcStandard: "spl-token",
|
|
5954
|
-
swiftContract:
|
|
7600
|
+
swiftContract: SOLANA_SWIFT_PROGRAM2,
|
|
7601
|
+
forwarderAddress: null,
|
|
7602
|
+
forwarderFunctionSelector: null
|
|
5955
7603
|
};
|
|
5956
7604
|
}
|
|
5957
7605
|
return fail("BRIDGE_UNSUPPORTED_ROUTE");
|
|
@@ -6015,12 +7663,12 @@ var validateCapability = (capability, facts) => {
|
|
|
6015
7663
|
sourceUsdcStandard: facts.sourceUsdcStandard,
|
|
6016
7664
|
sourceUsdcDecimals: 6,
|
|
6017
7665
|
swiftContract: facts.swiftContract,
|
|
6018
|
-
forwarderAddress: facts.sourceChainId ===
|
|
6019
|
-
forwarderFunctionSelector: facts.sourceChainId ===
|
|
6020
|
-
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,
|
|
6021
7669
|
builderEndpoint: DEFAULT_BUILDER_ENDPOINT,
|
|
6022
7670
|
explorerEndpoint: DEFAULT_EXPLORER_ENDPOINT,
|
|
6023
|
-
dependencies: facts.sourceChainId ===
|
|
7671
|
+
dependencies: facts.asset === "usdc" ? [...DIRECT_USDC_DEPENDENCIES] : facts.sourceChainId === SOLANA_CHAIN_ID2 ? [...DEPENDENCIES, "jupiter-v6-source-swap"] : [...DEPENDENCIES],
|
|
6024
7672
|
status: "active"
|
|
6025
7673
|
};
|
|
6026
7674
|
const actualKeys = Object.keys(capability).sort();
|
|
@@ -6061,10 +7709,12 @@ var validateBridgeRoute = (request) => {
|
|
|
6061
7709
|
);
|
|
6062
7710
|
const amountIn = normalizePositiveUint64(value.amountIn, "BRIDGE_INVALID_ARGUMENT");
|
|
6063
7711
|
const slippageBps = normalizeSlippage(value.slippageBps, "BRIDGE_INVALID_ARGUMENT");
|
|
6064
|
-
const facts = directionFacts(
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
7712
|
+
const facts = directionFacts(
|
|
7713
|
+
sourceChainId,
|
|
7714
|
+
destinationChainId,
|
|
7715
|
+
sourceTokenDeploymentId,
|
|
7716
|
+
destinationTokenDeploymentId
|
|
7717
|
+
);
|
|
6068
7718
|
validateCatalogDirection(facts);
|
|
6069
7719
|
const capability = findCapability(facts);
|
|
6070
7720
|
validateCapability(capability, facts);
|
|
@@ -6096,7 +7746,7 @@ var StrictJsonParser = class {
|
|
|
6096
7746
|
return value;
|
|
6097
7747
|
}
|
|
6098
7748
|
#value(depth) {
|
|
6099
|
-
if (depth >
|
|
7749
|
+
if (depth > MAX_JSON_DEPTH2) this.#invalid();
|
|
6100
7750
|
const start = this.#index;
|
|
6101
7751
|
const character = this.#source[this.#index];
|
|
6102
7752
|
if (character === "{") return this.#object(start, depth);
|
|
@@ -6308,7 +7958,7 @@ var decodeResponseBody = async (response, controlled, external) => {
|
|
|
6308
7958
|
const contentLength = response.headers.get("content-length");
|
|
6309
7959
|
if (contentLength !== null && /^\d+$/u.test(contentLength)) {
|
|
6310
7960
|
try {
|
|
6311
|
-
if (BigInt(contentLength) > BigInt(
|
|
7961
|
+
if (BigInt(contentLength) > BigInt(MAX_RESPONSE_BYTES2)) {
|
|
6312
7962
|
fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6313
7963
|
}
|
|
6314
7964
|
} catch {
|
|
@@ -6349,7 +7999,7 @@ var decodeResponseBody = async (response, controlled, external) => {
|
|
|
6349
7999
|
const chunk = result.value;
|
|
6350
8000
|
if (!(chunk instanceof Uint8Array)) return fail("BRIDGE_PROVIDER_TRANSPORT");
|
|
6351
8001
|
totalBytes += chunk.byteLength;
|
|
6352
|
-
if (totalBytes >
|
|
8002
|
+
if (totalBytes > MAX_RESPONSE_BYTES2) {
|
|
6353
8003
|
fail("BRIDGE_PROVIDER_INVALID_RESPONSE");
|
|
6354
8004
|
}
|
|
6355
8005
|
chunks.push(chunk);
|
|
@@ -6384,7 +8034,8 @@ var CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6384
8034
|
"allowUnauthenticatedBuild",
|
|
6385
8035
|
"minimumQuoteValiditySeconds",
|
|
6386
8036
|
"timeoutMs",
|
|
6387
|
-
"fetch"
|
|
8037
|
+
"fetch",
|
|
8038
|
+
"localBuild"
|
|
6388
8039
|
]);
|
|
6389
8040
|
var endpointWithPath2 = (base, path) => new URL(path.replace(/^\/+/, ""), `${base.toString().replace(/\/+$/u, "")}/`);
|
|
6390
8041
|
var normalizeProviderEndpoint = (value, fallback, label) => {
|
|
@@ -6456,6 +8107,15 @@ var normalizeBridgeConfig = (config) => {
|
|
|
6456
8107
|
const timeoutMs = timeoutMsValue;
|
|
6457
8108
|
const implementation = value.fetch ?? globalThis.fetch;
|
|
6458
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
|
+
}
|
|
6459
8119
|
return Object.freeze({
|
|
6460
8120
|
builderEndpoint,
|
|
6461
8121
|
explorerEndpoint,
|
|
@@ -6463,7 +8123,8 @@ var normalizeBridgeConfig = (config) => {
|
|
|
6463
8123
|
allowUnauthenticatedBuild,
|
|
6464
8124
|
minimumQuoteValiditySeconds,
|
|
6465
8125
|
timeoutMs,
|
|
6466
|
-
fetch: wrapFetch(implementation)
|
|
8126
|
+
fetch: wrapFetch(implementation),
|
|
8127
|
+
...localBuild === void 0 ? {} : { localBuild }
|
|
6467
8128
|
});
|
|
6468
8129
|
};
|
|
6469
8130
|
var requestSignal = (timeoutMs, external) => {
|
|
@@ -6573,18 +8234,18 @@ var encodeBase58 = (bytes) => {
|
|
|
6573
8234
|
}
|
|
6574
8235
|
let result = "1".repeat(zeroes);
|
|
6575
8236
|
for (let index = digits.length - 1; index >= 0; index -= 1) {
|
|
6576
|
-
result +=
|
|
8237
|
+
result += BASE58_ALPHABET2[digits[index] ?? 0] ?? "";
|
|
6577
8238
|
}
|
|
6578
8239
|
return result === "" ? "1" : result;
|
|
6579
8240
|
};
|
|
6580
8241
|
var decodeBase58 = (value, expectedBytes, code) => {
|
|
6581
8242
|
const text = requireString(value, code);
|
|
6582
|
-
if (text.length > expectedBytes * 2 || [...text].some((char) => !
|
|
8243
|
+
if (text.length > expectedBytes * 2 || [...text].some((char) => !BASE58_ALPHABET2.includes(char))) {
|
|
6583
8244
|
fail(code);
|
|
6584
8245
|
}
|
|
6585
8246
|
const bytes = [0];
|
|
6586
8247
|
for (const char of text) {
|
|
6587
|
-
const digit =
|
|
8248
|
+
const digit = BASE58_ALPHABET2.indexOf(char);
|
|
6588
8249
|
let carry = digit;
|
|
6589
8250
|
for (let index = 0; index < bytes.length; index += 1) {
|
|
6590
8251
|
const current = (bytes[index] ?? 0) * 58 + carry;
|
|
@@ -6728,7 +8389,7 @@ var providerInteger = (node, key) => {
|
|
|
6728
8389
|
var providerAddress = (node, key, expected) => {
|
|
6729
8390
|
const value = providerString(node, key);
|
|
6730
8391
|
if (!providerAddressEquals(value, expected)) providerInvalid();
|
|
6731
|
-
return
|
|
8392
|
+
return EVM_ADDRESS3.test(value) ? value.toLowerCase() : value;
|
|
6732
8393
|
};
|
|
6733
8394
|
var providerUint64 = (node, key, positive) => {
|
|
6734
8395
|
const value = providerString(node, key);
|
|
@@ -6747,14 +8408,14 @@ var providerToken = (node, expected) => {
|
|
|
6747
8408
|
if (mint !== expected.mint) providerInvalid();
|
|
6748
8409
|
const realOrigin = providerString(node, "realOriginContractAddress");
|
|
6749
8410
|
if (!providerAddressEquals(realOrigin, expected.address)) providerInvalid();
|
|
6750
|
-
if (providerString(node, "name") !==
|
|
8411
|
+
if (providerString(node, "name") !== expected.name) providerInvalid();
|
|
6751
8412
|
if (providerString(node, "standard") !== expected.standard) providerInvalid();
|
|
6752
8413
|
if (providerInteger(node, "chainId") !== expected.chainId) providerInvalid();
|
|
6753
8414
|
if (providerInteger(node, "wChainId") !== expected.wormholeChainId) providerInvalid();
|
|
6754
8415
|
if (providerInteger(node, "realOriginChainId") !== expected.wormholeChainId) providerInvalid();
|
|
6755
8416
|
if (providerInteger(node, "decimals") !== 6) providerInvalid();
|
|
6756
8417
|
};
|
|
6757
|
-
var quoteProviderStandard = (facts) => facts.sourceChainId ===
|
|
8418
|
+
var quoteProviderStandard = (facts) => facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl";
|
|
6758
8419
|
var ensureQuoteDeadline = (deadlineValue, margin) => {
|
|
6759
8420
|
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
6760
8421
|
if (!Number.isSafeInteger(Number(now)) || deadlineValue < now + BigInt(margin)) {
|
|
@@ -6786,17 +8447,19 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6786
8447
|
const destinationToken = requiredNode(node, "toToken");
|
|
6787
8448
|
providerToken(sourceToken, {
|
|
6788
8449
|
address: facts.sourceTokenAddress,
|
|
6789
|
-
standard: facts.sourceChainId ===
|
|
8450
|
+
standard: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl",
|
|
6790
8451
|
chainId: facts.sourceProviderChainId,
|
|
6791
8452
|
wormholeChainId: facts.sourceWormholeChainId,
|
|
6792
|
-
mint: facts.
|
|
8453
|
+
mint: facts.sourceTokenMint,
|
|
8454
|
+
name: facts.sourceTokenName
|
|
6793
8455
|
});
|
|
6794
8456
|
providerToken(destinationToken, {
|
|
6795
8457
|
address: facts.destinationTokenAddress,
|
|
6796
|
-
standard: facts.destinationChainId ===
|
|
8458
|
+
standard: facts.destinationChainId === ETHEREUM_CHAIN_ID2 ? "erc20" : "spl",
|
|
6797
8459
|
chainId: facts.destinationProviderChainId,
|
|
6798
8460
|
wormholeChainId: facts.destinationWormholeChainId,
|
|
6799
|
-
mint: facts.
|
|
8461
|
+
mint: facts.destinationTokenMint,
|
|
8462
|
+
name: facts.destinationTokenName
|
|
6800
8463
|
});
|
|
6801
8464
|
const sourceUsdcStandard = quoteProviderStandard(facts);
|
|
6802
8465
|
if (providerAddress(node, "swiftInputContract", facts.sourceUsdcAddress) !== facts.sourceUsdcAddress) {
|
|
@@ -6813,23 +8476,27 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6813
8476
|
}
|
|
6814
8477
|
let routerAddress;
|
|
6815
8478
|
let routerKind;
|
|
6816
|
-
|
|
6817
|
-
|
|
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(
|
|
6818
8486
|
providerString(node, "evmSwapRouterAddress"),
|
|
6819
8487
|
"BRIDGE_PROVIDER_INVALID_RESPONSE"
|
|
6820
8488
|
);
|
|
6821
8489
|
routerKind = "provider-selected-evm";
|
|
6822
8490
|
} else {
|
|
6823
|
-
routerAddress =
|
|
8491
|
+
routerAddress = SOLANA_JUPITER_V62;
|
|
6824
8492
|
routerKind = "jupiter-v6";
|
|
6825
|
-
const evmRouter = objectValue5(node, "evmSwapRouterAddress");
|
|
6826
8493
|
if (evmRouter !== void 0 && evmRouter !== null) providerInvalid();
|
|
6827
8494
|
}
|
|
6828
8495
|
const quoteId = providerString(node, "quoteId");
|
|
6829
8496
|
if (!/^0x[0-9a-fA-F]{32}$/u.test(quoteId)) providerInvalid();
|
|
6830
8497
|
const signature = providerString(node, "signature");
|
|
6831
8498
|
if (!EVM_SIGNATURE.test(signature)) providerInvalid();
|
|
6832
|
-
const dependencies = facts.sourceChainId ===
|
|
8499
|
+
const dependencies = facts.asset === "usdc" ? [...DIRECT_USDC_DEPENDENCIES] : facts.sourceChainId === SOLANA_CHAIN_ID2 ? [...DEPENDENCIES, "jupiter-v6-source-swap"] : [...DEPENDENCIES];
|
|
6833
8500
|
const quote = {
|
|
6834
8501
|
quoteKind: "mayan-swift-v2",
|
|
6835
8502
|
providerId: "mayan-swift-v2",
|
|
@@ -6846,8 +8513,8 @@ var validateProviderQuote = (node, text, request, facts, config) => {
|
|
|
6846
8513
|
quoteId: quoteId.toLowerCase(),
|
|
6847
8514
|
providerSignature: signature.toLowerCase(),
|
|
6848
8515
|
sourceSwap: {
|
|
6849
|
-
required:
|
|
6850
|
-
inputTokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8516
|
+
required: facts.asset === "eurc",
|
|
8517
|
+
inputTokenDeploymentId: facts.asset === "usdc" ? facts.sourceUsdcDeploymentId : facts.sourceTokenDeploymentId,
|
|
6851
8518
|
intermediateTokenDeploymentId: facts.sourceUsdcDeploymentId,
|
|
6852
8519
|
intermediateTokenAddress: facts.sourceUsdcAddress,
|
|
6853
8520
|
intermediateTokenStandard: sourceUsdcStandard,
|
|
@@ -6904,10 +8571,10 @@ var exactObjectKeys = (value, expected, code) => {
|
|
|
6904
8571
|
fail(code);
|
|
6905
8572
|
}
|
|
6906
8573
|
};
|
|
6907
|
-
var
|
|
6908
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
8574
|
+
var stableJson2 = (value) => {
|
|
8575
|
+
if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
|
|
6909
8576
|
if (isRecord4(value)) {
|
|
6910
|
-
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(",")}}`;
|
|
6911
8578
|
}
|
|
6912
8579
|
return JSON.stringify(value);
|
|
6913
8580
|
};
|
|
@@ -6924,8 +8591,23 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6924
8591
|
if (value.quoteKind !== "mayan-swift-v2" || value.providerId !== "mayan-swift-v2") fail(code);
|
|
6925
8592
|
const sourceChainId = requireString(value.sourceChainId, code);
|
|
6926
8593
|
const destinationChainId = requireString(value.destinationChainId, code);
|
|
6927
|
-
const
|
|
6928
|
-
|
|
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);
|
|
6929
8611
|
const amountIn = normalizePositiveUint64(value.amountIn, code);
|
|
6930
8612
|
const expectedAmountOut = normalizePositiveUint64(value.expectedAmountOut, code);
|
|
6931
8613
|
const minimumAmountOut = normalizePositiveUint64(value.minimumAmountOut, code);
|
|
@@ -6940,29 +8622,33 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6940
8622
|
if (!EVM_SIGNATURE.test(signature)) fail(code);
|
|
6941
8623
|
const sourceSwap = requireRecord(value.sourceSwap, code);
|
|
6942
8624
|
exactObjectKeys(sourceSwap, SOURCE_SWAP_KEYS, code);
|
|
6943
|
-
if (sourceSwap.required !==
|
|
6944
|
-
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);
|
|
6945
8627
|
if (sourceSwap.intermediateTokenAddress !== facts.sourceUsdcAddress) fail(code);
|
|
6946
|
-
const
|
|
6947
|
-
if (sourceSwap.intermediateTokenStandard !==
|
|
8628
|
+
const providerStandard2 = quoteProviderStandard(facts);
|
|
8629
|
+
if (sourceSwap.intermediateTokenStandard !== providerStandard2 || sourceSwap.intermediateTokenDecimals !== 6) fail(code);
|
|
6948
8630
|
const providerMinimumAmount = sourceSwap.providerMinimumAmount;
|
|
6949
8631
|
if (typeof providerMinimumAmount !== "string" || providerMinimumAmount.length === 0) fail(code);
|
|
6950
8632
|
let normalizedRouterAddress;
|
|
6951
8633
|
let normalizedRouterKind;
|
|
6952
|
-
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) {
|
|
6953
8639
|
const routerAddress = sourceSwap.routerAddress;
|
|
6954
|
-
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);
|
|
6955
8641
|
normalizedRouterAddress = routerAddress.toLowerCase();
|
|
6956
8642
|
normalizedRouterKind = "provider-selected-evm";
|
|
6957
|
-
} else if (sourceSwap.routerKind !== "jupiter-v6" || sourceSwap.routerAddress !==
|
|
8643
|
+
} else if (sourceSwap.routerKind !== "jupiter-v6" || sourceSwap.routerAddress !== SOLANA_JUPITER_V62) {
|
|
6958
8644
|
return fail(code);
|
|
6959
8645
|
} else {
|
|
6960
|
-
normalizedRouterAddress =
|
|
8646
|
+
normalizedRouterAddress = SOLANA_JUPITER_V62;
|
|
6961
8647
|
normalizedRouterKind = "jupiter-v6";
|
|
6962
8648
|
}
|
|
6963
8649
|
if (!Array.isArray(value.dependencies)) fail(code);
|
|
6964
|
-
const wantedDependencies = facts.sourceChainId ===
|
|
6965
|
-
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);
|
|
6966
8652
|
const rawSignedQuoteJson = requireString(value.rawSignedQuoteJson, code);
|
|
6967
8653
|
if (byteLength(rawSignedQuoteJson) > MAX_RAW_QUOTE_BYTES) fail(code);
|
|
6968
8654
|
return {
|
|
@@ -6981,11 +8667,11 @@ var validateNormalizedQuoteShape = (quote, code) => {
|
|
|
6981
8667
|
quoteId: quoteId.toLowerCase(),
|
|
6982
8668
|
providerSignature: signature.toLowerCase(),
|
|
6983
8669
|
sourceSwap: {
|
|
6984
|
-
required:
|
|
6985
|
-
inputTokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8670
|
+
required: facts.asset === "eurc",
|
|
8671
|
+
inputTokenDeploymentId: facts.asset === "usdc" ? facts.sourceUsdcDeploymentId : facts.sourceTokenDeploymentId,
|
|
6986
8672
|
intermediateTokenDeploymentId: facts.sourceUsdcDeploymentId,
|
|
6987
8673
|
intermediateTokenAddress: facts.sourceUsdcAddress,
|
|
6988
|
-
intermediateTokenStandard:
|
|
8674
|
+
intermediateTokenStandard: providerStandard2,
|
|
6989
8675
|
intermediateTokenDecimals: 6,
|
|
6990
8676
|
providerMinimumAmount,
|
|
6991
8677
|
routerKind: normalizedRouterKind,
|
|
@@ -7066,7 +8752,7 @@ var buildRequestSnapshot = (value) => {
|
|
|
7066
8752
|
};
|
|
7067
8753
|
};
|
|
7068
8754
|
var normalizeChainAddress = (value, chainId, code) => {
|
|
7069
|
-
if (chainId ===
|
|
8755
|
+
if (chainId === ETHEREUM_CHAIN_ID2) return normalizeEvmAddress4(value, code);
|
|
7070
8756
|
const address = requireString(value, code);
|
|
7071
8757
|
decodeBase58(address, 32, code);
|
|
7072
8758
|
return address;
|
|
@@ -7081,9 +8767,9 @@ var isCanonicalSolanaAddress = (value) => {
|
|
|
7081
8767
|
}
|
|
7082
8768
|
};
|
|
7083
8769
|
var rejectAddressFromOtherChain = (value, expectedChainId) => {
|
|
7084
|
-
const isEvm = typeof value === "string" &&
|
|
8770
|
+
const isEvm = typeof value === "string" && EVM_ADDRESS3.test(value) && !/^0x0{40}$/iu.test(value);
|
|
7085
8771
|
const isSolana = isCanonicalSolanaAddress(value);
|
|
7086
|
-
if (expectedChainId ===
|
|
8772
|
+
if (expectedChainId === ETHEREUM_CHAIN_ID2 && isSolana || expectedChainId === SOLANA_CHAIN_ID2 && isEvm) {
|
|
7087
8773
|
fail("BRIDGE_QUOTE_MISMATCH");
|
|
7088
8774
|
}
|
|
7089
8775
|
};
|
|
@@ -7098,7 +8784,7 @@ var buildRouteFromQuote = (quote) => {
|
|
|
7098
8784
|
if (error instanceof BridgeError) throw error;
|
|
7099
8785
|
return fail("BRIDGE_QUOTE_MISMATCH");
|
|
7100
8786
|
}
|
|
7101
|
-
if (
|
|
8787
|
+
if (stableJson2(quote) !== stableJson2(normalizedQuote)) fail("BRIDGE_QUOTE_MISMATCH");
|
|
7102
8788
|
const route = validateBridgeRoute({
|
|
7103
8789
|
sourceChainId: normalizedQuote.sourceChainId,
|
|
7104
8790
|
destinationChainId: normalizedQuote.destinationChainId,
|
|
@@ -7133,7 +8819,9 @@ var validateRawQuoteForBuild = (quote, route, config) => {
|
|
|
7133
8819
|
if (error instanceof BridgeError && error.code === "BRIDGE_QUOTE_EXPIRED") throw error;
|
|
7134
8820
|
return fail("BRIDGE_QUOTE_MISMATCH");
|
|
7135
8821
|
}
|
|
7136
|
-
if (
|
|
8822
|
+
if (stableJson2(rebuilt.quote) !== stableJson2(quote)) {
|
|
8823
|
+
fail("BRIDGE_QUOTE_MISMATCH");
|
|
8824
|
+
}
|
|
7137
8825
|
return deepFreeze6(quote);
|
|
7138
8826
|
};
|
|
7139
8827
|
var numericZero = (value) => {
|
|
@@ -7142,26 +8830,29 @@ var numericZero = (value) => {
|
|
|
7142
8830
|
if (value === "0") return true;
|
|
7143
8831
|
return /^0x0+$/iu.test(value);
|
|
7144
8832
|
};
|
|
7145
|
-
var validateEvmBuildResult = (wrapper, swapperAddress) => {
|
|
8833
|
+
var validateEvmBuildResult = (wrapper, swapperAddress, facts) => {
|
|
8834
|
+
const forwarderAddress = facts.forwarderAddress ?? providerInvalid();
|
|
8835
|
+
const forwarderFunctionSelector = facts.forwarderFunctionSelector ?? providerInvalid();
|
|
7146
8836
|
if (providerString(wrapper, "chainCategory") !== "evm") providerInvalid();
|
|
7147
8837
|
if (providerString(wrapper, "quoteType") !== "SWIFT") providerInvalid();
|
|
7148
8838
|
if (providerBoolean(wrapper, "gasless")) providerInvalid();
|
|
7149
8839
|
const transaction = requiredNode(wrapper, "transaction");
|
|
7150
8840
|
if (!isRecord4(transaction.value)) providerInvalid();
|
|
7151
8841
|
const to = providerString(transaction, "to");
|
|
7152
|
-
if (!providerAddressEquals(to,
|
|
8842
|
+
if (!providerAddressEquals(to, forwarderAddress)) providerInvalid();
|
|
7153
8843
|
const chainId = providerInteger(transaction, "chainId");
|
|
7154
8844
|
if (chainId !== ETHEREUM_PROVIDER_CHAIN_ID) providerInvalid();
|
|
7155
8845
|
if (!numericZero(objectValue5(transaction, "value"))) providerInvalid();
|
|
7156
8846
|
const data = providerString(transaction, "data").toLowerCase();
|
|
7157
|
-
|
|
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) {
|
|
7158
8849
|
providerInvalid();
|
|
7159
8850
|
}
|
|
7160
8851
|
return {
|
|
7161
8852
|
kind: "evm-unsigned-transaction",
|
|
7162
8853
|
chainId: "eip155:1",
|
|
7163
8854
|
from: swapperAddress,
|
|
7164
|
-
to:
|
|
8855
|
+
to: forwarderAddress,
|
|
7165
8856
|
data,
|
|
7166
8857
|
value: "0"
|
|
7167
8858
|
};
|
|
@@ -7175,7 +8866,7 @@ var validateSolanaBuildResult = (wrapper, swapperAddress) => {
|
|
|
7175
8866
|
const encoded = validateSolanaTransaction(transaction.value, swapperAddress);
|
|
7176
8867
|
return {
|
|
7177
8868
|
kind: "solana-v0-unsigned-transaction",
|
|
7178
|
-
chainId:
|
|
8869
|
+
chainId: SOLANA_CHAIN_ID2,
|
|
7179
8870
|
feePayer: swapperAddress,
|
|
7180
8871
|
transactionBase64: encoded
|
|
7181
8872
|
};
|
|
@@ -7196,7 +8887,7 @@ var validateBuildResponse = (response, quote, facts, swapperAddress) => {
|
|
|
7196
8887
|
}
|
|
7197
8888
|
let transaction;
|
|
7198
8889
|
try {
|
|
7199
|
-
transaction = facts.sourceChainId ===
|
|
8890
|
+
transaction = facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? validateEvmBuildResult(wrapper, swapperAddress, facts) : validateSolanaBuildResult(wrapper, swapperAddress);
|
|
7200
8891
|
} catch (error) {
|
|
7201
8892
|
if (error instanceof BridgeError) {
|
|
7202
8893
|
if (error.code === "BRIDGE_BUILD_INVALID") throw error;
|
|
@@ -7211,11 +8902,11 @@ var validateBuildResponse = (response, quote, facts, swapperAddress) => {
|
|
|
7211
8902
|
sourceChainId: quote.sourceChainId,
|
|
7212
8903
|
destinationChainId: quote.destinationChainId,
|
|
7213
8904
|
transaction,
|
|
7214
|
-
allowance: facts.sourceChainId ===
|
|
7215
|
-
tokenDeploymentId:
|
|
7216
|
-
tokenAddress:
|
|
8905
|
+
allowance: facts.sourceChainId === ETHEREUM_CHAIN_ID2 ? {
|
|
8906
|
+
tokenDeploymentId: facts.sourceTokenDeploymentId,
|
|
8907
|
+
tokenAddress: facts.sourceTokenAddress,
|
|
7217
8908
|
owner: swapperAddress,
|
|
7218
|
-
spender:
|
|
8909
|
+
spender: facts.forwarderAddress,
|
|
7219
8910
|
requiredAmount: quote.amountIn
|
|
7220
8911
|
} : null,
|
|
7221
8912
|
validation: {
|
|
@@ -7241,14 +8932,14 @@ var statusRequestSnapshot = (value) => {
|
|
|
7241
8932
|
};
|
|
7242
8933
|
var normalizeStatusRequest = (value) => {
|
|
7243
8934
|
const request = statusRequestSnapshot(value);
|
|
7244
|
-
if (request.sourceChainId ===
|
|
8935
|
+
if (request.sourceChainId === ETHEREUM_CHAIN_ID2) {
|
|
7245
8936
|
if (!EVM_HASH.test(request.sourceTransactionHash)) fail("BRIDGE_INVALID_ARGUMENT");
|
|
7246
8937
|
return {
|
|
7247
8938
|
sourceChainId: request.sourceChainId,
|
|
7248
8939
|
sourceTransactionHash: request.sourceTransactionHash.toLowerCase()
|
|
7249
8940
|
};
|
|
7250
8941
|
}
|
|
7251
|
-
if (request.sourceChainId ===
|
|
8942
|
+
if (request.sourceChainId === SOLANA_CHAIN_ID2) {
|
|
7252
8943
|
decodeBase58(request.sourceTransactionHash, 64, "BRIDGE_INVALID_ARGUMENT");
|
|
7253
8944
|
return request;
|
|
7254
8945
|
}
|
|
@@ -7284,7 +8975,7 @@ var buildBody = (quote, sourceChainId, swapperAddress, destinationAddress, refun
|
|
|
7284
8975
|
swapperAddress,
|
|
7285
8976
|
destinationAddress
|
|
7286
8977
|
};
|
|
7287
|
-
if (sourceChainId ===
|
|
8978
|
+
if (sourceChainId === ETHEREUM_CHAIN_ID2) params.signerChainId = 1;
|
|
7288
8979
|
if (refundAddress !== void 0) params.swiftRefundAddress = refundAddress;
|
|
7289
8980
|
return `{"quote":${quote.rawSignedQuoteJson},"params":${JSON.stringify(params)}}`;
|
|
7290
8981
|
};
|
|
@@ -7364,11 +9055,42 @@ var MayanSwiftV2BridgeClient = class {
|
|
|
7364
9055
|
const parsed = await providerJson(response, "status");
|
|
7365
9056
|
return statusFromResponse(parsed, normalized);
|
|
7366
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
|
+
}
|
|
7367
9089
|
close() {
|
|
7368
9090
|
}
|
|
7369
9091
|
};
|
|
7370
9092
|
var createMayanSwiftV2BridgeClient = (config) => new MayanSwiftV2BridgeClient(config);
|
|
7371
9093
|
|
|
7372
|
-
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 };
|
|
7373
9095
|
//# sourceMappingURL=index.js.map
|
|
7374
9096
|
//# sourceMappingURL=index.js.map
|