@shapeshiftoss/swapper 17.6.11 → 17.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/constants.js +16 -26
  3. package/dist/cjs/index.d.ts +0 -1
  4. package/dist/cjs/index.js +0 -1
  5. package/dist/cjs/solana-utils/getUnsignedSolanaTransaction.js +4 -2
  6. package/dist/cjs/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +3 -1
  7. package/dist/cjs/swappers/ChainflipSwapper/endpoints.js +14 -4
  8. package/dist/cjs/swappers/ChainflipSwapper/types.d.ts +1 -0
  9. package/dist/cjs/swappers/DebridgeSwapper/utils/fetchDebridgeTrade.d.ts +1 -1
  10. package/dist/cjs/swappers/DebridgeSwapper/utils/getTrade.js +7 -9
  11. package/dist/cjs/swappers/RelaySwapper/constant.js +3 -7
  12. package/dist/cjs/swappers/RelaySwapper/endpoints.js +1 -1
  13. package/dist/cjs/swappers/RelaySwapper/utils/getTrade.js +12 -2
  14. package/dist/cjs/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
  15. package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +2 -1
  16. package/dist/cjs/tron-utils/getUnsignedTronTransaction.js +16 -0
  17. package/dist/cjs/types.d.ts +3 -6
  18. package/dist/cjs/types.js +0 -1
  19. package/dist/cjs/utils.d.ts +3 -0
  20. package/dist/cjs/utils.js +9 -3
  21. package/dist/esm/.tsbuildinfo +1 -1
  22. package/dist/esm/constants.js +0 -10
  23. package/dist/esm/index.d.ts +0 -1
  24. package/dist/esm/index.js +0 -1
  25. package/dist/esm/solana-utils/getUnsignedSolanaTransaction.js +3 -1
  26. package/dist/esm/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +3 -1
  27. package/dist/esm/swappers/ChainflipSwapper/endpoints.js +14 -4
  28. package/dist/esm/swappers/ChainflipSwapper/types.d.ts +1 -0
  29. package/dist/esm/swappers/DebridgeSwapper/utils/fetchDebridgeTrade.d.ts +1 -1
  30. package/dist/esm/swappers/DebridgeSwapper/utils/getTrade.js +7 -9
  31. package/dist/esm/swappers/RelaySwapper/constant.js +4 -8
  32. package/dist/esm/swappers/RelaySwapper/endpoints.js +2 -2
  33. package/dist/esm/swappers/RelaySwapper/utils/getTrade.js +13 -3
  34. package/dist/esm/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
  35. package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +2 -1
  36. package/dist/esm/tron-utils/getUnsignedTronTransaction.js +16 -0
  37. package/dist/esm/types.d.ts +3 -6
  38. package/dist/esm/types.js +0 -1
  39. package/dist/esm/utils.d.ts +3 -0
  40. package/dist/esm/utils.js +7 -2
  41. package/package.json +6 -7
  42. package/dist/cjs/swappers/JupiterSwapper/JupiterSwapper.d.ts +0 -2
  43. package/dist/cjs/swappers/JupiterSwapper/JupiterSwapper.js +0 -27
  44. package/dist/cjs/swappers/JupiterSwapper/endpoints.d.ts +0 -2
  45. package/dist/cjs/swappers/JupiterSwapper/endpoints.js +0 -15
  46. package/dist/cjs/swappers/JupiterSwapper/errorPatterns.d.ts +0 -15
  47. package/dist/cjs/swappers/JupiterSwapper/errorPatterns.js +0 -29
  48. package/dist/cjs/swappers/JupiterSwapper/idls/referral.d.ts +0 -739
  49. package/dist/cjs/swappers/JupiterSwapper/idls/referral.js +0 -741
  50. package/dist/cjs/swappers/JupiterSwapper/index.d.ts +0 -2
  51. package/dist/cjs/swappers/JupiterSwapper/index.js +0 -18
  52. package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeQuote.d.ts +0 -3
  53. package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeQuote.js +0 -223
  54. package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeRate.d.ts +0 -3
  55. package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeRate.js +0 -181
  56. package/dist/cjs/swappers/JupiterSwapper/utils/constants.d.ts +0 -9
  57. package/dist/cjs/swappers/JupiterSwapper/utils/constants.js +0 -14
  58. package/dist/cjs/swappers/JupiterSwapper/utils/helpers.d.ts +0 -56
  59. package/dist/cjs/swappers/JupiterSwapper/utils/helpers.js +0 -178
  60. package/dist/cjs/swappers/JupiterSwapper/utils/jupiterService.d.ts +0 -5
  61. package/dist/cjs/swappers/JupiterSwapper/utils/jupiterService.js +0 -15
  62. package/dist/esm/swappers/JupiterSwapper/JupiterSwapper.d.ts +0 -2
  63. package/dist/esm/swappers/JupiterSwapper/JupiterSwapper.js +0 -24
  64. package/dist/esm/swappers/JupiterSwapper/endpoints.d.ts +0 -2
  65. package/dist/esm/swappers/JupiterSwapper/endpoints.js +0 -12
  66. package/dist/esm/swappers/JupiterSwapper/errorPatterns.d.ts +0 -15
  67. package/dist/esm/swappers/JupiterSwapper/errorPatterns.js +0 -25
  68. package/dist/esm/swappers/JupiterSwapper/idls/referral.d.ts +0 -739
  69. package/dist/esm/swappers/JupiterSwapper/idls/referral.js +0 -738
  70. package/dist/esm/swappers/JupiterSwapper/index.d.ts +0 -2
  71. package/dist/esm/swappers/JupiterSwapper/index.js +0 -2
  72. package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeQuote.d.ts +0 -3
  73. package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeQuote.js +0 -219
  74. package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeRate.d.ts +0 -3
  75. package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeRate.js +0 -177
  76. package/dist/esm/swappers/JupiterSwapper/utils/constants.d.ts +0 -9
  77. package/dist/esm/swappers/JupiterSwapper/utils/constants.js +0 -11
  78. package/dist/esm/swappers/JupiterSwapper/utils/helpers.d.ts +0 -56
  79. package/dist/esm/swappers/JupiterSwapper/utils/helpers.js +0 -169
  80. package/dist/esm/swappers/JupiterSwapper/utils/jupiterService.d.ts +0 -5
  81. package/dist/esm/swappers/JupiterSwapper/utils/jupiterService.js +0 -12
@@ -1,2 +0,0 @@
1
- export * from './utils/constants.js';
2
- export * from './errorPatterns.js';
@@ -1,2 +0,0 @@
1
- export * from './utils/constants.js';
2
- export * from './errorPatterns.js';
@@ -1,3 +0,0 @@
1
- import type { Result } from '@sniptt/monads';
2
- import type { CommonTradeQuoteInput, SwapErrorRight, SwapperDeps, TradeQuote } from '../../../types.js';
3
- export declare const getTradeQuote: (input: CommonTradeQuoteInput, deps: SwapperDeps) => Promise<Result<TradeQuote[], SwapErrorRight>>;
@@ -1,219 +0,0 @@
1
- import { ASSET_NAMESPACE, CHAIN_NAMESPACE, CHAIN_REFERENCE, fromAssetId, solAssetId, toAssetId, wrappedSolAssetId, } from '@shapeshiftoss/caip';
2
- import { bn, bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils';
3
- import { Err, Ok } from '@sniptt/monads';
4
- import { AddressLookupTableAccount, MessageV0, PublicKey, VersionedTransaction, } from '@solana/web3.js';
5
- import { v4 as uuid } from 'uuid';
6
- import { SwapperName, TradeQuoteError } from '../../../types.js';
7
- import { getInputOutputRate, makeSwapErrorRight } from '../../../utils.js';
8
- import { buildAffiliateFee } from '../../utils/affiliateFee.js';
9
- import { COMPUTE_UNIT_MARGIN_MULTIPLIER, TOKEN_2022_PROGRAM_ID } from '../utils/constants.js';
10
- import { calculateAccountCreationCosts, createSwapInstructions, getJupiterPrice, isSupportedChainId, } from '../utils/helpers.js';
11
- export const getTradeQuote = async (input, deps) => {
12
- const { sellAsset, buyAsset, receiveAddress, accountNumber, sendAddress, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, } = input;
13
- const { assetsById } = deps;
14
- const jupiterUrl = deps.config.VITE_JUPITER_API_URL;
15
- const solAsset = assetsById[solAssetId];
16
- if (accountNumber === undefined) {
17
- return Err(makeSwapErrorRight({
18
- message: `accountNumber is required`,
19
- code: TradeQuoteError.UnknownError,
20
- }));
21
- }
22
- if (!isSupportedChainId(sellAsset.chainId)) {
23
- return Err(makeSwapErrorRight({
24
- message: `unsupported chainId`,
25
- code: TradeQuoteError.UnsupportedChain,
26
- details: { chainId: sellAsset.chainId },
27
- }));
28
- }
29
- if (!isSupportedChainId(buyAsset.chainId)) {
30
- return Err(makeSwapErrorRight({
31
- message: `unsupported chainId`,
32
- code: TradeQuoteError.UnsupportedChain,
33
- details: { chainId: sellAsset.chainId },
34
- }));
35
- }
36
- if (!sendAddress) {
37
- return Err(makeSwapErrorRight({
38
- message: `sendAddress is required`,
39
- code: TradeQuoteError.UnknownError,
40
- }));
41
- }
42
- if (!solAsset) {
43
- return Err(makeSwapErrorRight({
44
- message: `solAsset is required`,
45
- code: TradeQuoteError.UnknownError,
46
- }));
47
- }
48
- const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
49
- const buyAssetAddress = buyAsset.assetId === solAssetId
50
- ? fromAssetId(wrappedSolAssetId).assetReference
51
- : fromAssetId(buyAsset.assetId).assetReference;
52
- const sellAssetAddress = sellAsset.assetId === solAssetId
53
- ? fromAssetId(wrappedSolAssetId).assetReference
54
- : fromAssetId(sellAsset.assetId).assetReference;
55
- const sellTokenInfo = await adapter
56
- .getConnection()
57
- .getAccountInfo(new PublicKey(sellAssetAddress));
58
- const buyTokenInfo = await adapter.getConnection().getAccountInfo(new PublicKey(buyAssetAddress));
59
- const isSellTokenToken2022 = sellTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString();
60
- const isBuyTokenToken2022 = buyTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString();
61
- const affiliateBps = isSellTokenToken2022 || isBuyTokenToken2022 ? '0' : input.affiliateBps;
62
- const maybePriceResponse = await getJupiterPrice({
63
- apiUrl: jupiterUrl,
64
- sourceAssetAddress: sellAssetAddress,
65
- destinationAssetAddress: buyAssetAddress,
66
- commissionBps: affiliateBps,
67
- amount: sellAmount,
68
- slippageBps: input.slippageTolerancePercentageDecimal
69
- ? convertDecimalPercentageToBasisPoints(input.slippageTolerancePercentageDecimal).toFixed()
70
- : undefined,
71
- });
72
- if (maybePriceResponse.isErr()) {
73
- return Err(makeSwapErrorRight({
74
- message: 'Quote request failed',
75
- code: TradeQuoteError.NoRouteFound,
76
- }));
77
- }
78
- const { data: priceResponse } = maybePriceResponse.unwrap();
79
- const slippageTolerancePercentageDecimal =
80
- // Divide by 100 to get actual decimal percentage from bps
81
- // e.g for 0.5% bps, Jupiter represents this as 50. 50/100 = 0.5, then we div by 100 again to honour our decimal format e.g 0.5/100 = 0.005
82
- bn(priceResponse.slippageBps).div(100).div(100).toString();
83
- const { instructions, addressLookupTableAddresses } = await createSwapInstructions({
84
- priceResponse,
85
- sendAddress,
86
- receiveAddress,
87
- affiliateBps,
88
- buyAsset,
89
- sellAsset,
90
- adapter,
91
- jupiterUrl,
92
- });
93
- // Build a trial VersionedTransaction to check if it exceeds the 1232-byte Solana tx size limit
94
- const isOversized = await (async () => {
95
- try {
96
- const lookupTableInfos = await adapter.getAddressLookupTableAccounts(addressLookupTableAddresses);
97
- const lookupTableAccounts = lookupTableInfos.map(info => new AddressLookupTableAccount({
98
- key: new PublicKey(info.key),
99
- state: AddressLookupTableAccount.deserialize(new Uint8Array(info.data)),
100
- }));
101
- const messageV0 = MessageV0.compile({
102
- payerKey: new PublicKey(sendAddress),
103
- instructions,
104
- // Blockhash doesn't affect size, use a dummy one
105
- recentBlockhash: PublicKey.default.toString(),
106
- addressLookupTableAccounts: lookupTableAccounts,
107
- });
108
- const txBytes = new VersionedTransaction(messageV0).serialize();
109
- return txBytes.length > 1232;
110
- }
111
- catch {
112
- return false;
113
- }
114
- })();
115
- const getFeeData = async () => {
116
- const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
117
- const getFeeDataInput = {
118
- to: '',
119
- value: '0',
120
- chainSpecific: {
121
- from: sendAddress,
122
- addressLookupTableAccounts: addressLookupTableAddresses,
123
- instructions,
124
- },
125
- };
126
- const feeData = await sellAdapter.getFeeData(getFeeDataInput);
127
- return {
128
- txFee: feeData.fast.txFee,
129
- chainSpecific: {
130
- computeUnits: bnOrZero(feeData.fast.chainSpecific.computeUnits)
131
- .times(COMPUTE_UNIT_MARGIN_MULTIPLIER)
132
- .toFixed(0),
133
- priorityFee: feeData.fast.chainSpecific.priorityFee,
134
- },
135
- };
136
- };
137
- const protocolFees = priceResponse.routePlan.reduce((acc, route) => {
138
- const feeAssetId = toAssetId({
139
- assetReference: route.swapInfo.feeMint,
140
- assetNamespace: ASSET_NAMESPACE.splToken,
141
- chainNamespace: CHAIN_NAMESPACE.Solana,
142
- chainReference: CHAIN_REFERENCE.SolanaMainnet,
143
- });
144
- const feeAsset = assetsById[feeAssetId];
145
- // If we can't find the feeAsset, we can't provide a protocol fee to display
146
- // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets
147
- if (!feeAsset)
148
- return acc;
149
- acc[feeAssetId] = {
150
- requiresBalance: false,
151
- amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0),
152
- asset: feeAsset,
153
- };
154
- return acc;
155
- }, {});
156
- const quotes = [];
157
- const feeData = await getFeeData();
158
- const rate = getInputOutputRate({
159
- sellAmountCryptoBaseUnit: priceResponse.inAmount,
160
- buyAmountCryptoBaseUnit: priceResponse.outAmount,
161
- sellAsset,
162
- buyAsset,
163
- });
164
- const accountCreationFees = calculateAccountCreationCosts(instructions);
165
- if (accountCreationFees !== '0') {
166
- const solProtocolFeeAmount = bnOrZero(protocolFees[solAssetId]?.amountCryptoBaseUnit);
167
- protocolFees[solAssetId] = {
168
- requiresBalance: true,
169
- amountCryptoBaseUnit: bnOrZero(solProtocolFeeAmount).plus(accountCreationFees).toFixed(),
170
- asset: solAsset,
171
- };
172
- }
173
- const tradeQuote = {
174
- id: uuid(),
175
- quoteOrRate: 'quote',
176
- rate,
177
- affiliateBps,
178
- receiveAddress,
179
- slippageTolerancePercentageDecimal,
180
- priceImpactPercentageDecimal: priceResponse.priceImpactPct,
181
- swapperName: SwapperName.Jupiter,
182
- steps: [
183
- {
184
- accountNumber,
185
- buyAmountBeforeFeesCryptoBaseUnit: priceResponse.outAmount,
186
- buyAmountAfterFeesCryptoBaseUnit: priceResponse.outAmount,
187
- sellAmountIncludingProtocolFeesCryptoBaseUnit: priceResponse.inAmount,
188
- jupiterQuoteResponse: priceResponse,
189
- solanaTransactionMetadata: {
190
- addressLookupTableAddresses,
191
- instructions,
192
- isOversized,
193
- },
194
- feeData: {
195
- protocolFees,
196
- networkFeeCryptoBaseUnit: feeData.txFee,
197
- chainSpecific: feeData.chainSpecific,
198
- },
199
- rate,
200
- source: SwapperName.Jupiter,
201
- buyAsset,
202
- sellAsset,
203
- allowanceContract: '0x0',
204
- // Swap are so fasts on solana that times are under 100ms displaying 0 or very small amount of time is not user friendly
205
- estimatedExecutionTimeMs: undefined,
206
- affiliateFee: buildAffiliateFee({
207
- strategy: 'buy_asset',
208
- affiliateBps,
209
- sellAsset,
210
- buyAsset,
211
- sellAmountCryptoBaseUnit: priceResponse.inAmount,
212
- buyAmountCryptoBaseUnit: priceResponse.outAmount,
213
- }),
214
- },
215
- ],
216
- };
217
- quotes.push(tradeQuote);
218
- return Ok(quotes);
219
- };
@@ -1,3 +0,0 @@
1
- import type { Result } from '@sniptt/monads';
2
- import type { GetTradeRateInput, SwapErrorRight, SwapperDeps, TradeRate } from '../../../types.js';
3
- export declare const getTradeRate: (input: GetTradeRateInput, deps: SwapperDeps) => Promise<Result<TradeRate[], SwapErrorRight>>;
@@ -1,177 +0,0 @@
1
- import { ASSET_NAMESPACE, CHAIN_NAMESPACE, CHAIN_REFERENCE, fromAssetId, solAssetId, toAssetId, wrappedSolAssetId, } from '@shapeshiftoss/caip';
2
- import { bn, bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils';
3
- import { Err, Ok } from '@sniptt/monads';
4
- import { PublicKey } from '@solana/web3.js';
5
- import { v4 as uuid } from 'uuid';
6
- import { SwapperName, TradeQuoteError } from '../../../types.js';
7
- import { getInputOutputRate, makeSwapErrorRight } from '../../../utils.js';
8
- import { buildAffiliateFee } from '../../utils/affiliateFee.js';
9
- import { SOLANA_RANDOM_ADDRESS, TOKEN_2022_PROGRAM_ID } from '../utils/constants.js';
10
- import { calculateAccountCreationCosts, createSwapInstructions, getJupiterPrice, isSupportedChainId, } from '../utils/helpers.js';
11
- export const getTradeRate = async (input, deps) => {
12
- const { sellAsset, buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, receiveAddress, accountNumber, } = input;
13
- const { assetsById } = deps;
14
- const jupiterUrl = deps.config.VITE_JUPITER_API_URL;
15
- const solAsset = assetsById[solAssetId];
16
- if (!isSupportedChainId(sellAsset.chainId)) {
17
- return Err(makeSwapErrorRight({
18
- message: `unsupported chainId`,
19
- code: TradeQuoteError.UnsupportedChain,
20
- details: { chainId: sellAsset.chainId },
21
- }));
22
- }
23
- if (!isSupportedChainId(buyAsset.chainId)) {
24
- return Err(makeSwapErrorRight({
25
- message: `unsupported chainId`,
26
- code: TradeQuoteError.UnsupportedChain,
27
- details: { chainId: sellAsset.chainId },
28
- }));
29
- }
30
- if (buyAsset.assetId === wrappedSolAssetId || sellAsset.assetId === wrappedSolAssetId) {
31
- return Err(makeSwapErrorRight({
32
- message: `Unsupported trade pair`,
33
- code: TradeQuoteError.UnsupportedTradePair,
34
- }));
35
- }
36
- if (!solAsset) {
37
- return Err(makeSwapErrorRight({
38
- message: `solAsset should be defined`,
39
- code: TradeQuoteError.UnknownError,
40
- }));
41
- }
42
- const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
43
- const buyAssetAddress = buyAsset.assetId === solAssetId
44
- ? fromAssetId(wrappedSolAssetId).assetReference
45
- : fromAssetId(buyAsset.assetId).assetReference;
46
- const sellAssetAddress = sellAsset.assetId === solAssetId
47
- ? fromAssetId(wrappedSolAssetId).assetReference
48
- : fromAssetId(sellAsset.assetId).assetReference;
49
- const sellTokenInfo = await adapter
50
- .getConnection()
51
- .getAccountInfo(new PublicKey(sellAssetAddress));
52
- const buyTokenInfo = await adapter.getConnection().getAccountInfo(new PublicKey(buyAssetAddress));
53
- const isSellTokenToken2022 = sellTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString();
54
- const isBuyTokenToken2022 = buyTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString();
55
- const affiliateBps = isSellTokenToken2022 || isBuyTokenToken2022 ? '0' : input.affiliateBps;
56
- const maybePriceResponse = await getJupiterPrice({
57
- apiUrl: jupiterUrl,
58
- sourceAssetAddress: sellAssetAddress,
59
- destinationAssetAddress: buyAssetAddress,
60
- commissionBps: affiliateBps,
61
- amount: sellAmount,
62
- slippageBps: input.slippageTolerancePercentageDecimal
63
- ? convertDecimalPercentageToBasisPoints(input.slippageTolerancePercentageDecimal).toFixed()
64
- : undefined,
65
- });
66
- if (maybePriceResponse.isErr()) {
67
- return Err(makeSwapErrorRight({
68
- message: 'Quote request failed',
69
- code: TradeQuoteError.NoRouteFound,
70
- }));
71
- }
72
- const { data: priceResponse } = maybePriceResponse.unwrap();
73
- const { instructions } = await createSwapInstructions({
74
- priceResponse,
75
- sendAddress: input.sendAddress ?? SOLANA_RANDOM_ADDRESS,
76
- receiveAddress,
77
- affiliateBps,
78
- buyAsset,
79
- sellAsset,
80
- adapter,
81
- jupiterUrl,
82
- });
83
- const getFeeData = async () => {
84
- const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
85
- const getFeeDataInput = {
86
- // Use real address and instructions for accurate fee estimation whenever possible (Solana account connected)
87
- to: input.sendAddress ?? SOLANA_RANDOM_ADDRESS,
88
- value: sellAmount,
89
- chainSpecific: {
90
- from: input.sendAddress ?? SOLANA_RANDOM_ADDRESS,
91
- instructions,
92
- },
93
- };
94
- const { fast } = await sellAdapter.getFeeData(getFeeDataInput);
95
- return { networkFeeCryptoBaseUnit: fast.txFee };
96
- };
97
- const protocolFees = priceResponse.routePlan.reduce((acc, route) => {
98
- const feeAssetId = toAssetId({
99
- assetReference: route.swapInfo.feeMint,
100
- assetNamespace: ASSET_NAMESPACE.splToken,
101
- chainNamespace: CHAIN_NAMESPACE.Solana,
102
- chainReference: CHAIN_REFERENCE.SolanaMainnet,
103
- });
104
- const feeAsset = assetsById[feeAssetId];
105
- // If we can't find the feeAsset, we can't provide a protocol fee to display
106
- // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets
107
- if (!feeAsset)
108
- return acc;
109
- acc[feeAssetId] = {
110
- requiresBalance: false,
111
- amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0),
112
- asset: feeAsset,
113
- };
114
- return acc;
115
- }, {});
116
- const rates = [];
117
- const feeData = await getFeeData();
118
- const inputOutputRate = getInputOutputRate({
119
- sellAmountCryptoBaseUnit: priceResponse.inAmount,
120
- buyAmountCryptoBaseUnit: priceResponse.outAmount,
121
- sellAsset,
122
- buyAsset,
123
- });
124
- const slippageTolerancePercentageDecimal =
125
- // Divide by 100 to get actual decimal percentage from bps
126
- // e.g for 0.5% bps, Jupiter represents this as 50. 50/100 = 0.5, then we div by 100 again to honour our decimal format e.g 0.5/100 = 0.005
127
- bn(priceResponse.slippageBps).div(100).div(100).toString();
128
- const accountCreationFees = calculateAccountCreationCosts(instructions);
129
- if (accountCreationFees !== '0') {
130
- const solProtocolFeeAmount = bnOrZero(protocolFees[solAssetId]?.amountCryptoBaseUnit);
131
- protocolFees[solAssetId] = {
132
- requiresBalance: true,
133
- amountCryptoBaseUnit: bnOrZero(solProtocolFeeAmount).plus(accountCreationFees).toFixed(),
134
- asset: solAsset,
135
- };
136
- }
137
- const tradeRate = {
138
- id: uuid(),
139
- quoteOrRate: 'rate',
140
- rate: inputOutputRate,
141
- receiveAddress,
142
- affiliateBps,
143
- priceImpactPercentageDecimal: priceResponse.priceImpactPct,
144
- slippageTolerancePercentageDecimal,
145
- swapperName: SwapperName.Jupiter,
146
- steps: [
147
- {
148
- buyAmountBeforeFeesCryptoBaseUnit: priceResponse.outAmount,
149
- buyAmountAfterFeesCryptoBaseUnit: priceResponse.outAmount,
150
- sellAmountIncludingProtocolFeesCryptoBaseUnit: priceResponse.inAmount,
151
- jupiterQuoteResponse: priceResponse,
152
- feeData: {
153
- protocolFees,
154
- ...feeData,
155
- },
156
- rate: inputOutputRate,
157
- source: SwapperName.Jupiter,
158
- buyAsset,
159
- sellAsset,
160
- accountNumber,
161
- allowanceContract: '0x0',
162
- // Swap are so fasts on solana that times are under 100ms displaying 0 or very small amount of time is not user friendly
163
- estimatedExecutionTimeMs: undefined,
164
- affiliateFee: buildAffiliateFee({
165
- strategy: 'buy_asset',
166
- affiliateBps,
167
- sellAsset,
168
- buyAsset,
169
- sellAmountCryptoBaseUnit: priceResponse.inAmount,
170
- buyAmountCryptoBaseUnit: priceResponse.outAmount,
171
- }),
172
- },
173
- ],
174
- };
175
- rates.push(tradeRate);
176
- return Ok(rates);
177
- };
@@ -1,9 +0,0 @@
1
- import type { ChainId } from '@shapeshiftoss/caip';
2
- export declare const jupiterSupportedChainIds: ChainId[];
3
- export declare const PDA_ACCOUNT_CREATION_COST = 2040000;
4
- export declare const SOLANA_RANDOM_ADDRESS = "2zHKF6tqam3tnNFPK2E9nBDkV7GMXnvdJautmzqQdn8A";
5
- export declare const TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
6
- export declare const COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.6;
7
- export declare const SHAPESHIFT_JUPITER_REFERRAL_KEY = "Ajgmo453yGmcHDPoJBrMUj3GFwLVL7HaaZGNLkB8vREG";
8
- export declare const JUPITER_AFFILIATE_CONTRACT_ADDRESS = "REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3";
9
- export declare const JUPITER_REFERALL_FEE_PROJECT_ACCOUNT = "45ruCyfdRkWpRNGEqWzjCiXRHkZs8WXCLQ67Pnpye7Hp";
@@ -1,11 +0,0 @@
1
- import { KnownChainIds } from '@shapeshiftoss/types';
2
- export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet];
3
- export const PDA_ACCOUNT_CREATION_COST = 2040000;
4
- export const SOLANA_RANDOM_ADDRESS = '2zHKF6tqam3tnNFPK2E9nBDkV7GMXnvdJautmzqQdn8A';
5
- export const TOKEN_2022_PROGRAM_ID = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';
6
- // Jupiter use 40% as a compute unit margin while calculating them, some TX reverts without this, as we add some compute units
7
- // for account creations and referral, for stability purposes we add 60% margin
8
- export const COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.6;
9
- export const SHAPESHIFT_JUPITER_REFERRAL_KEY = 'Ajgmo453yGmcHDPoJBrMUj3GFwLVL7HaaZGNLkB8vREG';
10
- export const JUPITER_AFFILIATE_CONTRACT_ADDRESS = 'REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3';
11
- export const JUPITER_REFERALL_FEE_PROJECT_ACCOUNT = '45ruCyfdRkWpRNGEqWzjCiXRHkZs8WXCLQ67Pnpye7Hp';
@@ -1,56 +0,0 @@
1
- import type { QuoteResponse, SwapInstructionsResponse } from '@jup-ag/api';
2
- import type { ChainId } from '@shapeshiftoss/caip';
3
- import type { solana } from '@shapeshiftoss/chain-adapters';
4
- import type { Asset, KnownChainIds } from '@shapeshiftoss/types';
5
- import type { Result } from '@sniptt/monads';
6
- import type { Connection } from '@solana/web3.js';
7
- import { PublicKey, TransactionInstruction } from '@solana/web3.js';
8
- import type { AxiosResponse } from 'axios';
9
- import type { SwapErrorRight } from '../../../types.js';
10
- export declare const isSupportedChainId: (chainId: ChainId) => chainId is KnownChainIds.SolanaMainnet;
11
- type GetJupiterQuoteArgs = {
12
- apiUrl: string;
13
- sourceAssetAddress: string;
14
- destinationAssetAddress: string;
15
- commissionBps: string;
16
- amount: string;
17
- slippageBps: string | undefined;
18
- };
19
- type GetJupiterSwapArgs = {
20
- apiUrl: string;
21
- fromAddress: string;
22
- rawQuote: unknown;
23
- toAddress?: string;
24
- feeAccount: string | undefined;
25
- };
26
- type CreateInstructionsParams = {
27
- priceResponse: QuoteResponse;
28
- sendAddress: string;
29
- receiveAddress?: string;
30
- affiliateBps: string;
31
- buyAsset: Asset;
32
- sellAsset: any;
33
- adapter: solana.ChainAdapter;
34
- jupiterUrl: string;
35
- };
36
- export declare const getJupiterPrice: ({ apiUrl, sourceAssetAddress, destinationAssetAddress, commissionBps, amount, slippageBps, }: GetJupiterQuoteArgs) => Promise<Result<AxiosResponse<QuoteResponse, any>, SwapErrorRight>>;
37
- export declare const getJupiterSwapInstructions: ({ apiUrl, fromAddress, toAddress, rawQuote, feeAccount, }: GetJupiterSwapArgs) => Promise<Result<AxiosResponse<SwapInstructionsResponse, any>, SwapErrorRight>>;
38
- export declare const getFeeTokenAccountAndInstruction: ({ feePayerPubKey, programId, buyAssetReferralPubKey, sellAssetReferralPubKey, buyTokenId, sellTokenId, instructionData, connection, }: {
39
- feePayerPubKey: PublicKey;
40
- programId: PublicKey;
41
- buyAssetReferralPubKey: PublicKey;
42
- sellAssetReferralPubKey: PublicKey;
43
- buyTokenId: string;
44
- sellTokenId: string;
45
- instructionData: Buffer;
46
- connection: Connection;
47
- }) => Promise<{
48
- tokenAccount?: PublicKey;
49
- instruction?: TransactionInstruction | undefined;
50
- }>;
51
- export declare const calculateAccountCreationCosts: (instructions: TransactionInstruction[]) => string;
52
- export declare const createSwapInstructions: ({ priceResponse, sendAddress, receiveAddress, affiliateBps, buyAsset, sellAsset, adapter, jupiterUrl, }: CreateInstructionsParams) => Promise<{
53
- instructions: TransactionInstruction[];
54
- addressLookupTableAddresses: string[];
55
- }>;
56
- export {};
@@ -1,169 +0,0 @@
1
- import { BorshInstructionCoder } from '@coral-xyz/anchor';
2
- import { ASSOCIATED_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@coral-xyz/anchor/dist/cjs/utils/token';
3
- import { fromAssetId, solAssetId, wrappedSolAssetId } from '@shapeshiftoss/caip';
4
- import { bnOrZero } from '@shapeshiftoss/utils';
5
- import { PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js';
6
- import { referralIdl } from '../idls/referral.js';
7
- import { JUPITER_AFFILIATE_CONTRACT_ADDRESS, JUPITER_REFERALL_FEE_PROJECT_ACCOUNT, jupiterSupportedChainIds, PDA_ACCOUNT_CREATION_COST, SHAPESHIFT_JUPITER_REFERRAL_KEY, TOKEN_2022_PROGRAM_ID, } from './constants.js';
8
- import { jupiterService } from './jupiterService.js';
9
- export const isSupportedChainId = (chainId) => {
10
- return jupiterSupportedChainIds.includes(chainId);
11
- };
12
- const JUPITER_TRANSACTION_MAX_ACCOUNTS = 54;
13
- export const getJupiterPrice = ({ apiUrl, sourceAssetAddress, destinationAssetAddress, commissionBps, amount, slippageBps, }) => jupiterService.get(`${apiUrl}/quote` +
14
- `?inputMint=${sourceAssetAddress}` +
15
- `&outputMint=${destinationAssetAddress}` +
16
- `&amount=${amount}` +
17
- (slippageBps ? `&slippageBps=${slippageBps}` : `&dynamicSlippage=true`) +
18
- `&maxAccounts=${JUPITER_TRANSACTION_MAX_ACCOUNTS}` +
19
- `&platformFeeBps=${commissionBps}`);
20
- export const getJupiterSwapInstructions = ({ apiUrl, fromAddress, toAddress, rawQuote, feeAccount, }) => jupiterService.post(`${apiUrl}/swap-instructions`, {
21
- userPublicKey: fromAddress,
22
- destinationTokenAccount: toAddress,
23
- quoteResponse: rawQuote,
24
- dynamicComputeUnitLimit: true,
25
- prioritizationFeeLamports: 'auto',
26
- feeAccount,
27
- });
28
- export const getFeeTokenAccountAndInstruction = async ({ feePayerPubKey, programId, buyAssetReferralPubKey, sellAssetReferralPubKey, buyTokenId, sellTokenId, instructionData, connection, }) => {
29
- const sellAssetTokenAccount = await connection.getAccountInfo(sellAssetReferralPubKey);
30
- if (sellAssetTokenAccount)
31
- return { tokenAccount: sellAssetReferralPubKey };
32
- const buyAssetTokenAccount = await connection.getAccountInfo(buyAssetReferralPubKey);
33
- if (buyAssetTokenAccount)
34
- return { tokenAccount: buyAssetReferralPubKey };
35
- const buyTokenInfo = await connection.getAccountInfo(new PublicKey(buyTokenId));
36
- const sellTokenInfo = await connection.getAccountInfo(new PublicKey(sellTokenId));
37
- const isSellTokenToken2022 = sellTokenInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString();
38
- if (buyTokenInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toString() &&
39
- sellTokenInfo?.owner.toString() !== TOKEN_PROGRAM_ID.toString()) {
40
- return { tokenAccount: undefined, instruction: undefined };
41
- }
42
- const project = new PublicKey(JUPITER_REFERALL_FEE_PROJECT_ACCOUNT);
43
- const referralPubkey = isSellTokenToken2022 ? buyAssetReferralPubKey : sellAssetReferralPubKey;
44
- return {
45
- tokenAccount: referralPubkey,
46
- instruction: new TransactionInstruction({
47
- keys: [
48
- {
49
- pubkey: feePayerPubKey,
50
- isSigner: true,
51
- isWritable: true,
52
- },
53
- {
54
- pubkey: project,
55
- isWritable: false,
56
- isSigner: false,
57
- },
58
- {
59
- pubkey: new PublicKey(SHAPESHIFT_JUPITER_REFERRAL_KEY),
60
- isSigner: false,
61
- isWritable: false,
62
- },
63
- {
64
- pubkey: referralPubkey,
65
- isSigner: false,
66
- isWritable: true,
67
- },
68
- {
69
- pubkey: new PublicKey(isSellTokenToken2022 ? buyTokenId : sellTokenId),
70
- isSigner: false,
71
- isWritable: false,
72
- },
73
- {
74
- pubkey: SystemProgram.programId,
75
- isSigner: false,
76
- isWritable: false,
77
- },
78
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
79
- ],
80
- data: instructionData,
81
- programId,
82
- }),
83
- };
84
- };
85
- export const calculateAccountCreationCosts = (instructions) => {
86
- let totalCost = bnOrZero(0);
87
- for (const ix of instructions) {
88
- if (ix.programId.toString() === ASSOCIATED_PROGRAM_ID.toString()) {
89
- if (ix.data?.[0] === 1) {
90
- totalCost = totalCost.plus(PDA_ACCOUNT_CREATION_COST);
91
- }
92
- }
93
- }
94
- return totalCost.toString();
95
- };
96
- export const createSwapInstructions = async ({ priceResponse, sendAddress, receiveAddress, affiliateBps, buyAsset, sellAsset, adapter, jupiterUrl, }) => {
97
- const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false;
98
- const buyAssetAddress = buyAsset.assetId === solAssetId
99
- ? fromAssetId(wrappedSolAssetId).assetReference
100
- : fromAssetId(buyAsset.assetId).assetReference;
101
- const sellAssetAddress = sellAsset.assetId === solAssetId
102
- ? fromAssetId(wrappedSolAssetId).assetReference
103
- : fromAssetId(sellAsset.assetId).assetReference;
104
- const contractAddress = buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference;
105
- const { instruction: createTokenAccountInstruction, destinationTokenAccount } = contractAddress && isCrossAccountTrade && receiveAddress
106
- ? await adapter.createAssociatedTokenAccountInstruction({
107
- from: sendAddress,
108
- to: receiveAddress,
109
- tokenId: contractAddress,
110
- })
111
- : { instruction: undefined, destinationTokenAccount: undefined };
112
- const [buyAssetReferralPubKey] = PublicKey.findProgramAddressSync([
113
- Buffer.from('referral_ata'),
114
- new PublicKey(SHAPESHIFT_JUPITER_REFERRAL_KEY).toBuffer(),
115
- new PublicKey(buyAssetAddress).toBuffer(),
116
- ], new PublicKey(JUPITER_AFFILIATE_CONTRACT_ADDRESS));
117
- const [sellAssetReferralPubKey] = PublicKey.findProgramAddressSync([
118
- Buffer.from('referral_ata'),
119
- new PublicKey(SHAPESHIFT_JUPITER_REFERRAL_KEY).toBuffer(),
120
- new PublicKey(sellAssetAddress).toBuffer(),
121
- ], new PublicKey(JUPITER_AFFILIATE_CONTRACT_ADDRESS));
122
- const instructionData = new BorshInstructionCoder(referralIdl).encode('initializeReferralTokenAccount', {});
123
- const { instruction: feeAccountInstruction, tokenAccount } = await getFeeTokenAccountAndInstruction({
124
- feePayerPubKey: new PublicKey(sendAddress),
125
- buyAssetReferralPubKey,
126
- sellAssetReferralPubKey,
127
- programId: new PublicKey(JUPITER_AFFILIATE_CONTRACT_ADDRESS),
128
- instructionData,
129
- buyTokenId: buyAssetAddress,
130
- sellTokenId: sellAssetAddress,
131
- connection: adapter.getConnection(),
132
- });
133
- const maybeSwapResponse = await getJupiterSwapInstructions({
134
- apiUrl: jupiterUrl,
135
- fromAddress: sendAddress,
136
- toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined,
137
- rawQuote: priceResponse,
138
- feeAccount: affiliateBps !== '0' && tokenAccount ? tokenAccount.toString() : undefined,
139
- });
140
- if (maybeSwapResponse.isErr()) {
141
- const error = maybeSwapResponse.unwrapErr();
142
- const cause = error.cause;
143
- throw Error(cause.response?.data.detail);
144
- }
145
- const { data: swapResponse } = maybeSwapResponse.unwrap();
146
- const convertJupiterInstruction = (instruction) => ({
147
- ...instruction,
148
- keys: instruction.accounts.map(account => ({
149
- ...account,
150
- pubkey: new PublicKey(account.pubkey),
151
- })),
152
- data: Buffer.from(instruction.data, 'base64'),
153
- programId: new PublicKey(instruction.programId),
154
- });
155
- const instructions = [
156
- ...swapResponse.setupInstructions.map(convertJupiterInstruction),
157
- convertJupiterInstruction(swapResponse.swapInstruction),
158
- ];
159
- if (feeAccountInstruction && affiliateBps !== '0') {
160
- instructions.unshift(feeAccountInstruction);
161
- }
162
- if (createTokenAccountInstruction) {
163
- instructions.unshift(createTokenAccountInstruction);
164
- }
165
- if (swapResponse.cleanupInstruction) {
166
- instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction));
167
- }
168
- return { instructions, addressLookupTableAddresses: swapResponse.addressLookupTableAddresses };
169
- };
@@ -1,5 +0,0 @@
1
- export declare const jupiterService: {
2
- get: <T = any>(url: string, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T, any, {}>, import("../../../index.js").SwapErrorRight>>;
3
- post: <T_1 = any>(url: string, data: any, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T_1, any, {}>, import("../../../index.js").SwapErrorRight>>;
4
- delete: <T_2 = any>(url: string, data: any, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T_2, any, {}>, import("../../../index.js").SwapErrorRight>>;
5
- };