restake 2.0.1 → 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 -21
- 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,34 +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
|
-
|
|
66
|
-
|
|
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));
|
|
67
72
|
}
|
|
68
73
|
else if (cafe_utility_1.Random.chance(1 / 2)) {
|
|
69
|
-
|
|
70
|
-
await transferBZZ(privateKeys[port - 1633], externalWallet, bzz);
|
|
74
|
+
await runAction(port, `top up postage batch ${postageBatchId}`, () => topup(bee, port));
|
|
71
75
|
}
|
|
72
76
|
else {
|
|
73
|
-
|
|
74
|
-
const postageBatch = postageBatches.find(batch => batch.batchID.toString() === postageBatchId);
|
|
75
|
-
if (!postageBatch) {
|
|
76
|
-
console.error(`Postage batch with ID ${postageBatchId} not found`);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const { amount } = await bee.calculateTopUpForBzz(postageBatch.depth, bzz);
|
|
80
|
-
console.log(`:${port} topping up postage batch ${postageBatchId} with ${amount} amount`);
|
|
81
|
-
await bee.topUpBatch(postageBatch.batchID, amount);
|
|
77
|
+
await runAction(port, `aid weakest node with ${bzz.toDecimalString()} BZZ`, () => aid(port));
|
|
82
78
|
}
|
|
83
79
|
}, sleep, console.error);
|
|
84
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
|
+
}
|
|
85
134
|
async function transferBZZ(privateKey, targetAddress, amount) {
|
|
86
135
|
const account = (0, accounts_1.privateKeyToAccount)(ensure0x(privateKey));
|
|
87
136
|
const client = (0, viem_1.createWalletClient)({
|
|
@@ -107,11 +156,12 @@ async function getGasPrice() {
|
|
|
107
156
|
return bee_js_1.DAI.fromWei(BigInt(price));
|
|
108
157
|
}
|
|
109
158
|
async function getTransactionCount(address) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
159
|
+
const payload = {
|
|
160
|
+
jsonrpc: '2.0',
|
|
161
|
+
id: 1,
|
|
162
|
+
method: 'eth_getTransactionCount',
|
|
163
|
+
params: [address.toLowerCase(), 'latest']
|
|
164
|
+
};
|
|
115
165
|
const count = await fetchJsonRpcHexString(payload);
|
|
116
166
|
return parseInt(count, 16);
|
|
117
167
|
}
|
|
@@ -128,5 +178,16 @@ async function fetchJsonRpcHexString(payload) {
|
|
|
128
178
|
function ensure0x(value) {
|
|
129
179
|
return value.startsWith('0x') ? value : `0x${value}`;
|
|
130
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
|
+
}
|
|
131
192
|
process.on('unhandledRejection', console.error);
|
|
132
193
|
process.on('uncaughtException', console.error);
|