pnpfucius 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.
@@ -0,0 +1,221 @@
1
+ // Helius API client for enhanced Solana interactions
2
+ // Provides DAS API, enhanced transactions, and webhook management
3
+
4
+ const HELIUS_API_BASE = 'https://api.helius.xyz/v0';
5
+
6
+ export class HeliusClient {
7
+ constructor(apiKey, network = 'devnet') {
8
+ if (!apiKey) {
9
+ throw new Error('Helius API key is required');
10
+ }
11
+ this.apiKey = apiKey;
12
+ this.network = network;
13
+ this.rpcUrl = `https://${network === 'mainnet' ? 'mainnet' : 'devnet'}.helius-rpc.com/?api-key=${apiKey}`;
14
+ }
15
+
16
+ // DAS API Methods
17
+
18
+ async getAssetsByOwner(ownerAddress, options = {}) {
19
+ const response = await this.dasRequest('getAssetsByOwner', {
20
+ ownerAddress,
21
+ page: options.page || 1,
22
+ limit: options.limit || 50,
23
+ sortBy: options.sortBy || { sortBy: 'created', sortDirection: 'desc' },
24
+ options: {
25
+ showFungible: options.showFungible || false,
26
+ showNativeBalance: options.showNativeBalance || false
27
+ }
28
+ });
29
+ return response.result;
30
+ }
31
+
32
+ async searchAssets(params) {
33
+ const response = await this.dasRequest('searchAssets', params);
34
+ return response.result;
35
+ }
36
+
37
+ async getSignaturesForAsset(assetId, options = {}) {
38
+ const response = await this.dasRequest('getSignaturesForAsset', {
39
+ id: assetId,
40
+ page: options.page || 1,
41
+ limit: options.limit || 100
42
+ });
43
+ return response.result;
44
+ }
45
+
46
+ async getAsset(assetId) {
47
+ const response = await this.dasRequest('getAsset', { id: assetId });
48
+ return response.result;
49
+ }
50
+
51
+ // Enhanced Transactions API
52
+
53
+ async getEnhancedTransactions(signatures) {
54
+ if (!Array.isArray(signatures)) {
55
+ signatures = [signatures];
56
+ }
57
+
58
+ const response = await fetch(`${HELIUS_API_BASE}/transactions?api-key=${this.apiKey}`, {
59
+ method: 'POST',
60
+ headers: { 'Content-Type': 'application/json' },
61
+ body: JSON.stringify({ transactions: signatures })
62
+ });
63
+
64
+ if (!response.ok) {
65
+ const error = await response.text();
66
+ throw new Error(`Helius API error: ${error}`);
67
+ }
68
+
69
+ return response.json();
70
+ }
71
+
72
+ async getEnhancedTransactionsByAddress(address, options = {}) {
73
+ const params = new URLSearchParams({
74
+ 'api-key': this.apiKey
75
+ });
76
+
77
+ if (options.type) params.append('type', options.type);
78
+ if (options.before) params.append('before', options.before);
79
+ if (options.until) params.append('until', options.until);
80
+
81
+ const response = await fetch(
82
+ `${HELIUS_API_BASE}/addresses/${address}/transactions?${params}`,
83
+ { method: 'GET' }
84
+ );
85
+
86
+ if (!response.ok) {
87
+ const error = await response.text();
88
+ throw new Error(`Helius API error: ${error}`);
89
+ }
90
+
91
+ return response.json();
92
+ }
93
+
94
+ // Webhook Management
95
+
96
+ async createWebhook(config) {
97
+ const webhookType = this.network === 'mainnet' ? 'enhanced' : 'enhancedDevnet';
98
+
99
+ const response = await fetch(`${HELIUS_API_BASE}/webhooks?api-key=${this.apiKey}`, {
100
+ method: 'POST',
101
+ headers: { 'Content-Type': 'application/json' },
102
+ body: JSON.stringify({
103
+ webhookURL: config.url,
104
+ transactionTypes: config.transactionTypes || ['ANY'],
105
+ accountAddresses: config.addresses || [],
106
+ webhookType: config.type || webhookType,
107
+ authHeader: config.authToken || undefined
108
+ })
109
+ });
110
+
111
+ if (!response.ok) {
112
+ const error = await response.text();
113
+ throw new Error(`Failed to create webhook: ${error}`);
114
+ }
115
+
116
+ return response.json();
117
+ }
118
+
119
+ async listWebhooks() {
120
+ const response = await fetch(`${HELIUS_API_BASE}/webhooks?api-key=${this.apiKey}`, {
121
+ method: 'GET'
122
+ });
123
+
124
+ if (!response.ok) {
125
+ const error = await response.text();
126
+ throw new Error(`Failed to list webhooks: ${error}`);
127
+ }
128
+
129
+ return response.json();
130
+ }
131
+
132
+ async getWebhook(webhookId) {
133
+ const response = await fetch(`${HELIUS_API_BASE}/webhooks/${webhookId}?api-key=${this.apiKey}`, {
134
+ method: 'GET'
135
+ });
136
+
137
+ if (!response.ok) {
138
+ const error = await response.text();
139
+ throw new Error(`Failed to get webhook: ${error}`);
140
+ }
141
+
142
+ return response.json();
143
+ }
144
+
145
+ async updateWebhook(webhookId, config) {
146
+ const response = await fetch(`${HELIUS_API_BASE}/webhooks/${webhookId}?api-key=${this.apiKey}`, {
147
+ method: 'PUT',
148
+ headers: { 'Content-Type': 'application/json' },
149
+ body: JSON.stringify(config)
150
+ });
151
+
152
+ if (!response.ok) {
153
+ const error = await response.text();
154
+ throw new Error(`Failed to update webhook: ${error}`);
155
+ }
156
+
157
+ return response.json();
158
+ }
159
+
160
+ async deleteWebhook(webhookId) {
161
+ const response = await fetch(`${HELIUS_API_BASE}/webhooks/${webhookId}?api-key=${this.apiKey}`, {
162
+ method: 'DELETE'
163
+ });
164
+
165
+ return response.ok;
166
+ }
167
+
168
+ // Priority Fee API
169
+
170
+ async getPriorityFeeEstimate(params = {}) {
171
+ const response = await fetch(`${HELIUS_API_BASE}/priority-fee?api-key=${this.apiKey}`, {
172
+ method: 'POST',
173
+ headers: { 'Content-Type': 'application/json' },
174
+ body: JSON.stringify({
175
+ accountKeys: params.accountKeys || [],
176
+ options: {
177
+ priorityLevel: params.priorityLevel || 'Medium'
178
+ }
179
+ })
180
+ });
181
+
182
+ if (!response.ok) {
183
+ const error = await response.text();
184
+ throw new Error(`Failed to get priority fee: ${error}`);
185
+ }
186
+
187
+ return response.json();
188
+ }
189
+
190
+ // Internal helper for DAS API requests
191
+
192
+ async dasRequest(method, params) {
193
+ const response = await fetch(this.rpcUrl, {
194
+ method: 'POST',
195
+ headers: { 'Content-Type': 'application/json' },
196
+ body: JSON.stringify({
197
+ jsonrpc: '2.0',
198
+ id: '1',
199
+ method,
200
+ params
201
+ })
202
+ });
203
+
204
+ if (!response.ok) {
205
+ const error = await response.text();
206
+ throw new Error(`DAS API error: ${error}`);
207
+ }
208
+
209
+ const result = await response.json();
210
+
211
+ if (result.error) {
212
+ throw new Error(`DAS API error: ${result.error.message}`);
213
+ }
214
+
215
+ return result;
216
+ }
217
+ }
218
+
219
+ export function createHeliusClient(apiKey, network) {
220
+ return new HeliusClient(apiKey, network);
221
+ }
@@ -0,0 +1,192 @@
1
+ // Transaction confirmation tracking with enhanced Helius methods
2
+ // Provides reliable transaction confirmation with retries and status updates
3
+
4
+ import { Connection } from '@solana/web3.js';
5
+
6
+ export class TransactionTracker {
7
+ constructor(config = {}) {
8
+ this.rpcUrl = config.rpcUrl;
9
+ this.heliusClient = config.heliusClient;
10
+ this.connection = new Connection(this.rpcUrl, 'confirmed');
11
+ this.maxRetries = config.maxRetries || 30;
12
+ this.retryDelay = config.retryDelay || 2000;
13
+ this.onStatusChange = config.onStatusChange || null;
14
+ }
15
+
16
+ async confirmTransaction(signature, options = {}) {
17
+ const maxRetries = options.maxRetries || this.maxRetries;
18
+ const retryDelay = options.retryDelay || this.retryDelay;
19
+ const commitment = options.commitment || 'confirmed';
20
+
21
+ this.emitStatus(signature, 'pending', 'Waiting for confirmation...');
22
+
23
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
24
+ try {
25
+ const status = await this.connection.getSignatureStatus(signature, {
26
+ searchTransactionHistory: true
27
+ });
28
+
29
+ if (status && status.value) {
30
+ const { confirmationStatus, err } = status.value;
31
+
32
+ if (err) {
33
+ this.emitStatus(signature, 'failed', `Transaction failed: ${JSON.stringify(err)}`);
34
+ return {
35
+ success: false,
36
+ signature,
37
+ error: err,
38
+ confirmationStatus
39
+ };
40
+ }
41
+
42
+ if (confirmationStatus === 'finalized') {
43
+ this.emitStatus(signature, 'finalized', 'Transaction finalized');
44
+ return {
45
+ success: true,
46
+ signature,
47
+ confirmationStatus: 'finalized',
48
+ slot: status.value.slot
49
+ };
50
+ }
51
+
52
+ if (confirmationStatus === 'confirmed' && commitment === 'confirmed') {
53
+ this.emitStatus(signature, 'confirmed', 'Transaction confirmed');
54
+ return {
55
+ success: true,
56
+ signature,
57
+ confirmationStatus: 'confirmed',
58
+ slot: status.value.slot
59
+ };
60
+ }
61
+
62
+ this.emitStatus(signature, 'processing', `Status: ${confirmationStatus} (attempt ${attempt}/${maxRetries})`);
63
+ }
64
+ } catch (error) {
65
+ this.emitStatus(signature, 'retrying', `Retry ${attempt}/${maxRetries}: ${error.message}`);
66
+ }
67
+
68
+ if (attempt < maxRetries) {
69
+ await this.sleep(retryDelay);
70
+ }
71
+ }
72
+
73
+ this.emitStatus(signature, 'timeout', 'Confirmation timeout');
74
+ return {
75
+ success: false,
76
+ signature,
77
+ error: 'Confirmation timeout',
78
+ confirmationStatus: 'unknown'
79
+ };
80
+ }
81
+
82
+ async getTransactionDetails(signature) {
83
+ // Try enhanced Helius API first for rich transaction data
84
+ if (this.heliusClient) {
85
+ try {
86
+ const enhanced = await this.heliusClient.getEnhancedTransactions([signature]);
87
+ if (enhanced && enhanced.length > 0) {
88
+ return {
89
+ enhanced: true,
90
+ data: enhanced[0]
91
+ };
92
+ }
93
+ } catch (error) {
94
+ // Fall back to standard RPC
95
+ }
96
+ }
97
+
98
+ // Standard RPC fallback
99
+ const tx = await this.connection.getTransaction(signature, {
100
+ maxSupportedTransactionVersion: 0
101
+ });
102
+
103
+ return {
104
+ enhanced: false,
105
+ data: tx
106
+ };
107
+ }
108
+
109
+ async waitForTransaction(signature, options = {}) {
110
+ const timeout = options.timeout || 60000;
111
+ const startTime = Date.now();
112
+
113
+ while (Date.now() - startTime < timeout) {
114
+ const result = await this.confirmTransaction(signature, {
115
+ maxRetries: 1,
116
+ ...options
117
+ });
118
+
119
+ if (result.success || result.error) {
120
+ return result;
121
+ }
122
+
123
+ await this.sleep(1000);
124
+ }
125
+
126
+ return {
127
+ success: false,
128
+ signature,
129
+ error: 'Transaction wait timeout'
130
+ };
131
+ }
132
+
133
+ async trackMultipleTransactions(signatures, options = {}) {
134
+ const results = new Map();
135
+ const pending = new Set(signatures);
136
+ const maxWait = options.maxWait || 120000;
137
+ const startTime = Date.now();
138
+
139
+ while (pending.size > 0 && Date.now() - startTime < maxWait) {
140
+ const statuses = await this.connection.getSignatureStatuses(
141
+ Array.from(pending),
142
+ { searchTransactionHistory: true }
143
+ );
144
+
145
+ for (let i = 0; i < statuses.value.length; i++) {
146
+ const sig = Array.from(pending)[i];
147
+ const status = statuses.value[i];
148
+
149
+ if (status) {
150
+ if (status.err) {
151
+ results.set(sig, { success: false, error: status.err });
152
+ pending.delete(sig);
153
+ } else if (status.confirmationStatus === 'finalized' ||
154
+ status.confirmationStatus === 'confirmed') {
155
+ results.set(sig, { success: true, status: status.confirmationStatus });
156
+ pending.delete(sig);
157
+ }
158
+ }
159
+ }
160
+
161
+ if (pending.size > 0) {
162
+ await this.sleep(2000);
163
+ }
164
+ }
165
+
166
+ // Mark remaining as timeout
167
+ for (const sig of pending) {
168
+ results.set(sig, { success: false, error: 'timeout' });
169
+ }
170
+
171
+ return results;
172
+ }
173
+
174
+ emitStatus(signature, status, message) {
175
+ if (this.onStatusChange) {
176
+ this.onStatusChange({
177
+ signature,
178
+ status,
179
+ message,
180
+ timestamp: Date.now()
181
+ });
182
+ }
183
+ }
184
+
185
+ sleep(ms) {
186
+ return new Promise(resolve => setTimeout(resolve, ms));
187
+ }
188
+ }
189
+
190
+ export function createTransactionTracker(config) {
191
+ return new TransactionTracker(config);
192
+ }
@@ -0,0 +1,233 @@
1
+ // Helius webhook server for receiving real-time blockchain events
2
+ // Express server with endpoints for market event notifications
3
+
4
+ import express from 'express';
5
+ import { agentEvents, AgentEvents } from '../events/emitter.js';
6
+
7
+ export class WebhookServer {
8
+ constructor(config = {}) {
9
+ this.port = config.port || 3000;
10
+ this.authToken = config.authToken || process.env.WEBHOOK_AUTH_TOKEN;
11
+ this.app = express();
12
+ this.server = null;
13
+ this.eventHandlers = new Map();
14
+
15
+ this.setupMiddleware();
16
+ this.setupRoutes();
17
+ }
18
+
19
+ setupMiddleware() {
20
+ this.app.use(express.json({ limit: '10mb' }));
21
+
22
+ // Auth middleware for webhook endpoints
23
+ this.app.use('/webhook', (req, res, next) => {
24
+ if (this.authToken) {
25
+ const auth = req.headers['authorization'];
26
+ if (auth !== this.authToken) {
27
+ return res.status(401).json({ error: 'Unauthorized' });
28
+ }
29
+ }
30
+ next();
31
+ });
32
+
33
+ // Request logging
34
+ this.app.use((req, res, next) => {
35
+ const start = Date.now();
36
+ res.on('finish', () => {
37
+ const duration = Date.now() - start;
38
+ if (req.path.startsWith('/webhook')) {
39
+ agentEvents.emitTyped(AgentEvents.WEBHOOK_RECEIVED, {
40
+ path: req.path,
41
+ method: req.method,
42
+ statusCode: res.statusCode,
43
+ duration
44
+ });
45
+ }
46
+ });
47
+ next();
48
+ });
49
+ }
50
+
51
+ setupRoutes() {
52
+ // Helius webhook endpoint
53
+ this.app.post('/webhook/helius', async (req, res) => {
54
+ try {
55
+ const events = Array.isArray(req.body) ? req.body : [req.body];
56
+ const processed = [];
57
+
58
+ for (const event of events) {
59
+ try {
60
+ await this.processHeliusEvent(event);
61
+ processed.push({ success: true, signature: event.signature });
62
+ } catch (error) {
63
+ processed.push({ success: false, error: error.message });
64
+ }
65
+ }
66
+
67
+ res.status(200).json({
68
+ success: true,
69
+ processed: processed.length,
70
+ results: processed
71
+ });
72
+ } catch (error) {
73
+ console.error('Webhook processing error:', error);
74
+ res.status(500).json({ error: error.message });
75
+ }
76
+ });
77
+
78
+ // Health check endpoint
79
+ this.app.get('/health', (req, res) => {
80
+ res.json({
81
+ status: 'ok',
82
+ timestamp: Date.now(),
83
+ uptime: process.uptime()
84
+ });
85
+ });
86
+
87
+ // Analytics endpoint for dashboard
88
+ this.app.get('/api/stats', async (req, res) => {
89
+ try {
90
+ const handler = this.eventHandlers.get('getStats');
91
+ if (handler) {
92
+ const stats = await handler();
93
+ res.json(stats);
94
+ } else {
95
+ res.json({ message: 'Stats handler not configured' });
96
+ }
97
+ } catch (error) {
98
+ res.status(500).json({ error: error.message });
99
+ }
100
+ });
101
+
102
+ // Recent markets endpoint
103
+ this.app.get('/api/markets', async (req, res) => {
104
+ try {
105
+ const handler = this.eventHandlers.get('getMarkets');
106
+ if (handler) {
107
+ const limit = parseInt(req.query.limit) || 20;
108
+ const status = req.query.status || null;
109
+ const markets = await handler({ limit, status });
110
+ res.json(markets);
111
+ } else {
112
+ res.json([]);
113
+ }
114
+ } catch (error) {
115
+ res.status(500).json({ error: error.message });
116
+ }
117
+ });
118
+
119
+ // 404 handler
120
+ this.app.use((req, res) => {
121
+ res.status(404).json({ error: 'Not found' });
122
+ });
123
+ }
124
+
125
+ async processHeliusEvent(event) {
126
+ // Extract event type and process accordingly
127
+ const eventType = event.type || 'UNKNOWN';
128
+ const signature = event.signature;
129
+
130
+ // Emit for any listeners
131
+ agentEvents.emitTyped(AgentEvents.HELIUS_EVENT, {
132
+ type: eventType,
133
+ signature,
134
+ data: event
135
+ });
136
+
137
+ // Handle specific event types
138
+ switch (eventType) {
139
+ case 'CREATE_MARKET':
140
+ await this.handleMarketCreation(event);
141
+ break;
142
+ case 'SWAP':
143
+ await this.handleSwap(event);
144
+ break;
145
+ case 'TRANSFER':
146
+ await this.handleTransfer(event);
147
+ break;
148
+ default:
149
+ // Generic event handling
150
+ const handler = this.eventHandlers.get(eventType);
151
+ if (handler) {
152
+ await handler(event);
153
+ }
154
+ }
155
+
156
+ return { processed: true, type: eventType };
157
+ }
158
+
159
+ async handleMarketCreation(event) {
160
+ const handler = this.eventHandlers.get('marketCreated');
161
+ if (handler) {
162
+ await handler(event);
163
+ }
164
+ }
165
+
166
+ async handleSwap(event) {
167
+ const handler = this.eventHandlers.get('swap');
168
+ if (handler) {
169
+ await handler(event);
170
+ }
171
+ }
172
+
173
+ async handleTransfer(event) {
174
+ const handler = this.eventHandlers.get('transfer');
175
+ if (handler) {
176
+ await handler(event);
177
+ }
178
+ }
179
+
180
+ // Register custom event handlers
181
+ on(eventType, handler) {
182
+ this.eventHandlers.set(eventType, handler);
183
+ return this;
184
+ }
185
+
186
+ // Remove event handler
187
+ off(eventType) {
188
+ this.eventHandlers.delete(eventType);
189
+ return this;
190
+ }
191
+
192
+ async start() {
193
+ return new Promise((resolve, reject) => {
194
+ try {
195
+ this.server = this.app.listen(this.port, () => {
196
+ console.log(`Webhook server listening on port ${this.port}`);
197
+ agentEvents.emitTyped(AgentEvents.WEBHOOK_SERVER_STARTED, {
198
+ port: this.port
199
+ });
200
+ resolve(this.port);
201
+ });
202
+
203
+ this.server.on('error', (error) => {
204
+ reject(error);
205
+ });
206
+ } catch (error) {
207
+ reject(error);
208
+ }
209
+ });
210
+ }
211
+
212
+ async stop() {
213
+ return new Promise((resolve) => {
214
+ if (this.server) {
215
+ this.server.close(() => {
216
+ console.log('Webhook server stopped');
217
+ agentEvents.emitTyped(AgentEvents.WEBHOOK_SERVER_STOPPED, {});
218
+ resolve();
219
+ });
220
+ } else {
221
+ resolve();
222
+ }
223
+ });
224
+ }
225
+
226
+ getExpressApp() {
227
+ return this.app;
228
+ }
229
+ }
230
+
231
+ export function createWebhookServer(config) {
232
+ return new WebhookServer(config);
233
+ }