@shapeshiftoss/swapper 17.6.5 → 17.6.6-alpha.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.
Files changed (87) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/constants.js +17 -8
  3. package/dist/cjs/swappers/NearIntentsSwapper/NearIntentsSwapper.d.ts +2 -0
  4. package/dist/cjs/swappers/NearIntentsSwapper/NearIntentsSwapper.js +11 -0
  5. package/dist/cjs/swappers/NearIntentsSwapper/constants.d.ts +3 -0
  6. package/dist/cjs/swappers/NearIntentsSwapper/constants.js +6 -0
  7. package/dist/cjs/swappers/NearIntentsSwapper/endpoints.d.ts +2 -0
  8. package/dist/cjs/swappers/NearIntentsSwapper/endpoints.js +165 -0
  9. package/dist/cjs/swappers/NearIntentsSwapper/index.d.ts +4 -0
  10. package/dist/cjs/swappers/NearIntentsSwapper/index.js +20 -0
  11. package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.d.ts +3 -0
  12. package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +209 -0
  13. package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.d.ts +3 -0
  14. package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +208 -0
  15. package/dist/cjs/swappers/NearIntentsSwapper/types.d.ts +6 -0
  16. package/dist/cjs/swappers/NearIntentsSwapper/types.js +32 -0
  17. package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers/helpers.d.ts +12 -0
  18. package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers/helpers.js +99 -0
  19. package/dist/cjs/swappers/NearIntentsSwapper/utils/oneClickService.d.ts +3 -0
  20. package/dist/cjs/swappers/NearIntentsSwapper/utils/oneClickService.js +16 -0
  21. package/dist/cjs/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.js +55 -12
  22. package/dist/cjs/swappers/RelaySwapper/constant.js +1 -0
  23. package/dist/cjs/swappers/RelaySwapper/utils/fetchRelayTrade.d.ts +1 -1
  24. package/dist/cjs/swappers/RelaySwapper/utils/getRelayPsbtRelayer.js +2 -2
  25. package/dist/cjs/swappers/RelaySwapper/utils/getTrade.js +45 -0
  26. package/dist/cjs/swappers/RelaySwapper/utils/notifyTransactionIndexing.d.ts +1 -1
  27. package/dist/cjs/swappers/RelaySwapper/utils/relayTokenToAssetId.js +0 -2
  28. package/dist/cjs/swappers/RelaySwapper/utils/types.d.ts +1 -0
  29. package/dist/cjs/swappers/RelaySwapper/utils/types.js +1 -0
  30. package/dist/cjs/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +3153 -3153
  31. package/dist/cjs/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +6 -6
  32. package/dist/cjs/swappers/ZrxSwapper/utils/helpers/helpers.js +1 -3
  33. package/dist/cjs/thorchain-utils/getL1RateOrQuote.js +20 -17
  34. package/dist/cjs/types.d.ts +18 -1
  35. package/dist/cjs/types.js +1 -0
  36. package/dist/cjs/utils/tenderly/index.d.ts +3 -0
  37. package/dist/cjs/utils/tenderly/index.js +19 -0
  38. package/dist/cjs/utils/tenderly/simulate.d.ts +20 -0
  39. package/dist/cjs/utils/tenderly/simulate.js +109 -0
  40. package/dist/cjs/utils/tenderly/storageSlots.d.ts +8 -0
  41. package/dist/cjs/utils/tenderly/storageSlots.js +94 -0
  42. package/dist/cjs/utils/tenderly/types.d.ts +56 -0
  43. package/dist/cjs/utils/tenderly/types.js +2 -0
  44. package/dist/esm/.tsbuildinfo +1 -1
  45. package/dist/esm/constants.js +9 -0
  46. package/dist/esm/swappers/NearIntentsSwapper/NearIntentsSwapper.d.ts +2 -0
  47. package/dist/esm/swappers/NearIntentsSwapper/NearIntentsSwapper.js +8 -0
  48. package/dist/esm/swappers/NearIntentsSwapper/constants.d.ts +3 -0
  49. package/dist/esm/swappers/NearIntentsSwapper/constants.js +3 -0
  50. package/dist/esm/swappers/NearIntentsSwapper/endpoints.d.ts +2 -0
  51. package/dist/esm/swappers/NearIntentsSwapper/endpoints.js +162 -0
  52. package/dist/esm/swappers/NearIntentsSwapper/index.d.ts +4 -0
  53. package/dist/esm/swappers/NearIntentsSwapper/index.js +4 -0
  54. package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.d.ts +3 -0
  55. package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +205 -0
  56. package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.d.ts +3 -0
  57. package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +204 -0
  58. package/dist/esm/swappers/NearIntentsSwapper/types.d.ts +6 -0
  59. package/dist/esm/swappers/NearIntentsSwapper/types.js +28 -0
  60. package/dist/esm/swappers/NearIntentsSwapper/utils/helpers/helpers.d.ts +12 -0
  61. package/dist/esm/swappers/NearIntentsSwapper/utils/helpers/helpers.js +91 -0
  62. package/dist/esm/swappers/NearIntentsSwapper/utils/oneClickService.d.ts +3 -0
  63. package/dist/esm/swappers/NearIntentsSwapper/utils/oneClickService.js +12 -0
  64. package/dist/esm/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.js +59 -16
  65. package/dist/esm/swappers/RelaySwapper/constant.js +1 -0
  66. package/dist/esm/swappers/RelaySwapper/utils/fetchRelayTrade.d.ts +1 -1
  67. package/dist/esm/swappers/RelaySwapper/utils/getRelayPsbtRelayer.js +2 -2
  68. package/dist/esm/swappers/RelaySwapper/utils/getTrade.js +47 -2
  69. package/dist/esm/swappers/RelaySwapper/utils/notifyTransactionIndexing.d.ts +1 -1
  70. package/dist/esm/swappers/RelaySwapper/utils/relayTokenToAssetId.js +0 -2
  71. package/dist/esm/swappers/RelaySwapper/utils/types.d.ts +1 -0
  72. package/dist/esm/swappers/RelaySwapper/utils/types.js +1 -0
  73. package/dist/esm/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +3153 -3153
  74. package/dist/esm/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +6 -6
  75. package/dist/esm/swappers/ZrxSwapper/utils/helpers/helpers.js +1 -3
  76. package/dist/esm/thorchain-utils/getL1RateOrQuote.js +20 -17
  77. package/dist/esm/types.d.ts +18 -1
  78. package/dist/esm/types.js +1 -0
  79. package/dist/esm/utils/tenderly/index.d.ts +3 -0
  80. package/dist/esm/utils/tenderly/index.js +3 -0
  81. package/dist/esm/utils/tenderly/simulate.d.ts +20 -0
  82. package/dist/esm/utils/tenderly/simulate.js +102 -0
  83. package/dist/esm/utils/tenderly/storageSlots.d.ts +8 -0
  84. package/dist/esm/utils/tenderly/storageSlots.js +86 -0
  85. package/dist/esm/utils/tenderly/types.d.ts +56 -0
  86. package/dist/esm/utils/tenderly/types.js +1 -0
  87. package/package.json +31 -5
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTradeRate = void 0;
4
+ const caip_1 = require("@shapeshiftoss/caip");
5
+ const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
6
+ const utils_1 = require("@shapeshiftoss/utils");
7
+ const monads_1 = require("@sniptt/monads");
8
+ const uuid_1 = require("uuid");
9
+ const viem_1 = require("viem");
10
+ const constants_1 = require("../../../constants");
11
+ const types_1 = require("../../../types");
12
+ const utils_2 = require("../../../utils");
13
+ const tenderly_1 = require("../../../utils/tenderly");
14
+ const helpers_1 = require("../../utils/helpers/helpers");
15
+ const constants_2 = require("../constants");
16
+ const types_2 = require("../types");
17
+ const helpers_2 = require("../utils/helpers/helpers");
18
+ const oneClickService_1 = require("../utils/oneClickService");
19
+ const getTradeRate = async (input, deps) => {
20
+ const { sellAsset, buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, slippageTolerancePercentageDecimal, affiliateBps, sendAddress, receiveAddress, } = input;
21
+ try {
22
+ (0, oneClickService_1.initializeOneClickService)(deps.config.VITE_NEAR_INTENTS_API_KEY);
23
+ const originAsset = await (0, helpers_2.assetToNearIntentsAsset)(sellAsset);
24
+ const destinationAsset = await (0, helpers_2.assetToNearIntentsAsset)(buyAsset);
25
+ if (!(originAsset && destinationAsset)) {
26
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
27
+ code: types_1.TradeQuoteError.UnsupportedTradePair,
28
+ message: 'Unsupported asset',
29
+ }));
30
+ }
31
+ // Wallet connected: use actual addresses
32
+ // No wallet: use "check-price" sentinel with INTENTS types
33
+ const hasWallet = sendAddress !== undefined;
34
+ const quoteRequest = {
35
+ dry: false,
36
+ swapType: types_2.QuoteRequest.swapType.EXACT_INPUT,
37
+ slippageTolerance: slippageTolerancePercentageDecimal
38
+ ? (0, utils_1.bnOrZero)(slippageTolerancePercentageDecimal).times(10000).toNumber()
39
+ : constants_2.DEFAULT_SLIPPAGE_BPS,
40
+ originAsset,
41
+ destinationAsset,
42
+ amount: sellAmount,
43
+ depositType: types_2.QuoteRequest.depositType.ORIGIN_CHAIN,
44
+ refundTo: sendAddress ?? 'check-price',
45
+ refundType: hasWallet
46
+ ? types_2.QuoteRequest.refundType.ORIGIN_CHAIN
47
+ : types_2.QuoteRequest.refundType.INTENTS,
48
+ recipient: receiveAddress ?? 'check-price',
49
+ recipientType: hasWallet
50
+ ? types_2.QuoteRequest.recipientType.DESTINATION_CHAIN
51
+ : types_2.QuoteRequest.recipientType.INTENTS,
52
+ deadline: new Date(Date.now() + constants_2.DEFAULT_QUOTE_DEADLINE_MS).toISOString(),
53
+ referral: 'shapeshift',
54
+ appFees: [
55
+ {
56
+ recipient: utils_1.DAO_TREASURY_NEAR,
57
+ fee: Number(affiliateBps),
58
+ },
59
+ ],
60
+ };
61
+ const quoteResponse = await oneClickService_1.OneClickService.getQuote(quoteRequest);
62
+ const { quote } = quoteResponse;
63
+ if (!quote.depositAddress) {
64
+ throw new Error('Missing deposit address in quote response');
65
+ }
66
+ const { chainNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
67
+ const depositAddress = quote.depositAddress;
68
+ const getFeeData = async () => {
69
+ switch (chainNamespace) {
70
+ case caip_1.CHAIN_NAMESPACE.Evm: {
71
+ try {
72
+ const contractAddress = (0, utils_1.contractAddressOrUndefined)(sellAsset.assetId);
73
+ const data = chain_adapters_1.evm.getErc20Data(depositAddress, sellAmount, contractAddress);
74
+ const simulationResult = await (0, tenderly_1.simulateWithStateOverrides)({
75
+ chainId: sellAsset.chainId,
76
+ from: (0, viem_1.getAddress)(sendAddress || depositAddress),
77
+ to: (0, viem_1.getAddress)(contractAddress ?? depositAddress),
78
+ data: (data || '0x'),
79
+ value: (0, helpers_1.isNativeEvmAsset)(sellAsset.assetId) ? sellAmount : '0',
80
+ sellAsset,
81
+ }, {
82
+ apiKey: deps.config.VITE_TENDERLY_API_KEY,
83
+ accountSlug: deps.config.VITE_TENDERLY_ACCOUNT_SLUG,
84
+ projectSlug: deps.config.VITE_TENDERLY_PROJECT_SLUG,
85
+ });
86
+ if (!simulationResult.success) {
87
+ return '0';
88
+ }
89
+ // Calculate network fee using the simulated gas limit
90
+ const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
91
+ const { average } = await sellAdapter.getGasFeeData();
92
+ const supportsEIP1559 = 'maxFeePerGas' in average;
93
+ const networkFeeCryptoBaseUnit = chain_adapters_1.evm.calcNetworkFeeCryptoBaseUnit({
94
+ ...average,
95
+ supportsEIP1559,
96
+ gasLimit: simulationResult.gasLimit.toString(),
97
+ });
98
+ return networkFeeCryptoBaseUnit;
99
+ }
100
+ catch (error) {
101
+ return '0';
102
+ }
103
+ }
104
+ case caip_1.CHAIN_NAMESPACE.Utxo: {
105
+ const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId);
106
+ const pubkey = input.xpub;
107
+ if (!pubkey) {
108
+ return undefined;
109
+ }
110
+ const feeData = await sellAdapter.getFeeData({
111
+ to: depositAddress,
112
+ value: sellAmount,
113
+ chainSpecific: { pubkey },
114
+ sendMax: false,
115
+ });
116
+ return feeData.fast.txFee;
117
+ }
118
+ case caip_1.CHAIN_NAMESPACE.Solana: {
119
+ try {
120
+ const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
121
+ const tokenId = (0, utils_1.isToken)(sellAsset.assetId)
122
+ ? (0, caip_1.fromAssetId)(sellAsset.assetId).assetReference
123
+ : undefined;
124
+ if (!sendAddress) {
125
+ return '0';
126
+ }
127
+ const instructions = await sellAdapter.buildEstimationInstructions({
128
+ from: sendAddress,
129
+ to: depositAddress,
130
+ tokenId,
131
+ value: sellAmount,
132
+ });
133
+ const feeData = await sellAdapter.getFeeData({
134
+ to: depositAddress,
135
+ value: sellAmount,
136
+ chainSpecific: {
137
+ from: sendAddress,
138
+ tokenId,
139
+ instructions,
140
+ },
141
+ sendMax: false,
142
+ });
143
+ const txFee = feeData.fast.txFee;
144
+ const ataCreationCost = (0, helpers_2.calculateAccountCreationCosts)(instructions);
145
+ return (0, utils_1.bn)(txFee).plus(ataCreationCost).toString();
146
+ }
147
+ catch (error) {
148
+ return '0';
149
+ }
150
+ }
151
+ default:
152
+ return undefined;
153
+ }
154
+ };
155
+ const networkFeeCryptoBaseUnit = (await getFeeData()) || '0';
156
+ const rate = (0, utils_2.getInputOutputRate)({
157
+ sellAmountCryptoBaseUnit: quote.amountIn,
158
+ buyAmountCryptoBaseUnit: quote.amountOut,
159
+ sellAsset,
160
+ buyAsset,
161
+ });
162
+ const tradeRate = {
163
+ id: (0, uuid_1.v4)(),
164
+ receiveAddress: receiveAddress ?? undefined,
165
+ affiliateBps,
166
+ rate,
167
+ slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ??
168
+ (0, constants_1.getDefaultSlippageDecimalPercentageForSwapper)(types_1.SwapperName.NearIntents),
169
+ quoteOrRate: 'rate',
170
+ swapperName: types_1.SwapperName.NearIntents,
171
+ steps: [
172
+ {
173
+ accountNumber: undefined,
174
+ allowanceContract: '',
175
+ buyAmountBeforeFeesCryptoBaseUnit: quote.amountOut,
176
+ buyAmountAfterFeesCryptoBaseUnit: quote.amountOut,
177
+ buyAsset,
178
+ feeData: {
179
+ protocolFees: {},
180
+ networkFeeCryptoBaseUnit,
181
+ },
182
+ rate,
183
+ sellAmountIncludingProtocolFeesCryptoBaseUnit: quote.amountIn,
184
+ sellAsset,
185
+ source: types_1.SwapperName.NearIntents,
186
+ estimatedExecutionTimeMs: quote.timeEstimate ? quote.timeEstimate * 1000 : undefined,
187
+ },
188
+ ],
189
+ };
190
+ return (0, monads_1.Ok)([tradeRate]);
191
+ }
192
+ catch (error) {
193
+ if (error instanceof oneClickService_1.ApiError &&
194
+ (error.body?.message === 'tokenIn is not valid' ||
195
+ error.body?.message === 'tokenOut is not valid')) {
196
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
197
+ code: types_1.TradeQuoteError.UnsupportedTradePair,
198
+ message: 'Unsupported asset',
199
+ }));
200
+ }
201
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
202
+ message: error instanceof Error ? error.message : 'Unknown error getting NEAR Intents rate',
203
+ code: types_1.TradeQuoteError.QueryFailed,
204
+ cause: error,
205
+ }));
206
+ }
207
+ };
208
+ exports.getTradeRate = getTradeRate;
@@ -0,0 +1,6 @@
1
+ import { KnownChainIds } from '@shapeshiftoss/types';
2
+ export { QuoteRequest } from '@defuse-protocol/one-click-sdk-typescript';
3
+ export type { QuoteResponse, GetExecutionStatusResponse, TokenResponse, } from '@defuse-protocol/one-click-sdk-typescript';
4
+ export declare const nearIntentsSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BaseMainnet, KnownChainIds.GnosisMainnet, KnownChainIds.BnbSmartChainMainnet, KnownChainIds.PolygonMainnet, KnownChainIds.AvalancheMainnet, KnownChainIds.OptimismMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.DogecoinMainnet, KnownChainIds.SolanaMainnet];
5
+ export type NearIntentsSupportedChainId = (typeof nearIntentsSupportedChainIds)[number];
6
+ export declare const chainIdToNearIntentsChain: Record<NearIntentsSupportedChainId, string>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chainIdToNearIntentsChain = exports.nearIntentsSupportedChainIds = exports.QuoteRequest = void 0;
4
+ const types_1 = require("@shapeshiftoss/types");
5
+ var one_click_sdk_typescript_1 = require("@defuse-protocol/one-click-sdk-typescript");
6
+ Object.defineProperty(exports, "QuoteRequest", { enumerable: true, get: function () { return one_click_sdk_typescript_1.QuoteRequest; } });
7
+ exports.nearIntentsSupportedChainIds = [
8
+ types_1.KnownChainIds.EthereumMainnet,
9
+ types_1.KnownChainIds.ArbitrumMainnet,
10
+ types_1.KnownChainIds.BaseMainnet,
11
+ types_1.KnownChainIds.GnosisMainnet,
12
+ types_1.KnownChainIds.BnbSmartChainMainnet,
13
+ types_1.KnownChainIds.PolygonMainnet,
14
+ types_1.KnownChainIds.AvalancheMainnet,
15
+ types_1.KnownChainIds.OptimismMainnet,
16
+ types_1.KnownChainIds.BitcoinMainnet,
17
+ types_1.KnownChainIds.DogecoinMainnet,
18
+ types_1.KnownChainIds.SolanaMainnet,
19
+ ];
20
+ exports.chainIdToNearIntentsChain = {
21
+ [types_1.KnownChainIds.EthereumMainnet]: 'eth',
22
+ [types_1.KnownChainIds.ArbitrumMainnet]: 'arb',
23
+ [types_1.KnownChainIds.BaseMainnet]: 'base',
24
+ [types_1.KnownChainIds.GnosisMainnet]: 'gnosis',
25
+ [types_1.KnownChainIds.BnbSmartChainMainnet]: 'bsc',
26
+ [types_1.KnownChainIds.PolygonMainnet]: 'pol',
27
+ [types_1.KnownChainIds.AvalancheMainnet]: 'avax',
28
+ [types_1.KnownChainIds.OptimismMainnet]: 'op',
29
+ [types_1.KnownChainIds.BitcoinMainnet]: 'btc',
30
+ [types_1.KnownChainIds.DogecoinMainnet]: 'doge',
31
+ [types_1.KnownChainIds.SolanaMainnet]: 'sol',
32
+ };
@@ -0,0 +1,12 @@
1
+ import type { Asset } from '@shapeshiftoss/types';
2
+ import { TxStatus } from '@shapeshiftoss/unchained-client';
3
+ import type { TransactionInstruction } from '@solana/web3.js';
4
+ import type { GetExecutionStatusResponse } from '../../types';
5
+ export declare const calculateAccountCreationCosts: (instructions: TransactionInstruction[]) => string;
6
+ export declare const getNearIntentsAsset: ({ nearNetwork, contractAddress, }: {
7
+ nearNetwork: string;
8
+ contractAddress: string;
9
+ }) => string;
10
+ export declare const assetToNearIntentsAsset: (asset: Asset) => Promise<string | null>;
11
+ export declare const mapNearIntentsStatus: (status: GetExecutionStatusResponse['status']) => TxStatus;
12
+ export declare const getNearIntentsStatusMessage: (status: GetExecutionStatusResponse['status']) => string | undefined;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNearIntentsStatusMessage = exports.mapNearIntentsStatus = exports.assetToNearIntentsAsset = exports.getNearIntentsAsset = exports.calculateAccountCreationCosts = void 0;
4
+ const token_1 = require("@coral-xyz/anchor/dist/cjs/utils/token");
5
+ const caip_1 = require("@shapeshiftoss/caip");
6
+ const unchained_client_1 = require("@shapeshiftoss/unchained-client");
7
+ const utils_1 = require("@shapeshiftoss/utils");
8
+ const viem_1 = require("viem");
9
+ const types_1 = require("../../types");
10
+ const oneClickService_1 = require("../oneClickService");
11
+ const ATA_RENT_LAMPORTS = 2040000;
12
+ const calculateAccountCreationCosts = (instructions) => {
13
+ let totalCost = (0, utils_1.bnOrZero)(0);
14
+ for (const ix of instructions) {
15
+ if (ix.programId.toString() === token_1.ASSOCIATED_PROGRAM_ID.toString()) {
16
+ totalCost = totalCost.plus(ATA_RENT_LAMPORTS);
17
+ }
18
+ }
19
+ return totalCost.toString();
20
+ };
21
+ exports.calculateAccountCreationCosts = calculateAccountCreationCosts;
22
+ const getNearIntentsAsset = ({ nearNetwork, contractAddress, }) => {
23
+ // Native EVM assets: "nep141:eth.omft.near"
24
+ if (contractAddress === viem_1.zeroAddress) {
25
+ return `nep141:${nearNetwork}.omft.near`;
26
+ }
27
+ // ERC20 tokens: "nep141:eth-0x{address}.omft.near"
28
+ return `nep141:${nearNetwork}-${contractAddress.toLowerCase()}.omft.near`;
29
+ };
30
+ exports.getNearIntentsAsset = getNearIntentsAsset;
31
+ const NEP245_CHAINS = ['bsc', 'pol', 'avax', 'op'];
32
+ const assetToNearIntentsAsset = async (asset) => {
33
+ const nearNetwork = types_1.chainIdToNearIntentsChain[asset.chainId];
34
+ if (!nearNetwork)
35
+ return null;
36
+ // NEP-245 chains (BSC, Polygon, Avalanche, Optimism) and Solana require token lookup
37
+ // Asset IDs use hashed format that can't be generated from contract addresses
38
+ const requiresLookup = NEP245_CHAINS.includes(nearNetwork) || asset.chainId === caip_1.solanaChainId;
39
+ if (requiresLookup) {
40
+ const tokens = await oneClickService_1.OneClickService.getTokens();
41
+ const contractAddress = (0, utils_1.isToken)(asset.assetId)
42
+ ? (0, caip_1.fromAssetId)(asset.assetId).assetReference.toLowerCase()
43
+ : null;
44
+ const match = tokens.find((t) => {
45
+ if (t.blockchain !== nearNetwork)
46
+ return false;
47
+ return contractAddress
48
+ ? t.contractAddress?.toLowerCase() === contractAddress
49
+ : !t.contractAddress;
50
+ });
51
+ if (!match)
52
+ return null;
53
+ return match.assetId;
54
+ }
55
+ // NEP-141 chains (ETH, ARB, BASE, GNOSIS, BTC, DOGE): use predictable format
56
+ const contractAddress = (0, utils_1.isToken)(asset.assetId)
57
+ ? (0, caip_1.fromAssetId)(asset.assetId).assetReference
58
+ : viem_1.zeroAddress;
59
+ return (0, exports.getNearIntentsAsset)({ nearNetwork, contractAddress });
60
+ };
61
+ exports.assetToNearIntentsAsset = assetToNearIntentsAsset;
62
+ const mapNearIntentsStatus = (status) => {
63
+ switch (status) {
64
+ case 'PENDING_DEPOSIT':
65
+ case 'KNOWN_DEPOSIT_TX':
66
+ case 'PROCESSING':
67
+ return unchained_client_1.TxStatus.Pending;
68
+ case 'SUCCESS':
69
+ return unchained_client_1.TxStatus.Confirmed;
70
+ case 'INCOMPLETE_DEPOSIT':
71
+ case 'REFUNDED':
72
+ case 'FAILED':
73
+ return unchained_client_1.TxStatus.Failed;
74
+ default:
75
+ return unchained_client_1.TxStatus.Unknown;
76
+ }
77
+ };
78
+ exports.mapNearIntentsStatus = mapNearIntentsStatus;
79
+ const getNearIntentsStatusMessage = (status) => {
80
+ switch (status) {
81
+ case 'PENDING_DEPOSIT':
82
+ return 'Waiting for deposit...';
83
+ case 'KNOWN_DEPOSIT_TX':
84
+ return 'Deposit detected, waiting for confirmation...';
85
+ case 'PROCESSING':
86
+ return 'Processing swap...';
87
+ case 'SUCCESS':
88
+ return undefined;
89
+ case 'INCOMPLETE_DEPOSIT':
90
+ return 'Insufficient deposit amount';
91
+ case 'REFUNDED':
92
+ return 'Swap failed, funds refunded';
93
+ case 'FAILED':
94
+ return 'Swap failed';
95
+ default:
96
+ return 'Unknown status';
97
+ }
98
+ };
99
+ exports.getNearIntentsStatusMessage = getNearIntentsStatusMessage;
@@ -0,0 +1,3 @@
1
+ import { ApiError, OneClickService } from '@defuse-protocol/one-click-sdk-typescript';
2
+ export declare const initializeOneClickService: (apiKey: string) => void;
3
+ export { ApiError, OneClickService };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OneClickService = exports.ApiError = exports.initializeOneClickService = void 0;
4
+ const one_click_sdk_typescript_1 = require("@defuse-protocol/one-click-sdk-typescript");
5
+ Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return one_click_sdk_typescript_1.ApiError; } });
6
+ Object.defineProperty(exports, "OneClickService", { enumerable: true, get: function () { return one_click_sdk_typescript_1.OneClickService; } });
7
+ const constants_1 = require("../constants");
8
+ let isInitialized = false;
9
+ const initializeOneClickService = (apiKey) => {
10
+ if (isInitialized)
11
+ return;
12
+ one_click_sdk_typescript_1.OpenAPI.BASE = constants_1.ONE_CLICK_BASE_URL;
13
+ one_click_sdk_typescript_1.OpenAPI.TOKEN = apiKey;
14
+ isInitialized = true;
15
+ };
16
+ exports.initializeOneClickService = initializeOneClickService;
@@ -10,12 +10,13 @@ const viem_1 = require("viem");
10
10
  const __1 = require("../../..");
11
11
  const types_1 = require("../../../types");
12
12
  const utils_2 = require("../../../utils");
13
+ const tenderly_1 = require("../../../utils/tenderly");
13
14
  const helpers_1 = require("../../utils/helpers/helpers");
14
15
  const constants_1 = require("../constants");
15
16
  const fetchPortalsTradeOrder_1 = require("../utils/fetchPortalsTradeOrder");
16
17
  const helpers_2 = require("../utils/helpers");
17
18
  async function getPortalsTradeRate(input, assertGetEvmChainAdapter, swapperConfig) {
18
- const { sellAsset, buyAsset, accountNumber, affiliateBps, chainId, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, } = input;
19
+ const { sellAsset, buyAsset, accountNumber, affiliateBps, chainId, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, supportsEIP1559, } = input;
19
20
  const adapter = assertGetEvmChainAdapter(chainId);
20
21
  const sellAssetChainId = sellAsset.chainId;
21
22
  const buyAssetChainId = buyAsset.chainId;
@@ -64,16 +65,32 @@ async function getPortalsTradeRate(input, assertGetEvmChainAdapter, swapperConfi
64
65
  : (0, utils_1.bnOrZero)((0, __1.getDefaultSlippageDecimalPercentageForSwapper)(types_1.SwapperName.Portals))
65
66
  .times(100)
66
67
  .toNumber();
67
- const quoteEstimateResponse = await (0, fetchPortalsTradeOrder_1.fetchPortalsTradeEstimate)({
68
+ // Calculate affiliate fee percentage (e.g., 55 bps = 0.55%)
69
+ const affiliateBpsPercentage = (0, utils_1.convertBasisPointsToDecimalPercentage)(affiliateBps)
70
+ .times(100)
71
+ .toNumber();
72
+ // Dummy address for rates (no wallet connected yet)
73
+ // Using Vitalik's address as a realistic test address (same approach as Bebop)
74
+ const RATE_DUMMY_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045';
75
+ // Use full quote endpoint (not estimate) to get transaction data for Tenderly simulation
76
+ // Skip validation since this is just a rate quote
77
+ const quoteResponse = await (0, fetchPortalsTradeOrder_1.fetchPortalsTradeOrder)({
78
+ sender: RATE_DUMMY_ADDRESS,
68
79
  inputToken,
69
80
  outputToken,
70
81
  inputAmount: sellAmountIncludingProtocolFeesCryptoBaseUnit,
71
82
  slippageTolerancePercentage: userSlippageTolerancePercentageDecimalOrDefault,
83
+ partner: (0, helpers_1.getTreasuryAddressFromChainId)(chainId),
84
+ feePercentage: affiliateBpsPercentage,
85
+ validate: false,
72
86
  swapperConfig,
73
87
  });
74
- // Estimate has no protocol fees, so after-fees = expected output amount
75
- const buyAmountAfterFeesCryptoBaseUnit = quoteEstimateResponse.outputAmount;
76
- // Use the quote estimate endpoint to get a quote without a wallet
88
+ if (!quoteResponse.tx) {
89
+ throw new Error('Portals quote response missing transaction data');
90
+ }
91
+ const { context, tx } = quoteResponse;
92
+ // Use outputAmount from context, not estimate
93
+ const buyAmountAfterFeesCryptoBaseUnit = context.outputAmount;
77
94
  const inputOutputRate = (0, utils_2.getInputOutputRate)({
78
95
  sellAmountCryptoBaseUnit: input.sellAmountIncludingProtocolFeesCryptoBaseUnit,
79
96
  buyAmountCryptoBaseUnit: buyAmountAfterFeesCryptoBaseUnit,
@@ -83,21 +100,47 @@ async function getPortalsTradeRate(input, assertGetEvmChainAdapter, swapperConfi
83
100
  const allowanceContract = (0, helpers_2.getPortalsRouterAddressByChainId)(chainId);
84
101
  // Don't use Portals' slippageTolerancePercentage field (it's a price indicator, not actual buffer)
85
102
  // Instead, calculate the actual buffer Portals applied from the amounts
86
- const actualBufferDecimal = (0, utils_1.bnOrZero)(quoteEstimateResponse.outputAmount)
87
- .minus(quoteEstimateResponse.minOutputAmount)
88
- .div(quoteEstimateResponse.outputAmount)
103
+ const actualBufferDecimal = (0, utils_1.bnOrZero)(context.outputAmount)
104
+ .minus(context.minOutputAmount)
105
+ .div(context.outputAmount)
89
106
  .toString();
90
107
  // Reverse the buffer to recover the expected output (minOutput / (1 - buffer) = output)
91
- const buyAmountBeforeSlippageCryptoBaseUnit = (0, utils_1.bnOrZero)(quoteEstimateResponse.minOutputAmount)
108
+ const buyAmountBeforeSlippageCryptoBaseUnit = (0, utils_1.bnOrZero)(context.minOutputAmount)
92
109
  .div((0, utils_1.bn)(1).minus(actualBufferDecimal))
93
110
  .toFixed(0);
94
111
  const slippageTolerancePercentageDecimal = actualBufferDecimal;
95
- const gasLimit = quoteEstimateResponse.context.gasLimit;
112
+ const gasLimit = await (async () => {
113
+ const tenderlySimulation = await (0, tenderly_1.simulateWithStateOverrides)({
114
+ chainId: sellAsset.chainId,
115
+ from: tx.from,
116
+ to: tx.to,
117
+ data: tx.data,
118
+ value: tx.value,
119
+ sellAsset,
120
+ spenderAddress: (0, viem_1.getAddress)(context.target),
121
+ }, {
122
+ apiKey: swapperConfig.VITE_TENDERLY_API_KEY,
123
+ accountSlug: swapperConfig.VITE_TENDERLY_ACCOUNT_SLUG,
124
+ projectSlug: swapperConfig.VITE_TENDERLY_PROJECT_SLUG,
125
+ });
126
+ if (tenderlySimulation.success) {
127
+ return tenderlySimulation.gasLimit.toString();
128
+ }
129
+ // Fallback to estimate endpoint (i.e simulation with overrides failed, but Portals still able to do their magic here)
130
+ const quoteEstimateResponse = await (0, fetchPortalsTradeOrder_1.fetchPortalsTradeEstimate)({
131
+ inputToken,
132
+ outputToken,
133
+ inputAmount: sellAmountIncludingProtocolFeesCryptoBaseUnit,
134
+ slippageTolerancePercentage: userSlippageTolerancePercentageDecimalOrDefault,
135
+ swapperConfig,
136
+ });
137
+ return quoteEstimateResponse.context.gasLimit.toString();
138
+ })();
96
139
  const { average } = await adapter.getGasFeeData();
97
140
  const networkFeeCryptoBaseUnit = chain_adapters_1.evm.calcNetworkFeeCryptoBaseUnit({
98
141
  ...average,
99
- supportsEIP1559: Boolean(input.supportsEIP1559),
100
- gasLimit: gasLimit.toString(),
142
+ supportsEIP1559: Boolean(supportsEIP1559),
143
+ gasLimit,
101
144
  });
102
145
  const tradeRate = {
103
146
  id: (0, uuid_1.v4)(),
@@ -55,6 +55,7 @@ exports.DEFAULT_RELAY_SOLANA_USER_ADDRESS = 'CbKGgVKLJFb8bBrf58DnAkdryX6ubewVytn
55
55
  exports.MAXIMUM_SUPPORTED_RELAY_STEPS = 2;
56
56
  exports.relayErrorCodeToTradeQuoteError = {
57
57
  [types_3.RelayErrorCode.AmountTooLow]: types_2.TradeQuoteError.SellAmountBelowMinimum,
58
+ [types_3.RelayErrorCode.ChainDisabled]: types_2.TradeQuoteError.TradingHalted,
58
59
  [types_3.RelayErrorCode.Erc20RouterAddressNotFound]: types_2.TradeQuoteError.UnsupportedTradePair,
59
60
  [types_3.RelayErrorCode.ExtraTransactionsNotSupported]: types_2.TradeQuoteError.UnsupportedTradePair,
60
61
  [types_3.RelayErrorCode.InsufficientFunds]: types_2.TradeQuoteError.SellAmountBelowTradeFee,
@@ -1,5 +1,5 @@
1
1
  import type { Result } from '@sniptt/monads';
2
2
  import type { AxiosResponse } from 'axios';
3
- import type { SwapErrorRight, SwapperConfig } from 'packages/swapper/src/types';
3
+ import type { SwapErrorRight, SwapperConfig } from '../../../types';
4
4
  import type { RelayFetchQuoteParams, RelayQuote } from './types';
5
5
  export declare const fetchRelayTrade: <T extends "rate" | "quote">(params: RelayFetchQuoteParams<T>, config: SwapperConfig) => Promise<Result<AxiosResponse<RelayQuote, any>, SwapErrorRight>>;
@@ -27,7 +27,7 @@ exports.getRelayPsbtRelayer = void 0;
27
27
  const bitcoin = __importStar(require("@shapeshiftoss/bitcoinjs-lib"));
28
28
  const getRelayPsbtRelayer = (psbtHex, sellAmountCryptoBaseUnit) => {
29
29
  const psbtBuffer = Buffer.from(psbtHex, 'hex');
30
- const psbt = bitcoin.Psbt.fromBuffer(new Uint8Array(psbtBuffer));
30
+ const psbt = bitcoin.Psbt.fromBuffer(psbtBuffer);
31
31
  const outputs = psbt.txOutputs;
32
32
  for (let i = 0; i < outputs.length; i++) {
33
33
  const output = outputs[i];
@@ -35,7 +35,7 @@ const getRelayPsbtRelayer = (psbtHex, sellAmountCryptoBaseUnit) => {
35
35
  try {
36
36
  const address = bitcoin.address.fromOutputScript(script);
37
37
  // Assuming the destination address is the one with the exact amount of sellAmountCryptoBaseUnit
38
- if (output.value === BigInt(sellAmountCryptoBaseUnit)) {
38
+ if (output.value === Number(sellAmountCryptoBaseUnit)) {
39
39
  return address;
40
40
  }
41
41
  }
@@ -13,6 +13,7 @@ const axios_1 = __importDefault(require("axios"));
13
13
  const viem_1 = require("viem");
14
14
  const types_1 = require("../../../types");
15
15
  const utils_2 = require("../../../utils");
16
+ const tenderly_1 = require("../../../utils/tenderly");
16
17
  const helpers_1 = require("../../utils/helpers/helpers");
17
18
  const constant_1 = require("../constant");
18
19
  const getRelayAssetAddress_1 = require("../utils/getRelayAssetAddress");
@@ -132,6 +133,11 @@ async function getTrade({ input, deps, relayChainMap, }) {
132
133
  code: tradeQuoteErrorCode,
133
134
  }));
134
135
  }
136
+ // Fallback for unmapped error codes (shouldn't happen, but prevents crashes)
137
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
138
+ message: relayError.message || 'Unknown Relay error',
139
+ code: types_1.TradeQuoteError.UnknownError,
140
+ }));
135
141
  }
136
142
  const { data: quote } = maybeQuote.unwrap();
137
143
  const { slippageTolerance, currencyOut, timeEstimate } = quote.details;
@@ -333,6 +339,45 @@ async function getTrade({ input, deps, relayChainMap, }) {
333
339
  const feeData = await adapter.getFeeData(getFeeDataInput);
334
340
  return feeData.fast.txFee;
335
341
  }
342
+ // Use Tenderly simulation with state overrides for EVM chains
343
+ if ((0, chain_adapters_1.isEvmChainId)(sellAsset.chainId)) {
344
+ const firstStep = swapSteps[0];
345
+ const selectedItem = firstStep?.items?.[0];
346
+ if (selectedItem?.data && (0, types_2.isRelayQuoteEvmItemData)(selectedItem.data)) {
347
+ try {
348
+ const tenderlySimulation = await (0, tenderly_1.simulateWithStateOverrides)({
349
+ chainId: sellAsset.chainId,
350
+ // NOTE: zeroAddress is here purely for the purpose of satisfying the type sistem
351
+ // That should never happen
352
+ from: (0, viem_1.getAddress)(sendAddress ?? viem_1.zeroAddress),
353
+ to: (0, viem_1.getAddress)(selectedItem.data.to ?? viem_1.zeroAddress),
354
+ data: (selectedItem.data.data ?? '0x'),
355
+ value: selectedItem.data.value ?? '0',
356
+ sellAsset,
357
+ }, {
358
+ apiKey: deps.config.VITE_TENDERLY_API_KEY,
359
+ accountSlug: deps.config.VITE_TENDERLY_ACCOUNT_SLUG,
360
+ projectSlug: deps.config.VITE_TENDERLY_PROJECT_SLUG,
361
+ });
362
+ if (tenderlySimulation.success) {
363
+ // Use Tenderly's gas estimate instead of Relay's
364
+ const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
365
+ const { average } = await adapter.getGasFeeData();
366
+ const supportsEIP1559 = 'maxFeePerGas' in average;
367
+ const tenderlyNetworkFee = chain_adapters_1.evm.calcNetworkFeeCryptoBaseUnit({
368
+ ...average,
369
+ supportsEIP1559,
370
+ gasLimit: tenderlySimulation.gasLimit.toString(),
371
+ });
372
+ return tenderlyNetworkFee;
373
+ }
374
+ }
375
+ catch (error) {
376
+ // Silently fall through to use Relay's gas estimate
377
+ }
378
+ }
379
+ }
380
+ // Fallback to Relay's gas amount
336
381
  return quote.fees.gas.amount;
337
382
  })();
338
383
  const steps = swapSteps.map((quoteStep) => {
@@ -1,6 +1,6 @@
1
1
  import type { Result } from '@sniptt/monads';
2
2
  import type { AxiosResponse } from 'axios';
3
- import type { SwapErrorRight, SwapperConfig } from 'packages/swapper/src/types';
3
+ import type { SwapErrorRight, SwapperConfig } from '../../../types';
4
4
  import type { RelayQuote } from './types';
5
5
  type NotifyTransactionIndexingParams = {
6
6
  requestId: string;
@@ -23,8 +23,6 @@ const relayTokenToAssetId = (relayToken) => {
23
23
  if (!isNativeAsset) {
24
24
  const assetNamespace = (() => {
25
25
  switch (true) {
26
- case caip_1.CHAIN_REFERENCE.BnbSmartChainMainnet === chainReference:
27
- return caip_1.ASSET_NAMESPACE.bep20;
28
26
  case (0, chain_adapters_1.isEvmChainId)(chainId):
29
27
  return caip_1.ASSET_NAMESPACE.erc20;
30
28
  case caip_1.CHAIN_REFERENCE.SolanaMainnet === chainReference:
@@ -131,6 +131,7 @@ export type RelaySolanaInstruction = {
131
131
  };
132
132
  export declare enum RelayErrorCode {
133
133
  AmountTooLow = "AMOUNT_TOO_LOW",
134
+ ChainDisabled = "CHAIN_DISABLED",
134
135
  Erc20RouterAddressNotFound = "ERC20_ROUTER_ADDRESS_NOT_FOUND",
135
136
  ExtraTransactionsNotSupported = "EXTRA_TXS_NOT_SUPPORTED",
136
137
  InsufficientFunds = "INSUFFICIENT_FUNDS",
@@ -16,6 +16,7 @@ exports.isRelayQuoteSolanaItemData = isRelayQuoteSolanaItemData;
16
16
  var RelayErrorCode;
17
17
  (function (RelayErrorCode) {
18
18
  RelayErrorCode["AmountTooLow"] = "AMOUNT_TOO_LOW";
19
+ RelayErrorCode["ChainDisabled"] = "CHAIN_DISABLED";
19
20
  RelayErrorCode["Erc20RouterAddressNotFound"] = "ERC20_ROUTER_ADDRESS_NOT_FOUND";
20
21
  RelayErrorCode["ExtraTransactionsNotSupported"] = "EXTRA_TXS_NOT_SUPPORTED";
21
22
  RelayErrorCode["InsufficientFunds"] = "INSUFFICIENT_FUNDS";