restake 2.0.0 → 2.1.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.
- package/dist/index.js +82 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29,6 +29,9 @@ const postageBatchId = cafe_utility_1.Arrays.requireStringArgument(process_1.arg
|
|
|
29
29
|
const externalWallet = cafe_utility_1.Arrays.requireStringArgument(process_1.argv, 'external-wallet');
|
|
30
30
|
const privateKeysPath = cafe_utility_1.Arrays.requireStringArgument(process_1.argv, 'private-keys-path');
|
|
31
31
|
const jsonRpcUrl = cafe_utility_1.Arrays.requireStringArgument(process_1.argv, 'json-rpc-url');
|
|
32
|
+
const telegramToken = cafe_utility_1.Arrays.requireStringArgument(process_1.argv, 'telegram-token');
|
|
33
|
+
const telegramChatId = cafe_utility_1.Arrays.requireStringArgument(process_1.argv, 'telegram-chat-id');
|
|
34
|
+
const BASE_PORT = 1633;
|
|
32
35
|
const privateKeys = (0, fs_1.readFileSync)(privateKeysPath, 'utf-8').split('\n').filter(Boolean);
|
|
33
36
|
if (n !== privateKeys.length) {
|
|
34
37
|
console.error(`Expected ${n} private keys, but got ${privateKeys.length}`);
|
|
@@ -42,7 +45,7 @@ async function main() {
|
|
|
42
45
|
async function validatePrivateKeys() {
|
|
43
46
|
for (let i = 0; i < n; i++) {
|
|
44
47
|
const privateKey = privateKeys[i];
|
|
45
|
-
const port =
|
|
48
|
+
const port = BASE_PORT + i;
|
|
46
49
|
const bee = new bee_js_1.Bee(`http://localhost:${port}`);
|
|
47
50
|
const addresses = await bee.getNodeAddresses();
|
|
48
51
|
const address = (0, accounts_1.privateKeyToAccount)(ensure0x(privateKey)).address;
|
|
@@ -54,31 +57,80 @@ async function validatePrivateKeys() {
|
|
|
54
57
|
}
|
|
55
58
|
function runLoop() {
|
|
56
59
|
cafe_utility_1.System.forever(async () => {
|
|
57
|
-
const port =
|
|
60
|
+
const port = BASE_PORT + cafe_utility_1.Random.intBetween(0, n - 1);
|
|
58
61
|
const bee = new bee_js_1.Bee(`http://localhost:${port}`);
|
|
59
62
|
const wallet = await bee.getWalletBalance();
|
|
60
63
|
if (wallet.bzzBalance.lt(bzz)) {
|
|
61
64
|
console.log(`:${port} balance is ${wallet.bzzBalance.toDecimalString()} BZZ, skipping`);
|
|
62
65
|
return;
|
|
63
66
|
}
|
|
64
|
-
if (cafe_utility_1.Random.chance(1 /
|
|
65
|
-
await
|
|
67
|
+
if (cafe_utility_1.Random.chance(1 / 4)) {
|
|
68
|
+
await runAction(port, `stake ${bzz.toDecimalString()} BZZ`, () => stake(bee, port));
|
|
69
|
+
}
|
|
70
|
+
else if (cafe_utility_1.Random.chance(1 / 3)) {
|
|
71
|
+
await runAction(port, `transfer ${bzz.toDecimalString()} BZZ to external wallet`, () => transfer(port));
|
|
66
72
|
}
|
|
67
73
|
else if (cafe_utility_1.Random.chance(1 / 2)) {
|
|
68
|
-
await
|
|
74
|
+
await runAction(port, `top up postage batch ${postageBatchId}`, () => topup(bee, port));
|
|
69
75
|
}
|
|
70
76
|
else {
|
|
71
|
-
|
|
72
|
-
const postageBatch = postageBatches.find(batch => batch.batchID.toString() === postageBatchId);
|
|
73
|
-
if (!postageBatch) {
|
|
74
|
-
console.error(`Postage batch with ID ${postageBatchId} not found`);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const { amount } = await bee.calculateTopUpForBzz(postageBatch.depth, bzz);
|
|
78
|
-
await bee.topUpBatch(postageBatch.batchID, amount);
|
|
77
|
+
await runAction(port, `aid weakest node with ${bzz.toDecimalString()} BZZ`, () => aid(port));
|
|
79
78
|
}
|
|
80
79
|
}, sleep, console.error);
|
|
81
80
|
}
|
|
81
|
+
async function runAction(port, description, action) {
|
|
82
|
+
try {
|
|
83
|
+
await action();
|
|
84
|
+
await sendTelegramMessage(`Port ${port}: ${description} succeeded`);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
await sendTelegramMessage(`Port ${port}: ${description} failed: ${error}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function stake(bee, port) {
|
|
91
|
+
console.log(`:${port} depositing ${bzz.toDecimalString()} BZZ as stake`);
|
|
92
|
+
await bee.depositStake(bzz);
|
|
93
|
+
}
|
|
94
|
+
async function transfer(port) {
|
|
95
|
+
console.log(`:${port} transferring ${bzz.toDecimalString()} BZZ to external wallet`);
|
|
96
|
+
await transferBZZ(privateKeys[port - BASE_PORT], externalWallet, bzz);
|
|
97
|
+
}
|
|
98
|
+
async function topup(bee, port) {
|
|
99
|
+
const postageBatches = await bee.getGlobalPostageBatches();
|
|
100
|
+
const postageBatch = postageBatches.find(batch => batch.batchID.toString() === postageBatchId);
|
|
101
|
+
if (!postageBatch) {
|
|
102
|
+
console.error(`Postage batch with ID ${postageBatchId} not found`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const { amount } = await bee.calculateTopUpForBzz(postageBatch.depth, bzz);
|
|
106
|
+
console.log(`:${port} topping up postage batch ${postageBatchId} with ${amount} amount`);
|
|
107
|
+
await bee.topUpBatch(postageBatch.batchID, amount);
|
|
108
|
+
}
|
|
109
|
+
async function aid(port) {
|
|
110
|
+
const weakestAddress = await findWeakestNodeAddress();
|
|
111
|
+
const currentAddress = (0, accounts_1.privateKeyToAccount)(ensure0x(privateKeys[port - BASE_PORT])).address;
|
|
112
|
+
if (weakestAddress && weakestAddress.toLowerCase() !== currentAddress.toLowerCase()) {
|
|
113
|
+
console.log(`:${port} aiding weakest node ${weakestAddress} with ${bzz.toDecimalString()} BZZ`);
|
|
114
|
+
await transferBZZ(privateKeys[port - BASE_PORT], weakestAddress, bzz);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log(`:${port} weakest node is self, skipping aid`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function findWeakestNodeAddress() {
|
|
121
|
+
let minStake = null;
|
|
122
|
+
let weakestAddress = null;
|
|
123
|
+
for (let i = 0; i < n; i++) {
|
|
124
|
+
const port = BASE_PORT + i;
|
|
125
|
+
const bee = new bee_js_1.Bee(`http://localhost:${port}`);
|
|
126
|
+
const stake = await bee.getStake();
|
|
127
|
+
if (minStake === null || stake.lt(minStake)) {
|
|
128
|
+
minStake = stake;
|
|
129
|
+
weakestAddress = (0, accounts_1.privateKeyToAccount)(ensure0x(privateKeys[i])).address;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return weakestAddress;
|
|
133
|
+
}
|
|
82
134
|
async function transferBZZ(privateKey, targetAddress, amount) {
|
|
83
135
|
const account = (0, accounts_1.privateKeyToAccount)(ensure0x(privateKey));
|
|
84
136
|
const client = (0, viem_1.createWalletClient)({
|
|
@@ -104,11 +156,12 @@ async function getGasPrice() {
|
|
|
104
156
|
return bee_js_1.DAI.fromWei(BigInt(price));
|
|
105
157
|
}
|
|
106
158
|
async function getTransactionCount(address) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
159
|
+
const payload = {
|
|
160
|
+
jsonrpc: '2.0',
|
|
161
|
+
id: 1,
|
|
162
|
+
method: 'eth_getTransactionCount',
|
|
163
|
+
params: [address.toLowerCase(), 'latest']
|
|
164
|
+
};
|
|
112
165
|
const count = await fetchJsonRpcHexString(payload);
|
|
113
166
|
return parseInt(count, 16);
|
|
114
167
|
}
|
|
@@ -125,5 +178,16 @@ async function fetchJsonRpcHexString(payload) {
|
|
|
125
178
|
function ensure0x(value) {
|
|
126
179
|
return value.startsWith('0x') ? value : `0x${value}`;
|
|
127
180
|
}
|
|
181
|
+
async function sendTelegramMessage(text) {
|
|
182
|
+
console.log('Sending Telegram message:', text);
|
|
183
|
+
await fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
headers: { 'Content-Type': 'application/json' },
|
|
186
|
+
body: JSON.stringify({ chat_id: telegramChatId, text }),
|
|
187
|
+
signal: AbortSignal.timeout(cafe_utility_1.Dates.seconds(10))
|
|
188
|
+
}).catch(error => {
|
|
189
|
+
console.error('Failed to send Telegram message:', error);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
128
192
|
process.on('unhandledRejection', console.error);
|
|
129
193
|
process.on('uncaughtException', console.error);
|