obol-mcp 2.0.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.
Files changed (58) hide show
  1. package/README.md +195 -0
  2. package/dist/app.d.ts +3 -0
  3. package/dist/app.d.ts.map +1 -0
  4. package/dist/app.js +130 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/config/env.d.ts +47 -0
  7. package/dist/config/env.d.ts.map +1 -0
  8. package/dist/config/env.js +63 -0
  9. package/dist/config/env.js.map +1 -0
  10. package/dist/config/pricing.d.ts +12 -0
  11. package/dist/config/pricing.d.ts.map +1 -0
  12. package/dist/config/pricing.js +99 -0
  13. package/dist/config/pricing.js.map +1 -0
  14. package/dist/mcp.d.ts +35 -0
  15. package/dist/mcp.d.ts.map +1 -0
  16. package/dist/mcp.js +150 -0
  17. package/dist/mcp.js.map +1 -0
  18. package/dist/middleware/validation.d.ts +6 -0
  19. package/dist/middleware/validation.d.ts.map +1 -0
  20. package/dist/middleware/validation.js +40 -0
  21. package/dist/middleware/validation.js.map +1 -0
  22. package/dist/middleware/x402.d.ts +33 -0
  23. package/dist/middleware/x402.d.ts.map +1 -0
  24. package/dist/middleware/x402.js +294 -0
  25. package/dist/middleware/x402.js.map +1 -0
  26. package/dist/plugins/defi/routes.d.ts +12 -0
  27. package/dist/plugins/defi/routes.d.ts.map +1 -0
  28. package/dist/plugins/defi/routes.js +430 -0
  29. package/dist/plugins/defi/routes.js.map +1 -0
  30. package/dist/plugins/token/routes.d.ts +10 -0
  31. package/dist/plugins/token/routes.d.ts.map +1 -0
  32. package/dist/plugins/token/routes.js +111 -0
  33. package/dist/plugins/token/routes.js.map +1 -0
  34. package/dist/plugins/wallet/routes.d.ts +13 -0
  35. package/dist/plugins/wallet/routes.d.ts.map +1 -0
  36. package/dist/plugins/wallet/routes.js +235 -0
  37. package/dist/plugins/wallet/routes.js.map +1 -0
  38. package/dist/server.d.ts +2 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +38 -0
  41. package/dist/server.js.map +1 -0
  42. package/dist/services/cache.d.ts +25 -0
  43. package/dist/services/cache.d.ts.map +1 -0
  44. package/dist/services/cache.js +82 -0
  45. package/dist/services/cache.js.map +1 -0
  46. package/dist/services/helius.d.ts +102 -0
  47. package/dist/services/helius.d.ts.map +1 -0
  48. package/dist/services/helius.js +456 -0
  49. package/dist/services/helius.js.map +1 -0
  50. package/dist/utils/logger.d.ts +3 -0
  51. package/dist/utils/logger.d.ts.map +1 -0
  52. package/dist/utils/logger.js +15 -0
  53. package/dist/utils/logger.js.map +1 -0
  54. package/dist/utils/retry.d.ts +9 -0
  55. package/dist/utils/retry.d.ts.map +1 -0
  56. package/dist/utils/retry.js +45 -0
  57. package/dist/utils/retry.js.map +1 -0
  58. package/package.json +81 -0
@@ -0,0 +1,235 @@
1
+ import { validateSolanaAddress } from '../../middleware/validation.js';
2
+ import { helius } from '../../services/helius.js';
3
+ import { config } from '../../config/env.js';
4
+ import { cache } from '../../services/cache.js';
5
+ /**
6
+ * Wallet analytics plugin — all /api/v1/wallet/* routes
7
+ *
8
+ * Endpoints:
9
+ * GET /api/v1/wallet/:address/overview ($0.01)
10
+ * GET /api/v1/wallet/:address/portfolio ($0.05)
11
+ * GET /api/v1/wallet/:address/activity ($0.05)
12
+ * GET /api/v1/wallet/:address/risk ($0.10)
13
+ * GET /api/v1/wallet/:address/pnl ($0.15)
14
+ */
15
+ export async function walletPlugin(app) {
16
+ const rateConfig = {
17
+ config: {
18
+ rateLimit: {
19
+ max: config.security.rateLimitMaxRequests,
20
+ timeWindow: config.security.rateLimitWindowMs,
21
+ },
22
+ },
23
+ };
24
+ // ── Overview ──
25
+ app.get('/api/v1/wallet/:address/overview', { preHandler: validateSolanaAddress, ...rateConfig }, async (request, reply) => {
26
+ const { address } = request.params;
27
+ try {
28
+ const data = await helius.getWalletOverview(address);
29
+ return reply.send({
30
+ success: true,
31
+ wallet: address,
32
+ payment: request.payment,
33
+ data,
34
+ });
35
+ }
36
+ catch (error) {
37
+ app.log.error({ error, address }, 'Wallet overview failed');
38
+ return reply.code(500).send({
39
+ error: 'Internal Server Error',
40
+ message: 'Failed to fetch wallet overview',
41
+ });
42
+ }
43
+ });
44
+ // ── Portfolio ──
45
+ app.get('/api/v1/wallet/:address/portfolio', { preHandler: validateSolanaAddress, ...rateConfig }, async (request, reply) => {
46
+ const { address } = request.params;
47
+ try {
48
+ const data = await helius.getWalletPortfolio(address);
49
+ return reply.send({
50
+ success: true,
51
+ wallet: address,
52
+ payment: request.payment,
53
+ data,
54
+ });
55
+ }
56
+ catch (error) {
57
+ app.log.error({ error, address }, 'Wallet portfolio failed');
58
+ return reply.code(500).send({
59
+ error: 'Internal Server Error',
60
+ message: 'Failed to fetch portfolio',
61
+ });
62
+ }
63
+ });
64
+ // ── Activity ──
65
+ app.get('/api/v1/wallet/:address/activity', { preHandler: validateSolanaAddress, ...rateConfig }, async (request, reply) => {
66
+ const { address } = request.params;
67
+ try {
68
+ const data = await helius.getWalletActivity(address);
69
+ return reply.send({
70
+ success: true,
71
+ wallet: address,
72
+ payment: request.payment,
73
+ data,
74
+ });
75
+ }
76
+ catch (error) {
77
+ app.log.error({ error, address }, 'Wallet activity failed');
78
+ return reply.code(500).send({
79
+ error: 'Internal Server Error',
80
+ message: 'Failed to fetch activity',
81
+ });
82
+ }
83
+ });
84
+ // ── Risk ──
85
+ app.get('/api/v1/wallet/:address/risk', { preHandler: validateSolanaAddress, ...rateConfig }, async (request, reply) => {
86
+ const { address } = request.params;
87
+ try {
88
+ const data = await helius.getWalletRisk(address);
89
+ return reply.send({
90
+ success: true,
91
+ wallet: address,
92
+ payment: request.payment,
93
+ data,
94
+ });
95
+ }
96
+ catch (error) {
97
+ app.log.error({ error, address }, 'Wallet risk failed');
98
+ return reply.code(500).send({
99
+ error: 'Internal Server Error',
100
+ message: 'Failed to fetch risk assessment',
101
+ });
102
+ }
103
+ });
104
+ // ── P&L ──
105
+ app.get('/api/v1/wallet/:address/pnl', { preHandler: validateSolanaAddress, ...rateConfig }, async (request, reply) => {
106
+ const { address } = request.params;
107
+ try {
108
+ const cacheKey = `wallet-pnl:${address}`;
109
+ const cached = await cache.get(cacheKey);
110
+ if (cached) {
111
+ return reply.send({ success: true, wallet: address, payment: request.payment, data: cached });
112
+ }
113
+ const heliusApiKey = config.solana.heliusApiKey;
114
+ if (!heliusApiKey) {
115
+ return reply.code(503).send({
116
+ error: 'Service Unavailable',
117
+ message: 'Helius API not configured',
118
+ });
119
+ }
120
+ // Step 1: Get current portfolio state
121
+ const portfolio = await helius.getWalletPortfolio(address);
122
+ // Step 2: Get parsed transaction history to compute cost basis
123
+ // Use Helius Enhanced Transactions API for cleaner data
124
+ const rpcUrl = `https://api.helius.xyz/v0/addresses/${address}/transactions?api-key=${heliusApiKey}&limit=100`;
125
+ const txResponse = await fetch(rpcUrl);
126
+ if (!txResponse.ok) {
127
+ return reply.code(502).send({
128
+ error: 'Helius API Error',
129
+ message: 'Failed to fetch transaction history for P&L',
130
+ });
131
+ }
132
+ const transactions = await txResponse.json();
133
+ // Step 3: Walk transactions to compute per-token cost basis
134
+ const tokenFlows = {};
135
+ for (const tx of transactions) {
136
+ if (tx.transactionError)
137
+ continue;
138
+ for (const transfer of tx.tokenTransfers ?? []) {
139
+ const mint = transfer.mint;
140
+ if (!mint)
141
+ continue;
142
+ if (!tokenFlows[mint]) {
143
+ tokenFlows[mint] = { totalIn: 0, totalOut: 0, costBasisUSD: 0 };
144
+ }
145
+ const amount = transfer.tokenAmount ?? 0;
146
+ if (transfer.toUserAccount === address) {
147
+ // Inflow — tokens received
148
+ tokenFlows[mint].totalIn += amount;
149
+ }
150
+ else if (transfer.fromUserAccount === address) {
151
+ // Outflow — tokens sent
152
+ tokenFlows[mint].totalOut += amount;
153
+ }
154
+ }
155
+ // Track SOL flows
156
+ for (const transfer of tx.nativeTransfers ?? []) {
157
+ const solMint = 'SOL';
158
+ if (!tokenFlows[solMint]) {
159
+ tokenFlows[solMint] = { totalIn: 0, totalOut: 0, costBasisUSD: 0 };
160
+ }
161
+ const amount = (transfer.amount ?? 0) / 1e9; // lamports to SOL
162
+ if (transfer.toUserAccount === address) {
163
+ tokenFlows[solMint].totalIn += amount;
164
+ }
165
+ else if (transfer.fromUserAccount === address) {
166
+ tokenFlows[solMint].totalOut += amount;
167
+ }
168
+ }
169
+ }
170
+ // Step 4: Get current prices for all tokens in flows
171
+ const mintAddresses = Object.keys(tokenFlows).filter(m => m !== 'SOL');
172
+ let currentPrices = {};
173
+ if (mintAddresses.length > 0) {
174
+ const priceResponse = await fetch(`https://lite-api.jup.ag/price/v3?ids=${mintAddresses.join(',')}`);
175
+ const priceData = await priceResponse.json();
176
+ for (const [mint, data] of Object.entries(priceData)) {
177
+ if (data?.usdPrice)
178
+ currentPrices[mint] = data.usdPrice;
179
+ }
180
+ }
181
+ // Add SOL price
182
+ const solPriceResponse = await fetch('https://lite-api.jup.ag/price/v3?ids=So11111111111111111111111111111111111111112');
183
+ const solPriceData = await solPriceResponse.json();
184
+ const solPrice = solPriceData['So11111111111111111111111111111111111111112']?.usdPrice ?? 0;
185
+ currentPrices['SOL'] = solPrice;
186
+ // Step 5: Compute P&L per token
187
+ const tokenPnL = [];
188
+ let totalUnrealizedUSD = 0;
189
+ let totalCurrentValueUSD = 0;
190
+ for (const [mint, flows] of Object.entries(tokenFlows)) {
191
+ const netTokens = flows.totalIn - flows.totalOut;
192
+ const currentPrice = currentPrices[mint] ?? 0;
193
+ const currentValue = netTokens * currentPrice;
194
+ // We can track flows but true cost basis requires swap price data
195
+ // which enhanced transactions don't always provide.
196
+ // Report holdings value and flow summary — agents can layer on cost basis.
197
+ if (Math.abs(netTokens) > 0.0001) {
198
+ tokenPnL.push({
199
+ mint,
200
+ netTokens: Number(netTokens.toFixed(6)),
201
+ totalIn: Number(flows.totalIn.toFixed(6)),
202
+ totalOut: Number(flows.totalOut.toFixed(6)),
203
+ currentPriceUSD: currentPrice,
204
+ currentValueUSD: Number(currentValue.toFixed(2)),
205
+ });
206
+ if (currentValue > 0) {
207
+ totalCurrentValueUSD += currentValue;
208
+ }
209
+ totalUnrealizedUSD += currentValue;
210
+ }
211
+ }
212
+ // Sort by absolute value descending
213
+ tokenPnL.sort((a, b) => Math.abs(b.currentValueUSD) - Math.abs(a.currentValueUSD));
214
+ const pnl = {
215
+ address,
216
+ portfolioValueUSD: portfolio.totalValueUSD ?? 0,
217
+ tokenFlows: tokenPnL,
218
+ totalCurrentValueFromFlows: Number(totalCurrentValueUSD.toFixed(2)),
219
+ transactionsAnalyzed: transactions.length,
220
+ note: 'P&L is computed from the last 100 transactions. Cost basis requires full history and swap price data for precision.',
221
+ timestamp: new Date().toISOString(),
222
+ };
223
+ await cache.set(cacheKey, pnl, 180); // 3 min cache
224
+ return reply.send({ success: true, wallet: address, payment: request.payment, data: pnl });
225
+ }
226
+ catch (error) {
227
+ app.log.error({ error, address }, 'Wallet P&L failed');
228
+ return reply.code(500).send({
229
+ error: 'Internal Server Error',
230
+ message: 'Failed to compute wallet P&L',
231
+ });
232
+ }
233
+ });
234
+ }
235
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/plugins/wallet/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
package/dist/server.js ADDED
@@ -0,0 +1,38 @@
1
+ import { createApp } from './app.js';
2
+ import { config } from './config/env.js';
3
+ import { cache } from './services/cache.js';
4
+ import { helius } from './services/helius.js';
5
+ import { logger } from './utils/logger.js';
6
+ async function start() {
7
+ // Initialize services
8
+ await cache.connect();
9
+ await helius.warmup();
10
+ // Create and start server
11
+ const app = await createApp();
12
+ try {
13
+ await app.listen({ port: config.server.port, host: config.server.host });
14
+ logger.info({
15
+ port: config.server.port,
16
+ mode: config.payment.mode,
17
+ network: config.solana.network,
18
+ }, 'obol running');
19
+ }
20
+ catch (error) {
21
+ logger.fatal({ error }, 'Server failed to start');
22
+ process.exit(1);
23
+ }
24
+ // Graceful shutdown
25
+ const shutdown = async (signal) => {
26
+ logger.info({ signal }, 'Shutting down');
27
+ await app.close();
28
+ await cache.disconnect();
29
+ process.exit(0);
30
+ };
31
+ process.on('SIGINT', () => shutdown('SIGINT'));
32
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
33
+ }
34
+ start().catch((error) => {
35
+ logger.fatal({ error }, 'Startup failed');
36
+ process.exit(1);
37
+ });
38
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,KAAK,UAAU,KAAK;IAClB,sBAAsB;IACtB,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IACtB,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IAEtB,0BAA0B;IAC1B,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;YACxB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YACzB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;SAC/B,EAAE,cAAc,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QACxC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC;QACzC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACtB,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ /** Upstash Redis cache — handles response caching and payment receipt storage */
2
+ declare class CacheService {
3
+ private client;
4
+ private connected;
5
+ connect(): Promise<void>;
6
+ disconnect(): Promise<void>;
7
+ get<T>(key: string): Promise<T | null>;
8
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
9
+ exists(key: string): Promise<boolean>;
10
+ /** Record a payment receipt (for analytics and replay prevention) */
11
+ recordPayment(memo: string, receipt: PaymentReceipt): Promise<void>;
12
+ /** Check if a payment memo has already been used (replay prevention) */
13
+ isPaymentUsed(memo: string): Promise<boolean>;
14
+ get isConnected(): boolean;
15
+ }
16
+ export interface PaymentReceipt {
17
+ txSignature: string;
18
+ fromAddress: string;
19
+ amount: number;
20
+ endpoint: string;
21
+ timestamp: string;
22
+ }
23
+ export declare const cache: CacheService;
24
+ export {};
25
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAIA,iFAAiF;AACjF,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAS;IAEpB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAUtC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAapE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS3C,qEAAqE;IAC/D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,wEAAwE;IAClE,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInD,IAAI,WAAW,IAAI,OAAO,CAEzB;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,KAAK,cAAqB,CAAC"}
@@ -0,0 +1,82 @@
1
+ import { Redis } from '@upstash/redis';
2
+ import { config } from '../config/env.js';
3
+ import { logger } from '../utils/logger.js';
4
+ /** Upstash Redis cache — handles response caching and payment receipt storage */
5
+ class CacheService {
6
+ client = null;
7
+ connected = false;
8
+ async connect() {
9
+ if (!config.redis.restUrl || !config.redis.restToken) {
10
+ logger.warn('Redis not configured — running without cache');
11
+ return;
12
+ }
13
+ try {
14
+ this.client = new Redis({
15
+ url: config.redis.restUrl,
16
+ token: config.redis.restToken,
17
+ });
18
+ const result = await this.client.ping();
19
+ if (result === 'PONG') {
20
+ this.connected = true;
21
+ logger.info('Redis connected');
22
+ }
23
+ }
24
+ catch (error) {
25
+ logger.error({ error }, 'Redis connection failed');
26
+ this.client = null;
27
+ }
28
+ }
29
+ async disconnect() {
30
+ this.client = null;
31
+ this.connected = false;
32
+ }
33
+ async get(key) {
34
+ if (!this.client || !this.connected)
35
+ return null;
36
+ try {
37
+ return await this.client.get(key);
38
+ }
39
+ catch (error) {
40
+ logger.error({ error, key }, 'Cache get error');
41
+ return null;
42
+ }
43
+ }
44
+ async set(key, value, ttlSeconds) {
45
+ if (!this.client || !this.connected)
46
+ return;
47
+ try {
48
+ if (ttlSeconds) {
49
+ await this.client.setex(key, ttlSeconds, value);
50
+ }
51
+ else {
52
+ await this.client.set(key, value);
53
+ }
54
+ }
55
+ catch (error) {
56
+ logger.error({ error, key }, 'Cache set error');
57
+ }
58
+ }
59
+ async exists(key) {
60
+ if (!this.client || !this.connected)
61
+ return false;
62
+ try {
63
+ return (await this.client.exists(key)) === 1;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /** Record a payment receipt (for analytics and replay prevention) */
70
+ async recordPayment(memo, receipt) {
71
+ await this.set(`payment:${memo}`, receipt, 86400); // 24h TTL
72
+ }
73
+ /** Check if a payment memo has already been used (replay prevention) */
74
+ async isPaymentUsed(memo) {
75
+ return this.exists(`payment:${memo}`);
76
+ }
77
+ get isConnected() {
78
+ return this.connected;
79
+ }
80
+ }
81
+ export const cache = new CacheService();
82
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { Connection } from '@solana/web3.js';
2
+ export interface TokenAccount {
3
+ mint: string;
4
+ address: string;
5
+ owner: string;
6
+ amount: string;
7
+ decimals: number;
8
+ uiAmount: number;
9
+ symbol?: string;
10
+ name?: string;
11
+ logoURI?: string;
12
+ priceUSD?: number;
13
+ valueUSD?: number;
14
+ }
15
+ export interface NFT {
16
+ mint: string;
17
+ name?: string;
18
+ symbol?: string;
19
+ collection?: string;
20
+ imageUrl?: string;
21
+ verified: boolean;
22
+ }
23
+ export interface WalletOverview {
24
+ address: string;
25
+ solBalance: number;
26
+ solBalanceUSD: number;
27
+ totalValueUSD: number;
28
+ tokenCount: number;
29
+ nftCount: number;
30
+ isActive: boolean;
31
+ topTokens: TokenAccount[];
32
+ }
33
+ export interface WalletPortfolio {
34
+ address: string;
35
+ totalValueUSD: number;
36
+ solBalance: number;
37
+ solBalanceUSD: number;
38
+ tokens: TokenAccount[];
39
+ nfts: NFT[];
40
+ breakdown: {
41
+ sol: number;
42
+ tokens: number;
43
+ nfts: number;
44
+ };
45
+ }
46
+ export interface WalletTransaction {
47
+ signature: string;
48
+ timestamp: number;
49
+ type: string;
50
+ status: 'success' | 'failed';
51
+ fee: number;
52
+ description: string;
53
+ }
54
+ export interface WalletActivity {
55
+ address: string;
56
+ transactionCount: number;
57
+ firstTransaction?: string;
58
+ lastTransaction?: string;
59
+ recentTransactions: WalletTransaction[];
60
+ }
61
+ export interface RiskFactor {
62
+ type: string;
63
+ severity: 'low' | 'medium' | 'high';
64
+ description: string;
65
+ impact: number;
66
+ }
67
+ export interface WalletRisk {
68
+ address: string;
69
+ riskScore: number;
70
+ riskLevel: 'low' | 'medium' | 'high';
71
+ factors: RiskFactor[];
72
+ warnings: string[];
73
+ }
74
+ declare class HeliusService {
75
+ private connection;
76
+ private apiKey;
77
+ private baseUrl;
78
+ constructor();
79
+ getConnection(): Connection;
80
+ private get rpcUrl();
81
+ /** DAS API call helper */
82
+ private dasCall;
83
+ getSOLBalance(address: string): Promise<number>;
84
+ getSOLPrice(): Promise<number>;
85
+ getTokenAccounts(address: string): Promise<TokenAccount[]>;
86
+ private enrichTokenMetadata;
87
+ getTokenPrices(mints: string[]): Promise<Map<string, number>>;
88
+ getNFTCount(address: string): Promise<number>;
89
+ getNFTs(address: string, limit?: number): Promise<NFT[]>;
90
+ isWalletActive(address: string): Promise<boolean>;
91
+ getWalletActivity(address: string, limit?: number): Promise<WalletActivity>;
92
+ getWalletOverview(address: string): Promise<WalletOverview>;
93
+ getWalletPortfolio(address: string): Promise<WalletPortfolio>;
94
+ getWalletRisk(address: string): Promise<WalletRisk>;
95
+ private getFirstTransaction;
96
+ /** Warmup connections and caches */
97
+ warmup(): Promise<void>;
98
+ }
99
+ /** Singleton */
100
+ export declare const helius: HeliusService;
101
+ export {};
102
+ //# sourceMappingURL=helius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helius.d.ts","sourceRoot":"","sources":["../../src/services/helius.ts"],"names":[],"mappings":"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"}