@solana-compass/cli 0.1.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 +327 -0
- package/bin/sol.mjs +6 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +73 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/lend.d.ts +2 -0
- package/dist/commands/lend.js +262 -0
- package/dist/commands/lend.js.map +1 -0
- package/dist/commands/lp.d.ts +2 -0
- package/dist/commands/lp.js +158 -0
- package/dist/commands/lp.js.map +1 -0
- package/dist/commands/network.d.ts +2 -0
- package/dist/commands/network.js +126 -0
- package/dist/commands/network.js.map +1 -0
- package/dist/commands/portfolio.d.ts +2 -0
- package/dist/commands/portfolio.js +187 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/stake.d.ts +2 -0
- package/dist/commands/stake.js +143 -0
- package/dist/commands/stake.js.map +1 -0
- package/dist/commands/token.d.ts +2 -0
- package/dist/commands/token.js +551 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/commands/tx.d.ts +2 -0
- package/dist/commands/tx.js +131 -0
- package/dist/commands/tx.js.map +1 -0
- package/dist/commands/wallet.d.ts +2 -0
- package/dist/commands/wallet.js +403 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/core/config-manager.d.ts +31 -0
- package/dist/core/config-manager.js +79 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/kamino-compat.d.ts +17 -0
- package/dist/core/kamino-compat.js +38 -0
- package/dist/core/kamino-compat.js.map +1 -0
- package/dist/core/lend-service.d.ts +41 -0
- package/dist/core/lend-service.js +331 -0
- package/dist/core/lend-service.js.map +1 -0
- package/dist/core/lp-service.d.ts +30 -0
- package/dist/core/lp-service.js +21 -0
- package/dist/core/lp-service.js.map +1 -0
- package/dist/core/onramp-service.d.ts +15 -0
- package/dist/core/onramp-service.js +57 -0
- package/dist/core/onramp-service.js.map +1 -0
- package/dist/core/portfolio-service.d.ts +55 -0
- package/dist/core/portfolio-service.js +272 -0
- package/dist/core/portfolio-service.js.map +1 -0
- package/dist/core/price-service.d.ts +8 -0
- package/dist/core/price-service.js +116 -0
- package/dist/core/price-service.js.map +1 -0
- package/dist/core/rpc.d.ts +5 -0
- package/dist/core/rpc.js +69 -0
- package/dist/core/rpc.js.map +1 -0
- package/dist/core/stake-service.d.ts +42 -0
- package/dist/core/stake-service.js +319 -0
- package/dist/core/stake-service.js.map +1 -0
- package/dist/core/swap-service.d.ts +31 -0
- package/dist/core/swap-service.js +142 -0
- package/dist/core/swap-service.js.map +1 -0
- package/dist/core/token-registry.d.ts +23 -0
- package/dist/core/token-registry.js +174 -0
- package/dist/core/token-registry.js.map +1 -0
- package/dist/core/token-service.d.ts +20 -0
- package/dist/core/token-service.js +92 -0
- package/dist/core/token-service.js.map +1 -0
- package/dist/core/transaction.d.ts +55 -0
- package/dist/core/transaction.js +196 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/wallet-manager.d.ts +20 -0
- package/dist/core/wallet-manager.js +142 -0
- package/dist/core/wallet-manager.js.map +1 -0
- package/dist/db/database.d.ts +3 -0
- package/dist/db/database.js +44 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/migrations/001_initial.d.ts +1 -0
- package/dist/db/migrations/001_initial.js +116 -0
- package/dist/db/migrations/001_initial.js.map +1 -0
- package/dist/db/migrations/002_tx_prices.d.ts +1 -0
- package/dist/db/migrations/002_tx_prices.js +5 -0
- package/dist/db/migrations/002_tx_prices.js.map +1 -0
- package/dist/db/repos/price-repo.d.ts +11 -0
- package/dist/db/repos/price-repo.js +14 -0
- package/dist/db/repos/price-repo.js.map +1 -0
- package/dist/db/repos/snapshot-repo.d.ts +27 -0
- package/dist/db/repos/snapshot-repo.js +32 -0
- package/dist/db/repos/snapshot-repo.js.map +1 -0
- package/dist/db/repos/token-repo.d.ts +17 -0
- package/dist/db/repos/token-repo.js +53 -0
- package/dist/db/repos/token-repo.js.map +1 -0
- package/dist/db/repos/transaction-repo.d.ts +22 -0
- package/dist/db/repos/transaction-repo.js +28 -0
- package/dist/db/repos/transaction-repo.js.map +1 -0
- package/dist/db/repos/wallet-repo.d.ts +18 -0
- package/dist/db/repos/wallet-repo.js +44 -0
- package/dist/db/repos/wallet-repo.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/output/formatter.d.ts +27 -0
- package/dist/output/formatter.js +76 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/output/portfolio-renderer.d.ts +3 -0
- package/dist/output/portfolio-renderer.js +205 -0
- package/dist/output/portfolio-renderer.js.map +1 -0
- package/dist/output/table.d.ts +8 -0
- package/dist/output/table.js +22 -0
- package/dist/output/table.js.map +1 -0
- package/dist/utils/fs.d.ts +7 -0
- package/dist/utils/fs.js +39 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/retry.d.ts +17 -0
- package/dist/utils/retry.js +55 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/solana.d.ts +9 -0
- package/dist/utils/solana.js +26 -0
- package/dist/utils/solana.js.map +1 -0
- package/dist/utils/token-list.d.ts +9 -0
- package/dist/utils/token-list.js +31 -0
- package/dist/utils/token-list.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const SOLANA_COMPASS_VOTE = "EARNynHRWg6GfyJCmrrizcZxARB3HVzcaasvNa8kBS72";
|
|
2
|
+
export interface StakeAccountInfo {
|
|
3
|
+
address: string;
|
|
4
|
+
lamports: number;
|
|
5
|
+
solBalance: number;
|
|
6
|
+
status: string;
|
|
7
|
+
validator?: string;
|
|
8
|
+
activationEpoch?: number;
|
|
9
|
+
deactivationEpoch?: number;
|
|
10
|
+
claimableExcess: number;
|
|
11
|
+
}
|
|
12
|
+
export interface CreateStakeResult {
|
|
13
|
+
stakeAccount: string;
|
|
14
|
+
validator: string;
|
|
15
|
+
amountSol: number;
|
|
16
|
+
signature: string;
|
|
17
|
+
explorerUrl: string;
|
|
18
|
+
}
|
|
19
|
+
export interface WithdrawStakeResult {
|
|
20
|
+
action: 'deactivated' | 'withdrawn' | 'split+deactivated';
|
|
21
|
+
stakeAccount: string;
|
|
22
|
+
splitAccount?: string;
|
|
23
|
+
amountSol?: number;
|
|
24
|
+
signature?: string;
|
|
25
|
+
explorerUrl?: string;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ClaimMevResult {
|
|
29
|
+
action: 'compounded' | 'withdrawn';
|
|
30
|
+
stakeAccount: string;
|
|
31
|
+
validator?: string;
|
|
32
|
+
amountSol: number;
|
|
33
|
+
withdrawSignature: string;
|
|
34
|
+
withdrawExplorerUrl: string;
|
|
35
|
+
newStakeAccount?: string;
|
|
36
|
+
stakeSignature?: string;
|
|
37
|
+
stakeExplorerUrl?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function getStakeAccounts(walletAddress: string): Promise<StakeAccountInfo[]>;
|
|
40
|
+
export declare function createAndDelegateStake(walletName: string, amountSol: number, validatorVote?: string): Promise<CreateStakeResult>;
|
|
41
|
+
export declare function withdrawStake(walletName: string, stakeAccountAddress: string, amountSol?: number, force?: boolean): Promise<WithdrawStakeResult>;
|
|
42
|
+
export declare function claimMev(walletName: string, stakeAccountAddress?: string, withdrawOnly?: boolean): Promise<ClaimMevResult[]>;
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { address, generateKeyPairSigner } from '@solana/kit';
|
|
2
|
+
import { getCreateAccountInstruction } from '@solana-program/system';
|
|
3
|
+
import { STAKE_PROGRAM_ADDRESS, getInitializeInstruction, getDelegateStakeInstruction, getDeactivateInstruction, getWithdrawInstruction, getSplitInstruction, } from '@solana-program/stake';
|
|
4
|
+
import { getRpc } from './rpc.js';
|
|
5
|
+
import { loadSigner } from './wallet-manager.js';
|
|
6
|
+
import { verbose } from '../output/formatter.js';
|
|
7
|
+
import { lamportsToSol, solToLamports } from '../utils/solana.js';
|
|
8
|
+
import { buildAndSendTransaction } from './transaction.js';
|
|
9
|
+
// Solana Compass validator — default recommendation
|
|
10
|
+
export const SOLANA_COMPASS_VOTE = 'EARNynHRWg6GfyJCmrrizcZxARB3HVzcaasvNa8kBS72';
|
|
11
|
+
const STAKE_ACCOUNT_SIZE = 200n;
|
|
12
|
+
const STAKE_HISTORY_SYSVAR = address('SysvarStakeHistory1111111111111111111111111');
|
|
13
|
+
const STAKE_CONFIG = address('StakeConfig11111111111111111111111111111111');
|
|
14
|
+
const SYSTEM_PROGRAM = address('11111111111111111111111111111111');
|
|
15
|
+
// ── Read operations ───────────────────────────────────────
|
|
16
|
+
export async function getStakeAccounts(walletAddress) {
|
|
17
|
+
const rpc = getRpc();
|
|
18
|
+
verbose(`Fetching stake accounts for ${walletAddress}`);
|
|
19
|
+
try {
|
|
20
|
+
const accounts = await rpc.getProgramAccounts(address('Stake11111111111111111111111111111111111111'), {
|
|
21
|
+
filters: [
|
|
22
|
+
{ memcmp: { offset: BigInt(12), bytes: walletAddress, encoding: 'base58' } },
|
|
23
|
+
],
|
|
24
|
+
encoding: 'jsonParsed',
|
|
25
|
+
}).send();
|
|
26
|
+
return accounts.map((acc) => {
|
|
27
|
+
const parsed = acc.account.data?.parsed?.info;
|
|
28
|
+
const stakeType = acc.account.data?.parsed?.type;
|
|
29
|
+
const meta = parsed?.meta;
|
|
30
|
+
const stake = parsed?.stake;
|
|
31
|
+
const lamportVal = Number(acc.account.lamports);
|
|
32
|
+
// Compute claimable MEV excess for delegated accounts
|
|
33
|
+
let claimableExcess = 0;
|
|
34
|
+
if (stakeType === 'delegated' && meta && stake?.delegation) {
|
|
35
|
+
const rentExemptReserve = BigInt(meta.rentExemptReserve || 0);
|
|
36
|
+
const delegatedStake = BigInt(stake.delegation.stake || 0);
|
|
37
|
+
const excess = BigInt(lamportVal) - rentExemptReserve - delegatedStake;
|
|
38
|
+
if (excess > 0n)
|
|
39
|
+
claimableExcess = lamportsToSol(Number(excess));
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
address: acc.pubkey,
|
|
43
|
+
lamports: lamportVal,
|
|
44
|
+
solBalance: lamportsToSol(lamportVal),
|
|
45
|
+
status: stakeType || 'unknown',
|
|
46
|
+
validator: stake?.delegation?.voter,
|
|
47
|
+
activationEpoch: stake?.delegation?.activationEpoch ? Number(stake.delegation.activationEpoch) : undefined,
|
|
48
|
+
deactivationEpoch: stake?.delegation?.deactivationEpoch ? Number(stake.delegation.deactivationEpoch) : undefined,
|
|
49
|
+
claimableExcess,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
verbose(`Failed to fetch stake accounts: ${err}`);
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ── Create + delegate ─────────────────────────────────────
|
|
59
|
+
export async function createAndDelegateStake(walletName, amountSol, validatorVote) {
|
|
60
|
+
const rpc = getRpc();
|
|
61
|
+
const signer = await loadSigner(walletName);
|
|
62
|
+
const validator = validatorVote || SOLANA_COMPASS_VOTE;
|
|
63
|
+
// Generate ephemeral keypair for the new stake account
|
|
64
|
+
const stakeAccountSigner = await generateKeyPairSigner();
|
|
65
|
+
// Calculate lamports: rent-exempt minimum + stake amount
|
|
66
|
+
const rentExempt = await rpc.getMinimumBalanceForRentExemption(STAKE_ACCOUNT_SIZE).send();
|
|
67
|
+
const stakeLamports = solToLamports(amountSol);
|
|
68
|
+
const totalLamports = rentExempt + stakeLamports;
|
|
69
|
+
verbose(`Creating stake account ${stakeAccountSigner.address}`);
|
|
70
|
+
verbose(`Rent exempt: ${rentExempt}, stake: ${stakeLamports}, total: ${totalLamports}`);
|
|
71
|
+
const instructions = [
|
|
72
|
+
// 1. Create account owned by stake program
|
|
73
|
+
getCreateAccountInstruction({
|
|
74
|
+
payer: signer,
|
|
75
|
+
newAccount: stakeAccountSigner,
|
|
76
|
+
lamports: totalLamports,
|
|
77
|
+
space: STAKE_ACCOUNT_SIZE,
|
|
78
|
+
programAddress: STAKE_PROGRAM_ADDRESS,
|
|
79
|
+
}),
|
|
80
|
+
// 2. Initialize: set staker + withdrawer to our wallet
|
|
81
|
+
getInitializeInstruction({
|
|
82
|
+
stake: stakeAccountSigner.address,
|
|
83
|
+
arg0: { staker: signer.address, withdrawer: signer.address },
|
|
84
|
+
arg1: { unixTimestamp: 0, epoch: 0, custodian: SYSTEM_PROGRAM },
|
|
85
|
+
}),
|
|
86
|
+
// 3. Delegate to validator
|
|
87
|
+
getDelegateStakeInstruction({
|
|
88
|
+
stake: stakeAccountSigner.address,
|
|
89
|
+
vote: address(validator),
|
|
90
|
+
stakeHistory: STAKE_HISTORY_SYSVAR,
|
|
91
|
+
unused: STAKE_CONFIG,
|
|
92
|
+
stakeAuthority: signer,
|
|
93
|
+
}),
|
|
94
|
+
];
|
|
95
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
96
|
+
txType: 'stake',
|
|
97
|
+
walletName,
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
stakeAccount: stakeAccountSigner.address,
|
|
101
|
+
validator,
|
|
102
|
+
amountSol,
|
|
103
|
+
signature: result.signature,
|
|
104
|
+
explorerUrl: result.explorerUrl,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// ── Smart withdraw ────────────────────────────────────────
|
|
108
|
+
export async function withdrawStake(walletName, stakeAccountAddress, amountSol, force) {
|
|
109
|
+
const rpc = getRpc();
|
|
110
|
+
const signer = await loadSigner(walletName);
|
|
111
|
+
const stakeAddr = address(stakeAccountAddress);
|
|
112
|
+
// If --force, just withdraw directly
|
|
113
|
+
if (force) {
|
|
114
|
+
return forceWithdraw(signer, stakeAddr, walletName, amountSol);
|
|
115
|
+
}
|
|
116
|
+
// Check stake account status
|
|
117
|
+
const accountInfo = await rpc.getAccountInfo(stakeAddr, { encoding: 'jsonParsed' }).send();
|
|
118
|
+
if (!accountInfo.value) {
|
|
119
|
+
throw new Error(`Stake account ${stakeAccountAddress} not found`);
|
|
120
|
+
}
|
|
121
|
+
const data = accountInfo.value.data;
|
|
122
|
+
const stakeType = data?.parsed?.type || 'unknown';
|
|
123
|
+
const parsed = data?.parsed?.info;
|
|
124
|
+
const lamportBalance = Number(accountInfo.value.lamports);
|
|
125
|
+
verbose(`Stake account status: ${stakeType}, balance: ${lamportsToSol(lamportBalance)} SOL`);
|
|
126
|
+
// Partial withdrawal → split + deactivate
|
|
127
|
+
if (amountSol !== undefined) {
|
|
128
|
+
return partialWithdraw(signer, stakeAddr, amountSol, walletName, rpc);
|
|
129
|
+
}
|
|
130
|
+
// Full withdrawal — depends on current state
|
|
131
|
+
switch (stakeType) {
|
|
132
|
+
case 'delegated': {
|
|
133
|
+
// Check deactivation epoch
|
|
134
|
+
const deactivationEpoch = parsed?.stake?.delegation?.deactivationEpoch;
|
|
135
|
+
const epochInfo = await rpc.getEpochInfo().send();
|
|
136
|
+
const currentEpoch = Number(epochInfo.epoch);
|
|
137
|
+
if (deactivationEpoch && Number(deactivationEpoch) < Number('18446744073709551615') && Number(deactivationEpoch) <= currentEpoch) {
|
|
138
|
+
// Already deactivated and cooldown passed → withdraw
|
|
139
|
+
return forceWithdraw(signer, stakeAddr, walletName);
|
|
140
|
+
}
|
|
141
|
+
if (deactivationEpoch && Number(deactivationEpoch) < Number('18446744073709551615')) {
|
|
142
|
+
// Deactivating but not ready yet
|
|
143
|
+
return {
|
|
144
|
+
action: 'deactivated',
|
|
145
|
+
stakeAccount: stakeAccountAddress,
|
|
146
|
+
message: `Stake account is deactivating (epoch ${deactivationEpoch}). Current epoch: ${currentEpoch}. Wait for the cooldown to complete, then run:\n sol stake withdraw ${stakeAccountAddress} --force`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Active → deactivate
|
|
150
|
+
const ix = getDeactivateInstruction({
|
|
151
|
+
stake: stakeAddr,
|
|
152
|
+
stakeAuthority: signer,
|
|
153
|
+
});
|
|
154
|
+
const result = await buildAndSendTransaction([ix], signer, {
|
|
155
|
+
txType: 'stake-deactivate',
|
|
156
|
+
walletName,
|
|
157
|
+
});
|
|
158
|
+
return {
|
|
159
|
+
action: 'deactivated',
|
|
160
|
+
stakeAccount: stakeAccountAddress,
|
|
161
|
+
signature: result.signature,
|
|
162
|
+
explorerUrl: result.explorerUrl,
|
|
163
|
+
message: `Stake account deactivated. Wait for the cooldown epoch to pass, then withdraw:\n sol stake withdraw ${stakeAccountAddress} --force`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
case 'initialized': {
|
|
167
|
+
// Not delegated, can withdraw directly
|
|
168
|
+
return forceWithdraw(signer, stakeAddr, walletName);
|
|
169
|
+
}
|
|
170
|
+
default:
|
|
171
|
+
throw new Error(`Unexpected stake account state: "${stakeType}". Use --force to attempt a direct withdraw.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ── Force withdraw ────────────────────────────────────────
|
|
175
|
+
async function forceWithdraw(signer, stakeAddr, walletName, amountSol) {
|
|
176
|
+
const rpc = getRpc();
|
|
177
|
+
// If no amount specified, withdraw everything
|
|
178
|
+
let withdrawLamports;
|
|
179
|
+
if (amountSol !== undefined) {
|
|
180
|
+
withdrawLamports = solToLamports(amountSol);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const accountInfo = await rpc.getAccountInfo(stakeAddr, { encoding: 'base64' }).send();
|
|
184
|
+
if (!accountInfo.value)
|
|
185
|
+
throw new Error(`Stake account not found`);
|
|
186
|
+
withdrawLamports = accountInfo.value.lamports;
|
|
187
|
+
}
|
|
188
|
+
const ix = getWithdrawInstruction({
|
|
189
|
+
stake: stakeAddr,
|
|
190
|
+
recipient: signer.address,
|
|
191
|
+
stakeHistory: STAKE_HISTORY_SYSVAR,
|
|
192
|
+
withdrawAuthority: signer,
|
|
193
|
+
args: withdrawLamports,
|
|
194
|
+
});
|
|
195
|
+
const result = await buildAndSendTransaction([ix], signer, {
|
|
196
|
+
txType: 'stake-withdraw',
|
|
197
|
+
walletName,
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
action: 'withdrawn',
|
|
201
|
+
stakeAccount: String(stakeAddr),
|
|
202
|
+
amountSol: lamportsToSol(withdrawLamports),
|
|
203
|
+
signature: result.signature,
|
|
204
|
+
explorerUrl: result.explorerUrl,
|
|
205
|
+
message: `Withdrew ${lamportsToSol(withdrawLamports)} SOL from stake account`,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// ── Partial withdraw (split + deactivate) ─────────────────
|
|
209
|
+
async function partialWithdraw(signer, stakeAddr, amountSol, walletName, rpc) {
|
|
210
|
+
const splitLamports = solToLamports(amountSol);
|
|
211
|
+
// Generate ephemeral keypair for the split account
|
|
212
|
+
const splitAccountSigner = await generateKeyPairSigner();
|
|
213
|
+
// Split requires the destination account to exist (system create with 0 lamports, stake program owner)
|
|
214
|
+
const rentExempt = await rpc.getMinimumBalanceForRentExemption(STAKE_ACCOUNT_SIZE).send();
|
|
215
|
+
const instructions = [
|
|
216
|
+
// Create the split destination account
|
|
217
|
+
getCreateAccountInstruction({
|
|
218
|
+
payer: signer,
|
|
219
|
+
newAccount: splitAccountSigner,
|
|
220
|
+
lamports: rentExempt,
|
|
221
|
+
space: STAKE_ACCOUNT_SIZE,
|
|
222
|
+
programAddress: STAKE_PROGRAM_ADDRESS,
|
|
223
|
+
}),
|
|
224
|
+
// Split desired amount into the new account
|
|
225
|
+
getSplitInstruction({
|
|
226
|
+
stake: stakeAddr,
|
|
227
|
+
splitStake: splitAccountSigner.address,
|
|
228
|
+
stakeAuthority: signer,
|
|
229
|
+
args: splitLamports,
|
|
230
|
+
}),
|
|
231
|
+
// Deactivate the split account so it can be withdrawn later
|
|
232
|
+
getDeactivateInstruction({
|
|
233
|
+
stake: splitAccountSigner.address,
|
|
234
|
+
stakeAuthority: signer,
|
|
235
|
+
}),
|
|
236
|
+
];
|
|
237
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
238
|
+
txType: 'stake-split',
|
|
239
|
+
walletName,
|
|
240
|
+
});
|
|
241
|
+
return {
|
|
242
|
+
action: 'split+deactivated',
|
|
243
|
+
stakeAccount: String(stakeAddr),
|
|
244
|
+
splitAccount: splitAccountSigner.address,
|
|
245
|
+
amountSol,
|
|
246
|
+
signature: result.signature,
|
|
247
|
+
explorerUrl: result.explorerUrl,
|
|
248
|
+
message: `Split ${amountSol} SOL into ${splitAccountSigner.address} and deactivated it. After the cooldown epoch, withdraw with:\n sol stake withdraw ${splitAccountSigner.address} --force`,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// ── Claim MEV ─────────────────────────────────────────────
|
|
252
|
+
export async function claimMev(walletName, stakeAccountAddress, withdrawOnly) {
|
|
253
|
+
const signer = await loadSigner(walletName);
|
|
254
|
+
const wallet = await import('../db/repos/wallet-repo.js').then(m => m.getWallet(walletName));
|
|
255
|
+
if (!wallet)
|
|
256
|
+
throw new Error(`Wallet "${walletName}" not found`);
|
|
257
|
+
// Get accounts with claimable excess
|
|
258
|
+
let targets;
|
|
259
|
+
if (stakeAccountAddress) {
|
|
260
|
+
const all = await getStakeAccounts(wallet.address);
|
|
261
|
+
const match = all.find(a => a.address === stakeAccountAddress);
|
|
262
|
+
if (!match)
|
|
263
|
+
throw new Error(`Stake account ${stakeAccountAddress} not found`);
|
|
264
|
+
if (match.claimableExcess <= 0)
|
|
265
|
+
throw new Error('No claimable MEV on this account');
|
|
266
|
+
targets = [match];
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
const all = await getStakeAccounts(wallet.address);
|
|
270
|
+
targets = all.filter(a => a.claimableExcess > 0);
|
|
271
|
+
if (targets.length === 0)
|
|
272
|
+
throw new Error('No claimable MEV across any stake accounts');
|
|
273
|
+
}
|
|
274
|
+
const results = [];
|
|
275
|
+
for (const target of targets) {
|
|
276
|
+
const stakeAddr = address(target.address);
|
|
277
|
+
const excessLamports = solToLamports(target.claimableExcess);
|
|
278
|
+
verbose(`Claiming ${target.claimableExcess} SOL MEV from ${target.address}`);
|
|
279
|
+
// Withdraw the excess
|
|
280
|
+
const withdrawIx = getWithdrawInstruction({
|
|
281
|
+
stake: stakeAddr,
|
|
282
|
+
recipient: signer.address,
|
|
283
|
+
stakeHistory: STAKE_HISTORY_SYSVAR,
|
|
284
|
+
withdrawAuthority: signer,
|
|
285
|
+
args: excessLamports,
|
|
286
|
+
});
|
|
287
|
+
const withdrawResult = await buildAndSendTransaction([withdrawIx], signer, {
|
|
288
|
+
txType: 'mev-claim',
|
|
289
|
+
walletName,
|
|
290
|
+
});
|
|
291
|
+
if (withdrawOnly) {
|
|
292
|
+
results.push({
|
|
293
|
+
action: 'withdrawn',
|
|
294
|
+
stakeAccount: target.address,
|
|
295
|
+
validator: target.validator,
|
|
296
|
+
amountSol: target.claimableExcess,
|
|
297
|
+
withdrawSignature: withdrawResult.signature,
|
|
298
|
+
withdrawExplorerUrl: withdrawResult.explorerUrl,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Compound: re-stake with the same validator
|
|
303
|
+
const stakeResult = await createAndDelegateStake(walletName, target.claimableExcess, target.validator);
|
|
304
|
+
results.push({
|
|
305
|
+
action: 'compounded',
|
|
306
|
+
stakeAccount: target.address,
|
|
307
|
+
validator: target.validator,
|
|
308
|
+
amountSol: target.claimableExcess,
|
|
309
|
+
withdrawSignature: withdrawResult.signature,
|
|
310
|
+
withdrawExplorerUrl: withdrawResult.explorerUrl,
|
|
311
|
+
newStakeAccount: stakeResult.stakeAccount,
|
|
312
|
+
stakeSignature: stakeResult.signature,
|
|
313
|
+
stakeExplorerUrl: stakeResult.explorerUrl,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return results;
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=stake-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stake-service.js","sourceRoot":"","sources":["../../src/core/stake-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface SwapQuote {
|
|
2
|
+
inputMint: string;
|
|
3
|
+
outputMint: string;
|
|
4
|
+
inputAmount: string;
|
|
5
|
+
outputAmount: string;
|
|
6
|
+
inputSymbol: string;
|
|
7
|
+
outputSymbol: string;
|
|
8
|
+
inputUiAmount: number;
|
|
9
|
+
outputUiAmount: number;
|
|
10
|
+
priceImpactPct: number;
|
|
11
|
+
slippageBps: number;
|
|
12
|
+
routePlan: string;
|
|
13
|
+
platformFee?: string;
|
|
14
|
+
_raw: any;
|
|
15
|
+
}
|
|
16
|
+
export interface SwapResult {
|
|
17
|
+
signature: string;
|
|
18
|
+
inputSymbol: string;
|
|
19
|
+
outputSymbol: string;
|
|
20
|
+
inputAmount: number;
|
|
21
|
+
outputAmount: number;
|
|
22
|
+
explorerUrl: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function getQuote(inputSymbol: string, outputSymbol: string, amount: number, opts?: {
|
|
25
|
+
slippageBps?: number;
|
|
26
|
+
}): Promise<SwapQuote>;
|
|
27
|
+
export declare function executeSwap(inputSymbol: string, outputSymbol: string, amount: number, walletName: string, opts?: {
|
|
28
|
+
slippageBps?: number;
|
|
29
|
+
skipPreflight?: boolean;
|
|
30
|
+
rewardBps?: number;
|
|
31
|
+
}): Promise<SwapResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { withRetry, isRetryableHttpError, RateLimiter } from '../utils/retry.js';
|
|
2
|
+
import { verbose } from '../output/formatter.js';
|
|
3
|
+
import { resolveToken } from './token-registry.js';
|
|
4
|
+
import { uiToTokenAmount, SOL_MINT } from '../utils/solana.js';
|
|
5
|
+
import { loadSigner } from './wallet-manager.js';
|
|
6
|
+
import { getTransactionDecoder, getBase64EncodedWireTransaction, } from '@solana/transactions';
|
|
7
|
+
import { getCompiledTransactionMessageDecoder, decompileTransactionMessageFetchingLookupTables, appendTransactionMessageInstructions, signTransactionMessageWithSigners, address, } from '@solana/kit';
|
|
8
|
+
import { getTransferSolInstruction } from '@solana-program/system';
|
|
9
|
+
import { sendEncodedTransaction } from './transaction.js';
|
|
10
|
+
import { getPrices } from './price-service.js';
|
|
11
|
+
import { getRpc } from './rpc.js';
|
|
12
|
+
const JUPITER_API = 'https://lite-api.jup.ag/swap/v1';
|
|
13
|
+
const jupiterLimiter = new RateLimiter(30, 60_000);
|
|
14
|
+
// compassSOL pool reserve — swap contributions fund staking yield for LST holders.
|
|
15
|
+
const COMPASS_RESERVE = address('8H2xjMT543YWBLRjJ24BrQyBgFuQRU6MgENA3mqXoh7y');
|
|
16
|
+
const DEFAULT_REWARD_BPS = 20; // 0.2% standard swap contribution
|
|
17
|
+
export async function getQuote(inputSymbol, outputSymbol, amount, opts = {}) {
|
|
18
|
+
const inputToken = await resolveToken(inputSymbol);
|
|
19
|
+
if (!inputToken)
|
|
20
|
+
throw new Error(`Unknown token: ${inputSymbol}`);
|
|
21
|
+
const outputToken = await resolveToken(outputSymbol);
|
|
22
|
+
if (!outputToken)
|
|
23
|
+
throw new Error(`Unknown token: ${outputSymbol}`);
|
|
24
|
+
const inputAmount = uiToTokenAmount(amount, inputToken.decimals);
|
|
25
|
+
const slippageBps = opts.slippageBps ?? 50; // 0.5% default
|
|
26
|
+
await jupiterLimiter.acquire();
|
|
27
|
+
const url = `${JUPITER_API}/quote?inputMint=${inputToken.mint}&outputMint=${outputToken.mint}&amount=${inputAmount}&slippageBps=${slippageBps}`;
|
|
28
|
+
verbose(`Fetching Jupiter quote: ${url}`);
|
|
29
|
+
const res = await withRetry(() => fetch(url), {
|
|
30
|
+
maxRetries: 2,
|
|
31
|
+
shouldRetry: isRetryableHttpError,
|
|
32
|
+
});
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
const body = await res.text();
|
|
35
|
+
throw new Error(`Jupiter quote failed (${res.status}): ${body}`);
|
|
36
|
+
}
|
|
37
|
+
const data = await res.json();
|
|
38
|
+
const outputUiAmount = Number(BigInt(data.outAmount)) / Math.pow(10, outputToken.decimals);
|
|
39
|
+
return {
|
|
40
|
+
inputMint: inputToken.mint,
|
|
41
|
+
outputMint: outputToken.mint,
|
|
42
|
+
inputAmount: String(inputAmount),
|
|
43
|
+
outputAmount: data.outAmount,
|
|
44
|
+
inputSymbol: inputToken.symbol,
|
|
45
|
+
outputSymbol: outputToken.symbol,
|
|
46
|
+
inputUiAmount: amount,
|
|
47
|
+
outputUiAmount,
|
|
48
|
+
priceImpactPct: parseFloat(data.priceImpactPct || '0'),
|
|
49
|
+
slippageBps,
|
|
50
|
+
routePlan: data.routePlan?.map((r) => r.swapInfo?.label || 'unknown').join(' → ') || 'direct',
|
|
51
|
+
_raw: data,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export async function executeSwap(inputSymbol, outputSymbol, amount, walletName, opts = {}) {
|
|
55
|
+
const quote = await getQuote(inputSymbol, outputSymbol, amount, { slippageBps: opts.slippageBps });
|
|
56
|
+
const signer = await loadSigner(walletName);
|
|
57
|
+
const rpc = getRpc();
|
|
58
|
+
// Determine contribution amount based on which side is SOL
|
|
59
|
+
const inputIsSol = quote.inputMint === SOL_MINT;
|
|
60
|
+
const outputIsSol = quote.outputMint === SOL_MINT;
|
|
61
|
+
const rewardBps = opts.rewardBps ?? DEFAULT_REWARD_BPS;
|
|
62
|
+
let contributionLamports = 0n;
|
|
63
|
+
if (inputIsSol) {
|
|
64
|
+
contributionLamports = BigInt(quote.inputAmount) * BigInt(rewardBps) / 10000n;
|
|
65
|
+
}
|
|
66
|
+
else if (outputIsSol) {
|
|
67
|
+
contributionLamports = BigInt(quote.outputAmount) * BigInt(rewardBps) / 10000n;
|
|
68
|
+
}
|
|
69
|
+
// Neither side is SOL: no contribution
|
|
70
|
+
await jupiterLimiter.acquire();
|
|
71
|
+
// Get swap transaction from Jupiter — pass the raw quote response
|
|
72
|
+
const swapRes = await withRetry(() => fetch(`${JUPITER_API}/swap`, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
quoteResponse: quote._raw,
|
|
77
|
+
userPublicKey: signer.address,
|
|
78
|
+
wrapAndUnwrapSol: true,
|
|
79
|
+
dynamicComputeUnitLimit: true,
|
|
80
|
+
prioritizationFeeLamports: 'auto',
|
|
81
|
+
}),
|
|
82
|
+
}), { maxRetries: 2, shouldRetry: isRetryableHttpError });
|
|
83
|
+
if (!swapRes.ok) {
|
|
84
|
+
const body = await swapRes.text();
|
|
85
|
+
throw new Error(`Jupiter swap failed (${swapRes.status}): ${body}`);
|
|
86
|
+
}
|
|
87
|
+
const swapData = await swapRes.json();
|
|
88
|
+
const swapTxBase64 = swapData.swapTransaction;
|
|
89
|
+
if (!swapTxBase64)
|
|
90
|
+
throw new Error('No swap transaction returned from Jupiter');
|
|
91
|
+
// 1. Decode and decompile the transaction
|
|
92
|
+
const txBytes = new Uint8Array(Buffer.from(swapTxBase64, 'base64'));
|
|
93
|
+
const rawTx = getTransactionDecoder().decode(txBytes);
|
|
94
|
+
const compiledMsg = getCompiledTransactionMessageDecoder().decode(rawTx.messageBytes);
|
|
95
|
+
let msg = await decompileTransactionMessageFetchingLookupTables(compiledMsg, rpc);
|
|
96
|
+
// 2. Append SOL transfer to reserve if applicable
|
|
97
|
+
if (contributionLamports > 0n) {
|
|
98
|
+
verbose(`Appending ${contributionLamports} lamport contribution to reserve`);
|
|
99
|
+
const transferIx = getTransferSolInstruction({
|
|
100
|
+
source: signer,
|
|
101
|
+
destination: COMPASS_RESERVE,
|
|
102
|
+
amount: contributionLamports,
|
|
103
|
+
});
|
|
104
|
+
msg = appendTransactionMessageInstructions([transferIx], msg);
|
|
105
|
+
}
|
|
106
|
+
// 3. Sign and encode
|
|
107
|
+
verbose('Signing swap transaction...');
|
|
108
|
+
const signedTx = await signTransactionMessageWithSigners(msg);
|
|
109
|
+
const encodedTx = getBase64EncodedWireTransaction(signedTx);
|
|
110
|
+
// 4. Fetch USD prices for cost-basis recording (best-effort)
|
|
111
|
+
let fromPriceUsd;
|
|
112
|
+
let toPriceUsd;
|
|
113
|
+
try {
|
|
114
|
+
const prices = await getPrices([quote.inputMint, quote.outputMint]);
|
|
115
|
+
fromPriceUsd = prices.get(quote.inputMint)?.priceUsd;
|
|
116
|
+
toPriceUsd = prices.get(quote.outputMint)?.priceUsd;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
verbose('Could not fetch prices for cost-basis stamping');
|
|
120
|
+
}
|
|
121
|
+
// 5. Send, confirm, and log
|
|
122
|
+
const result = await sendEncodedTransaction(encodedTx, {
|
|
123
|
+
skipPreflight: opts.skipPreflight,
|
|
124
|
+
txType: 'swap',
|
|
125
|
+
walletName,
|
|
126
|
+
fromMint: quote.inputMint,
|
|
127
|
+
toMint: quote.outputMint,
|
|
128
|
+
fromAmount: quote.inputAmount,
|
|
129
|
+
toAmount: quote.outputAmount,
|
|
130
|
+
fromPriceUsd,
|
|
131
|
+
toPriceUsd,
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
signature: result.signature,
|
|
135
|
+
inputSymbol: quote.inputSymbol,
|
|
136
|
+
outputSymbol: quote.outputSymbol,
|
|
137
|
+
inputAmount: quote.inputUiAmount,
|
|
138
|
+
outputAmount: quote.outputUiAmount,
|
|
139
|
+
explorerUrl: result.explorerUrl,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=swap-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swap-service.js","sourceRoot":"","sources":["../../src/core/swap-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface TokenMetadata {
|
|
2
|
+
mint: string;
|
|
3
|
+
symbol: string;
|
|
4
|
+
name: string;
|
|
5
|
+
decimals: number;
|
|
6
|
+
logoUri?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface TokenMetadataProvider {
|
|
10
|
+
name: string;
|
|
11
|
+
search(query: string): Promise<TokenMetadata[]>;
|
|
12
|
+
getByMint(mints: string[]): Promise<TokenMetadata[]>;
|
|
13
|
+
}
|
|
14
|
+
export declare class JupiterTokenProvider implements TokenMetadataProvider {
|
|
15
|
+
name: string;
|
|
16
|
+
private baseUrl;
|
|
17
|
+
search(query: string): Promise<TokenMetadata[]>;
|
|
18
|
+
getByMint(mints: string[]): Promise<TokenMetadata[]>;
|
|
19
|
+
}
|
|
20
|
+
export declare function registerProvider(provider: TokenMetadataProvider): void;
|
|
21
|
+
export declare function resolveToken(symbolOrMint: string): Promise<TokenMetadata | undefined>;
|
|
22
|
+
export declare function resolveTokens(queries: string[]): Promise<Map<string, TokenMetadata>>;
|
|
23
|
+
export declare function syncTokenCache(): Promise<number>;
|