I want to build a gateway for usdt payments and for this i'm using Tronweb tronWeb.utils.accounts.generateAccount() method
I have generated an address, transfered 1 usdt to it and now i want to transfer the funds to another address.
I get an error when sending the transaction:
error: 'CONTRACT_VALIDATE_ERROR',
message: 'contract validate error : account does not exist'
This is my code:
const TronWeb = require('tronweb');
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider("https://api.trongrid.io");
const solidityNode = new HttpProvider("https://api.trongrid.io");
const eventServer = new HttpProvider("https://api.trongrid.io");
const privateKey = "c83f36ae2e8661170e798ca73181693b76d75af016666e6f6baad92f69cfa1e2";
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer, privateKey);
const trc20ContractAddress = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";//contract address
const addressTo = "TYcDSZor5ZgTsVMCZe1czfPEu8kzn6qe7L";
async function transfer() {
try {
const ownerAddress = tronWeb.address.fromPrivateKey(privateKey);
const contractAddressHex = tronWeb.address.toHex(trc20ContractAddress);
const contractInstance = await tronWeb.contract().at(contractAddressHex);
const decimals = await contractInstance.decimals().call();
const amount = 7 * Math.pow(10, decimals);
const response = await contractInstance.transfer(addressTo, amount).send();
console.log(response);
} catch (e) {
console.error(e);
return null;`enter code here`
}
}
transfer();
Is it something else i should do for getting this to work?
After generating new account, you need to activate it by transferring TRX/TRC-10 token to the address.
Transferring TRC20 will not activate an account. However, the balance can be inquired from Tronscan by the address.
TRON Account Documentation
Related
I am building a crypto wallet app on the ethereum chain and have set it up so that I can send transactions. Next I would like to be able to speed up transactions and understand how this is done. As far as I know you send another transaction with the same nonce but more gas. To sped up a transaction where I am sending ETH this is straightforward.
Here is the original function to send the transaction:
export const sendTransaction = async (currentWallet, toAddress, value) => {
// // Create Provider
const url = "https://eth-mainnet.g.alchemy.com/v2/" + ALCHEMY_API_KEY;
const customHttpProvider = await new ethers.providers.JsonRpcProvider(url);
// // Create wallet and connect to provider
const wallet = await new Wallet(currentWallet.pk, customHttpProvider);
const currentChainId = await getChainId();
const feeData = await customHttpProvider.getFeeData();
let gasPrice = feeData.maxFeePerGas;
const transaction = {
to: toAddress,
value: Utils.parseEther(value),
gasLimit: "21000",
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
maxFeePerGas: feeData.maxFeePerGas,
nonce: await alchemy.core.getTransactionCount(currentWallet.walletInstance.address),
type: 2,
chainId: currentChainId
// chainId: 5
}
const rawTransaction = await wallet.signTransaction(transaction);
try {
const sentTransaction = await alchemy.core.sendTransaction(rawTransaction);
return sentTransaction;
} catch (err) {
return null;
}
}
and then to speed this up I would run the same function but replace the gas and set the same nonce.
However, with erc20 tokens my function to transfer the amount specified like so:
export const sendErc20Transaction = async (token, currentWallet, toAddress, value) => {
try {
// Create Provider
const url = "https://eth-mainnet.g.alchemy.com/v2/" + ALCHEMY_API_KEY;
const customHttpProvider = await new ethers.providers.JsonRpcProvider(url);
// Create wallet and connect to provider
const wallet = await new Wallet(currentWallet.pk, customHttpProvider);
// Dynamically get ABI
const abi = await getTokenABI(token, 'erc20');
// Create Smart Contract
const currentContract = new Contract(token.contractAddress, abi, wallet);
// // Send Transaction
const transaction = await currentContract.transfer(toAddress, Utils.parseUnits(value));
return transaction;
} catch (err) {
return null;
}
}
I don't see anywhere within this function where I can specify the gas or the nonce.
How would I resend this same transaction, still sending the same token, with higher gas and the same nonce?
I am able to set variables during my unit tests on the local Hardhat Node, however the same test fails on Goerli.
This is the code for my test:
const { getNamedAccounts, deployments, ethers, network } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
const { assert, expect } = require("chai")
const fs = require("fs")
const path = require("path")
developmentChains.includes(network.name)
? describe.skip
: describe("Whoopy Staging Tests", function () {
let whoopy,
deployer,
player,
cloneAddress,
clonedContract,
txReceipt,
tx,
accountConnectedClone,
manager,
create
const chainId = network.config.chainId
beforeEach(async function () {
accounts = await ethers.getSigners()
deployer = accounts[0]
player = accounts[1]
await deployments.fixture(["all"])
const dir = path.resolve(
__dirname,
"/Users/boss/hardhat-smartcontract-whoopy/artifacts/contracts/Whoopy.sol/Whoopy.json"
)
const file = fs.readFileSync(dir, "utf8")
const json = JSON.parse(file)
const abi = json.abi
whoopy = await ethers.getContract("Whoopy", deployer)
manager = await ethers.getContract("VRFv2SubscriptionManager", deployer)
wf = await ethers.getContract("WhoopyFactory", deployer)
tx = await (await wf.connect(player).createClone(player.address))
txReceipt = await tx.wait(1)
cloneAddress = await txReceipt.events[1].args._instance
clonedContract = new ethers.Contract(cloneAddress, abi, player)
accountConnectedClone = clonedContract.connect(player)
})
describe("Whoopy Tests", function () {
beforeEach(async function () {
create = await accountConnectedClone.createWhoopy(
"Test",
1,
{
value: ethers.utils.parseUnits("10000000000000000", "wei"),
gasLimit: 3000000
})
console.log(create)
})
it("creates Whoopy correctly", async function () {
const whoopyName = await accountConnectedClone.getWhoopyName()
const num = await accountConnectedClone.getNum()
expect(whoopyName).to.equal("Test")
expect(num).to.equal(1)
})
})
Here is the function I am testing:
function createWhoopy( //to be created only once
string memory s_whoopyName,
uint256 s_num,
) public payable restricted {
whoopyName = s_whoopyName;
num = s_num;
}
Seems pretty straight forward but don't know why it's not working. My accounts have enough test eth and goerli is correctly set up in Hardhat config. The test reverts as follows:
AssertionError: expected '' to equal 'Test'
+ expected - actual
+Test
Any guidance would be appreciated! Thanks!
I figured it out. It was something stupid (as I thought it would be). I forgot to put await create.wait(6) which was needed to wait for the blocks to mine the transaction.
It went through on Hardhat because Hardhat mines blocks immediately, but since Goerli is a live Testnet you need to wait for the transaction to be mined.
i have private key and this is how i access account (Binance Smart Chain network):
const web3 = new Web3('https://bsc-dataseed1.binance.org:443')
const account = await web3.eth.accounts.privateKeyToAccount(pk)
So, i have account object,
{ address: '0x...', privateKey: '0x...', signTransaction: [Function: signTransaction], sign: [Function: sign], encrypt: [Function: encrypt] }
I want to send() method on BEP-20 token address:
const contract = new web3.eth.Contract(ABI, address)
const tx = await contract.methods.transfer(address, amount).send({
from: account.address
})
But i am getting error Error: Returned error: unknown account
Do i have to sign each transaction and then send it?
Maybe there is a way when provider signs transaction for me?
How to do it? How to add account object to web3.eth.accounts ?
In here:
const tx = await contract.methods.transfer(address, amount).send({
from: account.address
})
You are essentially asking the Ethereum node that you're communicating with, to sign the transaction for you.
In order for this to work, you first need to unlock the specified account on that node, by sending an appropriate request.
Alternatively (and probably more securely), you can sign the transaction yourself:
async function signAndSend(web3, account, gasPrice, transaction, value = 0) {
while (true) {
try {
const options = {
to : transaction._parent._address,
data : transaction.encodeABI(),
gas : await transaction.estimateGas({from: account.address, value: value}),
gasPrice: gasPrice,
value : value,
};
const signed = await web3.eth.accounts.signTransaction(options, account.privateKey);
const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
return receipt;
}
catch (error) {
console.log(error.message);
}
}
}
async function yourFunc(web3, account, gasPrice, address, amount) {
const contract = new web3.eth.Contract(ABI, address)
const receipt = await signAndSend(web3, account, gasPrice, contract.methods.transfer(address, amount));
}
BTW, I find it quite odd that you are trying to transfer tokens from your account into the Token contract.
I am sending a raw transaction to Ropsten test network with web3js module in node. The web3s code lives on an express back end. Here is the code:
var express = require("express");
var router = express.Router();
var Tx = require("ethereumjs-tx");
const Web3 = require("web3");
const web3 = new Web3(
"https://ropsten.infura.io/v3/d55489f8ea264a1484c293b05ed7eb85"
);
const abi = [...];
const contractAddress = "0x15E1ff7d97CB0D7C054D19bCF579e3147FC9009b";
const myAccount = "0x59f568176e21EF86017EfED3660625F4397A2ecE";
const privateKey1 = new Buffer(
"...",
"hex"
);
hashValue = "newly updated value";
router.post("/", function(req, res, next) {
const hashValue = req.body.hash,
fileName = req.body.fileName,
value = req.body.value;
const contract = new web3.eth.Contract(abi, contractAddress, {
from: myAccount
});
web3.eth.getTransactionCount(myAccount, (err, txCount) => {
//Smart contract data
const data = contract.methods
.setHashValue(value + fileName + hashValue)
.encodeABI();
// Build the transaction
const txObject = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(1000000),
gasPrice: 20000000000,
data: data,
from: myAccount,
to: contractAddress
};
// Sign the transaction
const tx = new Tx(txObject);
tx.sign(privateKey1);
const serializedTx = tx.serialize();
// const raw = '0x' + serializedTx.toString('hex')
// Broadcast the transaction
web3.eth
.sendSignedTransaction("0x" + serializedTx.toString("hex"))
.on("receipt", console.log, receipt => {
callback(receipt);
})
.then(() => {
res.json({ transactionHash });
})
.catch(() => {
// fail
});
});
});
module.exports = router;
The .post looks like this
axios.post(
"http://compute.amazonaws.com:3000/users",
{
value: "value",
fileName: "fileName",
hash: "hash"
}
);
The transaction is successful and returns a json with all relevant block data. about 2-3 minutes later, the same transaction is sent and mined on Ropsten. About the time that the second transaction is mined, my console (the request is sent through an http from browser) shows the following errors:
POST http://ec2-54-67-28-69.us-west-1.compute.amazonaws.com:3000/users net::ERR_EMPTY_RESPONSE
createError.js:17 Uncaught (in promise) Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:87)
This didn't happen until I added
const hashValue = req.body.hash,
fileName = req.body.fileName,
value = req.body.value;
to the code.
Any ideas?
This doesn't answer why the double transaction was happening, but a work around is to put next() at the end of the code.
I'm developing an app for Shopify. Currently under development stage. Until now, I have successfully managed to authorise the app and then redirect it back to admin page using the Embedded App SDK. However, when I return to the admin page, it gives me an error saying Request origin cannot be verified.
The console shows Failed to load resource: the server responded with a status of 403 (Forbidden)
The URL in the console is something like this https://myshop.myshopify.com/admin/apps/dfdjf4343343434343434bfdf/shopify/shopify/callback?code=ffdfdffd&hmac=fdfdfdfdfdfdfdfdfddfdfdfdfdf&shop=myshop.myshopify.com&state=151193864548800×tamp=1511938648
The fdfdfdfdfdfdfdfdfddfdfdfdfdf are just random characters that I've replaced instead of a hash. FYI - I've removed the app name and user profile name and avatar from the image.
This is happening because, you are unable to match state, that is set in cookie, while responding with redirect url
const ShopifyToken = require('shopify-token')
const forwardingAddress = process.env.HOST
const shopifyToken = new ShopifyToken({
sharedSecret: process.env.SHOPIFY_API_SECRET,
redirectUri: forwardingAddress + '/shopify/callback',
apiKey: process.env.SHOPIFY_API_KEY
})
const shopify = {
// use this for authentication
auth: (req, res, next) => {
const shop = req.query.shop
if (!shop) {
return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request')
}
const shopRegex = /^([\w-]+)\.myshopify\.com/i
const shopName = shopRegex.exec(shop)[1]
const state = shopifyToken.generateNonce()
const url = shopifyToken.generateAuthUrl(shopName, scopes, state)
res.cookie('state', state)
res.redirect(url)
},
// use this as your callback function
authCallback: async (req, res) => {
const { shop, hmac, code, state } = req.query
const stateCookie = cookie.parse(req.headers.cookie).state
if (state !== stateCookie) {
// you are unable to set proper state ("nonce") in this case, thus you are getting this error
return res.status(403).send('Request origin cannot be verified')
}
if (!shop || !hmac || !code) {
res.status(400).send('Required parameters missing')
}
let hmacVerified = shopifyToken.verifyHmac(req.query)
console.log(`verifying -> ${hmacVerified}`)
// DONE: Validate request is from Shopify
if (!hmacVerified) {
return res.status(400).send('HMAC validation failed')
}
const accessToken = await shopifyToken.getAccessToken(shop, code)
const shopRequestUrl = 'https://' + shop + '/admin/shop.json'
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken
}
try {
const shopResponse = await request.get(shopRequestUrl, { headers: shopRequestHeaders })
res.status(200).end(shopResponse)
} catch (error) {
res.status(error.statusCode).send(error.error.error_description)
}
}
}
Simple as this is, also make sure that the protocol matches from what you typed in to start the app install.
If you accidentally use http for http://you.ngrok.io/ but your callback redirects to https (i.e. https://you.ngrok.io/auth/callback), the OAuth handshake will fail.
const express = require('express');
const router = express.Router();
const dotenv = require('dotenv').config();
const cookie = require('cookie');
const requestPromise = require('request-promise');
const ShopifyToken = require('shopify-token');
const scopes = "write_products";
const forwardingAddress = process.env.HOST;
var shopifyToken = new ShopifyToken({
sharedSecret: process.env.SHOPIFY_API_SECRET,
redirectUri: forwardingAddress + '/shopify/callback',
apiKey: process.env.SHOPIFY_API_KEY
})
router.get('/shopify', (req, res) => {
const shop = req.query.shop;
if (!shop) {
return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request')
}
const shopRegex = /^([\w-]+)\.myshopify\.com/i
const shopName = shopRegex.exec(shop)[1]
const state = shopifyToken.generateNonce();
const url = shopifyToken.generateAuthUrl(shopName, scopes, state);
res.cookie('state', state);
res.redirect(url);
});
router.get('/shopify/callback', (req, res) => {
const { shop, hmac, code, state } = req.query;
const stateCookie = cookie.parse(req.headers.cookie).state;
if (state !== stateCookie) {
// you are unable to set proper state ("nonce") in this case, thus you are getting this error
return res.status(403).send('Request origin cannot be verified')
}
if (!shop || !hmac || !code) {
res.status(400).send('Required parameters missing')
}
let hmacVerified = shopifyToken.verifyHmac(req.query)
console.log(`verifying -> ${hmacVerified}`)
// DONE: Validate request is from Shopify
if (!hmacVerified) {
return res.status(400).send('HMAC validation failed')
}
const accessToken = shopifyToken.getAccessToken(shop, code);
const shopRequestUrl = 'https://' + shop + '/admin/products.json'
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken
}
try {
const shopResponse = requestPromise.get(shopRequestUrl, { headers: shopRequestHeaders })
res.status(200).send(shopResponse)
} catch (error) {
res.status(error.statusCode).send(error.error.error_description)
}
});
module.exports = router;