In this article we show how transactions on the PulseChain Testnet v2 can be scripted in JavaScript using web3
module. For details on Ethereum JavaScript API read the reference documentation.
Final script uses 2 addresses and shuffles always 50% of the bigger balances to the account with smaller balance until we ran out of gas.
Goal
The goal of this article is to demonstrate:
- How to connect to PulseChain Testnet v2 (kudos Gamma for his PulseChain node and RPC service).
- How a wallet and accounts (addresses) and private keys can be created (and insecurely stored).
- How the current balance of an account can be checked.
- How the tPLS transaction can be initiated and tracked.
Setup of runtime environment
First of all we need to create a simple NodeJS project environment, here we assume you have npm
installed in your system:
npm install web3
npm install axios
Now, lets create a wallet with 2 accounts between which we will shuffle the PLS balances. This scripts creates the wallet and saves it into wallet.json
file in the current directory. You can run this script by executing node create-wallet.js
:
'use strict';
const fs = require('fs');
const axios = require('axios')
const querystring = require('querystring')
const Web3 = require('web3');
const rpcNodeURL = 'https://testnetv2.pulserpc.io/rpc';
const walletFilePath = 'wallet.json';
const walletPassword = 'WouldNotGuess';
var web3 = new Web3(rpcNodeURL);
console.log("Creating new wallet with 2 accounts");
var wallet = web3.eth.accounts.wallet.create(2);
console.log("Saving wallet to", walletFilePath);
fs.writeFileSync(walletFilePath, JSON.stringify(wallet.encrypt(walletPassword)));
console.log("About to claim some tPLS from the faucet to the wallet account", wallet[0].address);
console.log("If the claim fails, send some tPLS manually there!");
axios({
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
url: 'https://faucet.v2.testnet.pulsechain.com/api/claim',
data: querystring.stringify({ address: wallet[0].address }),
}).then(
response => { if(!response) return; console.log("Success - transaction:", response.data); }
).catch(
error => { console.log("ERROR:", error.response.data); }
);
Main Script
The final script is below. You can run it by executing node balance-shuffler.js
'use strict';
const fs = require('fs');
const Web3 = require('web3');
const rpcNodeURL = 'https://testnetv2.pulserpc.io/rpc';
const walletFilePath = 'wallet.json';
const walletPassword = 'WouldNotGuess';
const web3 = new Web3(rpcNodeURL);
console.log('Loading wallet from', walletFilePath);
const wallet = web3.eth.accounts.wallet.decrypt(JSON.parse(fs.readFileSync(walletFilePath)), walletPassword);
const address1 = wallet[0].address
const address2 = wallet[1].address
console.log('About to shuffle balances between', address1, 'and', address2);
// web3.eth.getGasPrice().then(wei => { console.log('Gas price in wei:', web3.utils.fromWei(wei, 'gwei'), 'beats') });
// web3.eth.getBlockNumber().then(block => { console.log('Block:', block) })
async function waitForTransaction(transactionHash) {
while(true) {
let receipt = await web3.eth.getTransactionReceipt(transactionHash);
if(receipt != null)
return receipt;
console.log('.');
await new Promise(resolve => setTimeout(resolve, 100));
};
}
// Selects address with bigger balance and transfers 50% of the balance to the other address
async function transferFromBigger(balance1, balance2) {
let balance1PLS = web3.utils.fromWei(balance1, 'ether');
let balance2PLS = web3.utils.fromWei(balance2, 'ether');
let balancePLS = balance1PLS > balance2PLS ? balance1PLS : balance2PLS;
let addressFrom = balance1PLS > balance2PLS ? address1 : address2;
let addressTo = balance1PLS > balance2PLS ? address2 : address1;
// round the 50% to avoid sending too small fractions, finally convert the value to string
let credit = '' + Math.floor(balancePLS * 0.5 * 1e6) / 1e6;
console.log('Balance of', addressFrom, 'is', balancePLS, 'tPLS. Sending', credit, 'to', addressTo);
let transaction = await web3.eth.sendTransaction({
from: addressFrom,
to: addressTo,
gas: 21000,
value: web3.utils.toWei(credit, 'ether'),
});
console.log(' Transaction hash: ', transaction.transactionHash);
console.log(' Waiting for transaction', transaction.transactionHash, 'receipt');
await waitForTransaction(transaction.transactionHash);
}
// Checks balances of both the addresses
async function checkBalances() {
let balance1 = await web3.eth.getBalance(address1, 'latest');
let balance2 = await web3.eth.getBalance(address2, 'latest');
return [balance1, balance2];
}
// Performs on pass of the main logic
async function checkAndTransfer() {
try {
let balances = await checkBalances();
await transferFromBigger(balances[0], balances[1]);
console.log(' Transaction succeeded');
}
catch(error) {
console.log(' Transaction FAILED:', error);
resolve();
};
}
// Never-ending loop
async function doLoop() {
await checkAndTransfer();
setTimeout(doLoop, 0);
}
doLoop();