@pioneer-platform/solana-network 8.11.1 → 8.11.2

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.
@@ -1,2 +1 @@
1
-
2
- $ tsc -p .
1
+ $ tsc -p .
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pioneer-platform/solana-network
2
2
 
3
+ ## 8.11.2
4
+
5
+ ### Patch Changes
6
+
7
+ - zcash working!
8
+
3
9
  ## 8.11.1
4
10
 
5
11
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # @pioneer-platform/solana-network
2
+
3
+ Solana blockchain network integration module for the Pioneer Platform.
4
+
5
+ ## Features
6
+
7
+ - ✅ SOL balance queries
8
+ - ✅ SPL token balance queries
9
+ - ✅ Transfer transaction building
10
+ - ✅ Fee estimation
11
+ - ✅ Transaction broadcasting
12
+ - ✅ Transaction status tracking
13
+ - ✅ Account information queries
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ bun install @pioneer-platform/solana-network
19
+ ```
20
+
21
+ ## Network Information
22
+
23
+ - **Network ID**: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`
24
+ - **Chain Symbol**: SOL
25
+ - **SLIP44**: 501
26
+ - **Decimals**: 9 (lamports)
27
+ - **Default RPC**: https://api.mainnet-beta.solana.com
28
+
29
+ ## Usage
30
+
31
+ ### Initialize Module
32
+
33
+ ```javascript
34
+ const solanaNetwork = require('@pioneer-platform/solana-network')
35
+
36
+ // Initialize with default RPC
37
+ await solanaNetwork.init()
38
+
39
+ // Or with custom RPC
40
+ await solanaNetwork.init('https://your-custom-rpc.com')
41
+
42
+ // Or with environment variable
43
+ // Set SOLANA_RPC_URL in .env
44
+ await solanaNetwork.init()
45
+ ```
46
+
47
+ ### Get SOL Balance
48
+
49
+ ```javascript
50
+ const balance = await solanaNetwork.getBalance('9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM')
51
+ console.log('Balance:', balance, 'SOL')
52
+ ```
53
+
54
+ ### Get SPL Token Balances
55
+
56
+ ```javascript
57
+ const tokens = await solanaNetwork.getTokenBalances('9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM')
58
+
59
+ tokens.forEach(token => {
60
+ console.log(`Token: ${token.mint}`)
61
+ console.log(`Balance: ${token.balance}`)
62
+ console.log(`Decimals: ${token.decimals}`)
63
+ })
64
+ ```
65
+
66
+ ### Build Transfer Transaction
67
+
68
+ ```javascript
69
+ const tx = await solanaNetwork.buildTransfer(
70
+ '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM', // from
71
+ 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK', // to
72
+ 0.001 // amount in SOL
73
+ )
74
+
75
+ console.log('Transaction:', {
76
+ from: tx.from,
77
+ to: tx.to,
78
+ amount: tx.amount,
79
+ lamports: tx.lamports,
80
+ blockhash: tx.blockhash,
81
+ serialized: tx.serialized // base64 encoded, ready for signing
82
+ })
83
+ ```
84
+
85
+ ### Estimate Transfer Fee
86
+
87
+ ```javascript
88
+ const fee = await solanaNetwork.estimateFee()
89
+ console.log('Fee:', fee, 'SOL') // typically ~0.000005 SOL
90
+ ```
91
+
92
+ ### Broadcast Signed Transaction
93
+
94
+ ```javascript
95
+ // After signing the transaction
96
+ const result = await solanaNetwork.broadcast(signedTransactionBase64)
97
+
98
+ if (result.success) {
99
+ console.log('Transaction ID:', result.txid)
100
+ } else {
101
+ console.error('Broadcast failed:', result.error)
102
+ }
103
+ ```
104
+
105
+ ### Get Transaction Details
106
+
107
+ ```javascript
108
+ const txDetails = await solanaNetwork.getTransaction('signature...')
109
+ console.log('Transaction:', txDetails)
110
+ ```
111
+
112
+ ### Get Recent Blockhash
113
+
114
+ ```javascript
115
+ const { blockhash, lastValidBlockHeight } = await solanaNetwork.getRecentBlockhash()
116
+ console.log('Blockhash:', blockhash)
117
+ console.log('Valid until block:', lastValidBlockHeight)
118
+ ```
119
+
120
+ ## API Reference
121
+
122
+ ### Module Exports
123
+
124
+ #### `init(url?, settings?): Promise<boolean>`
125
+ Initialize the Solana network module.
126
+ - `url`: Optional RPC URL (defaults to env var or mainnet)
127
+ - `settings`: Optional configuration object
128
+ - Returns: `true` if successful
129
+
130
+ #### `isOnline(): boolean`
131
+ Check if module is initialized and connected.
132
+
133
+ #### `getBalance(address): Promise<number>`
134
+ Get SOL balance for an address.
135
+ - `address`: Solana public key (base58 encoded)
136
+ - Returns: Balance in SOL
137
+
138
+ #### `getTokenBalances(address): Promise<Array>`
139
+ Get all SPL token balances for an address.
140
+ - `address`: Solana public key (base58 encoded)
141
+ - Returns: Array of token accounts with balances
142
+
143
+ #### `buildTransfer(from, to, amount): Promise<Object>`
144
+ Build an unsigned SOL transfer transaction.
145
+ - `from`: Sender's public key (base58)
146
+ - `to`: Recipient's public key (base58)
147
+ - `amount`: Amount in SOL
148
+ - Returns: Transaction object with serialized data
149
+
150
+ #### `estimateFee(): Promise<number>`
151
+ Estimate transfer fee.
152
+ - Returns: Fee in SOL (typically ~0.000005 SOL)
153
+
154
+ #### `broadcast(tx): Promise<Object>`
155
+ Broadcast a signed transaction.
156
+ - `tx`: Base64 encoded signed transaction
157
+ - Returns: `{ success: boolean, txid?: string, error?: string }`
158
+
159
+ #### `getTransaction(signature): Promise<Object>`
160
+ Get transaction details by signature.
161
+ - `signature`: Transaction signature
162
+ - Returns: Transaction details or null
163
+
164
+ #### `getRecentBlockhash(): Promise<Object>`
165
+ Get recent blockhash for transaction building.
166
+ - Returns: `{ blockhash: string, lastValidBlockHeight: number }`
167
+
168
+ #### `getAccount(address): Promise<Object>`
169
+ Get account information.
170
+ - `address`: Solana public key (base58 encoded)
171
+ - Returns: Account info or null
172
+
173
+ ### Constants
174
+
175
+ - `NETWORK_ID`: Solana network identifier
176
+ - `CHAIN_SYMBOL`: 'SOL'
177
+ - `DECIMALS`: 9
178
+
179
+ ## Testing
180
+
181
+ ```bash
182
+ # Run basic tests
183
+ bun run test
184
+
185
+ # Run transfer tests
186
+ cd __tests__
187
+ node test-transfer.js
188
+ ```
189
+
190
+ ## Environment Variables
191
+
192
+ ```bash
193
+ # Optional: Custom RPC URL
194
+ SOLANA_RPC_URL=https://your-custom-rpc.com
195
+ ```
196
+
197
+ ## Integration with Pioneer Platform
198
+
199
+ This module integrates with the Pioneer Platform's multi-chain architecture:
200
+
201
+ 1. **Balance Queries**: Used by `pioneer-balance` for portfolio calculations
202
+ 2. **Transaction Building**: Used by transaction routers for SOL transfers
203
+ 3. **Token Support**: SPL token discovery and balance tracking
204
+ 4. **Network State**: Health checks and network status monitoring
205
+
206
+ ## RPC Endpoints
207
+
208
+ ### Mainnet
209
+ - https://api.mainnet-beta.solana.com (default)
210
+ - https://solana-api.projectserum.com
211
+
212
+ ### Performance Tips
213
+ - Use private RPC endpoints for production (QuickNode, Alchemy, etc.)
214
+ - Default public RPCs have rate limits
215
+ - Consider connection pooling for high-frequency queries
216
+
217
+ ## Transaction Signing
218
+
219
+ This module builds **unsigned** transactions. To sign and broadcast:
220
+
221
+ ```javascript
222
+ // 1. Build transaction
223
+ const tx = await solanaNetwork.buildTransfer(from, to, amount)
224
+
225
+ // 2. Sign with your wallet/keypair (using @solana/web3.js)
226
+ const { Keypair } = require('@solana/web3.js')
227
+ const keypair = Keypair.fromSecretKey(secretKey)
228
+ tx.transaction.sign(keypair)
229
+
230
+ // 3. Serialize signed transaction
231
+ const signedTx = tx.transaction.serialize().toString('base64')
232
+
233
+ // 4. Broadcast
234
+ const result = await solanaNetwork.broadcast(signedTx)
235
+ ```
236
+
237
+ ## License
238
+
239
+ Pioneer Platform License
package/lib/index.js CHANGED
@@ -62,6 +62,7 @@ var axiosLib = require('axios');
62
62
  var Axios = axiosLib.default || axiosLib;
63
63
  var https = require('https');
64
64
  var log = require('@pioneer-platform/loggerdog')();
65
+ var _a = require('@solana/web3.js'), Connection = _a.Connection, PublicKey = _a.PublicKey, Transaction = _a.Transaction, SystemProgram = _a.SystemProgram, LAMPORTS_PER_SOL = _a.LAMPORTS_PER_SOL;
65
66
  // Default Solana mainnet RPC
66
67
  var DEFAULT_RPC_URL = "https://api.mainnet-beta.solana.com";
67
68
  // Network constants
@@ -80,6 +81,7 @@ var axios = Axios.create({
80
81
  // Module state
81
82
  var rpcUrl = DEFAULT_RPC_URL;
82
83
  var isInitialized = false;
84
+ var connection = null;
83
85
  /**********************************
84
86
  // Module Exports
85
87
  //**********************************/
@@ -115,6 +117,7 @@ module.exports = {
115
117
  testResult = _a.sent();
116
118
  if (!(testResult.data && testResult.data.result === 'ok')) return [3 /*break*/, 3];
117
119
  log.info(tag, "Successfully connected to Solana RPC");
120
+ connection = new Connection(rpcUrl, 'confirmed');
118
121
  isInitialized = true;
119
122
  return [2 /*return*/, true];
120
123
  case 3: return [4 /*yield*/, axios({
@@ -130,6 +133,7 @@ module.exports = {
130
133
  versionResult = _a.sent();
131
134
  if (versionResult.data && versionResult.data.result) {
132
135
  log.info(tag, "Connected to Solana RPC, version:", versionResult.data.result['solana-core']);
136
+ connection = new Connection(rpcUrl, 'confirmed');
133
137
  isInitialized = true;
134
138
  return [2 /*return*/, true];
135
139
  }
@@ -185,6 +189,31 @@ module.exports = {
185
189
  getTransaction: function (signature) {
186
190
  return get_transaction(signature);
187
191
  },
192
+ /**
193
+ * Build a SOL transfer transaction
194
+ * @param from - Sender's public key (base58)
195
+ * @param to - Recipient's public key (base58)
196
+ * @param amount - Amount in SOL
197
+ * @returns Unsigned transaction object
198
+ */
199
+ buildTransfer: function (from, to, amount) {
200
+ return build_transfer(from, to, amount);
201
+ },
202
+ /**
203
+ * Estimate transfer fee
204
+ * @returns Fee in SOL
205
+ */
206
+ estimateFee: function () {
207
+ return estimate_fee();
208
+ },
209
+ /**
210
+ * Get SPL token balances for an address
211
+ * @param address - Solana public key (base58)
212
+ * @returns Array of token accounts with balances
213
+ */
214
+ getTokenBalances: function (address) {
215
+ return get_token_balances(address);
216
+ },
188
217
  // Network constants
189
218
  NETWORK_ID: exports.NETWORK_ID,
190
219
  CHAIN_SYMBOL: exports.CHAIN_SYMBOL,
@@ -401,3 +430,150 @@ function get_transaction(signature) {
401
430
  });
402
431
  });
403
432
  }
433
+ function build_transfer(from, to, amount) {
434
+ return __awaiter(this, void 0, void 0, function () {
435
+ var tag, fromPubkey, toPubkey, lamports, _a, blockhash, lastValidBlockHeight, transferInstruction, transaction, serialized, e_7;
436
+ return __generator(this, function (_b) {
437
+ switch (_b.label) {
438
+ case 0:
439
+ tag = TAG + " | build_transfer | ";
440
+ _b.label = 1;
441
+ case 1:
442
+ _b.trys.push([1, 3, , 4]);
443
+ if (!connection) {
444
+ throw new Error("Module not initialized. Call init() first.");
445
+ }
446
+ log.debug(tag, "Building transfer from ".concat(from, " to ").concat(to, " for ").concat(amount, " SOL"));
447
+ fromPubkey = new PublicKey(from);
448
+ toPubkey = new PublicKey(to);
449
+ lamports = Math.floor(amount * LAMPORTS_PER_SOL);
450
+ return [4 /*yield*/, connection.getLatestBlockhash('confirmed')
451
+ // Create transfer instruction
452
+ ];
453
+ case 2:
454
+ _a = _b.sent(), blockhash = _a.blockhash, lastValidBlockHeight = _a.lastValidBlockHeight;
455
+ transferInstruction = SystemProgram.transfer({
456
+ fromPubkey: fromPubkey,
457
+ toPubkey: toPubkey,
458
+ lamports: lamports
459
+ });
460
+ transaction = new Transaction({
461
+ feePayer: fromPubkey,
462
+ blockhash: blockhash,
463
+ lastValidBlockHeight: lastValidBlockHeight
464
+ }).add(transferInstruction);
465
+ serialized = transaction.serializeMessage();
466
+ log.debug(tag, "Transfer transaction built successfully");
467
+ return [2 /*return*/, {
468
+ transaction: transaction,
469
+ serialized: serialized.toString('base64'),
470
+ blockhash: blockhash,
471
+ lastValidBlockHeight: lastValidBlockHeight,
472
+ from: from,
473
+ to: to,
474
+ amount: amount,
475
+ lamports: lamports
476
+ }];
477
+ case 3:
478
+ e_7 = _b.sent();
479
+ log.error(tag, "Error building transfer:", e_7.message);
480
+ throw e_7;
481
+ case 4: return [2 /*return*/];
482
+ }
483
+ });
484
+ });
485
+ }
486
+ function estimate_fee() {
487
+ return __awaiter(this, void 0, void 0, function () {
488
+ var tag, response, feeInLamports, feeInSOL, fallbackFee, e_8;
489
+ return __generator(this, function (_a) {
490
+ switch (_a.label) {
491
+ case 0:
492
+ tag = TAG + " | estimate_fee | ";
493
+ _a.label = 1;
494
+ case 1:
495
+ _a.trys.push([1, 3, , 4]);
496
+ if (!connection) {
497
+ throw new Error("Module not initialized. Call init() first.");
498
+ }
499
+ return [4 /*yield*/, axios({
500
+ url: rpcUrl,
501
+ method: 'POST',
502
+ data: {
503
+ "jsonrpc": "2.0",
504
+ "id": 1,
505
+ "method": "getFees"
506
+ }
507
+ })];
508
+ case 2:
509
+ response = _a.sent();
510
+ if (response.data && response.data.result) {
511
+ feeInLamports = response.data.result.value.feeCalculator.lamportsPerSignature;
512
+ feeInSOL = feeInLamports / LAMPORTS_PER_SOL;
513
+ log.debug(tag, "Estimated fee:", feeInSOL, "SOL");
514
+ return [2 /*return*/, feeInSOL];
515
+ }
516
+ fallbackFee = 5000 / LAMPORTS_PER_SOL;
517
+ log.debug(tag, "Using fallback fee:", fallbackFee, "SOL");
518
+ return [2 /*return*/, fallbackFee];
519
+ case 3:
520
+ e_8 = _a.sent();
521
+ log.debug(tag, "Using fallback fee due to error:", e_8.message);
522
+ // Return standard fee as fallback (5000 lamports = 0.000005 SOL)
523
+ return [2 /*return*/, 5000 / LAMPORTS_PER_SOL];
524
+ case 4: return [2 /*return*/];
525
+ }
526
+ });
527
+ });
528
+ }
529
+ function get_token_balances(address) {
530
+ return __awaiter(this, void 0, void 0, function () {
531
+ var tag, response, tokenAccounts, e_9;
532
+ return __generator(this, function (_a) {
533
+ switch (_a.label) {
534
+ case 0:
535
+ tag = TAG + " | get_token_balances | ";
536
+ _a.label = 1;
537
+ case 1:
538
+ _a.trys.push([1, 3, , 4]);
539
+ log.debug(tag, "Getting token balances for:", address);
540
+ return [4 /*yield*/, axios({
541
+ url: rpcUrl,
542
+ method: 'POST',
543
+ data: {
544
+ "jsonrpc": "2.0",
545
+ "id": 1,
546
+ "method": "getTokenAccountsByOwner",
547
+ "params": [
548
+ address,
549
+ { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
550
+ { "encoding": "jsonParsed" }
551
+ ]
552
+ }
553
+ })];
554
+ case 2:
555
+ response = _a.sent();
556
+ if (response.data && response.data.result && response.data.result.value) {
557
+ tokenAccounts = response.data.result.value.map(function (account) {
558
+ var parsedInfo = account.account.data.parsed.info;
559
+ return {
560
+ mint: parsedInfo.mint,
561
+ owner: parsedInfo.owner,
562
+ balance: parsedInfo.tokenAmount.uiAmount,
563
+ decimals: parsedInfo.tokenAmount.decimals,
564
+ uiAmountString: parsedInfo.tokenAmount.uiAmountString
565
+ };
566
+ });
567
+ log.debug(tag, "Found ".concat(tokenAccounts.length, " token accounts"));
568
+ return [2 /*return*/, tokenAccounts];
569
+ }
570
+ return [2 /*return*/, []];
571
+ case 3:
572
+ e_9 = _a.sent();
573
+ log.error(tag, "Error getting token balances:", e_9.message);
574
+ return [2 /*return*/, []];
575
+ case 4: return [2 /*return*/];
576
+ }
577
+ });
578
+ });
579
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/solana-network",
3
- "version": "8.11.1",
3
+ "version": "8.11.2",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "description": "Pioneer Platform Solana Network module",