@deserialize/swap-sdk 0.0.341 → 1.0.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/swapSDK.d.ts +133 -55
- package/dist/swapSDK.js +135 -86
- package/dist/swapSDK.js.map +1 -1
- package/package.json +1 -1
- package/src/swapSDK.ts +203 -108
package/dist/swapSDK.d.ts
CHANGED
@@ -3,22 +3,32 @@ import web3, { Connection, Keypair, PublicKey, TransactionInstruction, Versioned
|
|
3
3
|
* Parameters to request a swap.
|
4
4
|
*/
|
5
5
|
export interface SwapRequestParams {
|
6
|
-
/** User
|
6
|
+
/** User's public key */
|
7
7
|
publicKey: PublicKey;
|
8
|
-
/** Token A
|
8
|
+
/** Token A's address */
|
9
9
|
tokenA: PublicKey;
|
10
|
-
/** Token B
|
10
|
+
/** Token B's address */
|
11
11
|
tokenB: PublicKey;
|
12
12
|
/** Amount of Token A to swap (in human-readable units) */
|
13
13
|
amountIn: number;
|
14
|
-
/** DEX identifier –
|
15
|
-
dexId:
|
14
|
+
/** DEX identifier – "INVARIANT", "ORCA", or "ALL" */
|
15
|
+
dexId: DexIdTypes;
|
16
16
|
/**
|
17
17
|
* This is used to set options like limit the swap to just two hops to
|
18
18
|
* prevent errors like TooManyAccountLocks
|
19
19
|
*/
|
20
20
|
options?: RouteOptions;
|
21
21
|
}
|
22
|
+
export interface SwapTransactionResponse {
|
23
|
+
/** Fully constructed VersionedTransaction ready for signing */
|
24
|
+
transaction: VersionedTransaction;
|
25
|
+
/** Raw transaction data in base64 encoding */
|
26
|
+
serializedTransactions: string;
|
27
|
+
/** Associated lookup accounts */
|
28
|
+
lookupAccounts: PublicKey[];
|
29
|
+
/** Required transaction signers */
|
30
|
+
signers: Keypair[];
|
31
|
+
}
|
22
32
|
export interface RouteOptions {
|
23
33
|
reduceToTwoHops: boolean;
|
24
34
|
}
|
@@ -30,26 +40,28 @@ export type GetTokenMintBalanceType = {
|
|
30
40
|
* Result from the swapTx method.
|
31
41
|
*/
|
32
42
|
export interface SwapTxResult {
|
33
|
-
/**
|
43
|
+
/** Fully constructed VersionedTransaction ready for signing */
|
34
44
|
transaction: VersionedTransaction;
|
35
|
-
/**
|
45
|
+
/** Raw transaction data in base64 encoding */
|
46
|
+
serializedTransactions: string;
|
47
|
+
/** Output amount in token decimals */
|
36
48
|
amountOut: number;
|
37
|
-
/**
|
49
|
+
/** Human-readable output amount */
|
38
50
|
amountOutUi: number;
|
39
|
-
/**
|
40
|
-
|
51
|
+
/** Price of Token A in terms of Token B */
|
52
|
+
pairPrice: number;
|
53
|
+
/** Swap route details */
|
54
|
+
routePlan: Array<{
|
41
55
|
tokenA: PublicKey;
|
42
56
|
tokenB: PublicKey;
|
43
|
-
dexId:
|
44
|
-
}
|
45
|
-
/**
|
57
|
+
dexId: DexIdTypes;
|
58
|
+
}>;
|
59
|
+
/** Associated lookup accounts */
|
46
60
|
lookupAccounts: PublicKey[];
|
47
|
-
/**
|
61
|
+
/** Required transaction signers */
|
48
62
|
signers: Keypair[];
|
49
|
-
/**
|
50
|
-
pairPrice: number;
|
63
|
+
/** Protocol fee percentage */
|
51
64
|
feeRate: number;
|
52
|
-
serializedTransactions: string;
|
53
65
|
}
|
54
66
|
/**
|
55
67
|
* Structure representing a group of instructions from the API.
|
@@ -83,6 +95,24 @@ export interface SwapIxResult {
|
|
83
95
|
/** Any top-level signers returned (as base64 encoded strings) */
|
84
96
|
signers: string[];
|
85
97
|
}
|
98
|
+
/**
|
99
|
+
* Response from the quote endpoint
|
100
|
+
*/
|
101
|
+
export interface QuoteResponse {
|
102
|
+
tokenA: string;
|
103
|
+
tokenB: string;
|
104
|
+
amountIn: string;
|
105
|
+
amountOut: string;
|
106
|
+
tokenPrice: string;
|
107
|
+
priceImpact: string;
|
108
|
+
feeRate: string;
|
109
|
+
routePlan: Array<{
|
110
|
+
tokenA: string;
|
111
|
+
tokenB: string;
|
112
|
+
dexId: DexIdTypes;
|
113
|
+
}>;
|
114
|
+
dexId: DexIdTypes;
|
115
|
+
}
|
86
116
|
/**
|
87
117
|
* Token details returned from the /tokenList endpoint.
|
88
118
|
*/
|
@@ -96,54 +126,82 @@ export interface Token {
|
|
96
126
|
tokenProgram: string;
|
97
127
|
}
|
98
128
|
/**
|
99
|
-
*
|
129
|
+
* Balance Check Parameters
|
130
|
+
*/
|
131
|
+
export interface BalanceCheckParams {
|
132
|
+
/** User's wallet address in base58 */
|
133
|
+
userAddress: string;
|
134
|
+
/** Token mint addresses to check */
|
135
|
+
tokenMints: string[];
|
136
|
+
}
|
137
|
+
/**
|
138
|
+
* SwapSDK simplifies interaction with the decentralized exchange API, handling swaps, token data, and balance checks.
|
139
|
+
*
|
140
|
+
* Key Features:
|
141
|
+
* - Get swap quotes to preview expected outcomes
|
142
|
+
* - Build swap transactions with automatic route finding
|
143
|
+
* - Get underlying swap instructions for custom transaction handling
|
144
|
+
* - Retrieve token list and price data
|
145
|
+
* - Check token balances
|
146
|
+
* - Transaction simulation
|
100
147
|
*
|
101
148
|
* Usage:
|
102
149
|
* ```ts
|
103
|
-
* import { SwapSDK } from "./SwapSDK";
|
104
|
-
* import { PublicKey } from "@solana/web3.js";
|
150
|
+
* import { SwapSDK, DEX_IDS } from "./SwapSDK";
|
151
|
+
* import { PublicKey, Connection } from "@solana/web3.js";
|
105
152
|
*
|
106
|
-
* const sdk = new SwapSDK(
|
153
|
+
* const sdk = new SwapSDK(); // Uses default production URL
|
154
|
+
* const connection = new Connection("https://api.mainnet-beta.solana.com");
|
107
155
|
*
|
108
|
-
* async function
|
109
|
-
*
|
110
|
-
*
|
156
|
+
* async function fullSwapFlow() {
|
157
|
+
* // Example swap parameters
|
158
|
+
* const swapParams = {
|
159
|
+
* publicKey: new PublicKey("UserPublicKeyBase58"),
|
111
160
|
* tokenA: new PublicKey("GU7NS9xCwgNPiAdJ69iusFrRfawjDDPjeMBovhV1d4kn"),
|
112
161
|
* tokenB: new PublicKey("CEBP3CqAbW4zdZA57H2wfaSG1QNdzQ72GiQEbQXyW9Tm"),
|
113
162
|
* amountIn: 10.0,
|
114
|
-
* dexId:
|
163
|
+
* dexId: DEX_IDS.INVARIANT,
|
164
|
+
* options: { reduceToTwoHops: false }
|
115
165
|
* };
|
116
166
|
*
|
117
|
-
* //
|
118
|
-
* const
|
119
|
-
* console.log("
|
167
|
+
* // Get a quote first to see expected outcome
|
168
|
+
* const quote = await sdk.getSwapQuote(swapParams);
|
169
|
+
* console.log("Expected output amount:", quote.amountOut);
|
170
|
+
* console.log("Price impact:", quote.priceImpact);
|
120
171
|
*
|
121
|
-
* //
|
122
|
-
* const
|
123
|
-
*
|
172
|
+
* // Get complete swap transaction
|
173
|
+
* const txResult = await sdk.swapTx({
|
174
|
+
* ...swapParams,
|
175
|
+
* quote: quote
|
176
|
+
* });
|
177
|
+
* console.log("Serialized Transaction:", txResult.serializedTransactions);
|
124
178
|
*
|
125
|
-
* //
|
179
|
+
* // Simulate transaction before sending
|
180
|
+
* const simulation = await sdk.simulateTransaction(connection, txResult.transaction);
|
181
|
+
* console.log("Simulation Result:", simulation);
|
182
|
+
*
|
183
|
+
* // Get token list
|
126
184
|
* const tokens = await sdk.tokenList();
|
127
|
-
* console.log("Tokens:", tokens);
|
185
|
+
* console.log("Available Tokens:", tokens);
|
186
|
+
*
|
187
|
+
* // Check balances
|
188
|
+
* const balances = await sdk.getTokenMintBalance({
|
189
|
+
* userAddress: swapParams.publicKey.toBase58(),
|
190
|
+
* tokenMints: [swapParams.tokenA.toBase58(), swapParams.tokenB.toBase58()]
|
191
|
+
* });
|
192
|
+
* console.log("User Balances:", balances);
|
128
193
|
*
|
129
|
-
* //
|
130
|
-
* const
|
131
|
-
* console.log("
|
194
|
+
* // Get token price
|
195
|
+
* const solPrice = await sdk.tokenPrice("So11111111111111111111111111111111111111112");
|
196
|
+
* console.log("SOL Price:", solPrice);
|
132
197
|
* }
|
133
198
|
*
|
134
|
-
*
|
199
|
+
* fullSwapFlow();
|
135
200
|
* ```
|
136
201
|
*/
|
137
202
|
export declare class SwapSDK {
|
138
203
|
private baseUrl;
|
139
204
|
constructor(baseUrl?: string);
|
140
|
-
/**
|
141
|
-
* Calls the bestSwapRoute endpoint with the provided parameters.
|
142
|
-
*
|
143
|
-
* @param params Swap parameters.
|
144
|
-
* @returns The JSON-parsed API response.
|
145
|
-
*/
|
146
|
-
private callSwapEndpoint;
|
147
205
|
base58: import("base-x").default.BaseConverter;
|
148
206
|
web3: typeof web3;
|
149
207
|
DEX_IDS: {
|
@@ -152,19 +210,30 @@ export declare class SwapSDK {
|
|
152
210
|
readonly ALL: "ALL";
|
153
211
|
};
|
154
212
|
/**
|
155
|
-
*
|
213
|
+
* Gets a swap quote without executing the swap
|
156
214
|
*
|
157
|
-
* @param params Swap parameters
|
158
|
-
* @returns
|
215
|
+
* @param params Swap parameters
|
216
|
+
* @returns Quote information including expected output amount and price impact
|
159
217
|
*/
|
160
|
-
|
218
|
+
getSwapQuote(params: SwapRequestParams): Promise<QuoteResponse>;
|
219
|
+
/**
|
220
|
+
* Executes a swap based on a previously obtained quote
|
221
|
+
*
|
222
|
+
* @param params Swap parameters including the quote
|
223
|
+
* @returns Transaction and output details
|
224
|
+
*/
|
225
|
+
getSwapTransaction(params: {
|
226
|
+
publicKey: PublicKey;
|
227
|
+
quote: QuoteResponse;
|
228
|
+
}): Promise<SwapTransactionResponse>;
|
161
229
|
/**
|
162
|
-
* Calls the swap endpoint and returns
|
230
|
+
* Calls the swap endpoint and returns a fully constructed Transaction.
|
231
|
+
* This method is a wrapper that gets a quote first, then executes the swap.
|
163
232
|
*
|
164
233
|
* @param params Swap parameters.
|
165
|
-
* @returns A promise that resolves to a
|
234
|
+
* @returns A promise that resolves to a SwapTxResult.
|
166
235
|
*/
|
167
|
-
|
236
|
+
swapTx(params: SwapRequestParams): Promise<SwapTxResult>;
|
168
237
|
/**
|
169
238
|
* Calls the /tokenList endpoint and returns an array of tokens.
|
170
239
|
*
|
@@ -178,10 +247,19 @@ export declare class SwapSDK {
|
|
178
247
|
* @returns A promise that resolves to the token's price (number).
|
179
248
|
*/
|
180
249
|
tokenPrice(tokenAddress: string): Promise<number>;
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
250
|
+
/**
|
251
|
+
* Gets the token balances for a given wallet
|
252
|
+
*
|
253
|
+
* @param params User address and token mints to check
|
254
|
+
* @returns Array of token balances
|
255
|
+
*/
|
256
|
+
getTokenMintBalance(params: BalanceCheckParams): Promise<GetTokenMintBalanceType[]>;
|
257
|
+
/**
|
258
|
+
* Health check for the API
|
259
|
+
*
|
260
|
+
* @returns A string "Pong" if the service is operational
|
261
|
+
*/
|
262
|
+
ping(): Promise<string>;
|
185
263
|
/**
|
186
264
|
* Simulates a transaction.
|
187
265
|
* @param connection The connection to use.
|
package/dist/swapSDK.js
CHANGED
@@ -42,42 +42,68 @@ const web3_js_1 = __importStar(require("@solana/web3.js"));
|
|
42
42
|
const bs58_1 = __importDefault(require("bs58"));
|
43
43
|
const errors_1 = require("./errors");
|
44
44
|
/**
|
45
|
-
* SwapSDK simplifies
|
45
|
+
* SwapSDK simplifies interaction with the decentralized exchange API, handling swaps, token data, and balance checks.
|
46
|
+
*
|
47
|
+
* Key Features:
|
48
|
+
* - Get swap quotes to preview expected outcomes
|
49
|
+
* - Build swap transactions with automatic route finding
|
50
|
+
* - Get underlying swap instructions for custom transaction handling
|
51
|
+
* - Retrieve token list and price data
|
52
|
+
* - Check token balances
|
53
|
+
* - Transaction simulation
|
46
54
|
*
|
47
55
|
* Usage:
|
48
56
|
* ```ts
|
49
|
-
* import { SwapSDK } from "./SwapSDK";
|
50
|
-
* import { PublicKey } from "@solana/web3.js";
|
57
|
+
* import { SwapSDK, DEX_IDS } from "./SwapSDK";
|
58
|
+
* import { PublicKey, Connection } from "@solana/web3.js";
|
51
59
|
*
|
52
|
-
* const sdk = new SwapSDK(
|
60
|
+
* const sdk = new SwapSDK(); // Uses default production URL
|
61
|
+
* const connection = new Connection("https://api.mainnet-beta.solana.com");
|
53
62
|
*
|
54
|
-
* async function
|
55
|
-
*
|
56
|
-
*
|
63
|
+
* async function fullSwapFlow() {
|
64
|
+
* // Example swap parameters
|
65
|
+
* const swapParams = {
|
66
|
+
* publicKey: new PublicKey("UserPublicKeyBase58"),
|
57
67
|
* tokenA: new PublicKey("GU7NS9xCwgNPiAdJ69iusFrRfawjDDPjeMBovhV1d4kn"),
|
58
68
|
* tokenB: new PublicKey("CEBP3CqAbW4zdZA57H2wfaSG1QNdzQ72GiQEbQXyW9Tm"),
|
59
69
|
* amountIn: 10.0,
|
60
|
-
* dexId:
|
70
|
+
* dexId: DEX_IDS.INVARIANT,
|
71
|
+
* options: { reduceToTwoHops: false }
|
61
72
|
* };
|
62
73
|
*
|
63
|
-
* //
|
64
|
-
* const
|
65
|
-
* console.log("
|
74
|
+
* // Get a quote first to see expected outcome
|
75
|
+
* const quote = await sdk.getSwapQuote(swapParams);
|
76
|
+
* console.log("Expected output amount:", quote.amountOut);
|
77
|
+
* console.log("Price impact:", quote.priceImpact);
|
78
|
+
*
|
79
|
+
* // Get complete swap transaction
|
80
|
+
* const txResult = await sdk.swapTx({
|
81
|
+
* ...swapParams,
|
82
|
+
* quote: quote
|
83
|
+
* });
|
84
|
+
* console.log("Serialized Transaction:", txResult.serializedTransactions);
|
66
85
|
*
|
67
|
-
* //
|
68
|
-
* const
|
69
|
-
* console.log("
|
86
|
+
* // Simulate transaction before sending
|
87
|
+
* const simulation = await sdk.simulateTransaction(connection, txResult.transaction);
|
88
|
+
* console.log("Simulation Result:", simulation);
|
70
89
|
*
|
71
|
-
* //
|
90
|
+
* // Get token list
|
72
91
|
* const tokens = await sdk.tokenList();
|
73
|
-
* console.log("Tokens:", tokens);
|
92
|
+
* console.log("Available Tokens:", tokens);
|
74
93
|
*
|
75
|
-
* //
|
76
|
-
* const
|
77
|
-
*
|
94
|
+
* // Check balances
|
95
|
+
* const balances = await sdk.getTokenMintBalance({
|
96
|
+
* userAddress: swapParams.publicKey.toBase58(),
|
97
|
+
* tokenMints: [swapParams.tokenA.toBase58(), swapParams.tokenB.toBase58()]
|
98
|
+
* });
|
99
|
+
* console.log("User Balances:", balances);
|
100
|
+
*
|
101
|
+
* // Get token price
|
102
|
+
* const solPrice = await sdk.tokenPrice("So11111111111111111111111111111111111111112");
|
103
|
+
* console.log("SOL Price:", solPrice);
|
78
104
|
* }
|
79
105
|
*
|
80
|
-
*
|
106
|
+
* fullSwapFlow();
|
81
107
|
* ```
|
82
108
|
*/
|
83
109
|
class SwapSDK {
|
@@ -85,48 +111,23 @@ class SwapSDK {
|
|
85
111
|
this.base58 = bs58_1.default;
|
86
112
|
this.web3 = web3_js_1.default;
|
87
113
|
this.DEX_IDS = exports.DEX_IDS;
|
88
|
-
this.getTokenMintBalance = async (params) => {
|
89
|
-
const body = {
|
90
|
-
userAddress: params.publicKey,
|
91
|
-
tokenMints: params.mints,
|
92
|
-
};
|
93
|
-
try {
|
94
|
-
const response = await fetch(`${this.baseUrl}/getMintBalances`, {
|
95
|
-
method: "POST",
|
96
|
-
headers: {
|
97
|
-
"Content-Type": "application/json",
|
98
|
-
},
|
99
|
-
body: JSON.stringify(body),
|
100
|
-
});
|
101
|
-
if (!response.ok) {
|
102
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
103
|
-
}
|
104
|
-
const data = await response.json();
|
105
|
-
return data;
|
106
|
-
}
|
107
|
-
catch (error) {
|
108
|
-
console.log(error);
|
109
|
-
}
|
110
|
-
};
|
111
114
|
this.baseUrl = baseUrl || exports.BASE_URL;
|
112
115
|
}
|
113
116
|
/**
|
114
|
-
*
|
117
|
+
* Gets a swap quote without executing the swap
|
115
118
|
*
|
116
|
-
* @param params Swap parameters
|
117
|
-
* @returns
|
119
|
+
* @param params Swap parameters
|
120
|
+
* @returns Quote information including expected output amount and price impact
|
118
121
|
*/
|
119
|
-
async
|
120
|
-
// Prepare the payload by converting PublicKeys to base58 strings
|
122
|
+
async getSwapQuote(params) {
|
121
123
|
const body = {
|
122
|
-
publicKey: params.publicKey.toBase58(),
|
123
124
|
tokenA: params.tokenA.toBase58(),
|
124
125
|
tokenB: params.tokenB.toBase58(),
|
125
126
|
amountIn: params.amountIn.toString(),
|
126
127
|
dexId: params.dexId,
|
127
128
|
options: params.options,
|
128
129
|
};
|
129
|
-
const response = await fetch(`${this.baseUrl}/
|
130
|
+
const response = await fetch(`${this.baseUrl}/quote`, {
|
130
131
|
method: "POST",
|
131
132
|
headers: {
|
132
133
|
"Content-Type": "application/json",
|
@@ -136,71 +137,82 @@ class SwapSDK {
|
|
136
137
|
if (!response.ok) {
|
137
138
|
throw new Error(`API Error: ${response.statusText}`);
|
138
139
|
}
|
139
|
-
return response.json();
|
140
|
+
return await response.json();
|
140
141
|
}
|
141
142
|
/**
|
142
|
-
*
|
143
|
+
* Executes a swap based on a previously obtained quote
|
143
144
|
*
|
144
|
-
* @param params Swap parameters
|
145
|
-
* @returns
|
145
|
+
* @param params Swap parameters including the quote
|
146
|
+
* @returns Transaction and output details
|
146
147
|
*/
|
147
|
-
async
|
148
|
-
const
|
148
|
+
async getSwapTransaction(params) {
|
149
|
+
const body = {
|
150
|
+
publicKey: params.publicKey.toBase58(),
|
151
|
+
quote: params.quote,
|
152
|
+
};
|
153
|
+
const response = await fetch(`${this.baseUrl}/swap`, {
|
154
|
+
method: "POST",
|
155
|
+
headers: {
|
156
|
+
"Content-Type": "application/json",
|
157
|
+
},
|
158
|
+
body: JSON.stringify(body),
|
159
|
+
});
|
160
|
+
if (!response.ok) {
|
161
|
+
throw new Error(`API Error: ${response.statusText}`);
|
162
|
+
}
|
163
|
+
const data = await response.json();
|
149
164
|
// Convert the base64-encoded transaction into a VersionedTransaction.
|
150
165
|
const txBuffer = Buffer.from(data.transaction, "base64");
|
151
166
|
const transaction = web3_js_1.VersionedTransaction.deserialize(txBuffer);
|
152
167
|
// Convert lookup accounts from strings to PublicKey objects.
|
153
168
|
const lookupAccounts = (data.lookUpAccounts || []).map((addr) => new web3_js_1.PublicKey(addr));
|
154
|
-
// Convert
|
155
|
-
const routePlan = (data.routePlan || []).map((rp) => ({
|
156
|
-
tokenA: new web3_js_1.PublicKey(rp.tokenA),
|
157
|
-
tokenB: new web3_js_1.PublicKey(rp.tokenB),
|
158
|
-
dexId: rp.dexId,
|
159
|
-
}));
|
160
|
-
// Convert each base64-encoded signer secret into a Keypair.
|
169
|
+
// Convert each base58-encoded signer secret into a Keypair.
|
161
170
|
const signers = data.signers.map((s) => web3_js_1.Keypair.fromSecretKey(bs58_1.default.decode(s)));
|
162
171
|
transaction.sign(signers);
|
163
172
|
return {
|
164
173
|
transaction,
|
165
174
|
serializedTransactions: data.transaction,
|
166
|
-
amountOut: Number(data.amountOut),
|
167
|
-
amountOutUi: Number(data.amountOutUi),
|
168
|
-
pairPrice: data.pairPrice,
|
169
|
-
routePlan,
|
170
175
|
lookupAccounts,
|
171
176
|
signers,
|
172
|
-
feeRate: parseFloat(data.feeRate),
|
173
177
|
};
|
174
178
|
}
|
175
179
|
/**
|
176
|
-
* Calls the swap endpoint and returns
|
180
|
+
* Calls the swap endpoint and returns a fully constructed Transaction.
|
181
|
+
* This method is a wrapper that gets a quote first, then executes the swap.
|
177
182
|
*
|
178
183
|
* @param params Swap parameters.
|
179
|
-
* @returns A promise that resolves to a
|
184
|
+
* @returns A promise that resolves to a SwapTxResult.
|
180
185
|
*/
|
181
|
-
async
|
182
|
-
|
186
|
+
async swapTx(params) {
|
187
|
+
// First get a quote
|
188
|
+
const quote = await this.getSwapQuote(params);
|
189
|
+
// Then execute the swap with the quote
|
190
|
+
const data = await this.getSwapTransaction({
|
191
|
+
publicKey: params.publicKey,
|
192
|
+
quote,
|
193
|
+
});
|
194
|
+
const transaction = data.transaction;
|
183
195
|
// Convert lookup accounts from strings to PublicKey objects.
|
184
|
-
const lookupAccounts =
|
196
|
+
const lookupAccounts = data.lookupAccounts;
|
185
197
|
// Convert the route plan tokens into PublicKey objects.
|
186
|
-
const routePlan = (
|
198
|
+
const routePlan = (quote.routePlan || []).map((rp) => ({
|
187
199
|
tokenA: new web3_js_1.PublicKey(rp.tokenA),
|
188
200
|
tokenB: new web3_js_1.PublicKey(rp.tokenB),
|
189
201
|
dexId: rp.dexId,
|
190
202
|
}));
|
191
|
-
// Convert each
|
192
|
-
const
|
193
|
-
|
194
|
-
cleanupInstructions: (group.cleanupInstructions || []).map((inst) => this.convertAPIInstruction(inst)),
|
195
|
-
signers: group.signers || [],
|
196
|
-
}));
|
203
|
+
// Convert each base58-encoded signer secret into a Keypair.
|
204
|
+
const signers = data.signers;
|
205
|
+
transaction.sign(signers);
|
197
206
|
return {
|
198
|
-
|
199
|
-
|
200
|
-
|
207
|
+
transaction,
|
208
|
+
serializedTransactions: data.serializedTransactions,
|
209
|
+
amountOut: Number(quote.amountOut),
|
210
|
+
amountOutUi: Number(quote.amountOut),
|
211
|
+
pairPrice: Number(quote.tokenPrice),
|
201
212
|
routePlan,
|
202
213
|
lookupAccounts,
|
203
|
-
signers
|
214
|
+
signers,
|
215
|
+
feeRate: parseFloat(quote.feeRate),
|
204
216
|
};
|
205
217
|
}
|
206
218
|
/**
|
@@ -214,7 +226,7 @@ class SwapSDK {
|
|
214
226
|
throw new Error(`API Error: ${response.statusText}`);
|
215
227
|
}
|
216
228
|
const data = await response.json();
|
217
|
-
return data.
|
229
|
+
return data.map((token) => ({
|
218
230
|
name: token.metadata.name,
|
219
231
|
symbol: token.metadata.symbol,
|
220
232
|
address: token.address,
|
@@ -237,6 +249,44 @@ class SwapSDK {
|
|
237
249
|
const data = await response.json();
|
238
250
|
return Number(data.price);
|
239
251
|
}
|
252
|
+
/**
|
253
|
+
* Gets the token balances for a given wallet
|
254
|
+
*
|
255
|
+
* @param params User address and token mints to check
|
256
|
+
* @returns Array of token balances
|
257
|
+
*/
|
258
|
+
async getTokenMintBalance(params) {
|
259
|
+
try {
|
260
|
+
const response = await fetch(`${this.baseUrl}/getMintBalances`, {
|
261
|
+
method: "POST",
|
262
|
+
headers: {
|
263
|
+
"Content-Type": "application/json",
|
264
|
+
},
|
265
|
+
body: JSON.stringify(params),
|
266
|
+
});
|
267
|
+
if (!response.ok) {
|
268
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
269
|
+
}
|
270
|
+
const data = await response.json();
|
271
|
+
return data;
|
272
|
+
}
|
273
|
+
catch (error) {
|
274
|
+
console.error("Error fetching token balances:", error);
|
275
|
+
throw error;
|
276
|
+
}
|
277
|
+
}
|
278
|
+
/**
|
279
|
+
* Health check for the API
|
280
|
+
*
|
281
|
+
* @returns A string "Pong" if the service is operational
|
282
|
+
*/
|
283
|
+
async ping() {
|
284
|
+
const response = await fetch(`${this.baseUrl}/ping`);
|
285
|
+
if (!response.ok) {
|
286
|
+
throw new Error(`API Error: ${response.statusText}`);
|
287
|
+
}
|
288
|
+
return await response.text();
|
289
|
+
}
|
240
290
|
/**
|
241
291
|
* Simulates a transaction.
|
242
292
|
* @param connection The connection to use.
|
@@ -273,7 +323,6 @@ class SwapSDK {
|
|
273
323
|
exports.SwapSDK = SwapSDK;
|
274
324
|
exports.DEX_IDS = {
|
275
325
|
ORCA: "ORCA",
|
276
|
-
// SOLAR_DEX: "SOLAR_DEX",
|
277
326
|
INVARIANT: "INVARIANT",
|
278
327
|
ALL: "ALL",
|
279
328
|
};
|
package/dist/swapSDK.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"swapSDK.js","sourceRoot":"","sources":["../src/swapSDK.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,aAAa;AACb,2DASyB;AACzB,gDAA0B;AAC1B,qCAAiD;
|
1
|
+
{"version":3,"file":"swapSDK.js","sourceRoot":"","sources":["../src/swapSDK.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/swapSDK.ts
CHANGED
@@ -16,16 +16,16 @@ import { handleSimulationError } from "./errors";
|
|
16
16
|
* Parameters to request a swap.
|
17
17
|
*/
|
18
18
|
export interface SwapRequestParams {
|
19
|
-
/** User
|
19
|
+
/** User's public key */
|
20
20
|
publicKey: PublicKey;
|
21
|
-
/** Token A
|
21
|
+
/** Token A's address */
|
22
22
|
tokenA: PublicKey;
|
23
|
-
/** Token B
|
23
|
+
/** Token B's address */
|
24
24
|
tokenB: PublicKey;
|
25
25
|
/** Amount of Token A to swap (in human-readable units) */
|
26
26
|
amountIn: number;
|
27
|
-
/** DEX identifier –
|
28
|
-
dexId:
|
27
|
+
/** DEX identifier – "INVARIANT", "ORCA", or "ALL" */
|
28
|
+
dexId: DexIdTypes;
|
29
29
|
/**
|
30
30
|
* This is used to set options like limit the swap to just two hops to
|
31
31
|
* prevent errors like TooManyAccountLocks
|
@@ -33,39 +33,52 @@ export interface SwapRequestParams {
|
|
33
33
|
options?: RouteOptions;
|
34
34
|
}
|
35
35
|
|
36
|
+
export interface SwapTransactionResponse {
|
37
|
+
/** Fully constructed VersionedTransaction ready for signing */
|
38
|
+
transaction: VersionedTransaction;
|
39
|
+
/** Raw transaction data in base64 encoding */
|
40
|
+
serializedTransactions: string;
|
41
|
+
/** Associated lookup accounts */
|
42
|
+
lookupAccounts: PublicKey[];
|
43
|
+
/** Required transaction signers */
|
44
|
+
signers: Keypair[];
|
45
|
+
}
|
46
|
+
|
36
47
|
export interface RouteOptions {
|
37
48
|
reduceToTwoHops: boolean;
|
38
49
|
}
|
50
|
+
|
39
51
|
export type GetTokenMintBalanceType = {
|
40
52
|
mint: string;
|
41
53
|
balanceUiAmount: number;
|
42
54
|
};
|
55
|
+
|
43
56
|
/**
|
44
57
|
* Result from the swapTx method.
|
45
58
|
*/
|
46
59
|
export interface SwapTxResult {
|
47
|
-
/**
|
60
|
+
/** Fully constructed VersionedTransaction ready for signing */
|
48
61
|
transaction: VersionedTransaction;
|
49
|
-
/**
|
62
|
+
/** Raw transaction data in base64 encoding */
|
63
|
+
serializedTransactions: string;
|
64
|
+
/** Output amount in token decimals */
|
50
65
|
amountOut: number;
|
51
|
-
/**
|
66
|
+
/** Human-readable output amount */
|
52
67
|
amountOutUi: number;
|
53
|
-
/**
|
54
|
-
|
68
|
+
/** Price of Token A in terms of Token B */
|
69
|
+
pairPrice: number;
|
70
|
+
/** Swap route details */
|
71
|
+
routePlan: Array<{
|
55
72
|
tokenA: PublicKey;
|
56
73
|
tokenB: PublicKey;
|
57
|
-
dexId:
|
58
|
-
}
|
59
|
-
/**
|
74
|
+
dexId: DexIdTypes;
|
75
|
+
}>;
|
76
|
+
/** Associated lookup accounts */
|
60
77
|
lookupAccounts: PublicKey[];
|
61
|
-
/**
|
78
|
+
/** Required transaction signers */
|
62
79
|
signers: Keypair[];
|
63
|
-
/**
|
64
|
-
pairPrice: number;
|
65
|
-
|
80
|
+
/** Protocol fee percentage */
|
66
81
|
feeRate: number;
|
67
|
-
|
68
|
-
serializedTransactions: string;
|
69
82
|
}
|
70
83
|
|
71
84
|
/**
|
@@ -102,6 +115,25 @@ export interface SwapIxResult {
|
|
102
115
|
signers: string[];
|
103
116
|
}
|
104
117
|
|
118
|
+
/**
|
119
|
+
* Response from the quote endpoint
|
120
|
+
*/
|
121
|
+
export interface QuoteResponse {
|
122
|
+
tokenA: string;
|
123
|
+
tokenB: string;
|
124
|
+
amountIn: string;
|
125
|
+
amountOut: string;
|
126
|
+
tokenPrice: string;
|
127
|
+
priceImpact: string;
|
128
|
+
feeRate: string;
|
129
|
+
routePlan: Array<{
|
130
|
+
tokenA: string;
|
131
|
+
tokenB: string;
|
132
|
+
dexId: DexIdTypes;
|
133
|
+
}>;
|
134
|
+
dexId: DexIdTypes;
|
135
|
+
}
|
136
|
+
|
105
137
|
/**
|
106
138
|
* Token details returned from the /tokenList endpoint.
|
107
139
|
*/
|
@@ -116,60 +148,99 @@ export interface Token {
|
|
116
148
|
}
|
117
149
|
|
118
150
|
/**
|
119
|
-
*
|
151
|
+
* Balance Check Parameters
|
152
|
+
*/
|
153
|
+
export interface BalanceCheckParams {
|
154
|
+
/** User's wallet address in base58 */
|
155
|
+
userAddress: string;
|
156
|
+
/** Token mint addresses to check */
|
157
|
+
tokenMints: string[];
|
158
|
+
}
|
159
|
+
|
160
|
+
/**
|
161
|
+
* SwapSDK simplifies interaction with the decentralized exchange API, handling swaps, token data, and balance checks.
|
162
|
+
*
|
163
|
+
* Key Features:
|
164
|
+
* - Get swap quotes to preview expected outcomes
|
165
|
+
* - Build swap transactions with automatic route finding
|
166
|
+
* - Get underlying swap instructions for custom transaction handling
|
167
|
+
* - Retrieve token list and price data
|
168
|
+
* - Check token balances
|
169
|
+
* - Transaction simulation
|
120
170
|
*
|
121
171
|
* Usage:
|
122
172
|
* ```ts
|
123
|
-
* import { SwapSDK } from "./SwapSDK";
|
124
|
-
* import { PublicKey } from "@solana/web3.js";
|
173
|
+
* import { SwapSDK, DEX_IDS } from "./SwapSDK";
|
174
|
+
* import { PublicKey, Connection } from "@solana/web3.js";
|
125
175
|
*
|
126
|
-
* const sdk = new SwapSDK(
|
176
|
+
* const sdk = new SwapSDK(); // Uses default production URL
|
177
|
+
* const connection = new Connection("https://api.mainnet-beta.solana.com");
|
127
178
|
*
|
128
|
-
* async function
|
129
|
-
*
|
130
|
-
*
|
179
|
+
* async function fullSwapFlow() {
|
180
|
+
* // Example swap parameters
|
181
|
+
* const swapParams = {
|
182
|
+
* publicKey: new PublicKey("UserPublicKeyBase58"),
|
131
183
|
* tokenA: new PublicKey("GU7NS9xCwgNPiAdJ69iusFrRfawjDDPjeMBovhV1d4kn"),
|
132
184
|
* tokenB: new PublicKey("CEBP3CqAbW4zdZA57H2wfaSG1QNdzQ72GiQEbQXyW9Tm"),
|
133
185
|
* amountIn: 10.0,
|
134
|
-
* dexId:
|
186
|
+
* dexId: DEX_IDS.INVARIANT,
|
187
|
+
* options: { reduceToTwoHops: false }
|
135
188
|
* };
|
136
189
|
*
|
137
|
-
* //
|
138
|
-
* const
|
139
|
-
* console.log("
|
190
|
+
* // Get a quote first to see expected outcome
|
191
|
+
* const quote = await sdk.getSwapQuote(swapParams);
|
192
|
+
* console.log("Expected output amount:", quote.amountOut);
|
193
|
+
* console.log("Price impact:", quote.priceImpact);
|
140
194
|
*
|
141
|
-
* //
|
142
|
-
* const
|
143
|
-
*
|
195
|
+
* // Get complete swap transaction
|
196
|
+
* const txResult = await sdk.swapTx({
|
197
|
+
* ...swapParams,
|
198
|
+
* quote: quote
|
199
|
+
* });
|
200
|
+
* console.log("Serialized Transaction:", txResult.serializedTransactions);
|
144
201
|
*
|
145
|
-
* //
|
202
|
+
* // Simulate transaction before sending
|
203
|
+
* const simulation = await sdk.simulateTransaction(connection, txResult.transaction);
|
204
|
+
* console.log("Simulation Result:", simulation);
|
205
|
+
*
|
206
|
+
* // Get token list
|
146
207
|
* const tokens = await sdk.tokenList();
|
147
|
-
* console.log("Tokens:", tokens);
|
208
|
+
* console.log("Available Tokens:", tokens);
|
209
|
+
*
|
210
|
+
* // Check balances
|
211
|
+
* const balances = await sdk.getTokenMintBalance({
|
212
|
+
* userAddress: swapParams.publicKey.toBase58(),
|
213
|
+
* tokenMints: [swapParams.tokenA.toBase58(), swapParams.tokenB.toBase58()]
|
214
|
+
* });
|
215
|
+
* console.log("User Balances:", balances);
|
148
216
|
*
|
149
|
-
* //
|
150
|
-
* const
|
151
|
-
* console.log("
|
217
|
+
* // Get token price
|
218
|
+
* const solPrice = await sdk.tokenPrice("So11111111111111111111111111111111111111112");
|
219
|
+
* console.log("SOL Price:", solPrice);
|
152
220
|
* }
|
153
221
|
*
|
154
|
-
*
|
222
|
+
* fullSwapFlow();
|
155
223
|
* ```
|
156
224
|
*/
|
157
225
|
export class SwapSDK {
|
158
226
|
private baseUrl: string;
|
227
|
+
|
159
228
|
constructor(baseUrl?: string) {
|
160
229
|
this.baseUrl = baseUrl || BASE_URL;
|
161
230
|
}
|
162
231
|
|
232
|
+
base58 = base58;
|
233
|
+
web3 = web3;
|
234
|
+
DEX_IDS = DEX_IDS;
|
235
|
+
|
163
236
|
/**
|
164
|
-
*
|
237
|
+
* Gets a swap quote without executing the swap
|
165
238
|
*
|
166
|
-
* @param params Swap parameters
|
167
|
-
* @returns
|
239
|
+
* @param params Swap parameters
|
240
|
+
* @returns Quote information including expected output amount and price impact
|
168
241
|
*/
|
169
|
-
|
170
|
-
// Prepare the payload by converting PublicKeys to base58 strings
|
242
|
+
async getSwapQuote(params: SwapRequestParams): Promise<QuoteResponse> {
|
171
243
|
const body = {
|
172
|
-
publicKey: params.publicKey.toBase58(),
|
173
244
|
tokenA: params.tokenA.toBase58(),
|
174
245
|
tokenB: params.tokenB.toBase58(),
|
175
246
|
amountIn: params.amountIn.toString(),
|
@@ -177,7 +248,7 @@ export class SwapSDK {
|
|
177
248
|
options: params.options,
|
178
249
|
};
|
179
250
|
|
180
|
-
const response = await fetch(`${this.baseUrl}/
|
251
|
+
const response = await fetch(`${this.baseUrl}/quote`, {
|
181
252
|
method: "POST",
|
182
253
|
headers: {
|
183
254
|
"Content-Type": "application/json",
|
@@ -189,21 +260,37 @@ export class SwapSDK {
|
|
189
260
|
throw new Error(`API Error: ${response.statusText}`);
|
190
261
|
}
|
191
262
|
|
192
|
-
return response.json();
|
263
|
+
return await response.json();
|
193
264
|
}
|
194
265
|
|
195
|
-
base58 = base58;
|
196
|
-
web3 = web3;
|
197
|
-
DEX_IDS = DEX_IDS;
|
198
|
-
|
199
266
|
/**
|
200
|
-
*
|
267
|
+
* Executes a swap based on a previously obtained quote
|
201
268
|
*
|
202
|
-
* @param params Swap parameters
|
203
|
-
* @returns
|
269
|
+
* @param params Swap parameters including the quote
|
270
|
+
* @returns Transaction and output details
|
204
271
|
*/
|
205
|
-
async
|
206
|
-
|
272
|
+
async getSwapTransaction(params: {
|
273
|
+
publicKey: PublicKey;
|
274
|
+
quote: QuoteResponse;
|
275
|
+
}): Promise<SwapTransactionResponse> {
|
276
|
+
const body = {
|
277
|
+
publicKey: params.publicKey.toBase58(),
|
278
|
+
quote: params.quote,
|
279
|
+
};
|
280
|
+
|
281
|
+
const response = await fetch(`${this.baseUrl}/swap`, {
|
282
|
+
method: "POST",
|
283
|
+
headers: {
|
284
|
+
"Content-Type": "application/json",
|
285
|
+
},
|
286
|
+
body: JSON.stringify(body),
|
287
|
+
});
|
288
|
+
|
289
|
+
if (!response.ok) {
|
290
|
+
throw new Error(`API Error: ${response.statusText}`);
|
291
|
+
}
|
292
|
+
|
293
|
+
const data = await response.json();
|
207
294
|
|
208
295
|
// Convert the base64-encoded transaction into a VersionedTransaction.
|
209
296
|
const txBuffer = Buffer.from(data.transaction, "base64");
|
@@ -214,72 +301,63 @@ export class SwapSDK {
|
|
214
301
|
(addr: string) => new PublicKey(addr)
|
215
302
|
);
|
216
303
|
|
217
|
-
// Convert
|
218
|
-
const routePlan = (data.routePlan || []).map((rp: any) => ({
|
219
|
-
tokenA: new PublicKey(rp.tokenA),
|
220
|
-
tokenB: new PublicKey(rp.tokenB),
|
221
|
-
dexId: rp.dexId,
|
222
|
-
}));
|
223
|
-
|
224
|
-
// Convert each base64-encoded signer secret into a Keypair.
|
304
|
+
// Convert each base58-encoded signer secret into a Keypair.
|
225
305
|
const signers = data.signers.map((s: string) =>
|
226
306
|
Keypair.fromSecretKey(base58.decode(s))
|
227
307
|
);
|
308
|
+
|
228
309
|
transaction.sign(signers);
|
310
|
+
|
229
311
|
return {
|
230
312
|
transaction,
|
231
313
|
serializedTransactions: data.transaction,
|
232
|
-
amountOut: Number(data.amountOut),
|
233
|
-
amountOutUi: Number(data.amountOutUi),
|
234
|
-
pairPrice: data.pairPrice,
|
235
|
-
routePlan,
|
236
314
|
lookupAccounts,
|
237
315
|
signers,
|
238
|
-
feeRate: parseFloat(data.feeRate),
|
239
316
|
};
|
240
317
|
}
|
241
318
|
|
242
319
|
/**
|
243
|
-
* Calls the swap endpoint and returns
|
320
|
+
* Calls the swap endpoint and returns a fully constructed Transaction.
|
321
|
+
* This method is a wrapper that gets a quote first, then executes the swap.
|
244
322
|
*
|
245
323
|
* @param params Swap parameters.
|
246
|
-
* @returns A promise that resolves to a
|
324
|
+
* @returns A promise that resolves to a SwapTxResult.
|
247
325
|
*/
|
248
|
-
async
|
249
|
-
|
326
|
+
async swapTx(params: SwapRequestParams): Promise<SwapTxResult> {
|
327
|
+
// First get a quote
|
328
|
+
const quote = await this.getSwapQuote(params);
|
250
329
|
|
251
|
-
//
|
252
|
-
const
|
253
|
-
|
254
|
-
|
330
|
+
// Then execute the swap with the quote
|
331
|
+
const data = await this.getSwapTransaction({
|
332
|
+
publicKey: params.publicKey,
|
333
|
+
quote,
|
334
|
+
});
|
255
335
|
|
336
|
+
const transaction = data.transaction;
|
337
|
+
|
338
|
+
// Convert lookup accounts from strings to PublicKey objects.
|
339
|
+
const lookupAccounts: PublicKey[] = data.lookupAccounts;
|
256
340
|
// Convert the route plan tokens into PublicKey objects.
|
257
|
-
const routePlan = (
|
341
|
+
const routePlan = (quote.routePlan || []).map((rp: any) => ({
|
258
342
|
tokenA: new PublicKey(rp.tokenA),
|
259
343
|
tokenB: new PublicKey(rp.tokenB),
|
260
|
-
dexId: rp.dexId,
|
344
|
+
dexId: rp.dexId as DexIdTypes,
|
261
345
|
}));
|
262
346
|
|
263
|
-
// Convert each
|
264
|
-
const
|
265
|
-
|
266
|
-
instructions: (group.instructions || []).map((inst: any) =>
|
267
|
-
this.convertAPIInstruction(inst)
|
268
|
-
),
|
269
|
-
cleanupInstructions: (group.cleanupInstructions || []).map(
|
270
|
-
(inst: any) => this.convertAPIInstruction(inst)
|
271
|
-
),
|
272
|
-
signers: group.signers || [],
|
273
|
-
})
|
274
|
-
);
|
347
|
+
// Convert each base58-encoded signer secret into a Keypair.
|
348
|
+
const signers = data.signers;
|
349
|
+
transaction.sign(signers);
|
275
350
|
|
276
351
|
return {
|
277
|
-
|
278
|
-
|
279
|
-
|
352
|
+
transaction,
|
353
|
+
serializedTransactions: data.serializedTransactions,
|
354
|
+
amountOut: Number(quote.amountOut),
|
355
|
+
amountOutUi: Number(quote.amountOut),
|
356
|
+
pairPrice: Number(quote.tokenPrice),
|
280
357
|
routePlan,
|
281
358
|
lookupAccounts,
|
282
|
-
signers
|
359
|
+
signers,
|
360
|
+
feeRate: parseFloat(quote.feeRate),
|
283
361
|
};
|
284
362
|
}
|
285
363
|
|
@@ -294,7 +372,7 @@ export class SwapSDK {
|
|
294
372
|
throw new Error(`API Error: ${response.statusText}`);
|
295
373
|
}
|
296
374
|
const data = await response.json();
|
297
|
-
return data.
|
375
|
+
return data.map((token: any) => ({
|
298
376
|
name: token.metadata.name,
|
299
377
|
symbol: token.metadata.symbol,
|
300
378
|
address: token.address,
|
@@ -319,31 +397,49 @@ export class SwapSDK {
|
|
319
397
|
return Number(data.price);
|
320
398
|
}
|
321
399
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
400
|
+
/**
|
401
|
+
* Gets the token balances for a given wallet
|
402
|
+
*
|
403
|
+
* @param params User address and token mints to check
|
404
|
+
* @returns Array of token balances
|
405
|
+
*/
|
406
|
+
async getTokenMintBalance(
|
407
|
+
params: BalanceCheckParams
|
408
|
+
): Promise<GetTokenMintBalanceType[]> {
|
330
409
|
try {
|
331
410
|
const response = await fetch(`${this.baseUrl}/getMintBalances`, {
|
332
411
|
method: "POST",
|
333
412
|
headers: {
|
334
413
|
"Content-Type": "application/json",
|
335
414
|
},
|
336
|
-
body: JSON.stringify(
|
415
|
+
body: JSON.stringify(params),
|
337
416
|
});
|
417
|
+
|
338
418
|
if (!response.ok) {
|
339
419
|
throw new Error(`HTTP error! status: ${response.status}`);
|
340
420
|
}
|
421
|
+
|
341
422
|
const data = await response.json();
|
342
423
|
return data as GetTokenMintBalanceType[];
|
343
424
|
} catch (error) {
|
344
|
-
console.
|
425
|
+
console.error("Error fetching token balances:", error);
|
426
|
+
throw error;
|
427
|
+
}
|
428
|
+
}
|
429
|
+
|
430
|
+
/**
|
431
|
+
* Health check for the API
|
432
|
+
*
|
433
|
+
* @returns A string "Pong" if the service is operational
|
434
|
+
*/
|
435
|
+
async ping(): Promise<string> {
|
436
|
+
const response = await fetch(`${this.baseUrl}/ping`);
|
437
|
+
if (!response.ok) {
|
438
|
+
throw new Error(`API Error: ${response.statusText}`);
|
345
439
|
}
|
346
|
-
|
440
|
+
return await response.text();
|
441
|
+
}
|
442
|
+
|
347
443
|
/**
|
348
444
|
* Simulates a transaction.
|
349
445
|
* @param connection The connection to use.
|
@@ -384,7 +480,6 @@ export class SwapSDK {
|
|
384
480
|
|
385
481
|
export const DEX_IDS = {
|
386
482
|
ORCA: "ORCA",
|
387
|
-
// SOLAR_DEX: "SOLAR_DEX",
|
388
483
|
INVARIANT: "INVARIANT",
|
389
484
|
ALL: "ALL",
|
390
485
|
} as const;
|