文章目录
交易
本项目包含对交易进行签名,发送,接收交易回执,验证交易执行结果。也提供了事件监听的逻辑代码。
准备
需要安装web3.js
其他和上一个项目环境一样,需要准备私钥和项目id。参考 上一篇。
合约和代码逻辑
合约
java
pragma solidity ^0.8.0;
contract Incrementer {
uint256 public number;
event Increment(uint256 value);
event Reset();
constructor(uint256 _initialNumber) {
number = _initialNumber;
}
function increment(uint256 _value) public {
require(_value > 0, "increment value should be positive number");
number = number + _value;
emit Increment(_value);
}
function reset() public {
number = 0;
emit Reset();
}
function getNumber() public view returns (uint256) {
return number;
}
}
compile.js
java
const fs = require('fs');
const solc = require('solc');
// 以 utf8 方式加载合约
const source = fs.readFileSync('Incrementer.sol', 'utf8');
// 编译合约
const input = {
language: 'Solidity',
sources: {
'Incrementer.sol': {
content: source,
},
},
settings: {
outputSelection: {
'*': {
'*': ['*'],
},
},
},
};
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractOfIncrementer =
tempFile.contracts['Incrementer.sol']['Incrementer'];
// 导出合约数据,可以使用 console 打印 contractFile 中的具体内容信息
module.exports = contractOfIncrementer;
index.js
java
const Web3 = require('web3');
const fs = require('fs');
const contractOfIncrementer = require('./compile');
require('dotenv').config();
const privatekey = process.env.PRIVATE_KEY;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/*
-- Define Provider --
*/
// Provider
const providerRPC = {
development: 'https://sepolia.infura.io/v3/' + process.env.INFURA_ID,
moonbase: 'https://rpc.testnet.moonbeam.network',
};
const web3 = new Web3(providerRPC.development); //Change to correct network
// Create account with privatekey
const account = web3.eth.accounts.privateKeyToAccount(privatekey);
const account_from = {
privateKey: privatekey,
accountAddress: account.address,
};
// Get abi & bin
const bytecode = contractOfIncrementer.evm.bytecode.object;
const abi = contractOfIncrementer.abi;
/*
*
*
* -- Verify Deployment --
*
*/
const Trans = async () => {
console.log('============================ 1. Deploy Contract');
console.log(`Attempting to deploy from account ${account.address}`);
// Create Contract Instance
const deployContract = new web3.eth.Contract(abi);
// Create Deployment Tx
const deployTx = deployContract.deploy({
data: bytecode,
arguments: [5],
});
// Sign Tx
const createTransaction = await web3.eth.accounts.signTransaction(
{
data: deployTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
// Get Transaction Receipt
const createReceipt = await web3.eth.sendSignedTransaction(
createTransaction.rawTransaction
);
console.log(`Contract deployed at address: ${createReceipt.contractAddress}`);
const deployedBlockNumber = createReceipt.blockNumber;
/*
*
*
*
* -- Verify Interface of Increment --
*
*
*/
// Create the contract with contract address
console.log();
console.log(
'============================ 2. Call Contract Interface getNumber'
);
let incrementer = new web3.eth.Contract(abi, createReceipt.contractAddress);
console.log(
`Making a call to contract at address: ${createReceipt.contractAddress}`
);
let number = await incrementer.methods.getNumber().call();
console.log(`The current number stored is: ${number}`);
// Add 3 to Contract Public Variable
console.log();
console.log(
'============================ 3. Call Contract Interface increment'
);
const _value = 3;
let incrementTx = incrementer.methods.increment(_value);
// Sign with Pk
let incrementTransaction = await web3.eth.accounts.signTransaction(
{
to: createReceipt.contractAddress,
data: incrementTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
// Send Transactoin and Get TransactionHash
const incrementReceipt = await web3.eth.sendSignedTransaction(
incrementTransaction.rawTransaction
);
console.log(`Tx successful with hash: ${incrementReceipt.transactionHash}`);
number = await incrementer.methods.getNumber().call();
console.log(`After increment, the current number stored is: ${number}`);
/*
*
*
*
* -- Verify Interface of Reset --
*
*
*/
console.log();
console.log('============================ 4. Call Contract Interface reset');
const resetTx = incrementer.methods.reset();
const resetTransaction = await web3.eth.accounts.signTransaction(
{
to: createReceipt.contractAddress,
data: resetTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
const resetcReceipt = await web3.eth.sendSignedTransaction(
resetTransaction.rawTransaction
);
console.log(`Tx successful with hash: ${resetcReceipt.transactionHash}`);
number = await incrementer.methods.getNumber().call();
console.log(`After reset, the current number stored is: ${number}`);
/*
*
*
*
* -- Listen to Event Increment --
*
*
*/
console.log();
console.log('============================ 5. Listen to Events');
console.log(' Listen to Increment Event only once && continuouslly');
// sepolia don't support http protocol to event listen, need to use websocket
// more details , please refer to https://medium.com/blockcentric/listening-for-smart-contract-events-on-public-blockchains-fdb5a8ac8b9a
const web3Socket = new Web3(
'wss://sepolia.infura.io/ws/v3/' + process.env.INFURA_ID
);
// listen to Increment event only once
incrementer.once('Increment', (error, event) => {
console.log('I am a onetime event listner, I am going to die now');
});
// listen to Increment event continuously
web3Socket.eth.subscribe('logs',{
address: createReceipt.contractAddress,
topics: []
},(error,result) => {
if(error){
console.error(error)
}
}
).on("data", (event) => {
console.log("New event: ", event);
})
.on("error", (error) => {
console.error("Error: ", error);
});
for (let step = 0; step < 3; step++) {
incrementTransaction = await web3.eth.accounts.signTransaction(
{
to: createReceipt.contractAddress,
data: incrementTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
await web3.eth.sendSignedTransaction(incrementTransaction.rawTransaction);
console.log("Waiting for events")
await sleep(3000);
if (step == 2) {
// clear all the listeners
web3Socket.eth.clearSubscriptions();
console.log('Clearing all the events listeners !!!!');
}
}
/*
*
*
*
* -- Get past events --
*
*
*/
console.log();
console.log('============================ 6. Going to get past events');
const pastEvents = await incrementer.getPastEvents('Increment', {
fromBlock: deployedBlockNumber,
toBlock: 'latest',
});
pastEvents.map((event) => {
console.log(event);
});
/*
*
*
*
* -- Check Transaction Error --
*
*
*/
console.log();
console.log('============================ 7. Check the transaction error');
incrementTx = incrementer.methods.increment(0);
incrementTransaction = await web3.eth.accounts.signTransaction(
{
to: createReceipt.contractAddress,
data: incrementTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
await web3.eth
.sendSignedTransaction(incrementTransaction.rawTransaction)
.on('error', console.error);
};
Trans()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
运行
java
============================ 1. Deploy Contract
Attempting to deploy from account 0x953bAac08Cad29A4E354F0833c404Ed528775B68
Contract deployed at address: 0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369
============================ 2. Call Contract Interface getNumber
Making a call to contract at address: 0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369
The current number stored is: 5
============================ 3. Call Contract Interface increment
Tx successful with hash: 0xf9121315472943c6c316c600072798813317563ee3994cfc2334ba20a453a4a1
After increment, the current number stored is: 8
============================ 4. Call Contract Interface reset
Tx successful with hash: 0xda76d0a839a40acfb654a37b7afe133c44cd81873f91d51ddfcff2b6052c2e0b
After reset, the current number stored is: 0
============================ 5. Listen to Events
Listen to Increment Event only once && continuouslly
I am a onetime event listner, I am going to die now
New event: {
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
blockHash: '0x9e8d04cff3f2236eed7bf662036657963cf7475b0e350f77a396e89a4935de2c',
blockNumber: 7947790,
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
logIndex: 353,
removed: false,
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
],
transactionHash: '0xdc7dfda876800b365e70374b8f8f9f39d8603bebe89f961109f65229b93524d6',
transactionIndex: 189,
id: 'log_7432a4a4'
}
Waiting for events
New event: {
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
blockHash: '0x9ec619f890cdd8e0ab6a3e0bae4846351f81f6b81125fddd444c8e7a2598d970',
blockNumber: 7947792,
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
logIndex: 343,
removed: false,
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
],
transactionHash: '0x4956140582e6e0d62885e0646ad0642b6ae060fd4658d0374cd555799fa3a843',
transactionIndex: 181,
id: 'log_a193869e'
}
Waiting for events
New event: {
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
blockHash: '0xd8967836b9d85763611be4489042896b149b45b82f3404d530ad60a2cb8ca378',
blockNumber: 7947793,
blockTimestamp: '0x67dd0eb8',
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
logIndex: 248,
removed: false,
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
],
transactionHash: '0x35163a22db0cffeeab3e2c4f6ca6f6a3f5e622982514ea98a6f99b3abc0e5d74',
transactionIndex: 169,
id: 'log_97159c2a'
}
Waiting for events
Clearing all the events listeners !!!!
============================ 6. Going to get past events
{
removed: false,
logIndex: 413,
transactionIndex: 214,
transactionHash: '0xf9121315472943c6c316c600072798813317563ee3994cfc2334ba20a453a4a1',
blockHash: '0xdc82eb994a9884606ad817309a509f923aa4c9eb1444e1fdf0531f29919d67ca',
blockNumber: 7947788,
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
id: 'log_95b8ba97',
returnValues: Result { '0': '3', value: '3' },
event: 'Increment',
signature: '0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81',
raw: {
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
]
}
}
{
removed: false,
logIndex: 353,
transactionIndex: 189,
transactionHash: '0xdc7dfda876800b365e70374b8f8f9f39d8603bebe89f961109f65229b93524d6',
blockHash: '0x9e8d04cff3f2236eed7bf662036657963cf7475b0e350f77a396e89a4935de2c',
blockNumber: 7947790,
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
id: 'log_7432a4a4',
returnValues: Result { '0': '3', value: '3' },
event: 'Increment',
signature: '0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81',
raw: {
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
]
}
}
{
removed: false,
logIndex: 343,
transactionIndex: 181,
transactionHash: '0x4956140582e6e0d62885e0646ad0642b6ae060fd4658d0374cd555799fa3a843',
blockHash: '0x9ec619f890cdd8e0ab6a3e0bae4846351f81f6b81125fddd444c8e7a2598d970',
blockNumber: 7947792,
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
id: 'log_a193869e',
returnValues: Result { '0': '3', value: '3' },
event: 'Increment',
signature: '0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81',
raw: {
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
]
}
}
{
removed: false,
logIndex: 248,
transactionIndex: 169,
transactionHash: '0x35163a22db0cffeeab3e2c4f6ca6f6a3f5e622982514ea98a6f99b3abc0e5d74',
blockHash: '0xd8967836b9d85763611be4489042896b149b45b82f3404d530ad60a2cb8ca378',
blockNumber: 7947793,
address: '0xadD95f6bD6A0Fbd1423Bde9272dB999946A09369',
id: 'log_97159c2a',
returnValues: Result { '0': '3', value: '3' },
event: 'Increment',
signature: '0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81',
raw: {
data: '0x0000000000000000000000000000000000000000000000000000000000000003',
topics: [
'0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81'
]
}
}
============================ 7. Check the transaction error
Error: Transaction has been reverted by the EVM:
{
"blockHash": "0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f",
"blockNumber": 7947794,
"contractAddress": null,
"cumulativeGasUsed": 20244362,
"effectiveGasPrice": 7643386,
"from": "0x953baac08cad29a4e354f0833c404ed528775b68",
"gasUsed": 21875,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0xadd95f6bd6a0fbd1423bde9272db999946a09369",
"transactionHash": "0x655d2b7ce84608cec8bbc09b6092bf1aa1cf9199496152e953517e51775be7ca",
"transactionIndex": 143,
"type": "0x0"
}
at Object.TransactionError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:90:21)
at Object.TransactionRevertedWithoutReasonError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:101:21)
at C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-method\lib\index.js:396:57
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
receipt: {
blockHash: '0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f',
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
============================ 7. Check the transaction error
Error: Transaction has been reverted by the EVM:
{
"blockHash": "0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f",
"blockNumber": 7947794,
"contractAddress": null,
"cumulativeGasUsed": 20244362,
"effectiveGasPrice": 7643386,
"from": "0x953baac08cad29a4e354f0833c404ed528775b68",
"gasUsed": 21875,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0xadd95f6bd6a0fbd1423bde9272db999946a09369",
"transactionHash": "0x655d2b7ce84608cec8bbc09b6092bf1aa1cf9199496152e953517e51775be7ca",
"transactionIndex": 143,
"type": "0x0"
}
at Object.TransactionError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:90:21)
at Object.TransactionRevertedWithoutReasonError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:101:21)
at C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-method\lib\index.js:396:57
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
receipt: {
blockHash: '0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f',
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
"from": "0x953baac08cad29a4e354f0833c404ed528775b68",
"gasUsed": 21875,
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": false,
"to": "0xadd95f6bd6a0fbd1423bde9272db999946a09369",
"transactionHash": "0x655d2b7ce84608cec8bbc09b6092bf1aa1cf9199496152e953517e51775be7ca",
"transactionIndex": 143,
"type": "0x0"
}
at Object.TransactionError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:90:21)
at Object.TransactionRevertedWithoutReasonError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:101:21)
at C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-method\lib\index.js:396:57
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
receipt: {
blockHash: '0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f',
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
"type": "0x0"
}
at Object.TransactionError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:90:21)
at Object.TransactionRevertedWithoutReasonError (C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-helpers\lib\errors.js:101:21)
at C:\Users\26643\Downloads\Dapp-Learning-main\Dapp-Learning-main\basic\02-web3js-transaction\node_modules\web3-core-method\lib\index.js:396:57
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
receipt: {
blockHash: '0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f',
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
receipt: {
blockHash: '0x676c1930d40386e4011ae277099d0b0113fc9cddaff445c1ea529445f1a15d5f',
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
blockNumber: 7947794,
contractAddress: null,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
cumulativeGasUsed: 20244362,
effectiveGasPrice: 7643386,
effectiveGasPrice: 7643386,
from: '0x953baac08cad29a4e354f0833c404ed528775b68',
gasUsed: 21875,
logs: [],
logs: [],
logsBloom: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
00',
status: false,
status: false,
to: '0xadd95f6bd6a0fbd1423bde9272db999946a09369',
transactionHash: '0x655d2b7ce84608cec8bbc09b6092bf1aa1cf9199496152e953517e51775be7ca',
transactionIndex: 143,
type: '0x0'
}
}