How to get tokens transferred in transaction details using web3 js? - javascript

I am using web3js to get transaction details
my code:
const transactionHash = this._req.query.transactionHash;
const transaction = await this._web3.eth.getTransactionReceipt(transactionHash);
const logs = await transaction.logs;
const log = await logs.find(i => i.transactionHash === transactionHash);
const topics = await log.topics;
const test = await this._web3.eth.abi.decodeParameter('bytes32', topics[0]);
const from = await this._web3.eth.abi.decodeParameter('address', topics[1]);
const to = await this._web3.eth.abi.decodeParameter('address', topics[2]);
const value = await this._web3.eth.abi.decodeParameter('uint256', log.data);
const amount = await this._web3.utils.fromWei(value);
But I still haven't got the token name of the transaction
Give me some suggestions, thanks

To get the token symbol, you need to call the token contract's function symbol().
Since the Transfer event was emitted by the token contract, you have its address in the log.address property. Then you just need to call the symbol() function:
const abiJson = [
{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}
];
const contract = new web3.eth.Contract(abiJson, log.address);
const symbol = await contract.methods.symbol().call();

Related

GunDB SEA let other user write to user space

I need to exchange private data in user space.
because gun.grant and gun.trust is deprecated, I followed this example:
https://gun.eco/docs/SEA#quickstart
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script>
// var Gun = require('gun'); // in NodeJS
// require('gun/sea');
var SEA = Gun.SEA;
;(async () => {
var pair = await SEA.pair();
var enc = await SEA.encrypt('hello self', pair);
var data = await SEA.sign(enc, pair);
console.log(data);
var msg = await SEA.verify(data, pair.pub);
var dec = await SEA.decrypt(msg, pair);
var proof = await SEA.work(dec, pair);
var check = await SEA.work('hello self', pair);
console.log(dec);
console.log(proof === check);
// now let's share private data with someone:
var alice = await SEA.pair();
var bob = await SEA.pair();
var enc = await SEA.encrypt('shared secret', await SEA.secret(bob.epub, alice));
await SEA.decrypt(enc, await SEA.secret(alice.epub, bob));
// `.secret` is Elliptic-curve Diffie–Hellman
// Bob allows Alice to write to part of his graph, he creates a certificate for Alice
var certificate = await SEA.certify(alice.pub, ["^AliceOnly.*"], bob)
// Alice logs in
const gun = Gun();
await gun.user().auth(alice);
// and uses the certificate
await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').put(enc, null, {opt: {cert: certificate}})
await gun.get('~'+bob.pub).get('AliceOnly').get('do-not-tell-anyone').once(console.log) // return 'enc'
})();
</script>
but it always throws "Certificate verification fail."
I tried user.auth instead of SEA.pair() but still not working
SEA.certify will replace the deprecated methods to enable others to write on your graph. SEA.certify
var Alice = await SEA.pair()
var Bob = await SEA.pair()
var Dave = await SEA.pair()
// Alice wants to allow Bob and Dave to use write to her "inbox" and "stories" UNTIL TOMORROW
// On Alice's side:
var certificate = await SEA.certify([Bob.pub, Dave.pub], [{"*": "inbox", "+": "*"}, {"*": "stories"}], Alice, null, {expiry: Gun.state()+(60*60*24*1000)})
// Now on Bob/Dave's side, they can write to Alice's graph using gun.put:
gun.get('~'+Alice.pub).get('inbox').get('deeper'+Bob.pub).put('hello world', null, {opt: {cert: certificate}}) // {opt: {cert: certificate}} is how you use Certificate in gun.put
On a related note, there are some other very useful encryption examples here.
For the sake of this answer I will post them:
1-to-1 encryption
///////////////////////////////////
// On my side - logged in as myself
///////////////////////////////////
var myPair = gun.user()._.sea;
// retrieve bob's user
const bob = gun.user(bobPublicKey);
// generate encryption secret using bob's epub and my pair
// this means only bob will be able to regenerate this secret with my pub key and his pair
const secret = await SEA.secret(bob.epub, myPair)
// encrypt the data using the secret
const encryptedData = await SEA.encrypt('private message for bob', secret);
////////////////////////////////////
// on Bob's side - logged in as Bob
///////////////////////////////////
const myPair = gun.user()._.sea;
// generate the secret - this will output the same secret generated by myself
// but this time we generate with bobs pair and my epub
const secret = await SEA.secret(myPair.epub, bob)
// just decrypt the data using the secret
const decryptedData = await SEA.decrypt(encryptedData, secret);
Multiple users encryption
(async () => {
/////////////////////////////////////////////////////////////////
// Instead of logging in with actual users, we are
// going to generate SEA pairs which is basically the same thing
/////////////////////////////////////////////////////////////////
// User 1 encrypts one message
const user1 = await SEA.pair();
const plainMessage = 'Hello, how are you?';
const encryptionKey = 'this is my encryption key which is a normal string';
const encryptedMessage = await SEA.encrypt(plainMessage, encryptionKey);
// User 2, 3 and 4 will receive the message and decrypt it
const user2 = await SEA.pair();
const user3 = await SEA.pair();
const user4 = await SEA.pair();
// Each user gets an encrypted encryption key. If you print them, they all different
const encryptedEncryptionKeyUser2 = await SEA.encrypt(encryptionKey, await SEA.secret(user2.epub, user1));
const encryptedEncryptionKeyUser3 = await SEA.encrypt(encryptionKey, await SEA.secret(user3.epub, user1));
const encryptedEncryptionKeyUser4 = await SEA.encrypt(encryptionKey, await SEA.secret(user4.epub, user1));
// Each user decrypts his own encrypted encryption key
// These three decrypted encryptions keys that we get are all the same
const decryptedEncryptionKeyUser2 = await SEA.decrypt(
encryptedEncryptionKeyUser2,
await SEA.secret(user1.epub, user2)
);
const decryptedEncryptionKeyUser3 = await SEA.decrypt(
encryptedEncryptionKeyUser3,
await SEA.secret(user1.epub, user3)
);
const decryptedEncryptionKeyUser4 = await SEA.decrypt(
encryptedEncryptionKeyUser4,
await SEA.secret(user1.epub, user4)
);
// Each user decrypts the encrypted message using the decrypted encryption key
const decryptedMessageUser2 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser2);
const decryptedMessageUser3 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser3);
const decryptedMessageUser4 = await SEA.decrypt(encryptedMessage, decryptedEncryptionKeyUser4);
});

.balanceOf is not a function - Interact with existing Contract on Blockchain

I want to automate my staking on The Sandbox. For that I need in the first step to interact with the mSand-Matic Pool Contract. It is this one: https://polygonscan.com/address/0x4ab071c42c28c4858c4bac171f06b13586b20f30#code
I have written a little program in a GitHub repository to show what I have done: https://github.com/ChristianErdtmann/mSandMaticStakingAutomation
Or here is the code example from the contract-interact.js
Web3 = require('web3')
const fs = require('fs');
const web3 = new Web3("https://polygon-rpc.com")
const contractAddress = "0x4AB071C42C28c4858C4BAc171F06b13586b20F30"
const contractJson = fs.readFileSync('./abi.json')
const abi = JSON.parse(contractJson)
const mSandMaticContract = new web3.eth.Contract(abi, contractAddress)
mSandMaticContract.balanceOf('0x7e5475290Df8E66234A541483453B5503551C780')
The ABI I have taken from the contract link on the top. But it seems there is a problem.
I tried for testing to read something from the contract. For that I used the function balanceOf(address), how you can see in the code.
But I always get this error:
TypeError: mSandMaticContract.balanceOf is not a function
I found the solution
web3 needs .methots to get acces to the balanceOf() function
if we want only to read so we need to add .call()
we need to add await before the function is called this needs to be in a asynchonus function
So the final working code is:
Web3 = require('web3')
const fs = require('fs');
const web3 = new Web3("https://polygon-rpc.com")
const contractAddress = "0x4AB071C42C28c4858C4BAc171F06b13586b20F30"
const contractJson = fs.readFileSync('./abi.json')
const abi = JSON.parse(contractJson)
const mSandMaticContract = new web3.eth.Contract(abi, contractAddress)
asyncCall()
async function asyncCall() {
console.log(await mSandMaticContract.methods.balanceOf('0x7e5475290Df8E66234A541483453B5503551C780').call())
}
If you dont want only to read you need addtional to sign the transaction with:
The solution is, to sign the transaction before sending we can doing this with any method by this code:
encoded = mSandMaticContract.methods.getReward().encodeABI()
var block = await web3.eth.getBlock("latest");
var gasLimit = Math.round(block.gasLimit / block.transactions.length);
var tx = {
gas: gasLimit,
to: publicKey,
data: encoded
}
web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
web3.eth.sendSignedTransaction(signed.rawTransaction).on('receipt', console.log)
})

get data from another add-on on Excel javascript api

I saved data on workbook on following code
export const storeSettingsToWorkbook = async (settingsType: Settings, storeData:
WorkbookModel) => {
return Excel.run(async (context) => {
const originalXml = createXmlObject(storeData);
const customXmlPart = context.workbook.customXmlParts.add(originalXml);
customXmlPart.load("id");
await context.sync();
// Store the XML part's ID in a setting
const settings = context.workbook.settings;
settings.add(settingsTitles[settingsType], customXmlPart.id);
await context.sync();
})
}
when i get data -it works normally.But when i want to get this data form another "add-in" on Excel- I cannot get this data
const {settings} = context.workbook;
const sheet = context.workbook.worksheets.getActiveWorksheet().load("items");
const xmlPartIDSetting = settings.getItemOrNullObject(settingsTitles[settingsType]).load("value");
await context.sync();
if (xmlPartIDSetting.value) {
const customXmlPart = context.workbook.customXmlParts.getItem(xmlPartIDSetting.value);
const xmlBlob = customXmlPart.getXml();
await context.sync()
const parsedObject = parseFromXmlString(xmlBlob.value);
const normalizedData = normalizeParsedData(parsedObject);
Any ideas?
Thanks for reaching us.
This is by design. Each addin has its own setting and cannot share with each other.
You can use 'context.workbook.properties.custom' as a workaround.
You can also use 'context.workbook.worksheets.getActiveWorksheet().customProperties', but the two add-ins are required to be on the same worksheet.

I am trying to execute a swap on Pancakeswap using web3, but I get an error when calculating transaction cost

I am new at ethereum development and I am working on a simple script to execute swaps using Pancakeswap. Everything seems to be working well up to the point where I am building my transaction and calculate the tx-cost. I am using the UniswapRouterV02 abi create my Pancakeswap contract. The code:
const init = async () => {
const [WBNB, BUSD] = await Promise.all(
[addresses.WBNB, addresses.BUSD].map(tokenAddress => (
new Token(
ChainId.MAINNET,
tokenAddress,
18
)
)));
const pair = await Fetcher.fetchPairData(WBNB, BUSD, provider)
const route = await new Route([pair], WBNB)
const trade = await new Trade(route, new TokenAmount(WBNB, tradeAmount), TradeType.EXACT_INPUT)
const executionPrice = trade.executionPrice.toSignificant(12)
// Correct prices; everything seems correct up until here
const slippageTolerance = new Percent('50', '10000')
const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw
const path = [WBNB.address, BUSD.address]
const to = MY_ADDRESS
const deadline = Math.floor(Date.now() / 1000) + 60 * 20
const value = trade.inputAmount.raw
// Correct prices everything seems correct up until here
const pancakeSwap = new web3.eth.Contract(
abis.uniswapRouter.abi,
addresses.PANCAKE_ROUTER //'0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F'
);
let tx = pancakeSwap.methods.swapExactTokensForTokens(
tradeAmount,
web3.utils.toBN(amountOutMin.toString()),
path,
to,
deadline
)
const [gasPrice, gasCost] = await Promise.all([
web3.eth.getGasPrice(),
tx.estimateGas({from: admin}),
]);
console.log(`gasPrice: ${gasPrice}`)
console.log(`gasCost: ${gasCost}`)
}
init()
The price calculation for the swap returns correct prices. However when I try to calculate the transaction costs the following error is thrown:
Error: Returned error: gas required exceeds allowance (44038122) or always failing transaction
Any help would be greatly appreciated, please let me know if more of my code should be clarified!
In turns out that with web3 it is not possible to interact with the Pancakeswap contract. I found a solution using ethers.js. Following code worked for me to execute a swap on Pancake on mainnet.
Before executing the first transaction Pancakeswap needs to be allowed, this code is commented out.
I had to play around with the gasprice and gasLimit a bit to make it work.
require("dotenv").config()
const ethers = require('ethers')
const {ChainId, Token, TokenAmount, Fetcher, Pair, Route, Trade, TradeType, Percent} =
require('#pancakeswap-libs/sdk');
const Web3 = require('web3');
const web3 = new Web3('wss://apis.ankr.com/wss/c40792ffe3514537be9fb4109b32d257/946dd909d324e5a6caa2b72ba75c5799/binance/full/main');
const {JsonRpcProvider} = require("#ethersproject/providers");
const provider = new JsonRpcProvider('https://bsc-dataseed1.binance.org/');
const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY)
const addresses = {
WBNB: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
BUSD: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
PANCAKE_ROUTER: '0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F'
}
const ONE_ETH_IN_WEI = web3.utils.toBN(web3.utils.toWei('1'))
const tradeAmount = ONE_ETH_IN_WEI.div(web3.utils.toBN('1000'))
const init = async () => {
const [WBNB, BUSD] = await Promise.all(
[addresses.WBNB, addresses.BUSD].map(tokenAddress => (
new Token(
ChainId.MAINNET,
tokenAddress,
18
)
)));
const pair = await Fetcher.fetchPairData(WBNB, BUSD, provider)
const route = await new Route([pair], WBNB)
const trade = await new Trade(route, new TokenAmount(WBNB, tradeAmount), TradeType.EXACT_INPUT)
const slippageTolerance = new Percent('50', '10000')
// create transaction parameters
const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw
const path = [WBNB.address, BUSD.address]
const to = admin
const deadline = Math.floor(Date.now() / 1000) + 60 * 20
// Create signer
const wallet = new ethers.Wallet(
Buffer.from(
process.env.PRIVATE_KEY, // paste your private key from metamask here
"hex"
)
)
const signer = wallet.connect(provider)
// Create Pancakeswap ethers Contract
const pancakeswap = new ethers.Contract(
addresses.PANCAKE_ROUTER,
['function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'],
signer
)
// Allow Pancakeswap
// let abi = ["function approve(address _spender, uint256 _value) public returns (bool success)"]
// let contract = new ethers.Contract(WBNB.address, abi, signer)
// await contract.approve(addresses.PANCAKE_ROUTER, ethers.utils.parseUnits('1000.0', 18), {gasLimit: 100000, gasPrice: 5e9})
// Execute transaction
const tx = await pancakeswap.swapExactTokensForTokens(
ethers.utils.parseUnits('0.001', 18),
ethers.utils.parseUnits(web3.utils.fromWei(amountOutMin.toString()), 18),
path,
to,
deadline,
{ gasLimit: ethers.utils.hexlify(200000), gasPrice: ethers.utils.parseUnits("10", "gwei") }
)
console.log(`Tx-hash: ${tx.hash}`)
const receipt = await tx.wait();
console.log(`Tx was mined in block: ${receipt.blockNumber}`)
}
init()
You can check this working example that buys a token from pancakeswap.finance:
https://github.com/religion-counter/onlyone/blob/main/helper-scripts/buy-onlyone-pancakeswap.js
// Helper script that buys ONLYONE token from a specified address specified on text file SPECIFY_ACCOUNTS_YOU_WANT_TO_BUY_FOR_HERE.json
// The amount is specified with 'originalAmountToBuyWith' variable in the source
// The JSON file should have an array with objects with 'address' field and 'privateKey' field.
// Buys ONLYONE for ${bnbAmount} BNB from pancakeswap for address ${targetAccounts[targetIndex].address}
// targetIndex is passed as an argument: process.argv.splice(2)[0]
var fs = require('fs')
var Tx = require('ethereumjs-tx').Transaction;
var Web3 = require('web3')
var Common = require('ethereumjs-common').default;
var web3 = new Web3(new Web3.providers.HttpProvider('https://bsc-dataseed.binance.org/'))
var BSC_FORK = Common.forCustomChain(
'mainnet',
{
name: 'Binance Smart Chain Mainnet',
networkId: 56,
chainId: 56,
url: 'https://bsc-dataseed.binance.org/'
},
'istanbul',
);
// SPECIFY_THE_AMOUNT_OF_BNB_YOU_WANT_TO_BUY_FOR_HERE
var originalAmountToBuyWith = '0.007' + Math.random().toString().slice(2,7);
var bnbAmount = web3.utils.toWei(originalAmountToBuyWith, 'ether');
var targetAccounts = JSON.parse(fs.readFileSync('SPECIFY_ACCOUNTS_YOU_WANT_TO_BUY_FOR_HERE.json', 'utf-8'));
var targetIndex = Number(process.argv.splice(2)[0]);
var targetAccount = targetAccounts[targetIndex];
console.log(`Buying ONLYONE for ${originalAmountToBuyWith} BNB from pancakeswap for address ${targetAccount.address}`);
var res = buyOnlyone(targetAccounts[targetIndex], bnbAmount);
console.log(res);
async function buyOnlyone(targetAccount, amount) {
var amountToBuyWith = web3.utils.toHex(amount);
var privateKey = Buffer.from(targetAccount.privateKey.slice(2), 'hex') ;
var abiArray = JSON.parse(JSON.parse(fs.readFileSync('onlyone-abi.json','utf-8')));
var tokenAddress = '0xb899db682e6d6164d885ff67c1e676141deaaa40'; // ONLYONE contract address
var WBNBAddress = '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c'; // WBNB token address
// var onlyOneWbnbCakePairAddress = '0xd22fa770dad9520924217b51bf7433c4a26067c2';
// var pairAbi = JSON.parse(fs.readFileSync('cake-pair-onlyone-bnb-abi.json', 'utf-8'));
// var pairContract = new web3.eth.Contract(pairAbi, onlyOneWbnbCakePairAddress/*, {from: targetAccount.address}*/);
var amountOutMin = '100' + Math.random().toString().slice(2,6);
var pancakeSwapRouterAddress = '0x10ed43c718714eb63d5aa57b78b54704e256024e';
var routerAbi = JSON.parse(fs.readFileSync('pancake-router-abi.json', 'utf-8'));
var contract = new web3.eth.Contract(routerAbi, pancakeSwapRouterAddress, {from: targetAccount.address});
var data = contract.methods.swapExactETHForTokens(
web3.utils.toHex(amountOutMin),
[WBNBAddress,
tokenAddress],
targetAccount.address,
web3.utils.toHex(Math.round(Date.now()/1000)+60*20),
);
var count = await web3.eth.getTransactionCount(targetAccount.address);
var rawTransaction = {
"from":targetAccount.address,
"gasPrice":web3.utils.toHex(5000000000),
"gasLimit":web3.utils.toHex(290000),
"to":pancakeSwapRouterAddress,
"value":web3.utils.toHex(amountToBuyWith),
"data":data.encodeABI(),
"nonce":web3.utils.toHex(count)
};
var transaction = new Tx(rawTransaction, { 'common': BSC_FORK });
transaction.sign(privateKey);
var result = await web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex'));
console.log(result)
return result;
}
You can also contribute to the repository if you are interested.
I am a total beginner but have the same goal as you. I'm trying to get your code to work.
I used the following Code to create the signer. I used my 'mnemonic' instead of the private key:
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
I noticed that pancake uses the swapExactETHForTokens() function instead of swapExactTokensForTokens() for the transactions. Does that make any difference?
I am not quite sure whether the Output and Input Amount is calculated correctly... I don't quite understand it yet, but will try to go through it as soon as possible.
jklepatch has written a code which contains trading via pancakeswap V2. However, the trade does not work if i execute the code because the AmountOut generats an error (codeline 78)...
In the meantime, have you been able to modify your code or make it work? If it is helpful I can also post my version of your code here.

How upload images to two different path/places in firebase?

how to store a uploaded image to two different path/places in firebase Storage? I tried this but it isn't working
const { currentUser } = firebase.auth();
const ref = firebase.storage().ref().child(`images/${currentUser.uid}`);
const ref = firebase.storage().ref().child('photos')
const snapshot = await ref.put(blob);
blob.close();
Okay so first, you can't re-declare variables like that (const ref = ...; then const ref = ....; right below it). Second, you need to perform put on each ref. So should look something like this:
const { currentUser } = firebase.auth();
const ref1 = firebase.storage().ref().child(`images/${currentUser.uid}`);
const ref2 = firebase.storage().ref().child('photos')
const snapshot1 = await ref1.put(blob);
const snapshot2 = await ref2.put(blob);
blob.close();
Or if you want to have a little more optimized code:
const { currentUser } = firebase.auth();
const ref = firebase.storage().ref();
const imagesUpload = await ref.child(`images/${currentUser.uid}`).put(blob);
const photosUpload = await ref.child('photos').put(blob);
blob.close();
If you want to be more advanced with this and have only a single upload task, read more here: https://cloud.google.com/storage/docs/json_api/v1/how-tos/batch

Categories