@solard/cli 0.2.13 → 0.2.14
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/package.json +2 -2
- package/src/backtest-batch-command.ts +262 -0
- package/src/backtest-command.ts +533 -0
- package/src/commands/buy.ts +207 -0
- package/src/commands/jupiter-swap.test.ts +78 -0
- package/src/commands/jupiter-swap.ts +269 -0
- package/src/commands/sell.ts +239 -0
- package/src/commands/trade-result.ts +19 -0
- package/src/commands/trade-targets.ts +43 -0
- package/src/commands/trade-venue.test.ts +32 -0
- package/src/commands/trade-venue.ts +19 -0
- package/src/commands/transfer.ts +200 -0
- package/src/fairfun-commands.ts +381 -0
- package/src/index.ts +386 -290
- package/src/meteora-commands.ts +148 -6
- package/src/pump/external-deployment-cli.ts +136 -0
- package/src/pump/token-launch-cli.ts +82 -6
- package/src/raydium-commands.ts +398 -0
- package/src/refs.ts +56 -0
- package/src/token-history-command.ts +559 -0
- package/src/vault-onboarding.ts +214 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import {
|
|
2
|
+
executeJupiterSwap,
|
|
3
|
+
NATIVE_SOL_MINT,
|
|
4
|
+
nativePumpTradeAvailable,
|
|
5
|
+
quoteJupiterSwap,
|
|
6
|
+
resolveTradeRoute,
|
|
7
|
+
sol,
|
|
8
|
+
type SenderId,
|
|
9
|
+
type Solard,
|
|
10
|
+
} from "@solard/sdk";
|
|
11
|
+
|
|
12
|
+
import { resolveTradeTargets, type TradeTargets } from "./trade-targets.ts";
|
|
13
|
+
import { summarizeTradeRoute, type TradeRouteSummary } from "./trade-result.ts";
|
|
14
|
+
import { parseVenuePreference, type TradeCommandFlags } from "./trade-venue.ts";
|
|
15
|
+
|
|
16
|
+
export type SmartBuyCommandResult =
|
|
17
|
+
| {
|
|
18
|
+
mode: "simulation";
|
|
19
|
+
route: "native";
|
|
20
|
+
target: TradeTargets;
|
|
21
|
+
routing: TradeRouteSummary;
|
|
22
|
+
results: unknown[];
|
|
23
|
+
}
|
|
24
|
+
| {
|
|
25
|
+
mode: "quote";
|
|
26
|
+
route: "jupiter";
|
|
27
|
+
target: TradeTargets;
|
|
28
|
+
routing: TradeRouteSummary;
|
|
29
|
+
amountSol: string;
|
|
30
|
+
quote: Awaited<ReturnType<typeof quoteJupiterSwap>>;
|
|
31
|
+
hint: string;
|
|
32
|
+
}
|
|
33
|
+
| {
|
|
34
|
+
mode: "live";
|
|
35
|
+
route: "native";
|
|
36
|
+
target: TradeTargets;
|
|
37
|
+
routing: TradeRouteSummary;
|
|
38
|
+
receipts: unknown;
|
|
39
|
+
}
|
|
40
|
+
| {
|
|
41
|
+
mode: "live";
|
|
42
|
+
route: "jupiter";
|
|
43
|
+
target: TradeTargets;
|
|
44
|
+
routing: TradeRouteSummary;
|
|
45
|
+
results: Array<{
|
|
46
|
+
wallet: string;
|
|
47
|
+
result: Awaited<ReturnType<typeof executeJupiterSwap>>;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type RunSmartBuyCommandArgs = {
|
|
52
|
+
slrd: Solard;
|
|
53
|
+
values: string[];
|
|
54
|
+
flags: TradeCommandFlags;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function intFlag(
|
|
58
|
+
flags: TradeCommandFlags,
|
|
59
|
+
key: string,
|
|
60
|
+
fallback: number,
|
|
61
|
+
): number {
|
|
62
|
+
const value = flags.get(key);
|
|
63
|
+
if (!value || value === "true") return fallback;
|
|
64
|
+
const parsed = Number(value);
|
|
65
|
+
if (!Number.isInteger(parsed)) throw new Error(`--${key} must be an integer`);
|
|
66
|
+
return parsed;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function runSmartBuyCommand({
|
|
70
|
+
slrd,
|
|
71
|
+
values,
|
|
72
|
+
flags,
|
|
73
|
+
}: RunSmartBuyCommandArgs): Promise<SmartBuyCommandResult> {
|
|
74
|
+
const tokenRef = values[0];
|
|
75
|
+
const usage =
|
|
76
|
+
"Usage: slrd buy <token|ca> (--wallet <wallet> | --wallets <w1,w2> | --group <group>) --sol <amount> [--venue auto|native|jupiter]";
|
|
77
|
+
if (!tokenRef) throw new Error(usage);
|
|
78
|
+
|
|
79
|
+
const amountSol = flags.get("sol");
|
|
80
|
+
if (!amountSol || amountSol === "true") {
|
|
81
|
+
throw new Error("Buy requires explicit --sol <amount>");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const amount = sol(amountSol);
|
|
85
|
+
if (amount.raw <= 0n) throw new Error("--sol must be greater than zero");
|
|
86
|
+
|
|
87
|
+
const target = resolveTradeTargets(slrd, flags, usage);
|
|
88
|
+
const resolution = await resolveTradeRoute(
|
|
89
|
+
slrd,
|
|
90
|
+
tokenRef,
|
|
91
|
+
parseVenuePreference(flags),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (resolution.asset.mint === NATIVE_SOL_MINT) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"slrd buy expects an SPL token; SOL is already the input asset",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (resolution.route === "native") {
|
|
101
|
+
if (!nativePumpTradeAvailable(resolution.token)) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
"Native buy requires a registered Pump/PumpSwap token; use --venue jupiter for ordinary SPL assets",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const options = {
|
|
108
|
+
slippageBps: intFlag(flags, "slippage-bps", 1_500),
|
|
109
|
+
via: (flags.get("sender") ?? "rpc") as SenderId,
|
|
110
|
+
skipSimulation: flags.has("skip-simulation"),
|
|
111
|
+
skipPreflight:
|
|
112
|
+
flags.has("skip-preflight") || flags.has("skip-simulation"),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (flags.has("simulate-only")) {
|
|
116
|
+
const plans =
|
|
117
|
+
target.refs.length === 1
|
|
118
|
+
? [
|
|
119
|
+
await slrd
|
|
120
|
+
.tx(target.refs[0]!)
|
|
121
|
+
.buy(resolution.token!.mint, amount, options)
|
|
122
|
+
.build(),
|
|
123
|
+
]
|
|
124
|
+
: await slrd
|
|
125
|
+
.composeMany(target.refs)
|
|
126
|
+
.buy(resolution.token!.mint, amount, options)
|
|
127
|
+
.build();
|
|
128
|
+
const results = await Promise.all(
|
|
129
|
+
plans.map((plan) => slrd.simulatePlan(plan)),
|
|
130
|
+
);
|
|
131
|
+
return {
|
|
132
|
+
mode: "simulation",
|
|
133
|
+
route: "native",
|
|
134
|
+
target,
|
|
135
|
+
routing: summarizeTradeRoute(resolution),
|
|
136
|
+
results,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const receipts =
|
|
141
|
+
target.refs.length === 1
|
|
142
|
+
? await slrd.buy(
|
|
143
|
+
resolution.token!.mint,
|
|
144
|
+
target.refs[0]!,
|
|
145
|
+
amount,
|
|
146
|
+
options,
|
|
147
|
+
)
|
|
148
|
+
: await slrd.buyMany(
|
|
149
|
+
resolution.token!.mint,
|
|
150
|
+
target.refs,
|
|
151
|
+
amount,
|
|
152
|
+
options,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
mode: "live",
|
|
157
|
+
route: "native",
|
|
158
|
+
target,
|
|
159
|
+
routing: summarizeTradeRoute(resolution),
|
|
160
|
+
receipts,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (flags.has("simulate-only")) {
|
|
165
|
+
const quote = await quoteJupiterSwap({
|
|
166
|
+
inputMint: NATIVE_SOL_MINT,
|
|
167
|
+
outputMint: resolution.asset.mint,
|
|
168
|
+
amountRaw: amount.raw,
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
mode: "quote",
|
|
172
|
+
route: "jupiter",
|
|
173
|
+
target,
|
|
174
|
+
routing: summarizeTradeRoute(resolution),
|
|
175
|
+
amountSol,
|
|
176
|
+
quote,
|
|
177
|
+
hint: "Remove --simulate-only to execute this Jupiter-routed buy.",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Jupiter transport has its own measured, instance-scoped rate limiter. Keep
|
|
182
|
+
// multi-wallet execution sequential so a one-shot CLI command cannot create
|
|
183
|
+
// an avoidable burst against the API.
|
|
184
|
+
const results: Array<{
|
|
185
|
+
wallet: string;
|
|
186
|
+
result: Awaited<ReturnType<typeof executeJupiterSwap>>;
|
|
187
|
+
}> = [];
|
|
188
|
+
for (const wallet of target.refs) {
|
|
189
|
+
results.push({
|
|
190
|
+
wallet,
|
|
191
|
+
result: await executeJupiterSwap({
|
|
192
|
+
inputMint: NATIVE_SOL_MINT,
|
|
193
|
+
outputMint: resolution.asset.mint,
|
|
194
|
+
amountRaw: amount.raw,
|
|
195
|
+
signer: slrd.signer(wallet),
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
mode: "live",
|
|
202
|
+
route: "jupiter",
|
|
203
|
+
target,
|
|
204
|
+
routing: summarizeTradeRoute(resolution),
|
|
205
|
+
results,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
jupiterCliAmountRaw,
|
|
4
|
+
parseJupiterSwapCliRequest,
|
|
5
|
+
type JupiterCliAsset,
|
|
6
|
+
} from "./jupiter-swap.ts";
|
|
7
|
+
|
|
8
|
+
function flags(entries: Record<string, string>): ReadonlyMap<string, string> {
|
|
9
|
+
return new Map(Object.entries(entries));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe("Jupiter swap CLI parsing", () => {
|
|
13
|
+
test("parses generic from/to syntax", () => {
|
|
14
|
+
expect(
|
|
15
|
+
parseJupiterSwapCliRequest(
|
|
16
|
+
[],
|
|
17
|
+
flags({
|
|
18
|
+
from: "USDC",
|
|
19
|
+
to: "SOL",
|
|
20
|
+
amount: "90",
|
|
21
|
+
wallet: "phantom",
|
|
22
|
+
}),
|
|
23
|
+
),
|
|
24
|
+
).toEqual({
|
|
25
|
+
wallet: "phantom",
|
|
26
|
+
fromRef: "USDC",
|
|
27
|
+
toRef: "SOL",
|
|
28
|
+
amountUi: "90",
|
|
29
|
+
live: false,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("preserves legacy SOL input syntax", () => {
|
|
34
|
+
expect(
|
|
35
|
+
parseJupiterSwapCliRequest(
|
|
36
|
+
["USDC"],
|
|
37
|
+
flags({
|
|
38
|
+
wallet: "phantom",
|
|
39
|
+
sol: "1",
|
|
40
|
+
live: "true",
|
|
41
|
+
}),
|
|
42
|
+
),
|
|
43
|
+
).toEqual({
|
|
44
|
+
wallet: "phantom",
|
|
45
|
+
fromRef: "SOL",
|
|
46
|
+
toRef: "USDC",
|
|
47
|
+
amountUi: "1",
|
|
48
|
+
live: true,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("rejects --sol with non-SOL --from", () => {
|
|
53
|
+
expect(() =>
|
|
54
|
+
parseJupiterSwapCliRequest(
|
|
55
|
+
[],
|
|
56
|
+
flags({
|
|
57
|
+
wallet: "phantom",
|
|
58
|
+
from: "USDC",
|
|
59
|
+
to: "SOL",
|
|
60
|
+
sol: "1",
|
|
61
|
+
}),
|
|
62
|
+
),
|
|
63
|
+
).toThrow("--from SOL only");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("uses canonical SOL amount parsing", () => {
|
|
67
|
+
const solAsset: JupiterCliAsset = {
|
|
68
|
+
ref: "SOL",
|
|
69
|
+
kind: "sol",
|
|
70
|
+
symbol: "SOL",
|
|
71
|
+
mint: "So11111111111111111111111111111111111111112",
|
|
72
|
+
decimals: 9,
|
|
73
|
+
tokenProgram: null,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
expect(jupiterCliAmountRaw(solAsset, "1.25")).toBe(1_250_000_000n);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
executeJupiterSwap,
|
|
4
|
+
formatRaw,
|
|
5
|
+
quoteJupiterSwap,
|
|
6
|
+
RaydiumService,
|
|
7
|
+
resolveTradeAsset,
|
|
8
|
+
sol,
|
|
9
|
+
tokenAmount,
|
|
10
|
+
type JupiterSwapExecuteResult,
|
|
11
|
+
type JupiterSwapQuote,
|
|
12
|
+
type Solard,
|
|
13
|
+
type TradeAsset,
|
|
14
|
+
} from "@solard/sdk";
|
|
15
|
+
|
|
16
|
+
export type JupiterSwapCliFlags = ReadonlyMap<string, string>;
|
|
17
|
+
|
|
18
|
+
export type JupiterCliAsset = TradeAsset;
|
|
19
|
+
|
|
20
|
+
export type JupiterSwapCliRequest = {
|
|
21
|
+
wallet: string;
|
|
22
|
+
fromRef: string;
|
|
23
|
+
toRef: string;
|
|
24
|
+
amountUi: string;
|
|
25
|
+
live: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type JupiterSwapQuoteCommandResult = {
|
|
29
|
+
mode: "quote";
|
|
30
|
+
wallet: string;
|
|
31
|
+
input: JupiterCliAsset & { amountUi: string; amountRaw: bigint };
|
|
32
|
+
output: JupiterCliAsset & { expectedOutputUi: string };
|
|
33
|
+
quote: JupiterSwapQuote;
|
|
34
|
+
hint: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type JupiterSwapLiveCommandResult = {
|
|
38
|
+
mode: "live";
|
|
39
|
+
wallet: string;
|
|
40
|
+
input: JupiterCliAsset & { amountUi: string; amountRaw: bigint };
|
|
41
|
+
output: JupiterCliAsset;
|
|
42
|
+
result: JupiterSwapExecuteResult;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type JupiterSwapCommandResult =
|
|
46
|
+
JupiterSwapQuoteCommandResult | JupiterSwapLiveCommandResult;
|
|
47
|
+
|
|
48
|
+
export type RaydiumSwapCommandResult =
|
|
49
|
+
| {
|
|
50
|
+
mode: "quote";
|
|
51
|
+
route: "raydium";
|
|
52
|
+
wallet: string;
|
|
53
|
+
input: JupiterCliAsset & { amountUi: string; amountRaw: bigint };
|
|
54
|
+
output: JupiterCliAsset & {
|
|
55
|
+
expectedOutputUi: string;
|
|
56
|
+
minimumOutputUi: string;
|
|
57
|
+
};
|
|
58
|
+
quote: Awaited<ReturnType<RaydiumService["quoteExactIn"]>>;
|
|
59
|
+
hint: string;
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
mode: "live";
|
|
63
|
+
route: "raydium";
|
|
64
|
+
wallet: string;
|
|
65
|
+
input: JupiterCliAsset & { amountUi: string; amountRaw: bigint };
|
|
66
|
+
output: JupiterCliAsset;
|
|
67
|
+
result: Awaited<ReturnType<RaydiumService["executePrepared"]>>;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
type RunJupiterSwapCommandArgs = {
|
|
71
|
+
slrd: Solard;
|
|
72
|
+
values: string[];
|
|
73
|
+
flags: JupiterSwapCliFlags;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
function requiredFlag(flags: JupiterSwapCliFlags, key: string): string {
|
|
77
|
+
const value = flags.get(key);
|
|
78
|
+
if (!value || value === "true") {
|
|
79
|
+
throw new Error(`Missing --${key} <value>`);
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function parseJupiterSwapCliRequest(
|
|
85
|
+
values: readonly string[],
|
|
86
|
+
flags: JupiterSwapCliFlags,
|
|
87
|
+
): JupiterSwapCliRequest {
|
|
88
|
+
const usage =
|
|
89
|
+
"Usage: slrd swap --from <SOL|token|mint> --to <SOL|token|mint> --amount <ui> --wallet <wallet> [--live]\n" +
|
|
90
|
+
" or: slrd swap <token|mint> --wallet <wallet> --sol <amount> [--live]";
|
|
91
|
+
|
|
92
|
+
const wallet = requiredFlag(flags, "wallet");
|
|
93
|
+
const legacySolAmount = flags.get("sol");
|
|
94
|
+
const fromRef = flags.get("from") ?? (legacySolAmount ? "SOL" : undefined);
|
|
95
|
+
const toRef = flags.get("to") ?? values[0];
|
|
96
|
+
const amountUi = flags.get("amount") ?? legacySolAmount;
|
|
97
|
+
|
|
98
|
+
if (!fromRef || !toRef || !amountUi || amountUi === "true") {
|
|
99
|
+
throw new Error(usage);
|
|
100
|
+
}
|
|
101
|
+
if (legacySolAmount && fromRef.trim().toUpperCase() !== "SOL") {
|
|
102
|
+
throw new Error(
|
|
103
|
+
"--sol is compatibility syntax for --from SOL only; use --amount with non-SOL input",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
wallet,
|
|
109
|
+
fromRef,
|
|
110
|
+
toRef,
|
|
111
|
+
amountUi,
|
|
112
|
+
live: flags.has("live"),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function resolveJupiterCliAsset(
|
|
117
|
+
slrd: Solard,
|
|
118
|
+
refInput: string,
|
|
119
|
+
): Promise<JupiterCliAsset> {
|
|
120
|
+
return await resolveTradeAsset(slrd, refInput);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function jupiterCliAmountRaw(
|
|
124
|
+
asset: JupiterCliAsset,
|
|
125
|
+
amountUi: string,
|
|
126
|
+
): bigint {
|
|
127
|
+
const raw =
|
|
128
|
+
asset.kind === "sol"
|
|
129
|
+
? sol(amountUi).raw
|
|
130
|
+
: (() => {
|
|
131
|
+
if (!asset.tokenProgram) {
|
|
132
|
+
throw new Error(`Missing token program for ${asset.mint}`);
|
|
133
|
+
}
|
|
134
|
+
return tokenAmount(
|
|
135
|
+
amountUi,
|
|
136
|
+
new PublicKey(asset.mint),
|
|
137
|
+
asset.decimals,
|
|
138
|
+
new PublicKey(asset.tokenProgram),
|
|
139
|
+
).raw;
|
|
140
|
+
})();
|
|
141
|
+
|
|
142
|
+
if (raw <= 0n) throw new Error("Swap amount must be greater than zero");
|
|
143
|
+
return raw;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function runJupiterSwapCommand({
|
|
147
|
+
slrd,
|
|
148
|
+
values,
|
|
149
|
+
flags,
|
|
150
|
+
}: RunJupiterSwapCommandArgs): Promise<
|
|
151
|
+
JupiterSwapCommandResult | RaydiumSwapCommandResult
|
|
152
|
+
> {
|
|
153
|
+
const request = parseJupiterSwapCliRequest(values, flags);
|
|
154
|
+
|
|
155
|
+
const [input, output] = await Promise.all([
|
|
156
|
+
resolveJupiterCliAsset(slrd, request.fromRef),
|
|
157
|
+
resolveJupiterCliAsset(slrd, request.toRef),
|
|
158
|
+
]);
|
|
159
|
+
if (input.mint === output.mint) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Swap input and output resolve to the same mint: ${input.mint}`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const amountRaw = jupiterCliAmountRaw(input, request.amountUi);
|
|
166
|
+
|
|
167
|
+
const raydiumRequested =
|
|
168
|
+
flags.has("raydium") ||
|
|
169
|
+
(flags.get("venue") ?? "").toLowerCase() === "raydium";
|
|
170
|
+
if (raydiumRequested) {
|
|
171
|
+
const raydium = new RaydiumService(slrd);
|
|
172
|
+
const slippageBps = (() => {
|
|
173
|
+
const value = flags.get("slippage-bps");
|
|
174
|
+
if (!value || value === "true") return 100;
|
|
175
|
+
const parsed = Number(value);
|
|
176
|
+
if (!Number.isInteger(parsed))
|
|
177
|
+
throw new Error("--slippage-bps must be an integer");
|
|
178
|
+
return parsed;
|
|
179
|
+
})();
|
|
180
|
+
if (!request.live) {
|
|
181
|
+
const quote = await raydium.quoteExactIn({
|
|
182
|
+
inputMint: input.mint,
|
|
183
|
+
outputMint: output.mint,
|
|
184
|
+
amountRaw,
|
|
185
|
+
slippageBps,
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
mode: "quote",
|
|
189
|
+
route: "raydium",
|
|
190
|
+
wallet: request.wallet,
|
|
191
|
+
input: { ...input, amountUi: request.amountUi, amountRaw },
|
|
192
|
+
output: {
|
|
193
|
+
...output,
|
|
194
|
+
expectedOutputUi: formatRaw(quote.outputRaw, output.decimals),
|
|
195
|
+
minimumOutputUi: formatRaw(quote.minOutputRaw, output.decimals),
|
|
196
|
+
},
|
|
197
|
+
quote,
|
|
198
|
+
hint: "Re-run with --live and SOLARD_ENABLE_LIVE_TRADES=1 to execute this Raydium swap.",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const prepared = await raydium.buildSwapExactIn({
|
|
202
|
+
wallet: request.wallet,
|
|
203
|
+
inputMint: input.mint,
|
|
204
|
+
outputMint: output.mint,
|
|
205
|
+
amountRaw,
|
|
206
|
+
slippageBps,
|
|
207
|
+
computeUnitPriceMicroLamports:
|
|
208
|
+
flags.get("priority-micro-lamports") === "true"
|
|
209
|
+
? undefined
|
|
210
|
+
: flags.get("priority-micro-lamports"),
|
|
211
|
+
});
|
|
212
|
+
const result = await raydium.executePrepared(prepared, {
|
|
213
|
+
live: true,
|
|
214
|
+
simulate: !flags.has("skip-simulation"),
|
|
215
|
+
skipPreflight: flags.has("skip-preflight"),
|
|
216
|
+
});
|
|
217
|
+
return {
|
|
218
|
+
mode: "live",
|
|
219
|
+
route: "raydium",
|
|
220
|
+
wallet: request.wallet,
|
|
221
|
+
input: { ...input, amountUi: request.amountUi, amountRaw },
|
|
222
|
+
output,
|
|
223
|
+
result,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!request.live) {
|
|
228
|
+
const quote = await quoteJupiterSwap({
|
|
229
|
+
inputMint: input.mint,
|
|
230
|
+
outputMint: output.mint,
|
|
231
|
+
amountRaw,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
mode: "quote",
|
|
236
|
+
wallet: request.wallet,
|
|
237
|
+
input: {
|
|
238
|
+
...input,
|
|
239
|
+
amountUi: request.amountUi,
|
|
240
|
+
amountRaw,
|
|
241
|
+
},
|
|
242
|
+
output: {
|
|
243
|
+
...output,
|
|
244
|
+
expectedOutputUi: formatRaw(quote.outAmountRaw, output.decimals),
|
|
245
|
+
},
|
|
246
|
+
quote,
|
|
247
|
+
hint: "Re-run with --live to execute this exact-input Jupiter swap.",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const result = await executeJupiterSwap({
|
|
252
|
+
inputMint: input.mint,
|
|
253
|
+
outputMint: output.mint,
|
|
254
|
+
amountRaw,
|
|
255
|
+
signer: slrd.signer(request.wallet),
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
mode: "live",
|
|
260
|
+
wallet: request.wallet,
|
|
261
|
+
input: {
|
|
262
|
+
...input,
|
|
263
|
+
amountUi: request.amountUi,
|
|
264
|
+
amountRaw,
|
|
265
|
+
},
|
|
266
|
+
output,
|
|
267
|
+
result,
|
|
268
|
+
};
|
|
269
|
+
}
|