@shapeshiftoss/swapper 17.6.11 → 17.7.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/constants.js +16 -26
- package/dist/cjs/index.d.ts +0 -1
- package/dist/cjs/index.js +0 -1
- package/dist/cjs/solana-utils/getUnsignedSolanaTransaction.js +4 -2
- package/dist/cjs/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +3 -1
- package/dist/cjs/swappers/ChainflipSwapper/endpoints.js +14 -4
- package/dist/cjs/swappers/ChainflipSwapper/types.d.ts +1 -0
- package/dist/cjs/swappers/DebridgeSwapper/utils/fetchDebridgeTrade.d.ts +1 -1
- package/dist/cjs/swappers/DebridgeSwapper/utils/getTrade.js +7 -9
- package/dist/cjs/swappers/RelaySwapper/RelaySwapper.d.ts +1 -0
- package/dist/cjs/swappers/RelaySwapper/RelaySwapper.js +15 -0
- package/dist/cjs/swappers/RelaySwapper/constant.js +3 -7
- package/dist/cjs/swappers/RelaySwapper/endpoints.js +1 -1
- package/dist/cjs/swappers/RelaySwapper/utils/getTrade.js +12 -2
- package/dist/cjs/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
- package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +2 -1
- package/dist/cjs/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +0 -1
- package/dist/cjs/tron-utils/getUnsignedTronTransaction.js +16 -0
- package/dist/cjs/types.d.ts +3 -6
- package/dist/cjs/types.js +0 -1
- package/dist/cjs/utils.d.ts +3 -0
- package/dist/cjs/utils.js +9 -3
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/constants.js +0 -10
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +0 -1
- package/dist/esm/solana-utils/getUnsignedSolanaTransaction.js +3 -1
- package/dist/esm/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +3 -1
- package/dist/esm/swappers/ChainflipSwapper/endpoints.js +14 -4
- package/dist/esm/swappers/ChainflipSwapper/types.d.ts +1 -0
- package/dist/esm/swappers/DebridgeSwapper/utils/fetchDebridgeTrade.d.ts +1 -1
- package/dist/esm/swappers/DebridgeSwapper/utils/getTrade.js +7 -9
- package/dist/esm/swappers/RelaySwapper/RelaySwapper.d.ts +1 -0
- package/dist/esm/swappers/RelaySwapper/RelaySwapper.js +1 -0
- package/dist/esm/swappers/RelaySwapper/constant.js +4 -8
- package/dist/esm/swappers/RelaySwapper/endpoints.js +2 -2
- package/dist/esm/swappers/RelaySwapper/utils/getTrade.js +13 -3
- package/dist/esm/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
- package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +2 -1
- package/dist/esm/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +0 -1
- package/dist/esm/tron-utils/getUnsignedTronTransaction.js +16 -0
- package/dist/esm/types.d.ts +3 -6
- package/dist/esm/types.js +0 -1
- package/dist/esm/utils.d.ts +3 -0
- package/dist/esm/utils.js +7 -2
- package/package.json +2 -3
- package/dist/cjs/swappers/JupiterSwapper/JupiterSwapper.d.ts +0 -2
- package/dist/cjs/swappers/JupiterSwapper/JupiterSwapper.js +0 -27
- package/dist/cjs/swappers/JupiterSwapper/endpoints.d.ts +0 -2
- package/dist/cjs/swappers/JupiterSwapper/endpoints.js +0 -15
- package/dist/cjs/swappers/JupiterSwapper/errorPatterns.d.ts +0 -15
- package/dist/cjs/swappers/JupiterSwapper/errorPatterns.js +0 -29
- package/dist/cjs/swappers/JupiterSwapper/idls/referral.d.ts +0 -739
- package/dist/cjs/swappers/JupiterSwapper/idls/referral.js +0 -741
- package/dist/cjs/swappers/JupiterSwapper/index.d.ts +0 -2
- package/dist/cjs/swappers/JupiterSwapper/index.js +0 -18
- package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeQuote.d.ts +0 -3
- package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeQuote.js +0 -223
- package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeRate.d.ts +0 -3
- package/dist/cjs/swappers/JupiterSwapper/swapperApi/getTradeRate.js +0 -181
- package/dist/cjs/swappers/JupiterSwapper/utils/constants.d.ts +0 -9
- package/dist/cjs/swappers/JupiterSwapper/utils/constants.js +0 -14
- package/dist/cjs/swappers/JupiterSwapper/utils/helpers.d.ts +0 -56
- package/dist/cjs/swappers/JupiterSwapper/utils/helpers.js +0 -178
- package/dist/cjs/swappers/JupiterSwapper/utils/jupiterService.d.ts +0 -5
- package/dist/cjs/swappers/JupiterSwapper/utils/jupiterService.js +0 -15
- package/dist/esm/swappers/JupiterSwapper/JupiterSwapper.d.ts +0 -2
- package/dist/esm/swappers/JupiterSwapper/JupiterSwapper.js +0 -24
- package/dist/esm/swappers/JupiterSwapper/endpoints.d.ts +0 -2
- package/dist/esm/swappers/JupiterSwapper/endpoints.js +0 -12
- package/dist/esm/swappers/JupiterSwapper/errorPatterns.d.ts +0 -15
- package/dist/esm/swappers/JupiterSwapper/errorPatterns.js +0 -25
- package/dist/esm/swappers/JupiterSwapper/idls/referral.d.ts +0 -739
- package/dist/esm/swappers/JupiterSwapper/idls/referral.js +0 -738
- package/dist/esm/swappers/JupiterSwapper/index.d.ts +0 -2
- package/dist/esm/swappers/JupiterSwapper/index.js +0 -2
- package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeQuote.d.ts +0 -3
- package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeQuote.js +0 -219
- package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeRate.d.ts +0 -3
- package/dist/esm/swappers/JupiterSwapper/swapperApi/getTradeRate.js +0 -177
- package/dist/esm/swappers/JupiterSwapper/utils/constants.d.ts +0 -9
- package/dist/esm/swappers/JupiterSwapper/utils/constants.js +0 -11
- package/dist/esm/swappers/JupiterSwapper/utils/helpers.d.ts +0 -56
- package/dist/esm/swappers/JupiterSwapper/utils/helpers.js +0 -169
- package/dist/esm/swappers/JupiterSwapper/utils/jupiterService.d.ts +0 -5
- package/dist/esm/swappers/JupiterSwapper/utils/jupiterService.js +0 -12
|
@@ -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
|
-
};
|