@solard/sdk 0.2.29 → 0.2.31
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 +21 -6
- package/package.json +2 -2
- package/src/client.trade-fees.test.ts +60 -60
- package/src/client.ts +65 -76
- package/src/default.ts +51 -51
- package/src/export-surface.test.ts +203 -189
- package/src/index.ts +42 -6
- package/src/live.test.ts +108 -15
- package/src/live.ts +468 -307
- package/src/operator-api.architecture.test.ts +45 -44
package/README.md
CHANGED
|
@@ -3,11 +3,26 @@
|
|
|
3
3
|
Public Solard SDK. It intentionally contains no duplicate business logic; it re-exports the supported `@solard/core` API.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import {
|
|
6
|
+
import { createSolard } from "@solard/sdk";
|
|
7
7
|
|
|
8
|
-
const slrd =
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
const slrd = createSolard();
|
|
9
|
+
await slrd.addToken(mint, undefined, { venueHint: "pumpswap", pool: poolAddress });
|
|
10
|
+
const buy = await slrd.buy(
|
|
11
|
+
{ wallet: "trader-1", token: mint, amount: { sol: 0.001 }, slippageBps: 500 },
|
|
12
|
+
{ intentKey: "example:buy:1", priorityFee: { cuLimit: 600_000, microLamports: 200_000 } },
|
|
13
|
+
);
|
|
14
|
+
if (buy.status === "confirmed") {
|
|
15
|
+
console.log(buy.solPrincipalDeltaLamports, buy.networkFeeLamports, buy.targetTokenDeltaRaw);
|
|
16
|
+
}
|
|
17
|
+
// Sell through the same atomic quote-token -> SOL route.
|
|
18
|
+
// await slrd.sell({ wallet: "trader-1", token: mint, amount: "all", slippageBps: 500 });
|
|
13
19
|
```
|
|
20
|
+
|
|
21
|
+
The trader preset supports Pump/PumpSwap, Meteora DBC and DAMM v2. Custom quote
|
|
22
|
+
routes require a supported SOL market for the quote token and suitable lookup
|
|
23
|
+
tables when needed. Composer routes fall back to Jupiter instructions. Unavailable
|
|
24
|
+
converted prices are null. `unresolved` means reconcile with `resumeTrade(intentKey)`
|
|
25
|
+
before another trade. Buy accepts `minOutputRaw`; sell accepts `minOutputLamports`.
|
|
26
|
+
Both use confirmed/failed/unresolved results with phase, code, attempts and accounting.
|
|
27
|
+
`quote`, `curveLiquidity`, `maxSendableSol`, `transferToken` and `exitWallet` share the
|
|
28
|
+
core implementation. Raydium AMM/CPMM execution does not supply live pool prices.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solard/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "Public Solard SDK for wallets, trading, history, live market subscriptions and token metadata.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@solana/web3.js": "^1.98.4",
|
|
30
|
-
"@solard/core": "0.2.
|
|
30
|
+
"@solard/core": "0.2.31"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.browser.json",
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import { expect, spyOn, test } from "bun:test";
|
|
2
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { Keypair } from "@solana/web3.js";
|
|
6
|
-
import { Solard } from "../../core/src/core/solard.ts";
|
|
7
|
-
import { TransactionComposer } from "../../core/src/tx/composer.ts";
|
|
8
|
-
import type { PlannedTransaction, TransactionDraft } from "../../core/src/tx/types.ts";
|
|
9
|
-
import { createSolard } from "./client.ts";
|
|
10
|
-
|
|
11
|
-
test("SDK buy rebuild and sell preserve custom fees in immediate submitted results", async () => {
|
|
12
|
-
const directory = mkdtempSync(join(tmpdir(), "solard-sdk-fees-"));
|
|
13
|
-
const drafts: Array<TransactionDraft> = [];
|
|
14
|
-
// A sentinel plan is never compiled, signed, or broadcast in this test.
|
|
15
|
-
const payer = Keypair.generate();
|
|
16
|
-
const plan = { payer: payer.publicKey } as PlannedTransaction;
|
|
17
|
-
const build = spyOn(TransactionComposer.prototype, "build").mockImplementation(async function (this: TransactionComposer) {
|
|
18
|
-
drafts.push(this.snapshot());
|
|
19
|
-
return { ...plan, draft: this.snapshot() };
|
|
20
|
-
});
|
|
21
|
-
const signer = spyOn(Solard.prototype, "signer").mockImplementation(() => payer);
|
|
22
|
-
const compile = spyOn(Solard.prototype, "compile").mockImplementation(async (_payer, draft) => ({ ...plan, draft }));
|
|
23
|
-
let submissions = 0;
|
|
24
|
-
const submit = spyOn(Solard.prototype, "submitPlan").mockImplementation(async () => {
|
|
25
|
-
submissions += 1;
|
|
26
|
-
if (submissions === 1) {
|
|
27
|
-
throw new Error("Simulation failed: BuySlippageBelowMinBaseAmountOut");
|
|
28
|
-
}
|
|
29
|
-
return { signature: "test-signature", sender: "rpc", executionId: 42, plan };
|
|
30
|
-
});
|
|
31
|
-
const settle = spyOn(Solard.prototype, "settleSubmission").mockImplementation(async () => {
|
|
32
|
-
throw new Error("Immediate submission must not wait for confirmation");
|
|
33
|
-
});
|
|
34
|
-
const sdk = createSolard({ dbPath: join(directory, "test.sqlite") });
|
|
35
|
-
try {
|
|
36
|
-
const options = {
|
|
37
|
-
priorityFee: { cuLimit: 300_000, microLamports: 0 },
|
|
38
|
-
waitForConfirmation: false,
|
|
39
|
-
};
|
|
40
|
-
const buy = await sdk.buy({ token: "token", wallet: "wallet", amount: 0.1 }, options);
|
|
41
|
-
const sell = await sdk.sell({ token: "token", wallet: "wallet" }, options);
|
|
42
|
-
expect(drafts).toHaveLength(3);
|
|
43
|
-
for (const draft of drafts) {
|
|
44
|
-
expect(draft.cuLimit).toBe(300_000);
|
|
45
|
-
expect(draft.cuPriceMicroLamports).toBe(0);
|
|
46
|
-
}
|
|
47
|
-
expect(buy.status).toBe("
|
|
48
|
-
expect(sell.status).toBe("
|
|
49
|
-
expect(buy.executionId).toBe(42);
|
|
50
|
-
expect(settle).not.toHaveBeenCalled();
|
|
51
|
-
} finally {
|
|
52
|
-
sdk.close();
|
|
53
|
-
build.mockRestore();
|
|
54
|
-
signer.mockRestore();
|
|
55
|
-
compile.mockRestore();
|
|
56
|
-
submit.mockRestore();
|
|
57
|
-
settle.mockRestore();
|
|
58
|
-
rmSync(directory, { recursive: true, force: true });
|
|
59
|
-
}
|
|
60
|
-
});
|
|
1
|
+
import { expect, spyOn, test } from "bun:test";
|
|
2
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { Keypair } from "@solana/web3.js";
|
|
6
|
+
import { Solard } from "../../core/src/core/solard.ts";
|
|
7
|
+
import { TransactionComposer } from "../../core/src/tx/composer.ts";
|
|
8
|
+
import type { PlannedTransaction, TransactionDraft } from "../../core/src/tx/types.ts";
|
|
9
|
+
import { createSolard } from "./client.ts";
|
|
10
|
+
|
|
11
|
+
test("SDK buy rebuild and sell preserve custom fees in immediate submitted results", async () => {
|
|
12
|
+
const directory = mkdtempSync(join(tmpdir(), "solard-sdk-fees-"));
|
|
13
|
+
const drafts: Array<TransactionDraft> = [];
|
|
14
|
+
// A sentinel plan is never compiled, signed, or broadcast in this test.
|
|
15
|
+
const payer = Keypair.generate();
|
|
16
|
+
const plan = { payer: payer.publicKey } as PlannedTransaction;
|
|
17
|
+
const build = spyOn(TransactionComposer.prototype, "build").mockImplementation(async function (this: TransactionComposer) {
|
|
18
|
+
drafts.push(this.snapshot());
|
|
19
|
+
return { ...plan, draft: this.snapshot() };
|
|
20
|
+
});
|
|
21
|
+
const signer = spyOn(Solard.prototype, "signer").mockImplementation(() => payer);
|
|
22
|
+
const compile = spyOn(Solard.prototype, "compile").mockImplementation(async (_payer, draft) => ({ ...plan, draft }));
|
|
23
|
+
let submissions = 0;
|
|
24
|
+
const submit = spyOn(Solard.prototype, "submitPlan").mockImplementation(async () => {
|
|
25
|
+
submissions += 1;
|
|
26
|
+
if (submissions === 1) {
|
|
27
|
+
throw new Error("Simulation failed: BuySlippageBelowMinBaseAmountOut");
|
|
28
|
+
}
|
|
29
|
+
return { signature: "test-signature", sender: "rpc", executionId: 42, plan };
|
|
30
|
+
});
|
|
31
|
+
const settle = spyOn(Solard.prototype, "settleSubmission").mockImplementation(async () => {
|
|
32
|
+
throw new Error("Immediate submission must not wait for confirmation");
|
|
33
|
+
});
|
|
34
|
+
const sdk = createSolard({ dbPath: join(directory, "test.sqlite") });
|
|
35
|
+
try {
|
|
36
|
+
const options = {
|
|
37
|
+
priorityFee: { cuLimit: 300_000, microLamports: 0 },
|
|
38
|
+
waitForConfirmation: false,
|
|
39
|
+
};
|
|
40
|
+
const buy = await sdk.buy({ token: "token", wallet: "wallet", amount: 0.1 }, options);
|
|
41
|
+
const sell = await sdk.sell({ token: "token", wallet: "wallet" }, options);
|
|
42
|
+
expect(drafts).toHaveLength(3);
|
|
43
|
+
for (const draft of drafts) {
|
|
44
|
+
expect(draft.cuLimit).toBe(300_000);
|
|
45
|
+
expect(draft.cuPriceMicroLamports).toBe(0);
|
|
46
|
+
}
|
|
47
|
+
expect(buy.status).toBe("unresolved");
|
|
48
|
+
expect(sell.status).toBe("unresolved");
|
|
49
|
+
expect(buy.executionId).toBe(42);
|
|
50
|
+
expect(settle).not.toHaveBeenCalled();
|
|
51
|
+
} finally {
|
|
52
|
+
sdk.close();
|
|
53
|
+
build.mockRestore();
|
|
54
|
+
signer.mockRestore();
|
|
55
|
+
compile.mockRestore();
|
|
56
|
+
submit.mockRestore();
|
|
57
|
+
settle.mockRestore();
|
|
58
|
+
rmSync(directory, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
});
|
package/src/client.ts
CHANGED
|
@@ -17,8 +17,11 @@ import {
|
|
|
17
17
|
type ReplayOptions,
|
|
18
18
|
type ReplayEventsOptions,
|
|
19
19
|
type RecordConfirmedTradeInput,
|
|
20
|
-
type SendReceipt,
|
|
21
|
-
type TradeLandingPolicy,
|
|
20
|
+
type SendReceipt,
|
|
21
|
+
type TradeLandingPolicy,
|
|
22
|
+
type TradeResult,
|
|
23
|
+
type TradeExecutionOptions,
|
|
24
|
+
type LivePoolReserves,
|
|
22
25
|
type SenderId,
|
|
23
26
|
type SolardDecodedTransaction,
|
|
24
27
|
type SolardTransactionOptions,
|
|
@@ -35,7 +38,8 @@ import {
|
|
|
35
38
|
} from "@solard/core";
|
|
36
39
|
|
|
37
40
|
export type SolardOptions = {
|
|
38
|
-
rpcUrl?: string;
|
|
41
|
+
rpcUrl?: string;
|
|
42
|
+
rpcUrls?: readonly string[];
|
|
39
43
|
dbPath?: string;
|
|
40
44
|
cacheTtlMs?: number;
|
|
41
45
|
};
|
|
@@ -59,48 +63,50 @@ export type SolardEventsApi = {
|
|
|
59
63
|
merge(streams: readonly ReplayEventSubscription[]): MergedReplayEventStream;
|
|
60
64
|
};
|
|
61
65
|
|
|
62
|
-
export type SolardBuyInput = {
|
|
66
|
+
export type SolardBuyInput = {
|
|
67
|
+
reserves?: LivePoolReserves;
|
|
68
|
+
maxPriceSol?: string | number;
|
|
63
69
|
wallet: WalletRef;
|
|
64
70
|
token: TokenRef;
|
|
65
71
|
amount: HumanAmount | string | number;
|
|
66
72
|
slippageBps?: number;
|
|
73
|
+
minOutputRaw?: bigint | string;
|
|
67
74
|
};
|
|
68
75
|
|
|
69
|
-
export type SolardSellInput = {
|
|
76
|
+
export type SolardSellInput = {
|
|
77
|
+
closeTokenAccount?: boolean;
|
|
78
|
+
reserves?: LivePoolReserves;
|
|
79
|
+
minPriceSol?: string | number;
|
|
70
80
|
wallet: WalletRef;
|
|
71
81
|
token: TokenRef;
|
|
72
82
|
amount?: "all" | { bps: number };
|
|
73
83
|
slippageBps?: number;
|
|
84
|
+
minOutputLamports?: bigint | string;
|
|
74
85
|
};
|
|
75
86
|
|
|
76
|
-
export type SolardTradeExecutionOptions =
|
|
77
|
-
landing?: TradeLandingPolicy;
|
|
78
|
-
waitForConfirmation?: boolean;
|
|
79
|
-
priorityFee?: { cuLimit?: number; microLamports?: number };
|
|
80
|
-
via?: SenderId;
|
|
81
|
-
skipSimulation?: boolean;
|
|
82
|
-
skipPreflight?: boolean;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export type SolardTradeExecutionResult = {
|
|
86
|
-
attempts?: Array<{ executionId: number; signature: string; priorityMicroLamports: number }>;
|
|
87
|
-
executionId: number;
|
|
88
|
-
signature: string;
|
|
89
|
-
sender: string;
|
|
90
|
-
status: SendReceipt["status"];
|
|
91
|
-
slot: number | null;
|
|
92
|
-
error: string | null;
|
|
93
|
-
feeLamports?: number;
|
|
94
|
-
computeUnitsConsumed?: number;
|
|
95
|
-
/** Signed economic SOL delta excluding network fee and token-account rent. */
|
|
96
|
-
solPrincipalDeltaLamports?: bigint;
|
|
97
|
-
/** Signed target-token delta for the confirmed atomic route. */
|
|
98
|
-
targetTokenDeltaRaw?: bigint;
|
|
99
|
-
/** Confirmed transaction network fee. */
|
|
100
|
-
networkFeeLamports?: bigint;
|
|
101
|
-
};
|
|
87
|
+
export type SolardTradeExecutionOptions = TradeExecutionOptions;
|
|
102
88
|
|
|
103
|
-
export type
|
|
89
|
+
export type SolardTradeExecutionResult = TradeResult;
|
|
90
|
+
export type Solard = {
|
|
91
|
+
resolveCurrentMarket: ReturnType<typeof createCoreSolard>["resolveCurrentMarket"];
|
|
92
|
+
getClaimableCreatorFees: ReturnType<typeof createCoreSolard>["getClaimableCreatorFees"];
|
|
93
|
+
claimAllCreatorFees: ReturnType<typeof createCoreSolard>["claimAllCreatorFees"];
|
|
94
|
+
walletLedger: ReturnType<typeof createCoreSolard>["walletLedger"];
|
|
95
|
+
historicalTape: ReturnType<typeof createCoreSolard>["historicalTape"];
|
|
96
|
+
getSupportedPumpPairs: ReturnType<typeof createCoreSolard>["getSupportedPumpPairs"];
|
|
97
|
+
listVanityMints: ReturnType<typeof createCoreSolard>["listVanityMints"];
|
|
98
|
+
releaseVanityMint: ReturnType<typeof createCoreSolard>["releaseVanityMint"];
|
|
99
|
+
closeEmptyTokenAccounts: ReturnType<typeof createCoreSolard>["closeEmptyTokenAccounts"];
|
|
100
|
+
prepareTokenDeployment: ReturnType<typeof createCoreSolard>["prepareTokenDeployment"];
|
|
101
|
+
deployToken: ReturnType<typeof createCoreSolard>["deployToken"];
|
|
102
|
+
warmBlockhash: ReturnType<typeof createCoreSolard>["warmBlockhash"];
|
|
103
|
+
curveLiquidity: ReturnType<typeof createCoreSolard>["curveLiquidity"];
|
|
104
|
+
maxSendableSol: ReturnType<typeof createCoreSolard>["maxSendableSol"];
|
|
105
|
+
transferToken: ReturnType<typeof createCoreSolard>["transferToken"];
|
|
106
|
+
exitWallet: ReturnType<typeof createCoreSolard>["exitWallet"];
|
|
107
|
+
resumeTrade(intentKey: string): Promise<SolardTradeExecutionResult>;
|
|
108
|
+
reconcile(intentKey: string): Promise<SolardTradeExecutionResult>;
|
|
109
|
+
quote: ReturnType<typeof createCoreSolard>["quote"];
|
|
104
110
|
close(): void;
|
|
105
111
|
history: SolardHistoryApi;
|
|
106
112
|
events: SolardEventsApi;
|
|
@@ -183,49 +189,13 @@ async function executeTrade(
|
|
|
183
189
|
input: SolardBuyInput | SolardSellInput,
|
|
184
190
|
options: SolardTradeExecutionOptions = {},
|
|
185
191
|
): Promise<SolardTradeExecutionResult> {
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
composer.sell(sell.token, { bps: sellBps(sell.amount), slippageBps: sell.slippageBps });
|
|
194
|
-
}
|
|
195
|
-
return await composer.build();
|
|
196
|
-
}, options.via ?? "rpc", side, options);
|
|
197
|
-
const confirmedTrade =
|
|
198
|
-
receipt.status === "confirmed"
|
|
199
|
-
? (
|
|
200
|
-
await core.trades({
|
|
201
|
-
wallet: input.wallet,
|
|
202
|
-
token: input.token,
|
|
203
|
-
side,
|
|
204
|
-
status: "confirmed",
|
|
205
|
-
limit: 32,
|
|
206
|
-
})
|
|
207
|
-
).find((trade) => trade.signature === receipt.signature) ?? null
|
|
208
|
-
: null;
|
|
209
|
-
return {
|
|
210
|
-
executionId: submission.executionId,
|
|
211
|
-
signature: receipt.signature,
|
|
212
|
-
sender: receipt.sender,
|
|
213
|
-
status: receipt.status,
|
|
214
|
-
slot: receipt.slot,
|
|
215
|
-
error: receipt.error ?? null,
|
|
216
|
-
feeLamports: receipt.feeLamports,
|
|
217
|
-
computeUnitsConsumed: receipt.computeUnitsConsumed,
|
|
218
|
-
attempts,
|
|
219
|
-
...(confirmedTrade?.solDeltaLamports != null
|
|
220
|
-
? { solPrincipalDeltaLamports: confirmedTrade.solDeltaLamports }
|
|
221
|
-
: {}),
|
|
222
|
-
...(confirmedTrade?.tokenDeltaRaw != null
|
|
223
|
-
? { targetTokenDeltaRaw: confirmedTrade.tokenDeltaRaw }
|
|
224
|
-
: {}),
|
|
225
|
-
...(confirmedTrade?.networkFeeLamports != null
|
|
226
|
-
? { networkFeeLamports: confirmedTrade.networkFeeLamports }
|
|
227
|
-
: {}),
|
|
228
|
-
};
|
|
192
|
+
if (side === "buy") {
|
|
193
|
+
const buy = input as SolardBuyInput;
|
|
194
|
+
return await core.buy(buy.token, buy.wallet, tradeAmount(buy.amount), { ...options, slippageBps: buy.slippageBps, minOutputRaw: buy.minOutputRaw, maxPriceSol: buy.maxPriceSol, reserves: buy.reserves });
|
|
195
|
+
}
|
|
196
|
+
const sell = input as SolardSellInput;
|
|
197
|
+
return await core.sell(sell.token, sell.wallet, { ...options, bps: sellBps(sell.amount), slippageBps: sell.slippageBps, minOutputLamports: sell.minOutputLamports, minPriceSol: sell.minPriceSol, reserves: sell.reserves, closeTokenAccount: sell.closeTokenAccount });
|
|
198
|
+
|
|
229
199
|
}
|
|
230
200
|
|
|
231
201
|
export function createSolard(options: SolardOptions = {}): Solard {
|
|
@@ -240,7 +210,26 @@ export function createSolard(options: SolardOptions = {}): Solard {
|
|
|
240
210
|
core.events(token, eventOptions),
|
|
241
211
|
{ merge: core.events.merge },
|
|
242
212
|
) as SolardEventsApi;
|
|
243
|
-
return Object.freeze({
|
|
213
|
+
return Object.freeze({
|
|
214
|
+
resolveCurrentMarket: core.resolveCurrentMarket.bind(core),
|
|
215
|
+
getClaimableCreatorFees: core.getClaimableCreatorFees.bind(core),
|
|
216
|
+
claimAllCreatorFees: core.claimAllCreatorFees.bind(core),
|
|
217
|
+
walletLedger: core.walletLedger.bind(core),
|
|
218
|
+
historicalTape: core.historicalTape.bind(core),
|
|
219
|
+
getSupportedPumpPairs: core.getSupportedPumpPairs.bind(core),
|
|
220
|
+
listVanityMints: core.listVanityMints.bind(core),
|
|
221
|
+
releaseVanityMint: core.releaseVanityMint.bind(core),
|
|
222
|
+
closeEmptyTokenAccounts: core.closeEmptyTokenAccounts.bind(core),
|
|
223
|
+
prepareTokenDeployment: core.prepareTokenDeployment.bind(core),
|
|
224
|
+
deployToken: core.deployToken.bind(core),
|
|
225
|
+
warmBlockhash: core.warmBlockhash.bind(core),
|
|
226
|
+
curveLiquidity: core.curveLiquidity.bind(core),
|
|
227
|
+
maxSendableSol: core.maxSendableSol.bind(core),
|
|
228
|
+
transferToken: core.transferToken.bind(core),
|
|
229
|
+
exitWallet: core.exitWallet.bind(core),
|
|
230
|
+
resumeTrade: core.resumeTrade.bind(core),
|
|
231
|
+
reconcile: core.reconcile.bind(core),
|
|
232
|
+
quote: core.quote.bind(core),
|
|
244
233
|
close: core.close.bind(core),
|
|
245
234
|
history,
|
|
246
235
|
events: Object.freeze(events),
|
package/src/default.ts
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
import { getSolUsdPrice } from "@solard/core";
|
|
2
|
-
import {
|
|
3
|
-
listenTrades,
|
|
4
|
-
subscribeLaunches,
|
|
5
|
-
subscribeMigrations,
|
|
6
|
-
} from "./live.ts";
|
|
7
|
-
import { createSolard, type Solard } from "./client.ts";
|
|
8
|
-
|
|
9
|
-
type DefaultSolard = Solard & {
|
|
10
|
-
getSolUsdPrice: typeof getSolUsdPrice;
|
|
11
|
-
listenTrades: typeof listenTrades;
|
|
12
|
-
subscribeLaunches: typeof subscribeLaunches;
|
|
13
|
-
subscribeMigrations: typeof subscribeMigrations;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
let instance: Solard | undefined;
|
|
17
|
-
|
|
18
|
-
function client(): Solard {
|
|
19
|
-
instance ??= createSolard();
|
|
20
|
-
return instance;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const operations = {
|
|
24
|
-
getSolUsdPrice,
|
|
25
|
-
listenTrades,
|
|
26
|
-
subscribeLaunches,
|
|
27
|
-
subscribeMigrations,
|
|
28
|
-
} as const;
|
|
29
|
-
|
|
30
|
-
const slrd = new Proxy({} as DefaultSolard, {
|
|
31
|
-
get(_target, key) {
|
|
32
|
-
if (key === "close") {
|
|
33
|
-
return () => {
|
|
34
|
-
const current = instance;
|
|
35
|
-
instance = undefined;
|
|
36
|
-
current?.close();
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
if (typeof key === "string" && key in operations) {
|
|
40
|
-
return operations[key as keyof typeof operations];
|
|
41
|
-
}
|
|
42
|
-
const current = client();
|
|
43
|
-
const value = Reflect.get(current as object, key, current);
|
|
44
|
-
return typeof value === "function" ? value.bind(current) : value;
|
|
45
|
-
},
|
|
46
|
-
set() {
|
|
47
|
-
return false;
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
export default slrd;
|
|
1
|
+
import { getSolUsdPrice } from "@solard/core";
|
|
2
|
+
import {
|
|
3
|
+
listenTrades,
|
|
4
|
+
subscribeLaunches,
|
|
5
|
+
subscribeMigrations,
|
|
6
|
+
} from "./live.ts";
|
|
7
|
+
import { createSolard, type Solard } from "./client.ts";
|
|
8
|
+
|
|
9
|
+
type DefaultSolard = Solard & {
|
|
10
|
+
getSolUsdPrice: typeof getSolUsdPrice;
|
|
11
|
+
listenTrades: typeof listenTrades;
|
|
12
|
+
subscribeLaunches: typeof subscribeLaunches;
|
|
13
|
+
subscribeMigrations: typeof subscribeMigrations;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let instance: Solard | undefined;
|
|
17
|
+
|
|
18
|
+
function client(): Solard {
|
|
19
|
+
instance ??= createSolard();
|
|
20
|
+
return instance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const operations = {
|
|
24
|
+
getSolUsdPrice,
|
|
25
|
+
listenTrades,
|
|
26
|
+
subscribeLaunches,
|
|
27
|
+
subscribeMigrations,
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
const slrd = new Proxy({} as DefaultSolard, {
|
|
31
|
+
get(_target, key) {
|
|
32
|
+
if (key === "close") {
|
|
33
|
+
return () => {
|
|
34
|
+
const current = instance;
|
|
35
|
+
instance = undefined;
|
|
36
|
+
current?.close();
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (typeof key === "string" && key in operations) {
|
|
40
|
+
return operations[key as keyof typeof operations];
|
|
41
|
+
}
|
|
42
|
+
const current = client();
|
|
43
|
+
const value = Reflect.get(current as object, key, current);
|
|
44
|
+
return typeof value === "function" ? value.bind(current) : value;
|
|
45
|
+
},
|
|
46
|
+
set() {
|
|
47
|
+
return false;
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export default slrd;
|