@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,142 @@
|
|
|
1
|
+
import { createKeyPairSignerFromBytes } from '@solana/kit';
|
|
2
|
+
import { writeKeyFile, readKeyFile, softDeleteKeyFile, keyFileExists } from '../utils/fs.js';
|
|
3
|
+
import * as walletRepo from '../db/repos/wallet-repo.js';
|
|
4
|
+
import { getConfigValue } from './config-manager.js';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
8
|
+
export async function createWallet(name) {
|
|
9
|
+
if (walletRepo.getWallet(name)) {
|
|
10
|
+
throw new Error(`Wallet "${name}" already exists`);
|
|
11
|
+
}
|
|
12
|
+
if (keyFileExists(name)) {
|
|
13
|
+
throw new Error(`Key file for "${name}" already exists`);
|
|
14
|
+
}
|
|
15
|
+
// Generate 32 random bytes as seed, then derive the full 64-byte keypair
|
|
16
|
+
const privateKeyBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
17
|
+
// createKeyPairSignerFromPrivateKeyBytes derives the public key from the private key
|
|
18
|
+
const { createKeyPairFromPrivateKeyBytes } = await import('@solana/keys');
|
|
19
|
+
const keyPair = await createKeyPairFromPrivateKeyBytes(privateKeyBytes, true);
|
|
20
|
+
// Export: private key is PKCS8 (48-byte header + 32-byte key), public key is raw 32 bytes
|
|
21
|
+
const privatePkcs8 = new Uint8Array(await crypto.subtle.exportKey('pkcs8', keyPair.privateKey));
|
|
22
|
+
const publicRaw = new Uint8Array(await crypto.subtle.exportKey('raw', keyPair.publicKey));
|
|
23
|
+
// Solana CLI format: 64 bytes = 32 private + 32 public
|
|
24
|
+
const keypairBytes = new Uint8Array(64);
|
|
25
|
+
keypairBytes.set(privatePkcs8.slice(16), 0); // PKCS8 header for Ed25519 is 16 bytes
|
|
26
|
+
keypairBytes.set(publicRaw, 32);
|
|
27
|
+
// Validate by re-importing
|
|
28
|
+
const signer = await createKeyPairSignerFromBytes(keypairBytes);
|
|
29
|
+
const walletAddress = signer.address;
|
|
30
|
+
const filePath = writeKeyFile(name, keypairBytes);
|
|
31
|
+
walletRepo.insertWallet(name, walletAddress, filePath);
|
|
32
|
+
return {
|
|
33
|
+
name,
|
|
34
|
+
address: walletAddress,
|
|
35
|
+
filePath,
|
|
36
|
+
labels: [],
|
|
37
|
+
createdAt: new Date().toISOString(),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export async function createBatch(baseName, count) {
|
|
41
|
+
const results = [];
|
|
42
|
+
const digits = String(count).length;
|
|
43
|
+
for (let i = 1; i <= count; i++) {
|
|
44
|
+
const name = `${baseName}-${String(i).padStart(digits, '0')}`;
|
|
45
|
+
results.push(await createWallet(name));
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
export async function importFromFile(filePath, name) {
|
|
50
|
+
if (walletRepo.getWallet(name)) {
|
|
51
|
+
throw new Error(`Wallet "${name}" already exists`);
|
|
52
|
+
}
|
|
53
|
+
const keypairBytes = readKeyFileExternal(filePath);
|
|
54
|
+
const signer = await createKeyPairSignerFromBytes(keypairBytes);
|
|
55
|
+
const address = signer.address;
|
|
56
|
+
const savedPath = writeKeyFile(name, keypairBytes);
|
|
57
|
+
walletRepo.insertWallet(name, address, savedPath);
|
|
58
|
+
return {
|
|
59
|
+
name,
|
|
60
|
+
address,
|
|
61
|
+
filePath: savedPath,
|
|
62
|
+
labels: [],
|
|
63
|
+
createdAt: new Date().toISOString(),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export async function importFromSolanaCli(name) {
|
|
67
|
+
const solanaCfgPath = join(homedir(), '.config', 'solana', 'id.json');
|
|
68
|
+
if (!existsSync(solanaCfgPath)) {
|
|
69
|
+
throw new Error(`Solana CLI keypair not found at ${solanaCfgPath}`);
|
|
70
|
+
}
|
|
71
|
+
const walletName = name || 'solana-cli';
|
|
72
|
+
return importFromFile(solanaCfgPath, walletName);
|
|
73
|
+
}
|
|
74
|
+
function readKeyFileExternal(filePath) {
|
|
75
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
76
|
+
const arr = JSON.parse(raw);
|
|
77
|
+
return new Uint8Array(arr);
|
|
78
|
+
}
|
|
79
|
+
export async function loadSigner(name) {
|
|
80
|
+
const wallet = walletRepo.getWallet(name);
|
|
81
|
+
if (!wallet) {
|
|
82
|
+
throw new Error(`Wallet "${name}" not found`);
|
|
83
|
+
}
|
|
84
|
+
const keypairBytes = readKeyFile(wallet.file_path);
|
|
85
|
+
return createKeyPairSignerFromBytes(keypairBytes);
|
|
86
|
+
}
|
|
87
|
+
export function resolveWalletName(nameOrAddress) {
|
|
88
|
+
const byName = walletRepo.getWallet(nameOrAddress);
|
|
89
|
+
if (byName)
|
|
90
|
+
return byName.name;
|
|
91
|
+
const byAddress = walletRepo.getWalletByAddress(nameOrAddress);
|
|
92
|
+
if (byAddress)
|
|
93
|
+
return byAddress.name;
|
|
94
|
+
throw new Error(`Wallet "${nameOrAddress}" not found. Run \`sol wallet list\` to see available wallets.`);
|
|
95
|
+
}
|
|
96
|
+
export function getDefaultWalletName() {
|
|
97
|
+
// Check config for default wallet
|
|
98
|
+
const configured = getConfigValue('defaults.wallet');
|
|
99
|
+
if (configured) {
|
|
100
|
+
if (walletRepo.getWallet(configured))
|
|
101
|
+
return configured;
|
|
102
|
+
}
|
|
103
|
+
// Fall back to first wallet
|
|
104
|
+
const first = walletRepo.getDefaultWalletName();
|
|
105
|
+
if (!first)
|
|
106
|
+
throw new Error('No wallets found. Create one with: sol wallet create');
|
|
107
|
+
return first;
|
|
108
|
+
}
|
|
109
|
+
export function listWallets(label) {
|
|
110
|
+
const rows = label ? walletRepo.listWalletsByLabel(label) : walletRepo.listWallets();
|
|
111
|
+
return rows.map(row => ({
|
|
112
|
+
name: row.name,
|
|
113
|
+
address: row.address,
|
|
114
|
+
filePath: row.file_path,
|
|
115
|
+
labels: walletRepo.getLabels(row.name),
|
|
116
|
+
createdAt: row.created_at,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
export function removeWallet(name) {
|
|
120
|
+
const wallet = walletRepo.getWallet(name);
|
|
121
|
+
if (!wallet)
|
|
122
|
+
throw new Error(`Wallet "${name}" not found`);
|
|
123
|
+
// Soft-delete: rename key file so it can be recovered
|
|
124
|
+
softDeleteKeyFile(wallet.file_path);
|
|
125
|
+
walletRepo.removeWallet(name);
|
|
126
|
+
}
|
|
127
|
+
export function addLabel(name, label) {
|
|
128
|
+
const wallet = walletRepo.getWallet(name);
|
|
129
|
+
if (!wallet)
|
|
130
|
+
throw new Error(`Wallet "${name}" not found`);
|
|
131
|
+
walletRepo.addLabel(name, label);
|
|
132
|
+
}
|
|
133
|
+
export function removeLabel(name, label) {
|
|
134
|
+
walletRepo.removeLabel(name, label);
|
|
135
|
+
}
|
|
136
|
+
export function getWalletFilePath(name) {
|
|
137
|
+
const wallet = walletRepo.getWallet(name);
|
|
138
|
+
if (!wallet)
|
|
139
|
+
throw new Error(`Wallet "${name}" not found`);
|
|
140
|
+
return wallet.file_path;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=wallet-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-manager.js","sourceRoot":"","sources":["../../src/core/wallet-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAUnD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,kBAAkB,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,kBAAkB,CAAC,CAAC;IAC3D,CAAC;IAED,yEAAyE;IACzE,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnE,qFAAqF;IACrF,MAAM,EAAE,gCAAgC,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAE9E,0FAA0F;IAC1F,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAChG,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAE1F,uDAAuD;IACvD,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACxC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,uCAAuC;IACpF,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAEhC,2BAA2B;IAC3B,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;IAErC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAClD,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAEvD,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,aAAa;QACtB,QAAQ;QACR,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,KAAa;IAC/D,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAY;IACjE,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,kBAAkB,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAE/B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACnD,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAElD,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAa;IACrD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtE,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,mCAAmC,aAAa,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,IAAI,YAAY,CAAC;IACxC,OAAO,cAAc,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAa,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,aAAa,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,OAAO,4BAA4B,CAAC,YAAY,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,aAAqB;IACrD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IACnD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,UAAU,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAC/D,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC;IACrC,MAAM,IAAI,KAAK,CAAC,WAAW,aAAa,gEAAgE,CAAC,CAAC;AAC5G,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,kCAAkC;IAClC,MAAM,UAAU,GAAG,cAAc,CAAC,iBAAiB,CAAuB,CAAC;IAC3E,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC;YAAE,OAAO,UAAU,CAAC;IAC1D,CAAC;IACD,4BAA4B;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,oBAAoB,EAAE,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;IACrF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QACtC,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,aAAa,CAAC,CAAC;IAC3D,sDAAsD;IACtD,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,KAAa;IAClD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,aAAa,CAAC,CAAC;IAC3D,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa;IACrD,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,aAAa,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getSolDir, ensureSolDir } from '../core/config-manager.js';
|
|
4
|
+
import { migration001 } from './migrations/001_initial.js';
|
|
5
|
+
import { migration002 } from './migrations/002_tx_prices.js';
|
|
6
|
+
const DB_PATH = join(getSolDir(), 'data.db');
|
|
7
|
+
let db = null;
|
|
8
|
+
export function getDb() {
|
|
9
|
+
if (!db) {
|
|
10
|
+
ensureSolDir();
|
|
11
|
+
db = new Database(DB_PATH);
|
|
12
|
+
db.pragma('journal_mode = WAL');
|
|
13
|
+
db.pragma('foreign_keys = ON');
|
|
14
|
+
runMigrations(db);
|
|
15
|
+
}
|
|
16
|
+
return db;
|
|
17
|
+
}
|
|
18
|
+
export function closeDb() {
|
|
19
|
+
if (db) {
|
|
20
|
+
db.close();
|
|
21
|
+
db = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const migrations = [
|
|
25
|
+
{ id: 1, name: '001_initial', sql: migration001 },
|
|
26
|
+
{ id: 2, name: '002_tx_prices', sql: migration002 },
|
|
27
|
+
];
|
|
28
|
+
function runMigrations(database) {
|
|
29
|
+
database.exec(`
|
|
30
|
+
CREATE TABLE IF NOT EXISTS _migrations (
|
|
31
|
+
id INTEGER PRIMARY KEY,
|
|
32
|
+
name TEXT NOT NULL,
|
|
33
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
34
|
+
)
|
|
35
|
+
`);
|
|
36
|
+
const applied = new Set(database.prepare('SELECT id FROM _migrations').all().map((r) => r.id));
|
|
37
|
+
for (const migration of migrations) {
|
|
38
|
+
if (!applied.has(migration.id)) {
|
|
39
|
+
database.exec(migration.sql);
|
|
40
|
+
database.prepare('INSERT INTO _migrations (id, name) VALUES (?, ?)').run(migration.id, migration.name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,CAAC,CAAC;AAE7C,IAAI,EAAE,GAA6B,IAAI,CAAC;AAExC,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,YAAY,EAAE,CAAC;QACf,EAAE,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC3B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC/B,aAAa,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,GAAsB;IACpC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE;IACjD,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,EAAE;CACpD,CAAC;AAEF,SAAS,aAAa,CAAC,QAA2B;IAChD,QAAQ,CAAC,IAAI,CAAC;;;;;;GAMb,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,QAAQ,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC3E,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC7B,QAAQ,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC,GAAG,CACtE,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAC7B,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const migration001 = "\n-- Wallets\nCREATE TABLE IF NOT EXISTS wallets (\n name TEXT PRIMARY KEY,\n address TEXT NOT NULL UNIQUE,\n file_path TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_wallets_address ON wallets(address);\n\n-- Wallet labels (many-to-many tags)\nCREATE TABLE IF NOT EXISTS wallet_labels (\n wallet_name TEXT NOT NULL REFERENCES wallets(name) ON DELETE CASCADE,\n label TEXT NOT NULL,\n PRIMARY KEY (wallet_name, label)\n);\nCREATE INDEX IF NOT EXISTS idx_wallet_labels_label ON wallet_labels(label);\n\n-- Token metadata cache\nCREATE TABLE IF NOT EXISTS token_cache (\n mint TEXT PRIMARY KEY,\n symbol TEXT,\n name TEXT,\n decimals INTEGER NOT NULL,\n logo_uri TEXT,\n tags TEXT,\n source TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_token_cache_symbol ON token_cache(symbol);\n\n-- Price history\nCREATE TABLE IF NOT EXISTS price_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n mint TEXT NOT NULL,\n price_usd REAL NOT NULL,\n source TEXT NOT NULL,\n timestamp TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_price_history_mint ON price_history(mint);\nCREATE INDEX IF NOT EXISTS idx_price_history_timestamp ON price_history(timestamp);\n\n-- Snapshots\nCREATE TABLE IF NOT EXISTS snapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n label TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS snapshot_entries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n snapshot_id INTEGER NOT NULL REFERENCES snapshots(id) ON DELETE CASCADE,\n wallet_name TEXT NOT NULL,\n wallet_address TEXT NOT NULL,\n mint TEXT NOT NULL,\n symbol TEXT,\n balance TEXT NOT NULL,\n price_usd REAL,\n value_usd REAL,\n position_type TEXT DEFAULT 'token',\n protocol TEXT,\n pool_id TEXT\n);\nCREATE INDEX IF NOT EXISTS idx_snapshot_entries_snapshot ON snapshot_entries(snapshot_id);\n\n-- Transaction log\nCREATE TABLE IF NOT EXISTS transaction_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n signature TEXT UNIQUE,\n type TEXT NOT NULL,\n wallet_name TEXT,\n from_mint TEXT,\n to_mint TEXT,\n from_amount TEXT,\n to_amount TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n error TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_tx_log_signature ON transaction_log(signature);\nCREATE INDEX IF NOT EXISTS idx_tx_log_wallet ON transaction_log(wallet_name);\n\n-- Balance cache\nCREATE TABLE IF NOT EXISTS balance_cache (\n wallet_address TEXT NOT NULL,\n mint TEXT NOT NULL,\n balance TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (wallet_address, mint)\n);\n\n-- Positions (for yield fee tracking)\nCREATE TABLE IF NOT EXISTS positions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n wallet_address TEXT NOT NULL,\n type TEXT NOT NULL,\n protocol TEXT NOT NULL,\n mint TEXT,\n pool_id TEXT,\n deposit_amount TEXT NOT NULL,\n deposit_value_usd REAL,\n deposit_tx TEXT,\n deposit_at TEXT NOT NULL,\n withdraw_amount TEXT,\n withdraw_value_usd REAL,\n withdraw_tx TEXT,\n withdraw_at TEXT,\n status TEXT NOT NULL DEFAULT 'open',\n yield_fee_taken REAL DEFAULT 0,\n UNIQUE(deposit_tx)\n);\nCREATE INDEX IF NOT EXISTS idx_positions_wallet ON positions(wallet_address);\nCREATE INDEX IF NOT EXISTS idx_positions_status ON positions(status);\n";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export const migration001 = `
|
|
2
|
+
-- Wallets
|
|
3
|
+
CREATE TABLE IF NOT EXISTS wallets (
|
|
4
|
+
name TEXT PRIMARY KEY,
|
|
5
|
+
address TEXT NOT NULL UNIQUE,
|
|
6
|
+
file_path TEXT NOT NULL,
|
|
7
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
8
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
9
|
+
);
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_wallets_address ON wallets(address);
|
|
11
|
+
|
|
12
|
+
-- Wallet labels (many-to-many tags)
|
|
13
|
+
CREATE TABLE IF NOT EXISTS wallet_labels (
|
|
14
|
+
wallet_name TEXT NOT NULL REFERENCES wallets(name) ON DELETE CASCADE,
|
|
15
|
+
label TEXT NOT NULL,
|
|
16
|
+
PRIMARY KEY (wallet_name, label)
|
|
17
|
+
);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_wallet_labels_label ON wallet_labels(label);
|
|
19
|
+
|
|
20
|
+
-- Token metadata cache
|
|
21
|
+
CREATE TABLE IF NOT EXISTS token_cache (
|
|
22
|
+
mint TEXT PRIMARY KEY,
|
|
23
|
+
symbol TEXT,
|
|
24
|
+
name TEXT,
|
|
25
|
+
decimals INTEGER NOT NULL,
|
|
26
|
+
logo_uri TEXT,
|
|
27
|
+
tags TEXT,
|
|
28
|
+
source TEXT NOT NULL,
|
|
29
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
30
|
+
);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_token_cache_symbol ON token_cache(symbol);
|
|
32
|
+
|
|
33
|
+
-- Price history
|
|
34
|
+
CREATE TABLE IF NOT EXISTS price_history (
|
|
35
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
+
mint TEXT NOT NULL,
|
|
37
|
+
price_usd REAL NOT NULL,
|
|
38
|
+
source TEXT NOT NULL,
|
|
39
|
+
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
|
|
40
|
+
);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_price_history_mint ON price_history(mint);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_price_history_timestamp ON price_history(timestamp);
|
|
43
|
+
|
|
44
|
+
-- Snapshots
|
|
45
|
+
CREATE TABLE IF NOT EXISTS snapshots (
|
|
46
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47
|
+
label TEXT,
|
|
48
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS snapshot_entries (
|
|
52
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
53
|
+
snapshot_id INTEGER NOT NULL REFERENCES snapshots(id) ON DELETE CASCADE,
|
|
54
|
+
wallet_name TEXT NOT NULL,
|
|
55
|
+
wallet_address TEXT NOT NULL,
|
|
56
|
+
mint TEXT NOT NULL,
|
|
57
|
+
symbol TEXT,
|
|
58
|
+
balance TEXT NOT NULL,
|
|
59
|
+
price_usd REAL,
|
|
60
|
+
value_usd REAL,
|
|
61
|
+
position_type TEXT DEFAULT 'token',
|
|
62
|
+
protocol TEXT,
|
|
63
|
+
pool_id TEXT
|
|
64
|
+
);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_snapshot_entries_snapshot ON snapshot_entries(snapshot_id);
|
|
66
|
+
|
|
67
|
+
-- Transaction log
|
|
68
|
+
CREATE TABLE IF NOT EXISTS transaction_log (
|
|
69
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
70
|
+
signature TEXT UNIQUE,
|
|
71
|
+
type TEXT NOT NULL,
|
|
72
|
+
wallet_name TEXT,
|
|
73
|
+
from_mint TEXT,
|
|
74
|
+
to_mint TEXT,
|
|
75
|
+
from_amount TEXT,
|
|
76
|
+
to_amount TEXT,
|
|
77
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
78
|
+
error TEXT,
|
|
79
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
80
|
+
);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_tx_log_signature ON transaction_log(signature);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_tx_log_wallet ON transaction_log(wallet_name);
|
|
83
|
+
|
|
84
|
+
-- Balance cache
|
|
85
|
+
CREATE TABLE IF NOT EXISTS balance_cache (
|
|
86
|
+
wallet_address TEXT NOT NULL,
|
|
87
|
+
mint TEXT NOT NULL,
|
|
88
|
+
balance TEXT NOT NULL,
|
|
89
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
90
|
+
PRIMARY KEY (wallet_address, mint)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
-- Positions (for yield fee tracking)
|
|
94
|
+
CREATE TABLE IF NOT EXISTS positions (
|
|
95
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
96
|
+
wallet_address TEXT NOT NULL,
|
|
97
|
+
type TEXT NOT NULL,
|
|
98
|
+
protocol TEXT NOT NULL,
|
|
99
|
+
mint TEXT,
|
|
100
|
+
pool_id TEXT,
|
|
101
|
+
deposit_amount TEXT NOT NULL,
|
|
102
|
+
deposit_value_usd REAL,
|
|
103
|
+
deposit_tx TEXT,
|
|
104
|
+
deposit_at TEXT NOT NULL,
|
|
105
|
+
withdraw_amount TEXT,
|
|
106
|
+
withdraw_value_usd REAL,
|
|
107
|
+
withdraw_tx TEXT,
|
|
108
|
+
withdraw_at TEXT,
|
|
109
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
110
|
+
yield_fee_taken REAL DEFAULT 0,
|
|
111
|
+
UNIQUE(deposit_tx)
|
|
112
|
+
);
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_positions_wallet ON positions(wallet_address);
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_positions_status ON positions(status);
|
|
115
|
+
`;
|
|
116
|
+
//# sourceMappingURL=001_initial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"001_initial.js","sourceRoot":"","sources":["../../../src/db/migrations/001_initial.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkH3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const migration002 = "\nALTER TABLE transaction_log ADD COLUMN from_price_usd REAL;\nALTER TABLE transaction_log ADD COLUMN to_price_usd REAL;\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"002_tx_prices.js","sourceRoot":"","sources":["../../../src/db/migrations/002_tx_prices.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;;;CAG3B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PriceRow {
|
|
2
|
+
id: number;
|
|
3
|
+
mint: string;
|
|
4
|
+
price_usd: number;
|
|
5
|
+
source: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function insertPrice(mint: string, priceUsd: number, source: string): void;
|
|
9
|
+
export declare function getLatestPrice(mint: string): PriceRow | undefined;
|
|
10
|
+
export declare function getPriceAt(mint: string, timestamp: string): PriceRow | undefined;
|
|
11
|
+
export declare function getPriceHistory(mint: string, limit?: number): PriceRow[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getDb } from '../database.js';
|
|
2
|
+
export function insertPrice(mint, priceUsd, source) {
|
|
3
|
+
getDb().prepare('INSERT INTO price_history (mint, price_usd, source) VALUES (?, ?, ?)').run(mint, priceUsd, source);
|
|
4
|
+
}
|
|
5
|
+
export function getLatestPrice(mint) {
|
|
6
|
+
return getDb().prepare('SELECT * FROM price_history WHERE mint = ? ORDER BY timestamp DESC LIMIT 1').get(mint);
|
|
7
|
+
}
|
|
8
|
+
export function getPriceAt(mint, timestamp) {
|
|
9
|
+
return getDb().prepare('SELECT * FROM price_history WHERE mint = ? AND timestamp <= ? ORDER BY timestamp DESC LIMIT 1').get(mint, timestamp);
|
|
10
|
+
}
|
|
11
|
+
export function getPriceHistory(mint, limit = 100) {
|
|
12
|
+
return getDb().prepare('SELECT * FROM price_history WHERE mint = ? ORDER BY timestamp DESC LIMIT ?').all(mint, limit);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=price-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-repo.js","sourceRoot":"","sources":["../../../src/db/repos/price-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAUvC,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAgB,EAAE,MAAc;IACxE,KAAK,EAAE,CAAC,OAAO,CACb,sEAAsE,CACvE,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,4EAA4E,CAC7E,CAAC,GAAG,CAAC,IAAI,CAAyB,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,SAAiB;IACxD,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,+FAA+F,CAChG,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAyB,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAK,GAAG,GAAG;IACvD,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,4EAA4E,CAC7E,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAe,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface SnapshotRow {
|
|
2
|
+
id: number;
|
|
3
|
+
label: string | null;
|
|
4
|
+
created_at: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SnapshotEntryRow {
|
|
7
|
+
id: number;
|
|
8
|
+
snapshot_id: number;
|
|
9
|
+
wallet_name: string;
|
|
10
|
+
wallet_address: string;
|
|
11
|
+
mint: string;
|
|
12
|
+
symbol: string | null;
|
|
13
|
+
balance: string;
|
|
14
|
+
price_usd: number | null;
|
|
15
|
+
value_usd: number | null;
|
|
16
|
+
position_type: string;
|
|
17
|
+
protocol: string | null;
|
|
18
|
+
pool_id: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function createSnapshot(label?: string): number;
|
|
21
|
+
export declare function insertSnapshotEntry(entry: Omit<SnapshotEntryRow, 'id'>): void;
|
|
22
|
+
export declare function getSnapshot(id: number): SnapshotRow | undefined;
|
|
23
|
+
export declare function listSnapshots(limit?: number): SnapshotRow[];
|
|
24
|
+
export declare function getSnapshotEntries(snapshotId: number): SnapshotEntryRow[];
|
|
25
|
+
export declare function deleteSnapshot(id: number): boolean;
|
|
26
|
+
export declare function getLatestSnapshot(): SnapshotRow | undefined;
|
|
27
|
+
export declare function getSnapshotBefore(timestamp: string): SnapshotRow | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getDb } from '../database.js';
|
|
2
|
+
export function createSnapshot(label) {
|
|
3
|
+
const result = getDb().prepare('INSERT INTO snapshots (label) VALUES (?)').run(label ?? null);
|
|
4
|
+
return Number(result.lastInsertRowid);
|
|
5
|
+
}
|
|
6
|
+
export function insertSnapshotEntry(entry) {
|
|
7
|
+
getDb().prepare(`
|
|
8
|
+
INSERT INTO snapshot_entries
|
|
9
|
+
(snapshot_id, wallet_name, wallet_address, mint, symbol, balance, price_usd, value_usd, position_type, protocol, pool_id)
|
|
10
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
11
|
+
`).run(entry.snapshot_id, entry.wallet_name, entry.wallet_address, entry.mint, entry.symbol, entry.balance, entry.price_usd, entry.value_usd, entry.position_type, entry.protocol, entry.pool_id);
|
|
12
|
+
}
|
|
13
|
+
export function getSnapshot(id) {
|
|
14
|
+
return getDb().prepare('SELECT * FROM snapshots WHERE id = ?').get(id);
|
|
15
|
+
}
|
|
16
|
+
export function listSnapshots(limit = 50) {
|
|
17
|
+
return getDb().prepare('SELECT * FROM snapshots ORDER BY created_at DESC LIMIT ?').all(limit);
|
|
18
|
+
}
|
|
19
|
+
export function getSnapshotEntries(snapshotId) {
|
|
20
|
+
return getDb().prepare('SELECT * FROM snapshot_entries WHERE snapshot_id = ? ORDER BY wallet_name, symbol').all(snapshotId);
|
|
21
|
+
}
|
|
22
|
+
export function deleteSnapshot(id) {
|
|
23
|
+
const result = getDb().prepare('DELETE FROM snapshots WHERE id = ?').run(id);
|
|
24
|
+
return result.changes > 0;
|
|
25
|
+
}
|
|
26
|
+
export function getLatestSnapshot() {
|
|
27
|
+
return getDb().prepare('SELECT * FROM snapshots ORDER BY created_at DESC LIMIT 1').get();
|
|
28
|
+
}
|
|
29
|
+
export function getSnapshotBefore(timestamp) {
|
|
30
|
+
return getDb().prepare('SELECT * FROM snapshots WHERE created_at <= ? ORDER BY created_at DESC LIMIT 1').get(timestamp);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=snapshot-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-repo.js","sourceRoot":"","sources":["../../../src/db/repos/snapshot-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAuBvC,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,OAAO,CAC5B,0CAA0C,CAC3C,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IACrB,OAAO,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAmC;IACrE,KAAK,EAAE,CAAC,OAAO,CAAC;;;;GAIf,CAAC,CAAC,GAAG,CACJ,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,EAC1D,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EACzE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CACnD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,GAAG,CAAC,EAAE,CAA4B,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAK,GAAG,EAAE;IACtC,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC,GAAG,CAAC,KAAK,CAAkB,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,mFAAmF,CACpF,CAAC,GAAG,CAAC,UAAU,CAAuB,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC,GAAG,EAA6B,CAAC;AACtH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,gFAAgF,CACjF,CAAC,GAAG,CAAC,SAAS,CAA4B,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface TokenRow {
|
|
2
|
+
mint: string;
|
|
3
|
+
symbol: string | null;
|
|
4
|
+
name: string | null;
|
|
5
|
+
decimals: number;
|
|
6
|
+
logo_uri: string | null;
|
|
7
|
+
tags: string | null;
|
|
8
|
+
source: string;
|
|
9
|
+
updated_at: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function upsertToken(token: Omit<TokenRow, 'updated_at'>): void;
|
|
12
|
+
export declare function upsertTokenBatch(tokens: Omit<TokenRow, 'updated_at'>[]): void;
|
|
13
|
+
export declare function getTokenByMint(mint: string): TokenRow | undefined;
|
|
14
|
+
export declare function getTokenBySymbol(symbol: string): TokenRow[];
|
|
15
|
+
export declare function searchTokens(query: string): TokenRow[];
|
|
16
|
+
export declare function getAllTokens(): TokenRow[];
|
|
17
|
+
export declare function isTokenCacheStale(mint: string, ttlHours?: number): boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getDb } from '../database.js';
|
|
2
|
+
export function upsertToken(token) {
|
|
3
|
+
getDb().prepare(`
|
|
4
|
+
INSERT INTO token_cache (mint, symbol, name, decimals, logo_uri, tags, source, updated_at)
|
|
5
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
6
|
+
ON CONFLICT(mint) DO UPDATE SET
|
|
7
|
+
symbol = excluded.symbol,
|
|
8
|
+
name = excluded.name,
|
|
9
|
+
decimals = excluded.decimals,
|
|
10
|
+
logo_uri = excluded.logo_uri,
|
|
11
|
+
tags = excluded.tags,
|
|
12
|
+
source = excluded.source,
|
|
13
|
+
updated_at = datetime('now')
|
|
14
|
+
`).run(token.mint, token.symbol, token.name, token.decimals, token.logo_uri, token.tags, token.source);
|
|
15
|
+
}
|
|
16
|
+
export function upsertTokenBatch(tokens) {
|
|
17
|
+
const stmt = getDb().prepare(`
|
|
18
|
+
INSERT INTO token_cache (mint, symbol, name, decimals, logo_uri, tags, source, updated_at)
|
|
19
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
20
|
+
ON CONFLICT(mint) DO UPDATE SET
|
|
21
|
+
symbol = excluded.symbol,
|
|
22
|
+
name = excluded.name,
|
|
23
|
+
decimals = excluded.decimals,
|
|
24
|
+
logo_uri = excluded.logo_uri,
|
|
25
|
+
tags = excluded.tags,
|
|
26
|
+
source = excluded.source,
|
|
27
|
+
updated_at = datetime('now')
|
|
28
|
+
`);
|
|
29
|
+
const tx = getDb().transaction((items) => {
|
|
30
|
+
for (const t of items) {
|
|
31
|
+
stmt.run(t.mint, t.symbol, t.name, t.decimals, t.logo_uri, t.tags, t.source);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
tx(tokens);
|
|
35
|
+
}
|
|
36
|
+
export function getTokenByMint(mint) {
|
|
37
|
+
return getDb().prepare('SELECT * FROM token_cache WHERE mint = ?').get(mint);
|
|
38
|
+
}
|
|
39
|
+
export function getTokenBySymbol(symbol) {
|
|
40
|
+
return getDb().prepare('SELECT * FROM token_cache WHERE UPPER(symbol) = UPPER(?) ORDER BY updated_at DESC').all(symbol);
|
|
41
|
+
}
|
|
42
|
+
export function searchTokens(query) {
|
|
43
|
+
const like = `%${query}%`;
|
|
44
|
+
return getDb().prepare('SELECT * FROM token_cache WHERE UPPER(symbol) LIKE UPPER(?) OR UPPER(name) LIKE UPPER(?) ORDER BY symbol LIMIT 20').all(like, like);
|
|
45
|
+
}
|
|
46
|
+
export function getAllTokens() {
|
|
47
|
+
return getDb().prepare('SELECT * FROM token_cache ORDER BY symbol').all();
|
|
48
|
+
}
|
|
49
|
+
export function isTokenCacheStale(mint, ttlHours = 24) {
|
|
50
|
+
const row = getDb().prepare("SELECT updated_at FROM token_cache WHERE mint = ? AND datetime(updated_at, '+' || ? || ' hours') > datetime('now')").get(mint, ttlHours);
|
|
51
|
+
return !row;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=token-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-repo.js","sourceRoot":"","sources":["../../../src/db/repos/token-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAavC,MAAM,UAAU,WAAW,CAAC,KAAmC;IAC7D,KAAK,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;GAWf,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAsC;IACrE,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;GAW5B,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,KAAoB,EAAE,EAAE;QACtD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,CAAC,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAyB,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,mFAAmF,CACpF,CAAC,GAAG,CAAC,MAAM,CAAe,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,IAAI,GAAG,IAAI,KAAK,GAAG,CAAC;IAC1B,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,mHAAmH,CACpH,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAe,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,EAAgB,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAQ,GAAG,EAAE;IAC3D,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,OAAO,CACzB,oHAAoH,CACrH,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAuC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface TransactionRow {
|
|
2
|
+
id: number;
|
|
3
|
+
signature: string;
|
|
4
|
+
type: string;
|
|
5
|
+
wallet_name: string | null;
|
|
6
|
+
from_mint: string | null;
|
|
7
|
+
to_mint: string | null;
|
|
8
|
+
from_amount: string | null;
|
|
9
|
+
to_amount: string | null;
|
|
10
|
+
from_price_usd: number | null;
|
|
11
|
+
to_price_usd: number | null;
|
|
12
|
+
status: string;
|
|
13
|
+
error: string | null;
|
|
14
|
+
created_at: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function getRecentTransactions(opts?: {
|
|
17
|
+
walletName?: string;
|
|
18
|
+
type?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}): TransactionRow[];
|
|
21
|
+
export declare function getTransactionBySignature(signature: string): TransactionRow | undefined;
|
|
22
|
+
export declare function getTransactionCount(walletName?: string): number;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getDb } from '../database.js';
|
|
2
|
+
export function getRecentTransactions(opts = {}) {
|
|
3
|
+
const conditions = [];
|
|
4
|
+
const params = [];
|
|
5
|
+
if (opts.walletName) {
|
|
6
|
+
conditions.push('wallet_name = ?');
|
|
7
|
+
params.push(opts.walletName);
|
|
8
|
+
}
|
|
9
|
+
if (opts.type) {
|
|
10
|
+
conditions.push('type = ?');
|
|
11
|
+
params.push(opts.type);
|
|
12
|
+
}
|
|
13
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
14
|
+
const limit = opts.limit ?? 20;
|
|
15
|
+
return getDb().prepare(`SELECT * FROM transaction_log ${where} ORDER BY created_at DESC LIMIT ?`).all(...params, limit);
|
|
16
|
+
}
|
|
17
|
+
export function getTransactionBySignature(signature) {
|
|
18
|
+
return getDb().prepare('SELECT * FROM transaction_log WHERE signature = ?').get(signature);
|
|
19
|
+
}
|
|
20
|
+
export function getTransactionCount(walletName) {
|
|
21
|
+
if (walletName) {
|
|
22
|
+
const row = getDb().prepare('SELECT COUNT(*) as count FROM transaction_log WHERE wallet_name = ?').get(walletName);
|
|
23
|
+
return row.count;
|
|
24
|
+
}
|
|
25
|
+
const row = getDb().prepare('SELECT COUNT(*) as count FROM transaction_log').get();
|
|
26
|
+
return row.count;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=transaction-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-repo.js","sourceRoot":"","sources":["../../../src/db/repos/transaction-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAkBvC,MAAM,UAAU,qBAAqB,CAAC,OAIlC,EAAE;IACJ,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,MAAM,GAAc,EAAE,CAAC;IAE7B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAE/B,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,iCAAiC,KAAK,mCAAmC,CAC1E,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,KAAK,CAAqB,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACzD,OAAO,KAAK,EAAE,CAAC,OAAO,CACpB,mDAAmD,CACpD,CAAC,GAAG,CAAC,SAAS,CAA+B,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAmB;IACrD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,OAAO,CACzB,qEAAqE,CACtE,CAAC,GAAG,CAAC,UAAU,CAAsB,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,EAAuB,CAAC;IACxG,OAAO,GAAG,CAAC,KAAK,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface WalletRow {
|
|
2
|
+
name: string;
|
|
3
|
+
address: string;
|
|
4
|
+
file_path: string;
|
|
5
|
+
created_at: string;
|
|
6
|
+
updated_at: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function insertWallet(name: string, address: string, filePath: string): void;
|
|
9
|
+
export declare function getWallet(name: string): WalletRow | undefined;
|
|
10
|
+
export declare function getWalletByAddress(address: string): WalletRow | undefined;
|
|
11
|
+
export declare function listWallets(): WalletRow[];
|
|
12
|
+
export declare function listWalletsByLabel(label: string): WalletRow[];
|
|
13
|
+
export declare function removeWallet(name: string): boolean;
|
|
14
|
+
export declare function addLabel(walletName: string, label: string): void;
|
|
15
|
+
export declare function removeLabel(walletName: string, label: string): void;
|
|
16
|
+
export declare function getLabels(walletName: string): string[];
|
|
17
|
+
export declare function walletCount(): number;
|
|
18
|
+
export declare function getDefaultWalletName(): string | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getDb } from '../database.js';
|
|
2
|
+
export function insertWallet(name, address, filePath) {
|
|
3
|
+
getDb().prepare('INSERT INTO wallets (name, address, file_path) VALUES (?, ?, ?)').run(name, address, filePath);
|
|
4
|
+
}
|
|
5
|
+
export function getWallet(name) {
|
|
6
|
+
return getDb().prepare('SELECT * FROM wallets WHERE name = ?').get(name);
|
|
7
|
+
}
|
|
8
|
+
export function getWalletByAddress(address) {
|
|
9
|
+
return getDb().prepare('SELECT * FROM wallets WHERE address = ?').get(address);
|
|
10
|
+
}
|
|
11
|
+
export function listWallets() {
|
|
12
|
+
return getDb().prepare('SELECT * FROM wallets ORDER BY created_at').all();
|
|
13
|
+
}
|
|
14
|
+
export function listWalletsByLabel(label) {
|
|
15
|
+
return getDb().prepare(`
|
|
16
|
+
SELECT w.* FROM wallets w
|
|
17
|
+
JOIN wallet_labels wl ON w.name = wl.wallet_name
|
|
18
|
+
WHERE wl.label = ?
|
|
19
|
+
ORDER BY w.created_at
|
|
20
|
+
`).all(label);
|
|
21
|
+
}
|
|
22
|
+
export function removeWallet(name) {
|
|
23
|
+
const result = getDb().prepare('DELETE FROM wallets WHERE name = ?').run(name);
|
|
24
|
+
return result.changes > 0;
|
|
25
|
+
}
|
|
26
|
+
export function addLabel(walletName, label) {
|
|
27
|
+
getDb().prepare('INSERT OR IGNORE INTO wallet_labels (wallet_name, label) VALUES (?, ?)').run(walletName, label);
|
|
28
|
+
}
|
|
29
|
+
export function removeLabel(walletName, label) {
|
|
30
|
+
getDb().prepare('DELETE FROM wallet_labels WHERE wallet_name = ? AND label = ?').run(walletName, label);
|
|
31
|
+
}
|
|
32
|
+
export function getLabels(walletName) {
|
|
33
|
+
const rows = getDb().prepare('SELECT label FROM wallet_labels WHERE wallet_name = ? ORDER BY label').all(walletName);
|
|
34
|
+
return rows.map(r => r.label);
|
|
35
|
+
}
|
|
36
|
+
export function walletCount() {
|
|
37
|
+
const row = getDb().prepare('SELECT COUNT(*) as count FROM wallets').get();
|
|
38
|
+
return row.count;
|
|
39
|
+
}
|
|
40
|
+
export function getDefaultWalletName() {
|
|
41
|
+
const row = getDb().prepare('SELECT name FROM wallets ORDER BY created_at LIMIT 1').get();
|
|
42
|
+
return row?.name;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=wallet-repo.js.map
|