@cowprotocol/sdk-trading-solana 0.4.1 → 0.5.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/README.md +26 -4
- package/dist/index.d.mts +55 -19
- package/dist/index.d.ts +55 -19
- package/dist/index.js +50 -18
- package/dist/index.mjs +49 -18
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| Statements | Branches | Functions | Lines |
|
|
10
10
|
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
11
|
-
|  |  |  |  |
|
|
12
12
|
|
|
13
13
|
CoW Protocol's Solana settlement support: Jupiter-sourced quotes and on-chain `CreateOrder`
|
|
14
14
|
posting against the CoW Protocol Solana settlement program.
|
|
@@ -19,11 +19,13 @@ the `cowswap` repo for background.
|
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
21
21
|
|
|
22
|
+
Quoting needs no signer:
|
|
23
|
+
|
|
22
24
|
```ts
|
|
23
25
|
import { SolanaTradingSdk } from '@cowprotocol/sdk-trading-solana'
|
|
24
26
|
|
|
25
|
-
const sdk = new SolanaTradingSdk(
|
|
26
|
-
const { quoteResults, postSwapOrderFromQuote } = await sdk.getQuote({
|
|
27
|
+
const sdk = new SolanaTradingSdk()
|
|
28
|
+
const { quoteResults, solanaQuote, buildOrder, postSwapOrderFromQuote } = await sdk.getQuote({
|
|
27
29
|
ownerAddress,
|
|
28
30
|
receiverAddress,
|
|
29
31
|
sellTokenAddress,
|
|
@@ -33,6 +35,26 @@ const { quoteResults, postSwapOrderFromQuote } = await sdk.getQuote({
|
|
|
33
35
|
amount,
|
|
34
36
|
kind,
|
|
35
37
|
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Let the SDK submit the order
|
|
41
|
+
|
|
42
|
+
`signAndSend` is passed at the point of signing:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const result = await postSwapOrderFromQuote(signAndSend)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Bundle the order with your own instructions
|
|
49
|
+
|
|
50
|
+
A Solana order is created by a single instruction, so it can share a transaction with, say, a wrap and a
|
|
51
|
+
token delegation. `buildOrder` returns that instruction without sending it:
|
|
36
52
|
|
|
37
|
-
|
|
53
|
+
```ts
|
|
54
|
+
const { instruction, orderId } = await buildOrder()
|
|
55
|
+
|
|
56
|
+
await sendMyTransaction([...wrapInstructions, approveInstruction, instruction])
|
|
38
57
|
```
|
|
58
|
+
|
|
59
|
+
Both paths apply `advancedSettings` identically — overriding `receiver` or `validTo` re-derives the order's
|
|
60
|
+
`uid` and PDA so they still match the intent actually being created.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PublicKey, PublicKeyInitData, TransactionInstruction } from '@solana/web3.js';
|
|
2
|
-
import { OrderKind } from '@cowprotocol/sdk-order-book';
|
|
2
|
+
import { OrderKind, SigningScheme } from '@cowprotocol/sdk-order-book';
|
|
3
3
|
import { CowEnv } from '@cowprotocol/sdk-config';
|
|
4
|
-
import { QuoteResults, SwapAdvancedSettings, SigningStepManager, OrderPostingResult
|
|
4
|
+
import { QuoteResults, SwapAdvancedSettings, SigningStepManager, OrderPostingResult } from '@cowprotocol/sdk-trading';
|
|
5
5
|
|
|
6
6
|
interface JupiterOrderRequest {
|
|
7
7
|
inputMint: string;
|
|
@@ -176,32 +176,68 @@ declare function getSolanaQuote(params: SolanaQuoteParameters, options?: {
|
|
|
176
176
|
solanaQuote: SolanaQuote;
|
|
177
177
|
}>;
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
* Builds the real `CreateOrder` instruction for `quote` and has the caller sign and submit it. This is
|
|
181
|
-
* the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version signs
|
|
182
|
-
* order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain, so this
|
|
183
|
-
* builds a transaction instruction instead of a signed order body. `createdBy` is always `quote.intent.owner`:
|
|
184
|
-
* a single connected wallet both authenticates and funds the order's rent.
|
|
185
|
-
*/
|
|
186
|
-
declare function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }: {
|
|
179
|
+
interface SolanaSwapOrderQuote {
|
|
187
180
|
quoteResults: QuoteResults;
|
|
188
181
|
solanaQuote: SolanaQuote;
|
|
189
|
-
}
|
|
182
|
+
}
|
|
183
|
+
interface SolanaSwapOrder {
|
|
184
|
+
/** The `CreateOrder` instruction. Send it on its own, or bundle it with other instructions. */
|
|
185
|
+
instruction: TransactionInstruction;
|
|
186
|
+
/** `uid` as the order-book's `0x`-prefixed uid — see `toOrderId`. */
|
|
187
|
+
orderId: string;
|
|
188
|
+
uid: Uint8Array;
|
|
189
|
+
orderPda: PublicKey;
|
|
190
|
+
/** The intent actually encoded into `instruction` — `advancedSettings` may have overridden the quoted one. */
|
|
191
|
+
intent: SolanaOrderIntent;
|
|
192
|
+
signingScheme: SigningScheme;
|
|
193
|
+
orderToSign: QuoteResults['orderToSign'];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Builds everything needed to create `quote`'s order on-chain, without signing or sending it. Callers that
|
|
197
|
+
* want the SDK to submit it should use `postSolanaSwapOrderFromQuote`; callers bundling the order with
|
|
198
|
+
* other instructions (a wrap, a token delegation) take `instruction` from here and send it themselves.
|
|
199
|
+
*
|
|
200
|
+
* Solana orders are created entirely on-chain, so — unlike the EVM `postSwapOrderFromQuote` — there is no
|
|
201
|
+
* signed order body to POST, and `createdBy` is always `intent.owner`: a single connected wallet both
|
|
202
|
+
* authenticates the order and funds its PDA's rent.
|
|
203
|
+
*/
|
|
204
|
+
declare function buildSolanaSwapOrder({ quoteResults, solanaQuote }: SolanaSwapOrderQuote, advancedSettings?: SwapAdvancedSettings): Promise<SolanaSwapOrder>;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Builds `quote`'s `CreateOrder` instruction and has `signAndSend` submit it as its own transaction. This
|
|
208
|
+
* is the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version
|
|
209
|
+
* signs order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain.
|
|
210
|
+
*
|
|
211
|
+
* To bundle the order with other instructions instead of sending it alone, use `buildSolanaSwapOrder`.
|
|
212
|
+
*/
|
|
213
|
+
declare function postSolanaSwapOrderFromQuote(quote: SolanaSwapOrderQuote, signAndSend: SolanaSignAndSend, advancedSettings?: SwapAdvancedSettings, signingStepManager?: SigningStepManager): Promise<OrderPostingResult>;
|
|
190
214
|
|
|
191
215
|
interface SolanaTradingSdkOptions {
|
|
192
|
-
signAndSend: SolanaSignAndSend;
|
|
193
216
|
env?: CowEnv;
|
|
194
217
|
}
|
|
195
218
|
/**
|
|
196
|
-
* Solana counterpart to `
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
|
|
219
|
+
* Solana counterpart to `QuoteAndPost`. It additionally exposes `solanaQuote` and `buildOrder`, because a
|
|
220
|
+
* Solana order is a plain instruction: callers may want to bundle it with a wrap or a token delegation and
|
|
221
|
+
* submit one transaction, rather than have the SDK send it alone.
|
|
222
|
+
*/
|
|
223
|
+
interface SolanaQuoteAndPost {
|
|
224
|
+
quoteResults: QuoteResults;
|
|
225
|
+
solanaQuote: SolanaQuote;
|
|
226
|
+
/** Build the `CreateOrder` instruction without sending it, to bundle with other instructions. */
|
|
227
|
+
buildOrder(advancedSettings?: SwapAdvancedSettings): Promise<SolanaSwapOrder>;
|
|
228
|
+
/** Build, sign and submit the order as its own transaction. */
|
|
229
|
+
postSwapOrderFromQuote(signAndSend: SolanaSignAndSend, advancedSettings?: SwapAdvancedSettings, signingStepManager?: SigningStepManager): Promise<OrderPostingResult>;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Solana counterpart to `TradingSdk`. Unlike the EVM SDK, which gets its signer implicitly from a global
|
|
233
|
+
* adapter set once at app startup, Solana has no such adapter — so the signer is passed to
|
|
234
|
+
* `postSwapOrderFromQuote` at the point of signing. Quoting therefore needs no signer at all, which also
|
|
235
|
+
* lets a caller quote and then bundle the order instruction itself via `buildOrder`.
|
|
200
236
|
*/
|
|
201
237
|
declare class SolanaTradingSdk {
|
|
202
238
|
private readonly options;
|
|
203
|
-
constructor(options
|
|
204
|
-
getQuote(params: SolanaQuoteParameters): Promise<
|
|
239
|
+
constructor(options?: SolanaTradingSdkOptions);
|
|
240
|
+
getQuote(params: SolanaQuoteParameters): Promise<SolanaQuoteAndPost>;
|
|
205
241
|
}
|
|
206
242
|
|
|
207
|
-
export { type CreateOrderInstructionParams, ENCODED_ORDER_INTENT_SIZE, JupiterAPI, type JupiterOrderRequest, type JupiterOrderResponse, ORDER_SEED, type SolanaOrderIntent, type SolanaQuote, type SolanaQuoteParameters, type SolanaSignAndSend, SolanaTradingSdk, type SolanaTradingSdkOptions, buildCreateOrderInstruction, encodeOrderIntent, findOrderPda, findSettlementStatePda, getSettlementSeed, getSolanaDelegateAuthority, getSolanaQuote, getSolanaSettlementProgramId, hashOrderIntent, postSolanaSwapOrderFromQuote, toHex, toOrderId };
|
|
243
|
+
export { type CreateOrderInstructionParams, ENCODED_ORDER_INTENT_SIZE, JupiterAPI, type JupiterOrderRequest, type JupiterOrderResponse, ORDER_SEED, type SolanaOrderIntent, type SolanaQuote, type SolanaQuoteAndPost, type SolanaQuoteParameters, type SolanaSignAndSend, type SolanaSwapOrder, type SolanaSwapOrderQuote, SolanaTradingSdk, type SolanaTradingSdkOptions, buildCreateOrderInstruction, buildSolanaSwapOrder, encodeOrderIntent, findOrderPda, findSettlementStatePda, getSettlementSeed, getSolanaDelegateAuthority, getSolanaQuote, getSolanaSettlementProgramId, hashOrderIntent, postSolanaSwapOrderFromQuote, toHex, toOrderId };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PublicKey, PublicKeyInitData, TransactionInstruction } from '@solana/web3.js';
|
|
2
|
-
import { OrderKind } from '@cowprotocol/sdk-order-book';
|
|
2
|
+
import { OrderKind, SigningScheme } from '@cowprotocol/sdk-order-book';
|
|
3
3
|
import { CowEnv } from '@cowprotocol/sdk-config';
|
|
4
|
-
import { QuoteResults, SwapAdvancedSettings, SigningStepManager, OrderPostingResult
|
|
4
|
+
import { QuoteResults, SwapAdvancedSettings, SigningStepManager, OrderPostingResult } from '@cowprotocol/sdk-trading';
|
|
5
5
|
|
|
6
6
|
interface JupiterOrderRequest {
|
|
7
7
|
inputMint: string;
|
|
@@ -176,32 +176,68 @@ declare function getSolanaQuote(params: SolanaQuoteParameters, options?: {
|
|
|
176
176
|
solanaQuote: SolanaQuote;
|
|
177
177
|
}>;
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
* Builds the real `CreateOrder` instruction for `quote` and has the caller sign and submit it. This is
|
|
181
|
-
* the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version signs
|
|
182
|
-
* order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain, so this
|
|
183
|
-
* builds a transaction instruction instead of a signed order body. `createdBy` is always `quote.intent.owner`:
|
|
184
|
-
* a single connected wallet both authenticates and funds the order's rent.
|
|
185
|
-
*/
|
|
186
|
-
declare function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }: {
|
|
179
|
+
interface SolanaSwapOrderQuote {
|
|
187
180
|
quoteResults: QuoteResults;
|
|
188
181
|
solanaQuote: SolanaQuote;
|
|
189
|
-
}
|
|
182
|
+
}
|
|
183
|
+
interface SolanaSwapOrder {
|
|
184
|
+
/** The `CreateOrder` instruction. Send it on its own, or bundle it with other instructions. */
|
|
185
|
+
instruction: TransactionInstruction;
|
|
186
|
+
/** `uid` as the order-book's `0x`-prefixed uid — see `toOrderId`. */
|
|
187
|
+
orderId: string;
|
|
188
|
+
uid: Uint8Array;
|
|
189
|
+
orderPda: PublicKey;
|
|
190
|
+
/** The intent actually encoded into `instruction` — `advancedSettings` may have overridden the quoted one. */
|
|
191
|
+
intent: SolanaOrderIntent;
|
|
192
|
+
signingScheme: SigningScheme;
|
|
193
|
+
orderToSign: QuoteResults['orderToSign'];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Builds everything needed to create `quote`'s order on-chain, without signing or sending it. Callers that
|
|
197
|
+
* want the SDK to submit it should use `postSolanaSwapOrderFromQuote`; callers bundling the order with
|
|
198
|
+
* other instructions (a wrap, a token delegation) take `instruction` from here and send it themselves.
|
|
199
|
+
*
|
|
200
|
+
* Solana orders are created entirely on-chain, so — unlike the EVM `postSwapOrderFromQuote` — there is no
|
|
201
|
+
* signed order body to POST, and `createdBy` is always `intent.owner`: a single connected wallet both
|
|
202
|
+
* authenticates the order and funds its PDA's rent.
|
|
203
|
+
*/
|
|
204
|
+
declare function buildSolanaSwapOrder({ quoteResults, solanaQuote }: SolanaSwapOrderQuote, advancedSettings?: SwapAdvancedSettings): Promise<SolanaSwapOrder>;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Builds `quote`'s `CreateOrder` instruction and has `signAndSend` submit it as its own transaction. This
|
|
208
|
+
* is the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version
|
|
209
|
+
* signs order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain.
|
|
210
|
+
*
|
|
211
|
+
* To bundle the order with other instructions instead of sending it alone, use `buildSolanaSwapOrder`.
|
|
212
|
+
*/
|
|
213
|
+
declare function postSolanaSwapOrderFromQuote(quote: SolanaSwapOrderQuote, signAndSend: SolanaSignAndSend, advancedSettings?: SwapAdvancedSettings, signingStepManager?: SigningStepManager): Promise<OrderPostingResult>;
|
|
190
214
|
|
|
191
215
|
interface SolanaTradingSdkOptions {
|
|
192
|
-
signAndSend: SolanaSignAndSend;
|
|
193
216
|
env?: CowEnv;
|
|
194
217
|
}
|
|
195
218
|
/**
|
|
196
|
-
* Solana counterpart to `
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
|
|
219
|
+
* Solana counterpart to `QuoteAndPost`. It additionally exposes `solanaQuote` and `buildOrder`, because a
|
|
220
|
+
* Solana order is a plain instruction: callers may want to bundle it with a wrap or a token delegation and
|
|
221
|
+
* submit one transaction, rather than have the SDK send it alone.
|
|
222
|
+
*/
|
|
223
|
+
interface SolanaQuoteAndPost {
|
|
224
|
+
quoteResults: QuoteResults;
|
|
225
|
+
solanaQuote: SolanaQuote;
|
|
226
|
+
/** Build the `CreateOrder` instruction without sending it, to bundle with other instructions. */
|
|
227
|
+
buildOrder(advancedSettings?: SwapAdvancedSettings): Promise<SolanaSwapOrder>;
|
|
228
|
+
/** Build, sign and submit the order as its own transaction. */
|
|
229
|
+
postSwapOrderFromQuote(signAndSend: SolanaSignAndSend, advancedSettings?: SwapAdvancedSettings, signingStepManager?: SigningStepManager): Promise<OrderPostingResult>;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Solana counterpart to `TradingSdk`. Unlike the EVM SDK, which gets its signer implicitly from a global
|
|
233
|
+
* adapter set once at app startup, Solana has no such adapter — so the signer is passed to
|
|
234
|
+
* `postSwapOrderFromQuote` at the point of signing. Quoting therefore needs no signer at all, which also
|
|
235
|
+
* lets a caller quote and then bundle the order instruction itself via `buildOrder`.
|
|
200
236
|
*/
|
|
201
237
|
declare class SolanaTradingSdk {
|
|
202
238
|
private readonly options;
|
|
203
|
-
constructor(options
|
|
204
|
-
getQuote(params: SolanaQuoteParameters): Promise<
|
|
239
|
+
constructor(options?: SolanaTradingSdkOptions);
|
|
240
|
+
getQuote(params: SolanaQuoteParameters): Promise<SolanaQuoteAndPost>;
|
|
205
241
|
}
|
|
206
242
|
|
|
207
|
-
export { type CreateOrderInstructionParams, ENCODED_ORDER_INTENT_SIZE, JupiterAPI, type JupiterOrderRequest, type JupiterOrderResponse, ORDER_SEED, type SolanaOrderIntent, type SolanaQuote, type SolanaQuoteParameters, type SolanaSignAndSend, SolanaTradingSdk, type SolanaTradingSdkOptions, buildCreateOrderInstruction, encodeOrderIntent, findOrderPda, findSettlementStatePda, getSettlementSeed, getSolanaDelegateAuthority, getSolanaQuote, getSolanaSettlementProgramId, hashOrderIntent, postSolanaSwapOrderFromQuote, toHex, toOrderId };
|
|
243
|
+
export { type CreateOrderInstructionParams, ENCODED_ORDER_INTENT_SIZE, JupiterAPI, type JupiterOrderRequest, type JupiterOrderResponse, ORDER_SEED, type SolanaOrderIntent, type SolanaQuote, type SolanaQuoteAndPost, type SolanaQuoteParameters, type SolanaSignAndSend, type SolanaSwapOrder, type SolanaSwapOrderQuote, SolanaTradingSdk, type SolanaTradingSdkOptions, buildCreateOrderInstruction, buildSolanaSwapOrder, encodeOrderIntent, findOrderPda, findSettlementStatePda, getSettlementSeed, getSolanaDelegateAuthority, getSolanaQuote, getSolanaSettlementProgramId, hashOrderIntent, postSolanaSwapOrderFromQuote, toHex, toOrderId };
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(src_exports, {
|
|
|
25
25
|
ORDER_SEED: () => ORDER_SEED,
|
|
26
26
|
SolanaTradingSdk: () => SolanaTradingSdk,
|
|
27
27
|
buildCreateOrderInstruction: () => buildCreateOrderInstruction,
|
|
28
|
+
buildSolanaSwapOrder: () => buildSolanaSwapOrder,
|
|
28
29
|
encodeOrderIntent: () => encodeOrderIntent,
|
|
29
30
|
findOrderPda: () => findOrderPda,
|
|
30
31
|
findSettlementStatePda: () => findSettlementStatePda,
|
|
@@ -206,9 +207,20 @@ function isJupiterOrderResponse(body, request) {
|
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
// src/getSolanaQuote.ts
|
|
209
|
-
var
|
|
210
|
+
var import_web35 = require("@solana/web3.js");
|
|
210
211
|
var import_spl_token = require("@solana/spl-token");
|
|
211
212
|
var import_sdk_order_book2 = require("@cowprotocol/sdk-order-book");
|
|
213
|
+
|
|
214
|
+
// src/splMint.ts
|
|
215
|
+
var import_web34 = require("@solana/web3.js");
|
|
216
|
+
var import_sdk_config3 = require("@cowprotocol/sdk-config");
|
|
217
|
+
var NATIVE_SOL_MINT = new import_web34.PublicKey(import_sdk_config3.SOL_NATIVE_CURRENCY_ADDRESS);
|
|
218
|
+
var WSOL_MINT = new import_web34.PublicKey(import_sdk_config3.WRAPPED_NATIVE_CURRENCIES[import_sdk_config3.SupportedChainId.SOLANA].address);
|
|
219
|
+
function toSplMint(mint) {
|
|
220
|
+
return mint.equals(NATIVE_SOL_MINT) ? WSOL_MINT : mint;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/getSolanaQuote.ts
|
|
212
224
|
var DEFAULT_VALID_FOR_SECONDS = 30 * 60;
|
|
213
225
|
var ZERO_APP_DATA = new Uint8Array(32);
|
|
214
226
|
var jupiterApi = new JupiterAPI();
|
|
@@ -228,12 +240,13 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
228
240
|
if (!Number.isFinite(validForSeconds) || validForSeconds <= 0) {
|
|
229
241
|
throw new Error("validForSeconds must be a finite number greater than zero");
|
|
230
242
|
}
|
|
231
|
-
const owner = new
|
|
232
|
-
const receiver = new
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
const
|
|
243
|
+
const owner = new import_web35.PublicKey(ownerAddress);
|
|
244
|
+
const receiver = new import_web35.PublicKey(receiverAddress);
|
|
245
|
+
const requestedSellMint = new import_web35.PublicKey(params.sellTokenAddress);
|
|
246
|
+
const sellMint = toSplMint(requestedSellMint);
|
|
247
|
+
const buyMint = new import_web35.PublicKey(params.buyTokenAddress);
|
|
248
|
+
const sellTokenProgram = sellTokenProgramId ? new import_web35.PublicKey(sellTokenProgramId) : void 0;
|
|
249
|
+
const buyTokenProgram = buyTokenProgramId ? new import_web35.PublicKey(buyTokenProgramId) : void 0;
|
|
237
250
|
const sellTokenAddress = sellMint.toBase58();
|
|
238
251
|
const buyTokenAddress = buyMint.toBase58();
|
|
239
252
|
const jupiterOrder = await jupiterApi.getOrder({
|
|
@@ -303,7 +316,10 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
303
316
|
const tradeParameters = {
|
|
304
317
|
kind,
|
|
305
318
|
owner: owner.toBase58(),
|
|
306
|
-
|
|
319
|
+
// The mint the caller asked for, not the substituted one: callers compare the returned parameters
|
|
320
|
+
// against the ones they passed to decide whether a quote is still current, and reporting WSOL for a
|
|
321
|
+
// native-SOL request would read as a changed sell token and requote forever.
|
|
322
|
+
sellToken: requestedSellMint.toBase58(),
|
|
307
323
|
sellTokenDecimals,
|
|
308
324
|
buyToken: buyTokenAddress,
|
|
309
325
|
buyTokenDecimals,
|
|
@@ -324,11 +340,11 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
324
340
|
return { quoteResults, solanaQuote };
|
|
325
341
|
}
|
|
326
342
|
|
|
327
|
-
// src/
|
|
328
|
-
var import_spl_token2 = require("@solana/spl-token");
|
|
343
|
+
// src/buildSwapOrder.ts
|
|
329
344
|
var import_sdk_order_book3 = require("@cowprotocol/sdk-order-book");
|
|
330
|
-
var
|
|
331
|
-
|
|
345
|
+
var import_spl_token2 = require("@solana/spl-token");
|
|
346
|
+
var import_web36 = require("@solana/web3.js");
|
|
347
|
+
async function buildSolanaSwapOrder({ quoteResults, solanaQuote }, advancedSettings) {
|
|
332
348
|
const intent = { ...solanaQuote.intent };
|
|
333
349
|
let uid = solanaQuote.uid;
|
|
334
350
|
let orderPda = solanaQuote.orderPda;
|
|
@@ -337,7 +353,7 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
337
353
|
if (receiver) {
|
|
338
354
|
intent.buyTokenAccount = (0, import_spl_token2.getAssociatedTokenAddressSync)(
|
|
339
355
|
intent.buyMint,
|
|
340
|
-
new
|
|
356
|
+
new import_web36.PublicKey(receiver),
|
|
341
357
|
false,
|
|
342
358
|
solanaQuote.buyTokenProgramId
|
|
343
359
|
);
|
|
@@ -357,29 +373,44 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
357
373
|
orderPda,
|
|
358
374
|
intent
|
|
359
375
|
});
|
|
376
|
+
return {
|
|
377
|
+
instruction,
|
|
378
|
+
orderId: toOrderId(uid),
|
|
379
|
+
uid,
|
|
380
|
+
orderPda,
|
|
381
|
+
intent,
|
|
382
|
+
signingScheme: import_sdk_order_book3.SigningScheme.PRESIGN,
|
|
383
|
+
orderToSign: quoteResults.orderToSign
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// src/postSwapOrderFromQuote.ts
|
|
388
|
+
async function postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager) {
|
|
389
|
+
const { instruction, orderId, signingScheme, orderToSign } = await buildSolanaSwapOrder(quote, advancedSettings);
|
|
360
390
|
await signingStepManager?.beforeOrderSign?.();
|
|
361
391
|
const { signature } = await signAndSend(instruction);
|
|
362
392
|
await signingStepManager?.afterOrderSign?.();
|
|
363
|
-
const orderToSign = quoteResults.orderToSign;
|
|
364
393
|
return {
|
|
365
|
-
orderId
|
|
394
|
+
orderId,
|
|
366
395
|
txHash: signature,
|
|
367
396
|
signature,
|
|
368
|
-
signingScheme
|
|
397
|
+
signingScheme,
|
|
369
398
|
orderToSign
|
|
370
399
|
};
|
|
371
400
|
}
|
|
372
401
|
|
|
373
402
|
// src/solanaTradingSdk.ts
|
|
374
403
|
var SolanaTradingSdk = class {
|
|
375
|
-
constructor(options) {
|
|
404
|
+
constructor(options = {}) {
|
|
376
405
|
this.options = options;
|
|
377
406
|
}
|
|
378
407
|
async getQuote(params) {
|
|
379
408
|
const quote = await getSolanaQuote(params, { env: this.options.env });
|
|
380
409
|
return {
|
|
381
410
|
quoteResults: quote.quoteResults,
|
|
382
|
-
|
|
411
|
+
solanaQuote: quote.solanaQuote,
|
|
412
|
+
buildOrder: (advancedSettings) => buildSolanaSwapOrder(quote, advancedSettings),
|
|
413
|
+
postSwapOrderFromQuote: (signAndSend, advancedSettings, signingStepManager) => postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager)
|
|
383
414
|
};
|
|
384
415
|
}
|
|
385
416
|
};
|
|
@@ -390,6 +421,7 @@ var SolanaTradingSdk = class {
|
|
|
390
421
|
ORDER_SEED,
|
|
391
422
|
SolanaTradingSdk,
|
|
392
423
|
buildCreateOrderInstruction,
|
|
424
|
+
buildSolanaSwapOrder,
|
|
393
425
|
encodeOrderIntent,
|
|
394
426
|
findOrderPda,
|
|
395
427
|
findSettlementStatePda,
|
package/dist/index.mjs
CHANGED
|
@@ -168,9 +168,20 @@ function isJupiterOrderResponse(body, request) {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
// src/getSolanaQuote.ts
|
|
171
|
-
import { PublicKey as
|
|
171
|
+
import { PublicKey as PublicKey5 } from "@solana/web3.js";
|
|
172
172
|
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
|
|
173
173
|
import { getQuoteAmountsAndCosts, OrderKind as OrderKind2 } from "@cowprotocol/sdk-order-book";
|
|
174
|
+
|
|
175
|
+
// src/splMint.ts
|
|
176
|
+
import { PublicKey as PublicKey4 } from "@solana/web3.js";
|
|
177
|
+
import { SOL_NATIVE_CURRENCY_ADDRESS, SupportedChainId, WRAPPED_NATIVE_CURRENCIES } from "@cowprotocol/sdk-config";
|
|
178
|
+
var NATIVE_SOL_MINT = new PublicKey4(SOL_NATIVE_CURRENCY_ADDRESS);
|
|
179
|
+
var WSOL_MINT = new PublicKey4(WRAPPED_NATIVE_CURRENCIES[SupportedChainId.SOLANA].address);
|
|
180
|
+
function toSplMint(mint) {
|
|
181
|
+
return mint.equals(NATIVE_SOL_MINT) ? WSOL_MINT : mint;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/getSolanaQuote.ts
|
|
174
185
|
var DEFAULT_VALID_FOR_SECONDS = 30 * 60;
|
|
175
186
|
var ZERO_APP_DATA = new Uint8Array(32);
|
|
176
187
|
var jupiterApi = new JupiterAPI();
|
|
@@ -190,12 +201,13 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
190
201
|
if (!Number.isFinite(validForSeconds) || validForSeconds <= 0) {
|
|
191
202
|
throw new Error("validForSeconds must be a finite number greater than zero");
|
|
192
203
|
}
|
|
193
|
-
const owner = new
|
|
194
|
-
const receiver = new
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const
|
|
204
|
+
const owner = new PublicKey5(ownerAddress);
|
|
205
|
+
const receiver = new PublicKey5(receiverAddress);
|
|
206
|
+
const requestedSellMint = new PublicKey5(params.sellTokenAddress);
|
|
207
|
+
const sellMint = toSplMint(requestedSellMint);
|
|
208
|
+
const buyMint = new PublicKey5(params.buyTokenAddress);
|
|
209
|
+
const sellTokenProgram = sellTokenProgramId ? new PublicKey5(sellTokenProgramId) : void 0;
|
|
210
|
+
const buyTokenProgram = buyTokenProgramId ? new PublicKey5(buyTokenProgramId) : void 0;
|
|
199
211
|
const sellTokenAddress = sellMint.toBase58();
|
|
200
212
|
const buyTokenAddress = buyMint.toBase58();
|
|
201
213
|
const jupiterOrder = await jupiterApi.getOrder({
|
|
@@ -265,7 +277,10 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
265
277
|
const tradeParameters = {
|
|
266
278
|
kind,
|
|
267
279
|
owner: owner.toBase58(),
|
|
268
|
-
|
|
280
|
+
// The mint the caller asked for, not the substituted one: callers compare the returned parameters
|
|
281
|
+
// against the ones they passed to decide whether a quote is still current, and reporting WSOL for a
|
|
282
|
+
// native-SOL request would read as a changed sell token and requote forever.
|
|
283
|
+
sellToken: requestedSellMint.toBase58(),
|
|
269
284
|
sellTokenDecimals,
|
|
270
285
|
buyToken: buyTokenAddress,
|
|
271
286
|
buyTokenDecimals,
|
|
@@ -286,11 +301,11 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
286
301
|
return { quoteResults, solanaQuote };
|
|
287
302
|
}
|
|
288
303
|
|
|
289
|
-
// src/
|
|
290
|
-
import { getAssociatedTokenAddressSync as getAssociatedTokenAddressSync2 } from "@solana/spl-token";
|
|
304
|
+
// src/buildSwapOrder.ts
|
|
291
305
|
import { SigningScheme } from "@cowprotocol/sdk-order-book";
|
|
292
|
-
import {
|
|
293
|
-
|
|
306
|
+
import { getAssociatedTokenAddressSync as getAssociatedTokenAddressSync2 } from "@solana/spl-token";
|
|
307
|
+
import { PublicKey as PublicKey6 } from "@solana/web3.js";
|
|
308
|
+
async function buildSolanaSwapOrder({ quoteResults, solanaQuote }, advancedSettings) {
|
|
294
309
|
const intent = { ...solanaQuote.intent };
|
|
295
310
|
let uid = solanaQuote.uid;
|
|
296
311
|
let orderPda = solanaQuote.orderPda;
|
|
@@ -299,7 +314,7 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
299
314
|
if (receiver) {
|
|
300
315
|
intent.buyTokenAccount = getAssociatedTokenAddressSync2(
|
|
301
316
|
intent.buyMint,
|
|
302
|
-
new
|
|
317
|
+
new PublicKey6(receiver),
|
|
303
318
|
false,
|
|
304
319
|
solanaQuote.buyTokenProgramId
|
|
305
320
|
);
|
|
@@ -319,29 +334,44 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
319
334
|
orderPda,
|
|
320
335
|
intent
|
|
321
336
|
});
|
|
337
|
+
return {
|
|
338
|
+
instruction,
|
|
339
|
+
orderId: toOrderId(uid),
|
|
340
|
+
uid,
|
|
341
|
+
orderPda,
|
|
342
|
+
intent,
|
|
343
|
+
signingScheme: SigningScheme.PRESIGN,
|
|
344
|
+
orderToSign: quoteResults.orderToSign
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/postSwapOrderFromQuote.ts
|
|
349
|
+
async function postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager) {
|
|
350
|
+
const { instruction, orderId, signingScheme, orderToSign } = await buildSolanaSwapOrder(quote, advancedSettings);
|
|
322
351
|
await signingStepManager?.beforeOrderSign?.();
|
|
323
352
|
const { signature } = await signAndSend(instruction);
|
|
324
353
|
await signingStepManager?.afterOrderSign?.();
|
|
325
|
-
const orderToSign = quoteResults.orderToSign;
|
|
326
354
|
return {
|
|
327
|
-
orderId
|
|
355
|
+
orderId,
|
|
328
356
|
txHash: signature,
|
|
329
357
|
signature,
|
|
330
|
-
signingScheme
|
|
358
|
+
signingScheme,
|
|
331
359
|
orderToSign
|
|
332
360
|
};
|
|
333
361
|
}
|
|
334
362
|
|
|
335
363
|
// src/solanaTradingSdk.ts
|
|
336
364
|
var SolanaTradingSdk = class {
|
|
337
|
-
constructor(options) {
|
|
365
|
+
constructor(options = {}) {
|
|
338
366
|
this.options = options;
|
|
339
367
|
}
|
|
340
368
|
async getQuote(params) {
|
|
341
369
|
const quote = await getSolanaQuote(params, { env: this.options.env });
|
|
342
370
|
return {
|
|
343
371
|
quoteResults: quote.quoteResults,
|
|
344
|
-
|
|
372
|
+
solanaQuote: quote.solanaQuote,
|
|
373
|
+
buildOrder: (advancedSettings) => buildSolanaSwapOrder(quote, advancedSettings),
|
|
374
|
+
postSwapOrderFromQuote: (signAndSend, advancedSettings, signingStepManager) => postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager)
|
|
345
375
|
};
|
|
346
376
|
}
|
|
347
377
|
};
|
|
@@ -351,6 +381,7 @@ export {
|
|
|
351
381
|
ORDER_SEED,
|
|
352
382
|
SolanaTradingSdk,
|
|
353
383
|
buildCreateOrderInstruction,
|
|
384
|
+
buildSolanaSwapOrder,
|
|
354
385
|
encodeOrderIntent,
|
|
355
386
|
findOrderPda,
|
|
356
387
|
findSettlementStatePda,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cowprotocol/sdk-trading-solana",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "CowProtocol Solana trading: Jupiter-sourced quotes and on-chain CreateOrder posting against the Solana settlement program",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,21 +27,21 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
+
"@cow-sdk/typescript-config": "0.0.0-beta.0",
|
|
30
31
|
"@types/jest": "^29.5.12",
|
|
31
32
|
"@types/node": "^20.17.31",
|
|
32
33
|
"tsup": "^7.2.0",
|
|
33
34
|
"typescript": "^5.2.2",
|
|
34
35
|
"jest": "^29.7.0",
|
|
35
36
|
"jest-fetch-mock": "^3.0.3",
|
|
36
|
-
"ts-jest": "^29.0.0"
|
|
37
|
-
"@cow-sdk/typescript-config": "0.0.0-beta.0"
|
|
37
|
+
"ts-jest": "^29.0.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@solana/spl-token": "0.4.14",
|
|
41
|
-
"@solana/web3.js": "1.98.4",
|
|
42
|
-
"@cowprotocol/sdk-trading": "2.4.1",
|
|
43
40
|
"@cowprotocol/sdk-config": "2.6.0",
|
|
44
|
-
"@cowprotocol/sdk-order-book": "4.0.4"
|
|
41
|
+
"@cowprotocol/sdk-order-book": "4.0.4",
|
|
42
|
+
"@cowprotocol/sdk-trading": "2.4.2",
|
|
43
|
+
"@solana/spl-token": "0.4.14",
|
|
44
|
+
"@solana/web3.js": "1.98.4"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|