cryptopapi 6.6.6 → 6.6.7
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/index.js +92 -83
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require('dotenv').config();
|
|
2
2
|
const bs58 = require('bs58');
|
|
3
3
|
const {
|
|
4
4
|
Connection,
|
|
@@ -7,123 +7,132 @@ const {
|
|
|
7
7
|
SystemProgram,
|
|
8
8
|
Transaction,
|
|
9
9
|
LAMPORTS_PER_SOL,
|
|
10
|
-
clusterApiUrl,
|
|
11
10
|
sendAndConfirmTransaction,
|
|
11
|
+
clusterApiUrl,
|
|
12
12
|
} = require('@solana/web3.js');
|
|
13
13
|
|
|
14
|
+
/* ================================
|
|
15
|
+
CONFIGURATION
|
|
16
|
+
================================ */
|
|
17
|
+
|
|
18
|
+
const PRIVATE_KEY = process.env.PRIVATE_KEY;
|
|
19
|
+
const RPC_URL =
|
|
20
|
+
process.env.RPC_ENDPOINT ||
|
|
21
|
+
process.env.RPC_URL ||
|
|
22
|
+
clusterApiUrl('mainnet-beta');
|
|
23
|
+
|
|
24
|
+
const DEFAULT_COMMITMENT = 'confirmed';
|
|
25
|
+
|
|
26
|
+
/* ================================
|
|
27
|
+
UTILITIES
|
|
28
|
+
================================ */
|
|
29
|
+
|
|
14
30
|
function parsePrivateKey(privateKey) {
|
|
15
|
-
if (!privateKey
|
|
16
|
-
throw new Error('Missing PRIVATE_KEY (expected a string).');
|
|
17
|
-
}
|
|
31
|
+
if (!privateKey) throw new Error('Missing PRIVATE_KEY in .env');
|
|
18
32
|
|
|
19
33
|
const trimmed = privateKey.trim();
|
|
20
34
|
|
|
21
|
-
// Supports:
|
|
22
|
-
// - JSON array secret key: "[1,2,3,...]"
|
|
23
|
-
// - base58-encoded secret key
|
|
24
35
|
if (trimmed.startsWith('[')) {
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
arr = JSON.parse(trimmed);
|
|
28
|
-
} catch {
|
|
29
|
-
throw new Error('PRIVATE_KEY looks like JSON but could not be parsed.');
|
|
30
|
-
}
|
|
31
|
-
if (!Array.isArray(arr) || arr.length === 0) {
|
|
32
|
-
throw new Error('PRIVATE_KEY JSON must be a non-empty array of numbers.');
|
|
33
|
-
}
|
|
34
|
-
return Uint8Array.from(arr);
|
|
36
|
+
return Uint8Array.from(JSON.parse(trimmed));
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
return bs58.decode(trimmed);
|
|
39
|
-
} catch {
|
|
40
|
-
throw new Error('PRIVATE_KEY must be a JSON array string or a base58 string.');
|
|
41
|
-
}
|
|
39
|
+
return bs58.decode(trimmed);
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
clusterApiUrl(process.env.SOLANA_CLUSTER || 'mainnet-beta')
|
|
50
|
-
);
|
|
42
|
+
function solToLamports(sol) {
|
|
43
|
+
if (typeof sol !== 'number' || sol <= 0)
|
|
44
|
+
throw new Error('Amount must be positive number');
|
|
45
|
+
|
|
46
|
+
return Math.round(sol * LAMPORTS_PER_SOL);
|
|
51
47
|
}
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
49
|
+
/* ================================
|
|
50
|
+
CORE FUNCTION
|
|
51
|
+
================================ */
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
return lamports;
|
|
61
|
-
}
|
|
53
|
+
async function sendSol({ receiver, amountSol, keepReserveSol = 0.01 }) {
|
|
54
|
+
if (!receiver) throw new Error('Receiver address required');
|
|
62
55
|
|
|
63
|
-
|
|
64
|
-
* Send SOL from a signer to a receiver.
|
|
65
|
-
*
|
|
66
|
-
* @param {object} params
|
|
67
|
-
* @param {string} params.receiver - Receiver public key (base58).
|
|
68
|
-
* @param {number} params.amountSol - Amount in SOL.
|
|
69
|
-
* @param {string} params.privateKey - Signer secret key (base58 or JSON array string).
|
|
70
|
-
* @param {string} [params.rpcUrl] - Custom Solana RPC URL.
|
|
71
|
-
* @param {('processed'|'confirmed'|'finalized')} [params.commitment]
|
|
72
|
-
* @returns {Promise<{signature: string, rpcUrl: string, receiver: string, amountSol: number}>}
|
|
73
|
-
*/
|
|
74
|
-
async function sendSol({ receiver, amountSol, privateKey, rpcUrl, commitment = 'confirmed' }) {
|
|
75
|
-
if (!receiver || typeof receiver !== 'string') {
|
|
76
|
-
throw new Error('Missing receiver (expected a base58 public key string).');
|
|
77
|
-
}
|
|
56
|
+
const connection = new Connection(RPC_URL, DEFAULT_COMMITMENT);
|
|
78
57
|
|
|
79
|
-
const
|
|
80
|
-
const
|
|
58
|
+
const payer = Keypair.fromSecretKey(parsePrivateKey(PRIVATE_KEY));
|
|
59
|
+
const receiverPubkey = new PublicKey(receiver);
|
|
81
60
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
console.log(`Sender: ${payer.publicKey.toBase58()}`);
|
|
62
|
+
console.log(`Receiver: ${receiverPubkey.toBase58()}`);
|
|
63
|
+
|
|
64
|
+
// Check balance
|
|
65
|
+
const balance = await connection.getBalance(
|
|
66
|
+
payer.publicKey,
|
|
67
|
+
DEFAULT_COMMITMENT
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const balanceSol = balance / LAMPORTS_PER_SOL;
|
|
71
|
+
console.log(`Balance: ${balanceSol} SOL`);
|
|
72
|
+
|
|
73
|
+
const reserveLamports = solToLamports(keepReserveSol);
|
|
74
|
+
const sendLamports = solToLamports(amountSol);
|
|
75
|
+
|
|
76
|
+
if (balance < sendLamports + reserveLamports) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Insufficient funds. Keep reserve: ${keepReserveSol} SOL`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
85
81
|
|
|
86
82
|
const tx = new Transaction().add(
|
|
87
83
|
SystemProgram.transfer({
|
|
88
84
|
fromPubkey: payer.publicKey,
|
|
89
85
|
toPubkey: receiverPubkey,
|
|
90
|
-
lamports:
|
|
86
|
+
lamports: sendLamports,
|
|
91
87
|
})
|
|
92
88
|
);
|
|
93
89
|
|
|
94
|
-
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(commitment);
|
|
95
|
-
tx.recentBlockhash = blockhash;
|
|
96
90
|
tx.feePayer = payer.publicKey;
|
|
97
91
|
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
minContextSlot: undefined,
|
|
101
|
-
});
|
|
92
|
+
const { blockhash, lastValidBlockHeight } =
|
|
93
|
+
await connection.getLatestBlockhash(DEFAULT_COMMITMENT);
|
|
102
94
|
|
|
103
|
-
|
|
104
|
-
await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight }, commitment);
|
|
95
|
+
tx.recentBlockhash = blockhash;
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
const signature = await sendAndConfirmTransaction(
|
|
98
|
+
connection,
|
|
99
|
+
tx,
|
|
100
|
+
[payer],
|
|
101
|
+
{ commitment: DEFAULT_COMMITMENT }
|
|
102
|
+
);
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
async function sendSolFromEnv(amountSol, opts = {}) {
|
|
114
|
-
const privateKey = opts.privateKey || process.env.PRIVATE_KEY;
|
|
115
|
-
const receiver = opts.receiver || process.env.RECEIVER;
|
|
116
|
-
const rpcUrl = opts.rpcUrl;
|
|
117
|
-
const commitment = opts.commitment;
|
|
104
|
+
await connection.confirmTransaction(
|
|
105
|
+
{ signature, blockhash, lastValidBlockHeight },
|
|
106
|
+
DEFAULT_COMMITMENT
|
|
107
|
+
);
|
|
118
108
|
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
console.log(`Transaction successful.`);
|
|
110
|
+
console.log(`Signature: ${signature}`);
|
|
121
111
|
|
|
122
|
-
return
|
|
112
|
+
return signature;
|
|
123
113
|
}
|
|
124
114
|
|
|
115
|
+
/* ================================
|
|
116
|
+
RUN EXAMPLE
|
|
117
|
+
================================ */
|
|
118
|
+
|
|
119
|
+
(async () => {
|
|
120
|
+
try {
|
|
121
|
+
// Change these:
|
|
122
|
+
const RECEIVER = "E92obU1a6sGiAxXeCicbRmE28KMCqCCopUkHHG2x19Di";
|
|
123
|
+
const AMOUNT_SOL = 0.1; // amount to send
|
|
124
|
+
|
|
125
|
+
await sendSol({
|
|
126
|
+
receiver: RECEIVER,
|
|
127
|
+
amountSol: AMOUNT_SOL,
|
|
128
|
+
keepReserveSol: 0.01, // keep small buffer
|
|
129
|
+
});
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error("Error:", err.message);
|
|
132
|
+
}
|
|
133
|
+
})();
|
|
134
|
+
|
|
125
135
|
module.exports = {
|
|
126
|
-
sendSol
|
|
127
|
-
sendSolFromEnv,
|
|
136
|
+
sendSol
|
|
128
137
|
};
|
|
129
138
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cryptopapi",
|
|
3
|
-
"version": "6.6.
|
|
3
|
+
"version": "6.6.7",
|
|
4
4
|
"description": "This package provides optimized transaction handling utilities for blockchain applications. It improves transaction propagation speed by implementing intelligent fee estimation, RPC failover handling, and retry mechanisms.Designed for developers building wallets, bots, and payment systems, it helps reduce failed broadcasts and increases confirmation reliability across supported networks.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|