How to listen for smartcontract events and filter by receiver with Tron - blockchain

I'm trying to listen a specific event in USDT smartcontract on Tron blockchain. I want to update a database when a payment has been made to my address.
In order to do that, I use TronWeb. Here is my code :
const fullNode = 'https://api.shasta.trongrid.io';
const solidityNode = 'https://api.shasta.trongrid.io';
const eventServer = 'https://api.shasta.trongrid.io';
const tronweb = new Tronweb(fullNode,solidityNode,eventServer);
let contract = await tronweb.contract().at('TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs')
let watchTest = await contract.Transfer().watch({filters{"to":"TGdMonBPqH9THEhgNxMtHEcnxgbXxUuXeX"}},(err, res) => {
if(res) {
console.log(res)
}
})
However, this code is printing every event emmited by the smart contract (not only the transfer to my address).
I'm looking for an equivalent of the following code with ethereum blokchain and ethers.js librairy :
let contract = new ethers.Contract(contractAddress, abi, provider);
let filter=contract.filters.Transfer(null, payment.PublicAddress);
provider.on(filter,async (log) => {})
What's the correct way to do that ?

Related

How can I create a associated token address in solana from connected wallet address?

I want to create an associated token address in Solana from a connected wallet address. This is my code currently:
import { useWallet, useConnection } from "#solana/wallet-adapter-react";
...
const wallet = useWallet();
const { publicKey, sendTransaction } = wallet;
const associatedAccount = await getAssociatedTokenAddress(
mintPubkey,
wallet.publicKey
);
const transaction = new Transaction().add(
createAssociatedTokenAccountInstruction(
wallet.publicKey,
associatedAccount,
wallet.publicKey,
mintPubkey,
TOKEN_2022_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
)
);
signature = await sendTransaction(transaction, connection, {
skipPreflight: true,
});
await connection.confirmTransaction(signature, "confirmed");
...
But the tx is keep failing like this:
https://solscan.io/tx/ZaQtfVkNkkAweGug2JfDYz8hcFXh4jDUEJoz2Lik6jPv8huFgzpMXMwui51VJsk8yHmpcWUD6UgnqdmRhu4Covh?cluster=devnet
How can I achieve this?
Because you use Token-2022, you need to specify it when generating the associatedAccount address. Otherwise it uses the default Token Program.
Documentation: getAssociatedTokenAddress()
const associatedAccount = await getAssociatedTokenAddress(
mintPubkey,
wallet.publicKey,
false,
TOKEN_2022_PROGRAM_ID,
);

Owner of smart contract on hardhat development network is being returned 0x00000

I was trying to deploy my smart contract through unit testing using hardhat. The owner upon deployment is being returned as 0x0000.. although when writing my js script i assign a certain address from the hardhat network as the owner.
const hre = require('hardhat')
const { expect, assert } = require('chai')
describe('ProperSubsetFund', async function () {
// Initialize Contract Var
let deployERC20, deployer, user1, user2, trader1, trader2
let signers
beforeEach(async function () {
// Getting all the signers
signers = await hre.ethers.getSigners()
// console.log(signers.map(item => item.address));
// Assign addresses to roles for later use
deployer = signers[0].address
user1 = signers[1].address
user2 = signers[2].address
trader1 = signers[3].address
trader2 = signers[4].address
// Read Contract ERC20
const contractERC20 = await hre.ethers.getContractFactory('ProperSubsetERC20')
// Read Contract Launchpad
const contractLaunchpad = await hre.ethers.getContractFactory('ProperSubsetFactory')
// Read Contract Funds
const contractFunds = await hre.ethers.getContractFactory('ProperSubsetFund')
// Deploy the three contracts
deployERC20 = await contractERC20.connect(signers[0]).deploy(true)
});
describe('Deployment and Ownership', function () {
it('Check if the owner is the deployer', async function () {
expect(await deployERC20.owner()).to.equal(deployer)
});
});
})
These are the results
ProperSubsetFund
Deployment and Ownership
Deployment
Should set the right owner:
AssertionError: expected '0x00000000000000000000000000000000000…' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'
+ expected - actual
-0x0000000000000000000000000000000000000000
+0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
at Context.<anonymous> (test/ProperSubsetFund.test.js:71:49)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Hardhat is not returning address(0), your contract owner() is returning address(0). If you read the terminal it says
AssertionError: expected '0x00000000000000000000000000000000000…' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'
since you set this:
expect(await deployERC20.owner()).to.equal(deployer)
your deployer address by hardhat is '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'. But deployERC20.owner() is '0x00000000000000000000000000000000000…'

how likely is it to miss a solidity event?

Hi i am making a finance application that depends on Events from blockchain,
Basically i update my database based on Events i receive using web3js, and when user asks i sign with private key for the contract to be able to give user Money.
My only concern is can i depend on events? like can there be a case where i miss events?
here is my code for doing so :
const contract = new web3.eth.Contract(abi, contract_address)
const stale_keccak256 = "0x507ac39eb33610191cd8fd54286e91c5cc464c262861643be3978f5a9f18ab02";
const unStake_keccak256 = "0x4ac743692c9ced0a3f0052fb9917c0856b6b12671016afe41b649643a89b1ad5";
const getReward_keccak256 = "0x25c30c62c42b51e4f667b70ef60f1f683c376f6ace28312ed45a40665e01af37";
let userRepository: Repository<UserData> = connection.getRepository(UserData);
let globalRepository: Repository<GlobalStakingInfo> = connection.getRepository(GlobalStakingInfo);
let userStakingRepository: Repository<UserStakingInfo> = connection.getRepository(UserStakingInfo);
let transactionRepository: Repository<Transaction> = connection.getRepository(Transaction);
const topics = []
web3.eth.subscribe('logs', {
address: contract_address, topics: topics
},
function (error: Error, result: Log) {
if (error) console.log(error)
}).on("data", async function (log: Log) {
let response: Boolean = false;
try {
response = await SaveTransaction(rpc_url, log.address, log.transactionHash, transactionRepository)
} catch (e) {
}
if (response) {
try {
let global_instance: GlobalStakingInfo | null = await globalRepository.findOne({where: {id: 1}})
if (!global_instance) {
global_instance = new GlobalStakingInfo()
global_instance.id = 1;
global_instance = await globalRepository.save(global_instance);
}
if (log.topics[0] === stale_keccak256) {
await onStake(web3, log, contract, userRepository, globalRepository, userStakingRepository, global_instance);
} else if (log.topics[0] === unStake_keccak256) {
await onUnStake(web3, log, contract, userStakingRepository, userRepository, globalRepository, global_instance)
} else if (log.topics[0] === getReward_keccak256) {
await onGetReward(web3, log, userRepository)
}
} catch (e) {
console.log("I MADE A BOBO", e)
}
}
}
)
The Code works and everything, i am just concerned if i could maybe miss a event? cause finance is related and people will lose money if missing event is a thing.
Please advise
You can increase redundancy by adding more instances of the listener connected to other nodes.
And also by polling past logs - again recommended to use a separate node.
Having multiple instances doing practically the same thing will result in multiplication of incoming data, so don't forget to store only unique logs. This might be a bit tricky, because theoretically one transaction ID can produce the same log twice (e.g. through a multicall), so the unique key could be a combination of a transaction ID as well as the log index (unique per block).

Change sender account is when sending coins?

I have deployed an (openzeppelin's) ERC20 smart contract using truffle on my Ganache development network.
When contract is deployed, the first address (on the development ganache network) receives the amount of tokens specified by me below (in this case 20):
// 2_deploy_contracts.js
var GLDToken = artifacts.require("GLDToken");
module.exports = function(deployer) {
deployer.deploy(GLDToken, 20);
}
As per Openzeppelin docs I have made a function to make transfers which works perfectly, see below the full code:
// app.js
var GLDToken = artifacts.require("GLDToken");
var contractAddress = '0x3cAd6d5f5acFcCBAaC516Df696c65C2AAA2D1F82';
var testWallet1 = '0x35a356879a4573dE4CeD9D36ff76bBbA98afA2dA';
var testWallet2 = '0x8AB027e8439169Aa68514299c8bDa29C8A98483a';
var testWallet3 = '0xA384974dd53A21d10E3671FE23aB45E0CA0CDDf8';
module.exports = function() {
async function sendTransfer(recipient, amount) {
let ins = await GLDToken.at(contractAddress);
let res = await ins.transfer(recipient, amount);
console.log(res.toString());
}
sendTransfer(testWallet2, 5);
}
However I'm unable to specify a sender address and it defaults to the first wallet on my Ganache network, this means I'm able to make transfers from testWallet1 to testWallet2 and testWallet1 to testWallet3 but not from testWallet2 to testWallet3.
The transfer function of the smart contract is the one below and as you can see uses _msgSender():
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
How can I change this?
As you are not using from in the config, the contract would take the default account to do things.
You may set the default account as you want
web3.eth.defaultAccount = testWallet2;

Call constructor and deploy with web3 and ropsten

I have created a test contract which has been compiled successfully and want to broadcast on ropsten test network using web3js. I have a metmask account which i am using. I would like to know how can i call constructor of my contract and then broadcast on ropsten.
I did broadcast one of my contract without constructor and do have my transaction hash key which is 0xf7e5a8e93db9989b033b85323cdff713ba88b547ef64a544550e145961999aac but i am getting a following error Error encountered during contract execution [Reverted] and Transaction has been reverted by the EVM on console. I would like to know also why i am getting this error after broadcast has been done
const fs = require('fs')
var Tx = require('ethereumjs-tx').Transaction
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/v3/KEY')
deploy()
function deploy () {
const privateKey = 'PRIVATE_KEY'
const account1 = 'ACCOUNT_NUMBER'
const privateKey1 = Buffer.from(privateKey, 'hex')
const contractData = fs.readFileSync('../../build/contracts/Testcontract.json')
const contract = JSON.parse(contractData)
const byteCode = contract['bytecode']
web3.eth.getTransactionCount(account1, (err, txCount) => {
const txObject = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(100000),
gasPrice: web3.utils.toHex(web3.utils.toWei('0.004', 'gwei')),
data: byteCode
}
let tx = new Tx(txObject, {'chain':'ropsten'})
tx.sign(privateKey1)
const serializedTx = tx.serialize()
const raw = '0x' + serializedTx.toString('hex')
web3.eth.sendSignedTransaction(raw, (err, txHash) => {
console.log('err: ', err, 'txHash: ', txHash)
})
})
}
My contract with constructor looks like this
pragma solidity ^0.5.11;
contract Testcontract {
string public senderName;
string public receiverName;
uint public transferAmount;
constructor (string memory _sender, string memory _receiver, uint _amount) public {
senderName = _sender;
receiverName = _receiver;
transferAmount = _amount;
}
}
UPDATE
A simple way to deploy a contract through an Infura node is using Truffle. In your project's root directory
$ npm install truffle
$ truffle init
Here is a tutorial on how to configure Truffle to use your Infura project. In short, install Truffle's hd-wallet-provider
$ npm install #truffle/hdwallet-provider
Replace truffle-config.js with
const HDWalletProvider = require("#truffle/hdwallet-provider");
const mnemonic = "orange apple banana...";
module.exports = {
networks: {
ropsten: {
provider: () => new HDWalletProvider(mnemonic, 'https://ropsten.infura.io/v3/<YOUR INFURA PROJECT ID>'),
network_id: 3, // Ropsten's id
},
},
compilers: {
solc: {
version: "0.5.11", // Fetch exact version from solc-bin (default: truffle's version)
}
}
}
The previous code configures Truffle to connect to Infura an use your account. In ./migrations directory (created by truffle init) create a new file 2_deploy_testContrac.js where you can define how to deploy your contract and provide the arguments needed by TestContract.
var TestContract = artifacts.require("./TestContract");
module.exports = function(deployer) {
deployer.deploy(TestContract, "AliceSender", "BobSender", 120);
}
Finally, deploy your contract by executing
$ truffle migrate --network ropsten
The reason why your transaction has been reverted is because the constructor of TestContract expected three arguments but you have given zero. Since the constructor couldn't be executed, your deploying transaction was reverted as well.
Instead of manually creating your deploying transaction, you can use web3.eth.Contract.deploy. With this method you can conveniently provide all parameters required by the contract's constructor.
UPDATE: The solution below won't work with Infura because the Infura API does not expose web3.eth.personal functions and it only allows sending rawTranscations.
You should be able to deploy your contract with the following code. Note that it was mainly copy-pasted from the official web3 documentation.
var contractData = fs.readFileSync('../../build/contracts/Testcontract.json');
var contract = JSON.parse(contractData);
var abi = contract['abi'];
var bytecode = contract['bytecode'];
var testContract = eth3.eth.Contract(abi);
var account = ...;
var password = ...;
web3.eth.personal.unlockAccount(account, password);
testContract.deploy({
data: bytecode,
arguments: ['SenderAlice', 'ReceiverBob', 120]
})
.send({
from: account,
gas: 1500000,
gasPrice: '30000000000000'
}, function(error, transactionHash){
console.log(error, transactionHash);
})
.on('error', function(error){
console.log(error);
})
.on('transactionHash', function(transactionHash){
console.log(transactionHash);
})
.on('receipt', function(receipt){
console.log(receipt.contractAddress) // contains the new contract address
})
.on('confirmation', function(confirmationNumber, receipt){
console.log(confirmationNumber, transactionHash);
})
.then(function(newContractInstance){
console.log(newContractInstance.options.address) // instance with the new contract address
});