@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,79 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { parse, stringify } from 'smol-toml';
|
|
5
|
+
const SOL_DIR = join(homedir(), '.sol');
|
|
6
|
+
const CONFIG_PATH = join(SOL_DIR, 'config.toml');
|
|
7
|
+
export function getSolDir() {
|
|
8
|
+
return SOL_DIR;
|
|
9
|
+
}
|
|
10
|
+
export function getConfigPath() {
|
|
11
|
+
return CONFIG_PATH;
|
|
12
|
+
}
|
|
13
|
+
export function ensureSolDir() {
|
|
14
|
+
if (!existsSync(SOL_DIR)) {
|
|
15
|
+
mkdirSync(SOL_DIR, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function readConfig() {
|
|
19
|
+
ensureSolDir();
|
|
20
|
+
if (!existsSync(CONFIG_PATH))
|
|
21
|
+
return {};
|
|
22
|
+
const raw = readFileSync(CONFIG_PATH, 'utf-8');
|
|
23
|
+
return parse(raw);
|
|
24
|
+
}
|
|
25
|
+
export function writeConfig(config) {
|
|
26
|
+
ensureSolDir();
|
|
27
|
+
writeFileSync(CONFIG_PATH, stringify(config));
|
|
28
|
+
}
|
|
29
|
+
export function getConfigValue(key) {
|
|
30
|
+
const config = readConfig();
|
|
31
|
+
const parts = key.split('.');
|
|
32
|
+
let current = config;
|
|
33
|
+
for (const part of parts) {
|
|
34
|
+
if (current === null || current === undefined || typeof current !== 'object')
|
|
35
|
+
return undefined;
|
|
36
|
+
current = current[part];
|
|
37
|
+
}
|
|
38
|
+
return current;
|
|
39
|
+
}
|
|
40
|
+
export function setConfigValue(key, value) {
|
|
41
|
+
const config = readConfig();
|
|
42
|
+
const parts = key.split('.');
|
|
43
|
+
// Parse value — try number, boolean, else string
|
|
44
|
+
let parsed = value;
|
|
45
|
+
if (value === 'true')
|
|
46
|
+
parsed = true;
|
|
47
|
+
else if (value === 'false')
|
|
48
|
+
parsed = false;
|
|
49
|
+
else if (/^\d+$/.test(value))
|
|
50
|
+
parsed = parseInt(value, 10);
|
|
51
|
+
else if (/^\d+\.\d+$/.test(value))
|
|
52
|
+
parsed = parseFloat(value);
|
|
53
|
+
let current = config;
|
|
54
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
55
|
+
if (!(parts[i] in current) || typeof current[parts[i]] !== 'object') {
|
|
56
|
+
current[parts[i]] = {};
|
|
57
|
+
}
|
|
58
|
+
current = current[parts[i]];
|
|
59
|
+
}
|
|
60
|
+
current[parts[parts.length - 1]] = parsed;
|
|
61
|
+
writeConfig(config);
|
|
62
|
+
}
|
|
63
|
+
export function listConfig() {
|
|
64
|
+
return flatten(readConfig());
|
|
65
|
+
}
|
|
66
|
+
function flatten(obj, prefix = '') {
|
|
67
|
+
const result = {};
|
|
68
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
69
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
70
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
71
|
+
Object.assign(result, flatten(value, fullKey));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
result[fullKey] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=config-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/core/config-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type IInstruction } from '@solana/kit';
|
|
2
|
+
export declare const KLEND_PROGRAM_ID = "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD";
|
|
3
|
+
export declare const KAMINO_MAIN_MARKET = "7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF";
|
|
4
|
+
export declare const RECENT_SLOT_DURATION_MS = 400;
|
|
5
|
+
/** Our kit v2 RPC, cast for klend-sdk consumption. */
|
|
6
|
+
export declare function getKaminoRpc(): any;
|
|
7
|
+
/** Kit v2 address string, cast for klend-sdk. */
|
|
8
|
+
export declare function kAddress(addr: string): any;
|
|
9
|
+
/** Cast a kit v2 KeyPairSigner to klend-sdk's TransactionSigner. */
|
|
10
|
+
export declare function kSigner(signer: any): any;
|
|
11
|
+
/**
|
|
12
|
+
* Convert klend-sdk Instruction[] to kit v2 IInstruction[].
|
|
13
|
+
* The shapes are identical at runtime — this is a type-level bridge.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toV2Instructions(ixs: any[]): IInstruction[];
|
|
16
|
+
/** Fetch current slot as bigint (klend-sdk expects Slot = bigint). */
|
|
17
|
+
export declare function getCurrentSlot(): Promise<bigint>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getRpc } from './rpc.js';
|
|
2
|
+
// ── Kamino Lending constants ─────────────────────────────────
|
|
3
|
+
export const KLEND_PROGRAM_ID = 'KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD';
|
|
4
|
+
export const KAMINO_MAIN_MARKET = '7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF';
|
|
5
|
+
// Slot duration used by klend-sdk for APY calculations
|
|
6
|
+
export const RECENT_SLOT_DURATION_MS = 400;
|
|
7
|
+
// ── Type bridge (kit v2 ↔ klend-sdk's kit v3) ───────────────
|
|
8
|
+
//
|
|
9
|
+
// klend-sdk v7.x uses @solana/kit v3 types internally. Our codebase
|
|
10
|
+
// uses kit v2. The runtime shapes are identical (Address is a branded
|
|
11
|
+
// string, Rpc has the same methods, Instruction has programAddress +
|
|
12
|
+
// accounts + data). These helpers centralise the casts so
|
|
13
|
+
// lend-service.ts stays clean.
|
|
14
|
+
/** Our kit v2 RPC, cast for klend-sdk consumption. */
|
|
15
|
+
export function getKaminoRpc() {
|
|
16
|
+
return getRpc();
|
|
17
|
+
}
|
|
18
|
+
/** Kit v2 address string, cast for klend-sdk. */
|
|
19
|
+
export function kAddress(addr) {
|
|
20
|
+
return addr;
|
|
21
|
+
}
|
|
22
|
+
/** Cast a kit v2 KeyPairSigner to klend-sdk's TransactionSigner. */
|
|
23
|
+
export function kSigner(signer) {
|
|
24
|
+
return signer;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Convert klend-sdk Instruction[] to kit v2 IInstruction[].
|
|
28
|
+
* The shapes are identical at runtime — this is a type-level bridge.
|
|
29
|
+
*/
|
|
30
|
+
export function toV2Instructions(ixs) {
|
|
31
|
+
return ixs;
|
|
32
|
+
}
|
|
33
|
+
/** Fetch current slot as bigint (klend-sdk expects Slot = bigint). */
|
|
34
|
+
export async function getCurrentSlot() {
|
|
35
|
+
const slot = await getRpc().getSlot().send();
|
|
36
|
+
return BigInt(slot);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=kamino-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kamino-compat.js","sourceRoot":"","sources":["../../src/core/kamino-compat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,gEAAgE;AAEhE,MAAM,CAAC,MAAM,gBAAgB,GAAG,6CAA6C,CAAC;AAC9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,8CAA8C,CAAC;AAEjF,uDAAuD;AACvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C,+DAA+D;AAC/D,EAAE;AACF,oEAAoE;AACpE,sEAAsE;AACtE,qEAAqE;AACrE,0DAA0D;AAC1D,+BAA+B;AAE/B,sDAAsD;AACtD,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,EAAE,CAAC;AAClB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,OAAO,CAAC,MAAW;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAU;IACzC,OAAO,GAAqB,CAAC;AAC/B,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface LendingRate {
|
|
2
|
+
protocol: string;
|
|
3
|
+
token: string;
|
|
4
|
+
mint: string;
|
|
5
|
+
depositApy: number;
|
|
6
|
+
borrowApy: number;
|
|
7
|
+
totalDeposited: number;
|
|
8
|
+
totalBorrowed: number;
|
|
9
|
+
utilizationPct: number;
|
|
10
|
+
}
|
|
11
|
+
export interface LendingPosition {
|
|
12
|
+
protocol: string;
|
|
13
|
+
token: string;
|
|
14
|
+
mint: string;
|
|
15
|
+
type: 'deposit' | 'borrow';
|
|
16
|
+
amount: number;
|
|
17
|
+
valueUsd: number;
|
|
18
|
+
apy: number;
|
|
19
|
+
healthFactor?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function getRates(token: string): Promise<LendingRate[]>;
|
|
22
|
+
export declare function getPositions(walletAddress: string): Promise<LendingPosition[]>;
|
|
23
|
+
export declare function deposit(walletName: string, token: string, amount: number): Promise<{
|
|
24
|
+
signature: string;
|
|
25
|
+
protocol: string;
|
|
26
|
+
explorerUrl: string;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function withdraw(walletName: string, token: string, amount: number): Promise<{
|
|
29
|
+
signature: string;
|
|
30
|
+
explorerUrl: string;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function borrow(walletName: string, token: string, amount: number, collateralToken: string): Promise<{
|
|
33
|
+
signature: string;
|
|
34
|
+
explorerUrl: string;
|
|
35
|
+
healthFactor?: number;
|
|
36
|
+
}>;
|
|
37
|
+
export declare function repay(walletName: string, token: string, amount: number): Promise<{
|
|
38
|
+
signature: string;
|
|
39
|
+
explorerUrl: string;
|
|
40
|
+
remainingDebt?: number;
|
|
41
|
+
}>;
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { KaminoMarket, KaminoAction, VanillaObligation, U64_MAX, } from '@kamino-finance/klend-sdk';
|
|
2
|
+
import { KLEND_PROGRAM_ID, KAMINO_MAIN_MARKET, RECENT_SLOT_DURATION_MS, getKaminoRpc, kAddress, kSigner, toV2Instructions, getCurrentSlot, } from './kamino-compat.js';
|
|
3
|
+
import { loadSigner } from './wallet-manager.js';
|
|
4
|
+
import { resolveToken } from './token-registry.js';
|
|
5
|
+
import { getPrices } from './price-service.js';
|
|
6
|
+
import { buildAndSendTransaction } from './transaction.js';
|
|
7
|
+
import { verbose } from '../output/formatter.js';
|
|
8
|
+
import { uiToTokenAmount } from '../utils/solana.js';
|
|
9
|
+
import { getTokenBalances } from './token-service.js';
|
|
10
|
+
// ── Market caching ────────────────────────────────────────
|
|
11
|
+
let cachedMarket = null;
|
|
12
|
+
let marketLoadedAt = 0;
|
|
13
|
+
const MARKET_TTL_MS = 60_000;
|
|
14
|
+
async function loadMarket() {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
if (cachedMarket && (now - marketLoadedAt) < MARKET_TTL_MS) {
|
|
17
|
+
return cachedMarket;
|
|
18
|
+
}
|
|
19
|
+
verbose('Loading Kamino lending market...');
|
|
20
|
+
const market = await KaminoMarket.load(getKaminoRpc(), kAddress(KAMINO_MAIN_MARKET), RECENT_SLOT_DURATION_MS, kAddress(KLEND_PROGRAM_ID), true);
|
|
21
|
+
if (!market)
|
|
22
|
+
throw new Error('Failed to load Kamino lending market');
|
|
23
|
+
cachedMarket = market;
|
|
24
|
+
marketLoadedAt = now;
|
|
25
|
+
return market;
|
|
26
|
+
}
|
|
27
|
+
function invalidateMarketCache() {
|
|
28
|
+
cachedMarket = null;
|
|
29
|
+
marketLoadedAt = 0;
|
|
30
|
+
}
|
|
31
|
+
// ── Helpers ───────────────────────────────────────────────
|
|
32
|
+
async function resolveTokenStrict(symbolOrMint) {
|
|
33
|
+
const meta = await resolveToken(symbolOrMint);
|
|
34
|
+
if (!meta)
|
|
35
|
+
throw new Error(`Unknown token: ${symbolOrMint}`);
|
|
36
|
+
return meta;
|
|
37
|
+
}
|
|
38
|
+
function obligationHealthFactor(obligation) {
|
|
39
|
+
const stats = obligation.refreshedStats;
|
|
40
|
+
const borrowValue = stats.userTotalBorrowBorrowFactorAdjusted.toNumber();
|
|
41
|
+
const liquidationLimit = stats.borrowLiquidationLimit.toNumber();
|
|
42
|
+
if (borrowValue <= 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
return liquidationLimit / borrowValue;
|
|
45
|
+
}
|
|
46
|
+
async function getWalletBalance(walletAddress, mint) {
|
|
47
|
+
const balances = await getTokenBalances(walletAddress);
|
|
48
|
+
const token = balances.find(b => b.mint === mint);
|
|
49
|
+
return token?.uiBalance ?? 0;
|
|
50
|
+
}
|
|
51
|
+
async function getUserObligation(market, walletAddress) {
|
|
52
|
+
return market.getObligationByWallet(kAddress(walletAddress), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)));
|
|
53
|
+
}
|
|
54
|
+
// ── Read operations ───────────────────────────────────────
|
|
55
|
+
export async function getRates(token) {
|
|
56
|
+
verbose(`Fetching Kamino lending rates for ${token}`);
|
|
57
|
+
const meta = await resolveTokenStrict(token);
|
|
58
|
+
const market = await loadMarket();
|
|
59
|
+
const reserve = market.getReserveByMint(kAddress(meta.mint));
|
|
60
|
+
if (!reserve)
|
|
61
|
+
return [];
|
|
62
|
+
const slot = await getCurrentSlot();
|
|
63
|
+
const supplyApy = reserve.totalSupplyAPY(slot);
|
|
64
|
+
const borrowApy = reserve.totalBorrowAPY(slot);
|
|
65
|
+
const utilization = reserve.calculateUtilizationRatio();
|
|
66
|
+
const mintFactor = Math.pow(10, reserve.getMintDecimals());
|
|
67
|
+
const totalDeposited = reserve.getTotalSupply().toNumber() / mintFactor;
|
|
68
|
+
const totalBorrowed = reserve.getBorrowedAmount().toNumber() / mintFactor;
|
|
69
|
+
return [{
|
|
70
|
+
protocol: 'kamino',
|
|
71
|
+
token: meta.symbol,
|
|
72
|
+
mint: meta.mint,
|
|
73
|
+
depositApy: supplyApy,
|
|
74
|
+
borrowApy: borrowApy,
|
|
75
|
+
totalDeposited,
|
|
76
|
+
totalBorrowed,
|
|
77
|
+
utilizationPct: utilization * 100,
|
|
78
|
+
}];
|
|
79
|
+
}
|
|
80
|
+
export async function getPositions(walletAddress) {
|
|
81
|
+
verbose(`Fetching Kamino lending positions for ${walletAddress}`);
|
|
82
|
+
const market = await loadMarket();
|
|
83
|
+
const obligations = await market.getAllUserObligations(kAddress(walletAddress));
|
|
84
|
+
if (obligations.length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
const slot = await getCurrentSlot();
|
|
87
|
+
const positions = [];
|
|
88
|
+
for (const obligation of obligations) {
|
|
89
|
+
const healthFactor = obligationHealthFactor(obligation);
|
|
90
|
+
// Deposits
|
|
91
|
+
for (const [reserveAddr, deposit] of obligation.deposits) {
|
|
92
|
+
const reserve = market.getReserveByAddress(reserveAddr);
|
|
93
|
+
if (!reserve)
|
|
94
|
+
continue;
|
|
95
|
+
const mintFactor = Math.pow(10, reserve.getMintDecimals());
|
|
96
|
+
const amount = deposit.amount.toNumber() / mintFactor;
|
|
97
|
+
if (amount <= 0)
|
|
98
|
+
continue;
|
|
99
|
+
positions.push({
|
|
100
|
+
protocol: 'kamino',
|
|
101
|
+
token: reserve.getTokenSymbol(),
|
|
102
|
+
mint: String(reserve.getLiquidityMint()),
|
|
103
|
+
type: 'deposit',
|
|
104
|
+
amount,
|
|
105
|
+
valueUsd: deposit.marketValueRefreshed.toNumber(),
|
|
106
|
+
apy: reserve.totalSupplyAPY(slot),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Borrows
|
|
110
|
+
for (const [reserveAddr, borrow] of obligation.borrows) {
|
|
111
|
+
const reserve = market.getReserveByAddress(reserveAddr);
|
|
112
|
+
if (!reserve)
|
|
113
|
+
continue;
|
|
114
|
+
const mintFactor = Math.pow(10, reserve.getMintDecimals());
|
|
115
|
+
const amount = borrow.amount.toNumber() / mintFactor;
|
|
116
|
+
if (amount <= 0)
|
|
117
|
+
continue;
|
|
118
|
+
positions.push({
|
|
119
|
+
protocol: 'kamino',
|
|
120
|
+
token: reserve.getTokenSymbol(),
|
|
121
|
+
mint: String(reserve.getLiquidityMint()),
|
|
122
|
+
type: 'borrow',
|
|
123
|
+
amount,
|
|
124
|
+
valueUsd: borrow.marketValueRefreshed.toNumber(),
|
|
125
|
+
apy: reserve.totalBorrowAPY(slot),
|
|
126
|
+
healthFactor,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return positions;
|
|
131
|
+
}
|
|
132
|
+
// ── Write operations ──────────────────────────────────────
|
|
133
|
+
export async function deposit(walletName, token, amount) {
|
|
134
|
+
const meta = await resolveTokenStrict(token);
|
|
135
|
+
const signer = await loadSigner(walletName);
|
|
136
|
+
const market = await loadMarket();
|
|
137
|
+
const reserve = market.getReserveByMint(kAddress(meta.mint));
|
|
138
|
+
if (!reserve)
|
|
139
|
+
throw new Error(`No Kamino reserve for ${meta.symbol}`);
|
|
140
|
+
const rawAmount = uiToTokenAmount(amount, meta.decimals).toString();
|
|
141
|
+
const action = await KaminoAction.buildDepositTxns(market, rawAmount, kAddress(meta.mint), kSigner(signer), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)), true, // useV2Ixs
|
|
142
|
+
undefined, // scopeRefreshConfig
|
|
143
|
+
300_000, // extraComputeBudget
|
|
144
|
+
true);
|
|
145
|
+
const instructions = toV2Instructions(KaminoAction.actionToIxs(action));
|
|
146
|
+
const prices = await getPrices([meta.mint]);
|
|
147
|
+
const price = prices.get(meta.mint)?.priceUsd;
|
|
148
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
149
|
+
txType: 'lend-deposit',
|
|
150
|
+
walletName,
|
|
151
|
+
fromMint: meta.mint,
|
|
152
|
+
fromAmount: rawAmount,
|
|
153
|
+
fromPriceUsd: price,
|
|
154
|
+
});
|
|
155
|
+
invalidateMarketCache();
|
|
156
|
+
return {
|
|
157
|
+
signature: result.signature,
|
|
158
|
+
protocol: 'kamino',
|
|
159
|
+
explorerUrl: result.explorerUrl,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
export async function withdraw(walletName, token, amount) {
|
|
163
|
+
const meta = await resolveTokenStrict(token);
|
|
164
|
+
const signer = await loadSigner(walletName);
|
|
165
|
+
const market = await loadMarket();
|
|
166
|
+
const reserve = market.getReserveByMint(kAddress(meta.mint));
|
|
167
|
+
if (!reserve)
|
|
168
|
+
throw new Error(`No Kamino reserve for ${meta.symbol}`);
|
|
169
|
+
// Detect "withdraw all": use U64_MAX so the on-chain program withdraws exact deposit
|
|
170
|
+
let rawAmount;
|
|
171
|
+
if (!isFinite(amount)) {
|
|
172
|
+
rawAmount = U64_MAX;
|
|
173
|
+
verbose('Using U64_MAX for full withdrawal');
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Check if amount covers full deposit — if so, use U64_MAX for clean withdrawal
|
|
177
|
+
const obligation = await getUserObligation(market, signer.address);
|
|
178
|
+
if (obligation) {
|
|
179
|
+
const depositPos = obligation.getDepositByMint(kAddress(meta.mint));
|
|
180
|
+
if (depositPos) {
|
|
181
|
+
const depositUi = depositPos.amount.toNumber() / Math.pow(10, meta.decimals);
|
|
182
|
+
if (amount >= depositUi) {
|
|
183
|
+
rawAmount = U64_MAX;
|
|
184
|
+
verbose(`Withdraw amount ${amount} >= deposit ${depositUi.toFixed(meta.decimals)}, using U64_MAX for clean full withdrawal`);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
rawAmount = uiToTokenAmount(amount, meta.decimals).toString();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
rawAmount = uiToTokenAmount(amount, meta.decimals).toString();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
rawAmount = uiToTokenAmount(amount, meta.decimals).toString();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const action = await KaminoAction.buildWithdrawTxns(market, rawAmount, kAddress(meta.mint), kSigner(signer), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)), true, undefined, 300_000, true);
|
|
199
|
+
const instructions = toV2Instructions(KaminoAction.actionToIxs(action));
|
|
200
|
+
const prices = await getPrices([meta.mint]);
|
|
201
|
+
const price = prices.get(meta.mint)?.priceUsd;
|
|
202
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
203
|
+
txType: 'lend-withdraw',
|
|
204
|
+
walletName,
|
|
205
|
+
toMint: meta.mint,
|
|
206
|
+
toAmount: rawAmount,
|
|
207
|
+
toPriceUsd: price,
|
|
208
|
+
});
|
|
209
|
+
invalidateMarketCache();
|
|
210
|
+
return {
|
|
211
|
+
signature: result.signature,
|
|
212
|
+
explorerUrl: result.explorerUrl,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export async function borrow(walletName, token, amount, collateralToken) {
|
|
216
|
+
const borrowMeta = await resolveTokenStrict(token);
|
|
217
|
+
const collateralMeta = await resolveTokenStrict(collateralToken);
|
|
218
|
+
const signer = await loadSigner(walletName);
|
|
219
|
+
const market = await loadMarket();
|
|
220
|
+
const borrowReserve = market.getReserveByMint(kAddress(borrowMeta.mint));
|
|
221
|
+
if (!borrowReserve)
|
|
222
|
+
throw new Error(`No Kamino reserve for ${borrowMeta.symbol}`);
|
|
223
|
+
const collateralReserve = market.getReserveByMint(kAddress(collateralMeta.mint));
|
|
224
|
+
if (!collateralReserve)
|
|
225
|
+
throw new Error(`No Kamino reserve for ${collateralMeta.symbol}`);
|
|
226
|
+
const rawAmount = uiToTokenAmount(amount, borrowMeta.decimals).toString();
|
|
227
|
+
const action = await KaminoAction.buildBorrowTxns(market, rawAmount, kAddress(borrowMeta.mint), kSigner(signer), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)), true, undefined, 300_000, true);
|
|
228
|
+
const instructions = toV2Instructions(KaminoAction.actionToIxs(action));
|
|
229
|
+
const prices = await getPrices([borrowMeta.mint]);
|
|
230
|
+
const borrowPrice = prices.get(borrowMeta.mint)?.priceUsd;
|
|
231
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
232
|
+
txType: 'lend-borrow',
|
|
233
|
+
walletName,
|
|
234
|
+
toMint: borrowMeta.mint,
|
|
235
|
+
toAmount: rawAmount,
|
|
236
|
+
toPriceUsd: borrowPrice,
|
|
237
|
+
});
|
|
238
|
+
invalidateMarketCache();
|
|
239
|
+
// Fetch updated health factor (best-effort)
|
|
240
|
+
let healthFactor;
|
|
241
|
+
try {
|
|
242
|
+
const updated = await loadMarket();
|
|
243
|
+
const obligation = await updated.getObligationByWallet(kAddress(signer.address), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)));
|
|
244
|
+
if (obligation)
|
|
245
|
+
healthFactor = obligationHealthFactor(obligation);
|
|
246
|
+
}
|
|
247
|
+
catch { /* non-critical */ }
|
|
248
|
+
return {
|
|
249
|
+
signature: result.signature,
|
|
250
|
+
explorerUrl: result.explorerUrl,
|
|
251
|
+
healthFactor,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export async function repay(walletName, token, amount) {
|
|
255
|
+
const meta = await resolveTokenStrict(token);
|
|
256
|
+
const signer = await loadSigner(walletName);
|
|
257
|
+
const market = await loadMarket();
|
|
258
|
+
const reserve = market.getReserveByMint(kAddress(meta.mint));
|
|
259
|
+
if (!reserve)
|
|
260
|
+
throw new Error(`No Kamino reserve for ${meta.symbol}`);
|
|
261
|
+
// Determine repay amount:
|
|
262
|
+
// - "repay max" (Infinity): full repay using U64_MAX sentinel
|
|
263
|
+
// - exact amount >= debt: use U64_MAX for clean close (avoids dust)
|
|
264
|
+
// - exact amount < debt: partial repay (must leave non-dust remainder)
|
|
265
|
+
//
|
|
266
|
+
// On-chain constraints:
|
|
267
|
+
// - U64_MAX tells the program to repay exact debt + interest, but requires
|
|
268
|
+
// the wallet to hold enough tokens to cover it
|
|
269
|
+
// - Partial repay that leaves near-zero debt triggers NetValueRemainingTooSmall
|
|
270
|
+
const obligation = await getUserObligation(market, signer.address);
|
|
271
|
+
const borrowPos = obligation?.getBorrowByMint(kAddress(meta.mint));
|
|
272
|
+
const debtUi = borrowPos
|
|
273
|
+
? borrowPos.amount.toNumber() / Math.pow(10, meta.decimals)
|
|
274
|
+
: 0;
|
|
275
|
+
let rawAmount;
|
|
276
|
+
const wantFullRepay = !isFinite(amount) || (debtUi > 0 && amount >= debtUi);
|
|
277
|
+
if (wantFullRepay && debtUi > 0) {
|
|
278
|
+
// Check wallet can cover debt + interest margin
|
|
279
|
+
const walletBalance = await getWalletBalance(signer.address, meta.mint);
|
|
280
|
+
if (walletBalance >= debtUi * 1.002) {
|
|
281
|
+
rawAmount = U64_MAX;
|
|
282
|
+
verbose(`Wallet balance ${walletBalance} covers debt ${debtUi}, using U64_MAX for full repay`);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// Not enough to cover debt + interest — give actionable error
|
|
286
|
+
const shortfall = Math.max(debtUi * 1.002 - walletBalance, 0.000001);
|
|
287
|
+
throw new Error(`Insufficient ${meta.symbol} to fully repay. Debt: ~${debtUi.toFixed(meta.decimals)} ${meta.symbol}, ` +
|
|
288
|
+
`balance: ${walletBalance} ${meta.symbol}. ` +
|
|
289
|
+
`Get ~${shortfall.toFixed(meta.decimals)} more, then: sol lend repay max ${token}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
rawAmount = uiToTokenAmount(amount, meta.decimals).toString();
|
|
294
|
+
}
|
|
295
|
+
const slot = await getCurrentSlot();
|
|
296
|
+
const action = await KaminoAction.buildRepayTxns(market, rawAmount, kAddress(meta.mint), kSigner(signer), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)), true, undefined, slot, undefined, // payer (defaults to owner)
|
|
297
|
+
300_000, true);
|
|
298
|
+
const instructions = toV2Instructions(KaminoAction.actionToIxs(action));
|
|
299
|
+
const prices = await getPrices([meta.mint]);
|
|
300
|
+
const price = prices.get(meta.mint)?.priceUsd;
|
|
301
|
+
const result = await buildAndSendTransaction(instructions, signer, {
|
|
302
|
+
txType: 'lend-repay',
|
|
303
|
+
walletName,
|
|
304
|
+
fromMint: meta.mint,
|
|
305
|
+
fromAmount: rawAmount,
|
|
306
|
+
fromPriceUsd: price,
|
|
307
|
+
});
|
|
308
|
+
invalidateMarketCache();
|
|
309
|
+
// Fetch remaining debt (best-effort)
|
|
310
|
+
let remainingDebt;
|
|
311
|
+
try {
|
|
312
|
+
const updated = await loadMarket();
|
|
313
|
+
const obligation = await updated.getObligationByWallet(kAddress(signer.address), new VanillaObligation(kAddress(KLEND_PROGRAM_ID)));
|
|
314
|
+
if (obligation) {
|
|
315
|
+
const borrowPos = obligation.getBorrowByMint(kAddress(meta.mint));
|
|
316
|
+
if (borrowPos) {
|
|
317
|
+
remainingDebt = borrowPos.amount.toNumber() / Math.pow(10, meta.decimals);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
remainingDebt = 0;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
catch { /* non-critical */ }
|
|
325
|
+
return {
|
|
326
|
+
signature: result.signature,
|
|
327
|
+
explorerUrl: result.explorerUrl,
|
|
328
|
+
remainingDebt,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=lend-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lend-service.js","sourceRoot":"","sources":["../../src/core/lend-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface PoolInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
protocol: string;
|
|
4
|
+
tokenA: string;
|
|
5
|
+
tokenB: string;
|
|
6
|
+
tvl: number;
|
|
7
|
+
apy: number;
|
|
8
|
+
fee: number;
|
|
9
|
+
}
|
|
10
|
+
export interface LpPosition {
|
|
11
|
+
poolId: string;
|
|
12
|
+
protocol: string;
|
|
13
|
+
tokenA: string;
|
|
14
|
+
tokenB: string;
|
|
15
|
+
amountA: number;
|
|
16
|
+
amountB: number;
|
|
17
|
+
valueUsd: number;
|
|
18
|
+
feesEarned: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function getPools(tokenA: string, tokenB: string): Promise<PoolInfo[]>;
|
|
21
|
+
export declare function getPositions(walletAddress: string): Promise<LpPosition[]>;
|
|
22
|
+
export declare function deposit(walletName: string, poolId: string, amountA: number, tokenA: string, amountB: number, tokenB: string): Promise<{
|
|
23
|
+
signature: string;
|
|
24
|
+
}>;
|
|
25
|
+
export declare function withdraw(walletName: string, poolId: string, percent?: number): Promise<{
|
|
26
|
+
signature: string;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function claimFees(walletName: string, poolId: string): Promise<{
|
|
29
|
+
signature: string;
|
|
30
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { verbose } from '../output/formatter.js';
|
|
2
|
+
export async function getPools(tokenA, tokenB) {
|
|
3
|
+
verbose(`Fetching LP pools for ${tokenA}/${tokenB}`);
|
|
4
|
+
// TODO: Implement with Orca and Meteora SDKs in Phase 10
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
export async function getPositions(walletAddress) {
|
|
8
|
+
verbose(`Fetching LP positions for ${walletAddress}`);
|
|
9
|
+
// TODO: Implement in Phase 10
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
export async function deposit(walletName, poolId, amountA, tokenA, amountB, tokenB) {
|
|
13
|
+
throw new Error('LP deposit not yet implemented. Coming in Phase 10.');
|
|
14
|
+
}
|
|
15
|
+
export async function withdraw(walletName, poolId, percent) {
|
|
16
|
+
throw new Error('LP withdraw not yet implemented. Coming in Phase 10.');
|
|
17
|
+
}
|
|
18
|
+
export async function claimFees(walletName, poolId) {
|
|
19
|
+
throw new Error('LP fee claim not yet implemented. Coming in Phase 10.');
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=lp-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lp-service.js","sourceRoot":"","sources":["../../src/core/lp-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AA0BjD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,MAAc;IAC3D,OAAO,CAAC,yBAAyB,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;IAErD,yDAAyD;IACzD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,aAAqB;IACtD,OAAO,CAAC,6BAA6B,aAAa,EAAE,CAAC,CAAC;IAEtD,8BAA8B;IAC9B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAkB,EAClB,MAAc,EACd,OAAe,EACf,MAAc,EACd,OAAe,EACf,MAAc;IAEd,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAkB,EAClB,MAAc,EACd,OAAgB;IAEhB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAkB,EAClB,MAAc;IAEd,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface OnrampProvider {
|
|
2
|
+
name: string;
|
|
3
|
+
generateUrl(params: {
|
|
4
|
+
walletAddress: string;
|
|
5
|
+
amount?: number;
|
|
6
|
+
currency?: string;
|
|
7
|
+
}): string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getOnrampUrl(params: {
|
|
10
|
+
walletAddress: string;
|
|
11
|
+
amount?: number;
|
|
12
|
+
currency?: string;
|
|
13
|
+
provider?: string;
|
|
14
|
+
}): string;
|
|
15
|
+
export declare function listProviders(): string[];
|