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