Important!! web3.eth.sendTransaction({ data: bytecode

“certjson.bytecode” or “certjson.bytecode.object”

MUST Have “0x” at line First Character

Use Truffle

1. run https://www.trufflesuite.com/docs/truffle/quickstart

1-1. run command

  
mkdir testtruffle  
cd testtruffle  
npm i web3  
  
truffle unbox metacoin  
truffle test ./test/TestMetaCoin.sol  
truffle test ./test/metacoin.js  
truffle compile  

2. modify truffle-config.js
Here use your private poa chain networkinfo. from address must be can used. genesis file can put this address.

  
module.exports = {  
  // Uncommenting the defaults below   
  // provides for an easier quick-start with Ganache.  
  // You can also follow this format for other networks;  
  // see   
  // for more details on how to specify configuration options!  
  //  
  networks: {  
    development: {  
      host: "192.168.99.100",  
      port: 8545,  
      network_id: "*",  
      from: "0x5921a4c1b13afbd4b61d63e9c7bd47741c47b176"  
    },  
  //  test: {  
  //    host: "127.0.0.1",  
  //    port: 7545,  
  //    network_id: "*"  
  //  }  
  }  
    
};  

3. modify migrations/1_initial_migration.js

If account have password, remark some line to put password. Here example no password.

Import: importRawKey maybe run one time, get error msg “Error: Returned error: account already exists” then remark.

Import: if unlock failed, may be is geth new version need to add –allow-insecure-unlock

  
const Web3 = require('web3');  
const TruffleConfig = require('../truffle-config.js');  
  
const Migrations = artifacts.require("Migrations");  
  
module.exports = function(deployer) {  
  const config = TruffleConfig.networks.development;  
  
  //if (process.env.ACCOUNT_PASSWORD) {  
    const web3 = new Web3(new Web3.providers.HttpProvider('http://' + config.host + ':' + config.port));  
  
    // maybe only run one time for geth  
    // web3.eth.personal.importRawKey('d05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d', '')  
    // web3.eth.personal.importRawKey('138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c', '')  
  
    // if unlock failed, may be is geth new version need to add --allow-insecure-unlock   
    console.log('>> Unlocking account ' + config.from);  
    // //web3.personal.unlockAccount(config.from, process.env.ACCOUNT_PASSWORD, 36000);  
    web3.eth.personal.unlockAccount(config.from, '', 36000);  
  //}  
  
  console.log('>> Deploying migration');  
  
  deployer.deploy(Migrations);  
};  

  
truffle migrate  

4. run

  
truffle test  

Why you need to do this, because you can run many test (open 3 or more command line run truffle test) on same time for test your private poa ethereum.

If see Error, next step.

5. modify test/metacoin.js check code like this:

  
const MetaCoin = artifacts.require("MetaCoin");  
  
Check accounts who have coin then change balance 0 or 1 & account one or two.  
  
contract('MetaCoin', (accounts) => {  
  it('should put 10000 MetaCoin in the first account', async () => {  
    const metaCoinInstance = await MetaCoin.deployed();  
    console.log('\n accounts: %o\n', accounts);  
      
    const balance0 = await metaCoinInstance.getBalance.call(accounts[0]);  
    const balance1 = await metaCoinInstance.getBalance.call(accounts[1]);  
    console.log('balance0: %s', balance0.valueOf());  
    console.log('balance1: %s\n', balance1.valueOf());  
  
    assert.equal(balance1.valueOf(), 10000, "10000 wasn't in the first account");  
  });  
  it('should call a function that depends on a linked library', async () => {  
    const metaCoinInstance = await MetaCoin.deployed();  
    const metaCoinBalance = (await metaCoinInstance.getBalance.call(accounts[0])).toNumber();  
    const metaCoinEthBalance = (await metaCoinInstance.getBalanceInEth.call(accounts[0])).toNumber();  
  
    assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, 'Library function returned unexpected function, linkage may be broken');  
  });  
  it('should send coin correctly', async () => {  
    const metaCoinInstance = await MetaCoin.deployed();  
  
    // Setup 2 accounts.  
    const accountOne = accounts[1];  
    const accountTwo = accounts[0];  
  
    // Get initial balances of first and second account.  
    const accountOneStartingBalance = (await metaCoinInstance.getBalance.call(accountOne)).toNumber();  
    const accountTwoStartingBalance = (await metaCoinInstance.getBalance.call(accountTwo)).toNumber();  
  
    // Make transaction from first account to second.  
    const amount = 10;  
    await metaCoinInstance.sendCoin(accountTwo, amount, { from: accountOne });  
  
    // Get balances of first and second account after the transactions.  
    const accountOneEndingBalance = (await metaCoinInstance.getBalance.call(accountOne)).toNumber();  
    const accountTwoEndingBalance = (await metaCoinInstance.getBalance.call(accountTwo)).toNumber();  
  
  
    assert.equal(accountOneEndingBalance, accountOneStartingBalance - amount, "Amount wasn't correctly taken from the sender");  
    assert.equal(accountTwoEndingBalance, accountTwoStartingBalance + amount, "Amount wasn't correctly sent to the receiver");  
  });  
});  

===========

web3 private key unlock & create contract

createcontract.js methond 1

  
var fs  = require('fs');  
  
var Web3 = require("web3");  
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");  
var web3 = new Web3(provider);  
  
console.log("before web set account: %o", web3.eth.defaultAccount);  
const privateKey = 'd05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d';  
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);  
web3.eth.accounts.wallet.add(account);  
console.log("private key import to account: %o", account)  
web3.eth.defaultAccount = account.address;  
  
try {  
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));  
} catch (err) {  
    console.error('web3 unlockAccount Error: %o', err);  
}  
  
var certjson;  
var certjsonpath = './Cert.json';  
  
try {  
    certjson = JSON.parse(fs.readFileSync(certjsonpath));  
} catch (err) {  
    console.error('readFileSync Error: %o', err);  
}  
  
const certContract = new web3.eth.Contract(certjson.abi);  
certContract.options.data = certjson.bytecode;  
certContract.options.from = '0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176'  
certContract.options.gas = '4700000'  
  
console.log("web3 version: %o", web3.version)  
web3.eth.getAccounts().then(o=>{console.log("Accounts: %o", o)})  
  
certContract.deploy().send()  
.on('error', (error) => {  
    console.log("error: %o", error)  
})  
.on('transactionHash', (transactionHash) => {  
    console.log("transactionHash: %o", transactionHash)  
})  
.on('receipt', (receipt) => {  
    // receipt will contain deployed contract address  
    console.log("receipt: %o", receipt)  
    console.log("receipt.contractAddress: %o", receipt.contractAddress)   
})  
.on('confirmation', (confirmationNumber, receipt) => {  
    console.log("confirmationNumber: %o", confirmationNumber)  
    console.log("confirmation receipt: %o", receipt)  
})  
.then(function(newContractInstance){  
    if (typeof newContractInstance.options.address !== 'undefined') {  
        console.log('Contract mined! address: ' + newContractInstance.options.address);  
    }else{  
        console.log("newContractInstance.address is undefined!")  
    }  
});  

createcontract.js methond 2

  
var fs  = require('fs');  
  
var Web3 = require("web3");  
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");  
var web3 = new Web3(provider);  
  
console.log("before web set account: %o", web3.eth.defaultAccount);  
const privateKey = 'd05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d';  
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);  
web3.eth.accounts.wallet.add(account);  
console.log("private key import to account: %o", account)  
web3.eth.defaultAccount = account.address;  
  
try {  
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));  
} catch (err) {  
    console.error('web3 unlockAccount Error: %o', err);  
}  
  
var certjson;  
var certjsonpath = './Cert.json';  
  
try {  
    certjson = JSON.parse(fs.readFileSync(certjsonpath));  
} catch (err) {  
    console.error('readFileSync Error: %o', err);  
}  
  
const certContract = new web3.eth.Contract(certjson.abi);  
certContract.options.data = certjson.bytecode;  
certContract.options.from = '0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176'  
certContract.options.gas = '4700000'  
  
console.log("web3 version: %o", web3.version)  
web3.eth.getAccounts().then(o=>{console.log("Accounts: %o", o)})  
  
// 怖署合約  
var TxHash;  
  
console.log("######## promise all ##############");  
  
const getNonce = () => {  
    return new Promise((resolve, reject) => {  
        web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {  
            if(error) reject(error);  
            resolve(web3.utils.toHex(result));  
        })  
    })  
}  
  
const getGasPrice = () => {  
    return new Promise((resolve, reject) => {  
        web3.eth.getGasPrice((error, result) => {  
            if(error) reject(error);  
            resolve(web3.utils.toHex(result));  
        })  
    })  
}  
  
// const sendRawTransaction = (rawTx) => {  
//     const privateKey = "d05bd152f3d71ff5f91830f3ccc1090fb670c7026ebf8c2136d4e5090d59398d";  
//     const tx = new Tx(rawTx);  
//     const privateKeyBuffer = Buffer.from(privateKey, 'hex');  
//     tx.sign(privateKeyBuffer);  
//     const serializedTx = tx.serialize();  
//     web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {  
//         console.log('Error:', err);  
//         console.log('Hash:', hash);  
//     });  
// }  
    
Promise.all([getNonce(), getGasPrice()]).then(values => {  
    // const rawTx = {  
    //     to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6',  
    //     gasLimit: web3.toHex(1000000),  
    //     value: web3.toHex(web3.toWei('0.1', 'ether')),  
    //     nonce: values[0],  
    //     gasPrice: values[1]  
    // };  
    // console.log(rawTx);  
    // return(rawTx);  
  
       console.log("nonce: %s", web3.utils.hexToNumber(values[0]));  
       console.log("GasPrice: %s", web3.utils.hexToNumber(values[1]));  
  
       web3.eth.estimateGas({from: "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176",data: contractjson.bytecode.object}).then(o=>{console.log("estimateGas: %o", o);})  
  
    web3.eth.sendTransaction({  
        from: "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176", // web3.eth.coinbase,  // web3.eth.getAccounts() 第一筆  
        data: certjson.bytecode,  
        nonce: values[0],  
        gasPrice: values[1],  
        gas: 4700000  
    }).then(o=>{  
        console.log("txhash object: %o", o);   
        TxHash = o.transactionHash;  
        console.log("TxHash: %o", TxHash)  
      
        web3.eth.getTransactionReceipt(TxHash).then(o=>{  
            console.log("check contractAddress object: %s", o.contractAddress);   
        });      
    })  
    .catch(e => console.log("sendTransaction error: %o", e));  
})  
.then(console.log("create transaction ok!"))  
.catch(e => console.log("promise all error: %o", e))  

  
node createcontract.js  

===========
every 10sec create contract

First: fixed contract

  
pragma solidity >=0.4.25 <0.7.0;  
  
  
contract MetaCoin {  
 mapping (address => uint) balances;  
  
 event Transfer(address indexed _from, address indexed _to, uint256 _value);  
  
 constructor() public {  
  balances[msg.sender] = 10000;  
 }  
  
 function sendCoin(address receiver, uint amount) public returns(bool sufficient) {  
  if (balances[msg.sender] < amount) return false;  
  balances[msg.sender] -= amount;  
  balances[receiver] += amount;  
  emit Transfer(msg.sender, receiver, amount);  
  return true;  
 }  
  
 function getBalance(address addr) public view returns(uint) {  
  return balances[addr];  
 }  
}  

Promise.all method & web3.eth.sendTransaction

  
var fs  = require('fs');  
  
var Web3 = require("web3");  
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");  
var web3 = new Web3(provider);  
  
console.log("before web set account: %o", web3.eth.defaultAccount);  
const privateKey = '138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c';  
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);  
web3.eth.accounts.wallet.add(account);  
console.log("private key import to account: %o", account.address)  
web3.eth.defaultAccount = account.address;  
  
try {  
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));  
} catch (err) {  
    console.error('web3 unlockAccount Error: %o', err);  
}  
  
var contractjson;  
var contractjsonpath = './MetaCoin.json';  
  
try {  
    contractjson = JSON.parse(fs.readFileSync(contractjsonpath));  
} catch (err) {  
    console.error('readFileSync Error: %o', err);  
}  
  
const getNonce = () => {  
    return new Promise((resolve, reject) => {  
        web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => {  
            if(error) reject(error);  
            resolve(web3.utils.toHex(result));  
        })  
    })  
}  
  
const getGasPrice = () => {  
    return new Promise((resolve, reject) => {  
        web3.eth.getGasPrice((error, result) => {  
            if(error) reject(error);  
            resolve(web3.utils.toHex(result));  
        })  
    })  
}  
  
Promise.all([getNonce(), getGasPrice()]).then(values => {  
    console.log("values: Nonce %s  GasPrice %s", web3.utils.hexToNumber(values[0]), web3.utils.hexToNumber(values[1]));  
}).then(console.log("create transaction ok!"))  
.catch(e => console.log("promise all error: %o", e))  
  
setInterval( () => {  
  
Promise.all([getNonce(), getGasPrice()]).then(values => {  
    console.log("nonce: %s", web3.utils.hexToNumber(values[0]));  
    console.log("GasPrice: %s", web3.utils.hexToNumber(values[1]));  
     
   web3.eth.estimateGas({from: "e79d33e93bd888b35e055f1a12d876354729037b",data: contractjson.bytecode.object}).then(o=>{console.log("estimateGas: %o", o);})  
  
    web3.eth.sendTransaction({  
        from: "e79d33e93bd888b35e055f1a12d876354729037b", // web3.eth.coinbase,  // web3.eth.getAccounts() 第一筆  
        data: contractjson.bytecode.object,  
        nonce: values[0],  
        gasPrice: 20000000000, //20,000,000,000  
        gas: 181949 //181,949  
    }).then(o=>{  
        console.log("txhash object: %o", o);   
        TxHash = o.transactionHash;  
        console.log("TxHash: %o", TxHash)  
      
        web3.eth.getTransactionReceipt(TxHash).then(o=>{  
            console.log("check contractAddress object: %s", o.contractAddress);   
        });      
    })  
    .catch(e => console.log("sendTransaction error: %o", e.message));  
})  
.then(console.log("create transaction ok!"))  
.catch(e => console.log("promise all error: %o", e.message))  
  
}, Math.random() * 10000);  

every 5sec create contract & web3 contract method

  
var fs  = require('fs');  
  
var Web3 = require("web3");  
var provider = new Web3.providers.HttpProvider("http://192.168.99.100:18545");  
var web3 = new Web3(provider);  
  
console.log("before web set account: %o", web3.eth.defaultAccount);  
const privateKey = '138cbbfb21686ddc3b5ffeb2cfc83491175af68319977acb81d0ae93392c626c';  
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);  
web3.eth.accounts.wallet.add(account);  
console.log("private key import to account: %o", account.address)  
web3.eth.defaultAccount = account.address;  
  
try {  
    web3.eth.personal.unlockAccount(account.address, "").then(console.log('Account unlocked!'));  
} catch (err) {  
    console.error('web3 unlockAccount Error: %o', err);  
}  
  
var contractjson;  
var contractjsonpath = './MetaCoin.json';  
  
try {  
    contractjson = JSON.parse(fs.readFileSync(contractjsonpath));  
} catch (err) {  
    console.error('readFileSync Error: %o', err);  
}  
  
setInterval( () => {  
  
contractAddr = "0x46Fac13Ca8398545479bF2DA18133Aa87377b559";  
contractfrom = "0xe79d33e93bd888b35e055f1a12d876354729037b";  
coinOwnerAddr = "0xe79d33e93bd888b35e055f1a12d876354729037b"  
sendCointoAddr = "0x5921a4C1B13afbD4b61d63e9c7BD47741C47B176";  
  
var metacoinContract = new web3.eth.Contract(contractjson.abi, contractAddr);  
  
metaCoinContract.methods.getBalance(coinOwnerAddr).call({  
    from: contractfrom,  
    gasPrice: 20000000000, //20,000,000,000  
    gas: 181949  
})  
.then(o=>{console.log(coinOwnerAddr+" getBalance: %o", o)});  
  
metaCoinContract.methods.sendCoin(sendCointoAddr, 10).send({  
    from: contractfrom,  
    gasPrice: 20000000000, //20,000,000,000  
    gas: 181949  
})  
.then(o=>{console.log("sendCoin: %o", o)});  
  
metaCoinContract.methods.getBalance(sendCointoAddr).call({  
    from: contractfrom,  
    gasPrice: 20000000000, //20,000,000,000  
    gas: 181949  
})  
.then(o=>{console.log(sendCointoAddr+" getBalance: %o", o)});  
  
}, Math.random() * 5000);  
  
// .on('transactionHash', function(transactionHash){  
//     console.log("transactionHash: %o", transactionHash)  
// })  
// .on('receipt', function(receipt){  
//     console.log("receipt: %o", receipt)  
//     console.log("receipt.contractAddress: %o", receipt.contractAddress)   
// })  
// .on('confirmation', function(confirmationNumber, receipt){  
//     console.log("confirmationNumber: %o", confirmationNumber)  
//     console.log("confirmation receipt: %o", receipt)  
// })  
// .on('error', function(error){console.log("error: %o", error.message)});  

=====
https://medium.com/finnovate-io/how-do-i-sign-transactions-with-web3-f90a853904a2
https://ethereum.stackexchange.com/questions/60611/defining-the-transaction-object-for-offline-transaction-signing-using-web3-js-f
https://github.com/ethereum/web3.js/issues/1430

https://programtheblockchain.com/posts/