@cowprotocol/sdk-trading-solana 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -3
- package/dist/index.d.mts +61 -19
- package/dist/index.d.ts +61 -19
- package/dist/index.js +57 -20
- package/dist/index.mjs +54 -19
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -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;
|
|
@@ -64,6 +64,12 @@ declare function encodeOrderIntent(intent: SolanaOrderIntent): Uint8Array;
|
|
|
64
64
|
*/
|
|
65
65
|
declare function hashOrderIntent(encoded: Uint8Array): Promise<Uint8Array>;
|
|
66
66
|
declare function toHex(bytes: Uint8Array): string;
|
|
67
|
+
/**
|
|
68
|
+
* Formats a uid as an order id in the same "0x"-prefixed form the order-book API returns in
|
|
69
|
+
* `EnrichedOrder.uid` (matching EVM order uids). Code that looks an order up by the API's uid
|
|
70
|
+
* (reducer batch actions, notifications, etc.) needs this to match whatever id was stored locally.
|
|
71
|
+
*/
|
|
72
|
+
declare function toOrderId(uid: Uint8Array): string;
|
|
67
73
|
|
|
68
74
|
interface SolanaQuoteParameters {
|
|
69
75
|
ownerAddress: PublicKeyInitData;
|
|
@@ -170,32 +176,68 @@ declare function getSolanaQuote(params: SolanaQuoteParameters, options?: {
|
|
|
170
176
|
solanaQuote: SolanaQuote;
|
|
171
177
|
}>;
|
|
172
178
|
|
|
173
|
-
|
|
174
|
-
* Builds the real `CreateOrder` instruction for `quote` and has the caller sign and submit it. This is
|
|
175
|
-
* the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version signs
|
|
176
|
-
* order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain, so this
|
|
177
|
-
* builds a transaction instruction instead of a signed order body. `createdBy` is always `quote.intent.owner`:
|
|
178
|
-
* a single connected wallet both authenticates and funds the order's rent.
|
|
179
|
-
*/
|
|
180
|
-
declare function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }: {
|
|
179
|
+
interface SolanaSwapOrderQuote {
|
|
181
180
|
quoteResults: QuoteResults;
|
|
182
181
|
solanaQuote: SolanaQuote;
|
|
183
|
-
}
|
|
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>;
|
|
184
214
|
|
|
185
215
|
interface SolanaTradingSdkOptions {
|
|
186
|
-
signAndSend: SolanaSignAndSend;
|
|
187
216
|
env?: CowEnv;
|
|
188
217
|
}
|
|
189
218
|
/**
|
|
190
|
-
* Solana counterpart to `
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
|
|
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`.
|
|
194
236
|
*/
|
|
195
237
|
declare class SolanaTradingSdk {
|
|
196
238
|
private readonly options;
|
|
197
|
-
constructor(options
|
|
198
|
-
getQuote(params: SolanaQuoteParameters): Promise<
|
|
239
|
+
constructor(options?: SolanaTradingSdkOptions);
|
|
240
|
+
getQuote(params: SolanaQuoteParameters): Promise<SolanaQuoteAndPost>;
|
|
199
241
|
}
|
|
200
242
|
|
|
201
|
-
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 };
|
|
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;
|
|
@@ -64,6 +64,12 @@ declare function encodeOrderIntent(intent: SolanaOrderIntent): Uint8Array;
|
|
|
64
64
|
*/
|
|
65
65
|
declare function hashOrderIntent(encoded: Uint8Array): Promise<Uint8Array>;
|
|
66
66
|
declare function toHex(bytes: Uint8Array): string;
|
|
67
|
+
/**
|
|
68
|
+
* Formats a uid as an order id in the same "0x"-prefixed form the order-book API returns in
|
|
69
|
+
* `EnrichedOrder.uid` (matching EVM order uids). Code that looks an order up by the API's uid
|
|
70
|
+
* (reducer batch actions, notifications, etc.) needs this to match whatever id was stored locally.
|
|
71
|
+
*/
|
|
72
|
+
declare function toOrderId(uid: Uint8Array): string;
|
|
67
73
|
|
|
68
74
|
interface SolanaQuoteParameters {
|
|
69
75
|
ownerAddress: PublicKeyInitData;
|
|
@@ -170,32 +176,68 @@ declare function getSolanaQuote(params: SolanaQuoteParameters, options?: {
|
|
|
170
176
|
solanaQuote: SolanaQuote;
|
|
171
177
|
}>;
|
|
172
178
|
|
|
173
|
-
|
|
174
|
-
* Builds the real `CreateOrder` instruction for `quote` and has the caller sign and submit it. This is
|
|
175
|
-
* the Solana analogue of `postSwapOrderFromQuote` in `postSwapOrder.ts` — but where the EVM version signs
|
|
176
|
-
* order data and POSTs it to the CoW order-book, Solana orders are created entirely on-chain, so this
|
|
177
|
-
* builds a transaction instruction instead of a signed order body. `createdBy` is always `quote.intent.owner`:
|
|
178
|
-
* a single connected wallet both authenticates and funds the order's rent.
|
|
179
|
-
*/
|
|
180
|
-
declare function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }: {
|
|
179
|
+
interface SolanaSwapOrderQuote {
|
|
181
180
|
quoteResults: QuoteResults;
|
|
182
181
|
solanaQuote: SolanaQuote;
|
|
183
|
-
}
|
|
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>;
|
|
184
214
|
|
|
185
215
|
interface SolanaTradingSdkOptions {
|
|
186
|
-
signAndSend: SolanaSignAndSend;
|
|
187
216
|
env?: CowEnv;
|
|
188
217
|
}
|
|
189
218
|
/**
|
|
190
|
-
* Solana counterpart to `
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
|
|
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`.
|
|
194
236
|
*/
|
|
195
237
|
declare class SolanaTradingSdk {
|
|
196
238
|
private readonly options;
|
|
197
|
-
constructor(options
|
|
198
|
-
getQuote(params: SolanaQuoteParameters): Promise<
|
|
239
|
+
constructor(options?: SolanaTradingSdkOptions);
|
|
240
|
+
getQuote(params: SolanaQuoteParameters): Promise<SolanaQuoteAndPost>;
|
|
199
241
|
}
|
|
200
242
|
|
|
201
|
-
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 };
|
|
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,
|
|
@@ -34,7 +35,8 @@ __export(src_exports, {
|
|
|
34
35
|
getSolanaSettlementProgramId: () => getSolanaSettlementProgramId,
|
|
35
36
|
hashOrderIntent: () => hashOrderIntent,
|
|
36
37
|
postSolanaSwapOrderFromQuote: () => postSolanaSwapOrderFromQuote,
|
|
37
|
-
toHex: () => toHex
|
|
38
|
+
toHex: () => toHex,
|
|
39
|
+
toOrderId: () => toOrderId
|
|
38
40
|
});
|
|
39
41
|
module.exports = __toCommonJS(src_exports);
|
|
40
42
|
|
|
@@ -91,6 +93,9 @@ async function hashOrderIntent(encoded) {
|
|
|
91
93
|
function toHex(bytes) {
|
|
92
94
|
return Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
93
95
|
}
|
|
96
|
+
function toOrderId(uid) {
|
|
97
|
+
return `0x${toHex(uid)}`;
|
|
98
|
+
}
|
|
94
99
|
|
|
95
100
|
// src/orderPda.ts
|
|
96
101
|
var import_web3 = require("@solana/web3.js");
|
|
@@ -202,9 +207,20 @@ function isJupiterOrderResponse(body, request) {
|
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
// src/getSolanaQuote.ts
|
|
205
|
-
var
|
|
210
|
+
var import_web35 = require("@solana/web3.js");
|
|
206
211
|
var import_spl_token = require("@solana/spl-token");
|
|
207
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
|
|
208
224
|
var DEFAULT_VALID_FOR_SECONDS = 30 * 60;
|
|
209
225
|
var ZERO_APP_DATA = new Uint8Array(32);
|
|
210
226
|
var jupiterApi = new JupiterAPI();
|
|
@@ -224,12 +240,13 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
224
240
|
if (!Number.isFinite(validForSeconds) || validForSeconds <= 0) {
|
|
225
241
|
throw new Error("validForSeconds must be a finite number greater than zero");
|
|
226
242
|
}
|
|
227
|
-
const owner = new
|
|
228
|
-
const receiver = new
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
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;
|
|
233
250
|
const sellTokenAddress = sellMint.toBase58();
|
|
234
251
|
const buyTokenAddress = buyMint.toBase58();
|
|
235
252
|
const jupiterOrder = await jupiterApi.getOrder({
|
|
@@ -299,7 +316,10 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
299
316
|
const tradeParameters = {
|
|
300
317
|
kind,
|
|
301
318
|
owner: owner.toBase58(),
|
|
302
|
-
|
|
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(),
|
|
303
323
|
sellTokenDecimals,
|
|
304
324
|
buyToken: buyTokenAddress,
|
|
305
325
|
buyTokenDecimals,
|
|
@@ -320,11 +340,11 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
320
340
|
return { quoteResults, solanaQuote };
|
|
321
341
|
}
|
|
322
342
|
|
|
323
|
-
// src/
|
|
324
|
-
var import_spl_token2 = require("@solana/spl-token");
|
|
343
|
+
// src/buildSwapOrder.ts
|
|
325
344
|
var import_sdk_order_book3 = require("@cowprotocol/sdk-order-book");
|
|
326
|
-
var
|
|
327
|
-
|
|
345
|
+
var import_spl_token2 = require("@solana/spl-token");
|
|
346
|
+
var import_web36 = require("@solana/web3.js");
|
|
347
|
+
async function buildSolanaSwapOrder({ quoteResults, solanaQuote }, advancedSettings) {
|
|
328
348
|
const intent = { ...solanaQuote.intent };
|
|
329
349
|
let uid = solanaQuote.uid;
|
|
330
350
|
let orderPda = solanaQuote.orderPda;
|
|
@@ -333,7 +353,7 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
333
353
|
if (receiver) {
|
|
334
354
|
intent.buyTokenAccount = (0, import_spl_token2.getAssociatedTokenAddressSync)(
|
|
335
355
|
intent.buyMint,
|
|
336
|
-
new
|
|
356
|
+
new import_web36.PublicKey(receiver),
|
|
337
357
|
false,
|
|
338
358
|
solanaQuote.buyTokenProgramId
|
|
339
359
|
);
|
|
@@ -353,29 +373,44 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
353
373
|
orderPda,
|
|
354
374
|
intent
|
|
355
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);
|
|
356
390
|
await signingStepManager?.beforeOrderSign?.();
|
|
357
391
|
const { signature } = await signAndSend(instruction);
|
|
358
392
|
await signingStepManager?.afterOrderSign?.();
|
|
359
|
-
const orderToSign = quoteResults.orderToSign;
|
|
360
393
|
return {
|
|
361
|
-
orderId
|
|
394
|
+
orderId,
|
|
362
395
|
txHash: signature,
|
|
363
396
|
signature,
|
|
364
|
-
signingScheme
|
|
397
|
+
signingScheme,
|
|
365
398
|
orderToSign
|
|
366
399
|
};
|
|
367
400
|
}
|
|
368
401
|
|
|
369
402
|
// src/solanaTradingSdk.ts
|
|
370
403
|
var SolanaTradingSdk = class {
|
|
371
|
-
constructor(options) {
|
|
404
|
+
constructor(options = {}) {
|
|
372
405
|
this.options = options;
|
|
373
406
|
}
|
|
374
407
|
async getQuote(params) {
|
|
375
408
|
const quote = await getSolanaQuote(params, { env: this.options.env });
|
|
376
409
|
return {
|
|
377
410
|
quoteResults: quote.quoteResults,
|
|
378
|
-
|
|
411
|
+
solanaQuote: quote.solanaQuote,
|
|
412
|
+
buildOrder: (advancedSettings) => buildSolanaSwapOrder(quote, advancedSettings),
|
|
413
|
+
postSwapOrderFromQuote: (signAndSend, advancedSettings, signingStepManager) => postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager)
|
|
379
414
|
};
|
|
380
415
|
}
|
|
381
416
|
};
|
|
@@ -386,6 +421,7 @@ var SolanaTradingSdk = class {
|
|
|
386
421
|
ORDER_SEED,
|
|
387
422
|
SolanaTradingSdk,
|
|
388
423
|
buildCreateOrderInstruction,
|
|
424
|
+
buildSolanaSwapOrder,
|
|
389
425
|
encodeOrderIntent,
|
|
390
426
|
findOrderPda,
|
|
391
427
|
findSettlementStatePda,
|
|
@@ -395,5 +431,6 @@ var SolanaTradingSdk = class {
|
|
|
395
431
|
getSolanaSettlementProgramId,
|
|
396
432
|
hashOrderIntent,
|
|
397
433
|
postSolanaSwapOrderFromQuote,
|
|
398
|
-
toHex
|
|
434
|
+
toHex,
|
|
435
|
+
toOrderId
|
|
399
436
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -51,6 +51,9 @@ async function hashOrderIntent(encoded) {
|
|
|
51
51
|
function toHex(bytes) {
|
|
52
52
|
return Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
53
53
|
}
|
|
54
|
+
function toOrderId(uid) {
|
|
55
|
+
return `0x${toHex(uid)}`;
|
|
56
|
+
}
|
|
54
57
|
|
|
55
58
|
// src/orderPda.ts
|
|
56
59
|
import { PublicKey } from "@solana/web3.js";
|
|
@@ -165,9 +168,20 @@ function isJupiterOrderResponse(body, request) {
|
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
// src/getSolanaQuote.ts
|
|
168
|
-
import { PublicKey as
|
|
171
|
+
import { PublicKey as PublicKey5 } from "@solana/web3.js";
|
|
169
172
|
import { getAssociatedTokenAddressSync } from "@solana/spl-token";
|
|
170
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
|
|
171
185
|
var DEFAULT_VALID_FOR_SECONDS = 30 * 60;
|
|
172
186
|
var ZERO_APP_DATA = new Uint8Array(32);
|
|
173
187
|
var jupiterApi = new JupiterAPI();
|
|
@@ -187,12 +201,13 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
187
201
|
if (!Number.isFinite(validForSeconds) || validForSeconds <= 0) {
|
|
188
202
|
throw new Error("validForSeconds must be a finite number greater than zero");
|
|
189
203
|
}
|
|
190
|
-
const owner = new
|
|
191
|
-
const receiver = new
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
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;
|
|
196
211
|
const sellTokenAddress = sellMint.toBase58();
|
|
197
212
|
const buyTokenAddress = buyMint.toBase58();
|
|
198
213
|
const jupiterOrder = await jupiterApi.getOrder({
|
|
@@ -262,7 +277,10 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
262
277
|
const tradeParameters = {
|
|
263
278
|
kind,
|
|
264
279
|
owner: owner.toBase58(),
|
|
265
|
-
|
|
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(),
|
|
266
284
|
sellTokenDecimals,
|
|
267
285
|
buyToken: buyTokenAddress,
|
|
268
286
|
buyTokenDecimals,
|
|
@@ -283,11 +301,11 @@ async function getSolanaQuote(params, options = {}) {
|
|
|
283
301
|
return { quoteResults, solanaQuote };
|
|
284
302
|
}
|
|
285
303
|
|
|
286
|
-
// src/
|
|
287
|
-
import { getAssociatedTokenAddressSync as getAssociatedTokenAddressSync2 } from "@solana/spl-token";
|
|
304
|
+
// src/buildSwapOrder.ts
|
|
288
305
|
import { SigningScheme } from "@cowprotocol/sdk-order-book";
|
|
289
|
-
import {
|
|
290
|
-
|
|
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) {
|
|
291
309
|
const intent = { ...solanaQuote.intent };
|
|
292
310
|
let uid = solanaQuote.uid;
|
|
293
311
|
let orderPda = solanaQuote.orderPda;
|
|
@@ -296,7 +314,7 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
296
314
|
if (receiver) {
|
|
297
315
|
intent.buyTokenAccount = getAssociatedTokenAddressSync2(
|
|
298
316
|
intent.buyMint,
|
|
299
|
-
new
|
|
317
|
+
new PublicKey6(receiver),
|
|
300
318
|
false,
|
|
301
319
|
solanaQuote.buyTokenProgramId
|
|
302
320
|
);
|
|
@@ -316,29 +334,44 @@ async function postSolanaSwapOrderFromQuote({ quoteResults, solanaQuote }, signA
|
|
|
316
334
|
orderPda,
|
|
317
335
|
intent
|
|
318
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);
|
|
319
351
|
await signingStepManager?.beforeOrderSign?.();
|
|
320
352
|
const { signature } = await signAndSend(instruction);
|
|
321
353
|
await signingStepManager?.afterOrderSign?.();
|
|
322
|
-
const orderToSign = quoteResults.orderToSign;
|
|
323
354
|
return {
|
|
324
|
-
orderId
|
|
355
|
+
orderId,
|
|
325
356
|
txHash: signature,
|
|
326
357
|
signature,
|
|
327
|
-
signingScheme
|
|
358
|
+
signingScheme,
|
|
328
359
|
orderToSign
|
|
329
360
|
};
|
|
330
361
|
}
|
|
331
362
|
|
|
332
363
|
// src/solanaTradingSdk.ts
|
|
333
364
|
var SolanaTradingSdk = class {
|
|
334
|
-
constructor(options) {
|
|
365
|
+
constructor(options = {}) {
|
|
335
366
|
this.options = options;
|
|
336
367
|
}
|
|
337
368
|
async getQuote(params) {
|
|
338
369
|
const quote = await getSolanaQuote(params, { env: this.options.env });
|
|
339
370
|
return {
|
|
340
371
|
quoteResults: quote.quoteResults,
|
|
341
|
-
|
|
372
|
+
solanaQuote: quote.solanaQuote,
|
|
373
|
+
buildOrder: (advancedSettings) => buildSolanaSwapOrder(quote, advancedSettings),
|
|
374
|
+
postSwapOrderFromQuote: (signAndSend, advancedSettings, signingStepManager) => postSolanaSwapOrderFromQuote(quote, signAndSend, advancedSettings, signingStepManager)
|
|
342
375
|
};
|
|
343
376
|
}
|
|
344
377
|
};
|
|
@@ -348,6 +381,7 @@ export {
|
|
|
348
381
|
ORDER_SEED,
|
|
349
382
|
SolanaTradingSdk,
|
|
350
383
|
buildCreateOrderInstruction,
|
|
384
|
+
buildSolanaSwapOrder,
|
|
351
385
|
encodeOrderIntent,
|
|
352
386
|
findOrderPda,
|
|
353
387
|
findSettlementStatePda,
|
|
@@ -357,5 +391,6 @@ export {
|
|
|
357
391
|
getSolanaSettlementProgramId,
|
|
358
392
|
hashOrderIntent,
|
|
359
393
|
postSolanaSwapOrderFromQuote,
|
|
360
|
-
toHex
|
|
394
|
+
toHex,
|
|
395
|
+
toOrderId
|
|
361
396
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cowprotocol/sdk-trading-solana",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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
40
|
"@cowprotocol/sdk-config": "2.6.0",
|
|
43
41
|
"@cowprotocol/sdk-order-book": "4.0.4",
|
|
44
|
-
"@cowprotocol/sdk-trading": "2.4.1"
|
|
42
|
+
"@cowprotocol/sdk-trading": "2.4.1",
|
|
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",
|