I'm trying to send USDT (custom token) with the metamask API using web3. I'm developing on ReactJS and I could detected correctly the user account from metamask.
My code:
const web3 = new Web3(window.web3.currentProvider);
const contractInstance = new web3.eth.Contract(abiUSDT, addressUSDT);
const amount = 200;
const tx = {
from: 'PERSON_SENDER',
to: contractInstance._address,
data: contractInstance.methods.transfer('PERSON_RECIPIENT', web3.utils.toWei( amount.toString() ) ).encodeABI(),
}
web3.eth.sendTransaction(tx).then(res => {
console.log("res",res)
}).catch(err => {
console.log("err",err)
});
obviously, I replace the fields called: PERSON_SENDER and PERSON_RECIPIENT with:
PERSON_SENDER: The user account
PERSON_RECIPIENT: My personal account (I want to deposit in this account)
Using this config, the transaction doesn't send to my account when I check in etherscan (and the amount was sent to the address of the contract), and a user communicate that if he uses real values for him real account, metamask doesn't touch his amount.
I made the same code and it works. But check the correct ABI, and adrresses format. The address "FROM" must be tha same address that your metamask is conected.
My code:
var contractABI = [{"YOUR TOKEN ABI HERE"}]
addressUSDT = "0xf80e1C5e28226cAfc7B0Ee6729E553ef54A7774F"; //IT'S OTHER CONTRACT
const web3 = new Web3(window.web3.currentProvider);
const contractInstance = new web3.eth.Contract(contractABI, addressUSDT);
const amount = 200;
const tx = {
from: '0x2acd4F50ee814d5092d9FC892d2BDEab91f5594d',
to: contractInstance._address,
data: contractInstance.methods.transfer('0xe54356F4e1aD4215973E7180BeBb4644a07DF508', web3.utils.toWei( amount.toString() ) ).encodeABI(),
}
web3.eth.sendTransaction(tx).then(res => {
console.log("res",res)
}).catch(err => {
console.log("err",err)
});
Related
Guys i'm trying to do an manual trade bot in pancake for study , but i can't understand what it's wrong with my code now , i'm trying for a few days understand what is wrong but i really don't know what is happen.
const Web3 = require('web3');
async function swapToken(privateKeys, tokenAddress, amount, bnbAddress) {
// made an web3 instance with URL from Binance Smart Chain
const web3 = new Web3(new Web3.providers.HttpProvider('https://bsc-dataseed.binance.org/'));
// Get atual gás price
const gasPrice = await web3.eth.getGasPrice();
// Loop to get all pk's
for (const privateKey of privateKeys) {
// get the account of my pk
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
// define transaction options
const options = {
from: account.address,
to: tokenAddress,
value: 0,
gasPrice: gasPrice,
gas: '200000',
data: bnbAddress,
};
// assign and send the transaction to trade token
const signedTransaction = await web3.eth.accounts.signTransaction(options, privateKey);
web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);
}
}
// all pk ( multi wallet system)
const privateKeys = [
'my private key'
];
// token address on Binance Smart Chain
const tokenAddress = '0xe9e7cea3dedca5984780bafc599bd69add087d56';
// Quantity of tokens to be traded
const amount = '2';
//token output
const bnbAddress = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
swapToken(privateKeys, tokenAddress, amount, bnbAddress);
and the error is :
error after run the code
i tried some changes in code variables but nothing really works ... I'm really need help with this error and understand what is wrong to do this error
I am following the inner instructions of a Solana NFT to create the process of listing an NFT for sale.
According to this NFT, https://solscan.io/tx/25g9L7rDCn8ZbZAZoCvyVNe5woZUoK2PVU3VEXftqySa2EYsLUJB2GA42qDwxsezUBRH2A9eJX1iUUD2LCK9Fua9, the first instruction is to create an account.
The instruction shows
NewAccount - E61SDPzHP61C4KwwiSqG4FAHXof852wsaSjh3F4kLbwmicon
Source - H2eud1RCJu8u8vEQ8jJLQ32jM5oKfARGxz5LwEKKfTLuicon
TransferAmount(SOL) - 0.00223416
ProgramOwner - M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7Kicon
New Account seems to be a newly generated account and Source is the wallet which was used when the user connected their wallet to the client.
I am using the this code from the Solana Cookbook for reference
import { clusterApiUrl, Connection, PublicKey, Keypair, Transaction, SystemProgram } from "#solana/web3.js";
import { Token, TOKEN_PROGRAM_ID, AccountLayout } from "#solana/spl-token";
import * as bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode("588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2")
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode("4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp")
);
const mintPubkey = new PublicKey("54dQ8cfHsW1YfKYpmdVZhWpb9iSi6Pac82Nf7sg3bVb");
// generate a new keypair for token account
const tokenAccount = Keypair.generate();
console.log(`token account: ${tokenAccount.publicKey.toBase58()}`);
let tx = new Transaction().add(
// create token account
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: tokenAccount.publicKey,
space: AccountLayout.span,
lamports: await Token.getMinBalanceRentForExemptAccount(connection),
programId: TOKEN_PROGRAM_ID,
}),
/**... some other instruction*/
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer, tokenAccount])}`);
})();
From my understanding, in this scenario the feePayer is the user who connected their wallet. (Source from the instructions), tokenAccount is the account that we want to transfer the SOL to (NewAccount from the instructions), and programID is ProgramOwner from the instructions.
When I run this exact code from the Solana Cookbook it works.
When I try using the provider as the feePayer (wallet that was connected in the client) it doesn't work.
I have a function to get my provider
getProvider = () => {
if ("solana" in window) {
const anyWindow = window;
const provider = anyWindow.solana;
if (provider.isPhantom) {
return provider;
}
}
window.open("https://phantom.app/", "_blank");
};
Then I grab my provider with
const provider = this.getProvider();
I replace the original feePayer created with Keypair.fromSecretKey with the provider.
My assumption as to why provider isn't working as one of the signers in await connection.sendTransaction(tx, [provider, tokenAccount]) is because the signer requires a secret key.
So what I try to do instead is sign the transaction myself using some code I've found online on how to sign a transaction.
const blockHash = await connection.getRecentBlockhash()
tx.feePayer = provider.publicKey
tx.recentBlockhash = await blockHash.blockhash
const signed = await provider.signTransaction(tx);
This runs fine and I'm able to see the results when I do console.log(signed);
The problem I'm getting is that there are 2 signatures and one of them is null. One is the signature of the provider and the other is the signature of the tokenAccount.
When I use console.log() to show the public key of the provider and the public key of the tokenAccount and try to match it to the public keys within the signature, I find that the signature of the tokenAccount is the one that is returning null.
So when it's time to run const signature = await connection.sendRawTransaction(signed.serialize()); I get an error from signed.serialize() saying Signature verification failed
What am I doing wrong here?
Can I create a Signer from a user connecting their phantom wallet? If not, how can I sign the transaction so that neither of the signatures come out null?
So I would recommend using the wallet-adapter to connect and send transactions from wallets.
This will make the code above look something like this:
const { publicKey, sendTransaction } = useWallet();
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode("4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp")
);
const mintPubkey = new PublicKey("54dQ8cfHsW1YfKYpmdVZhWpb9iSi6Pac82Nf7sg3bVb");
// generate a new keypair for token account
const tokenAccount = Keypair.generate();
console.log(`token account: ${tokenAccount.publicKey.toBase58()}`);
let tx = new Transaction().add(
// create token account
SystemProgram.createAccount({
fromPubkey: publicKey,
newAccountPubkey: tokenAccount.publicKey,
space: AccountLayout.span,
lamports: await Token.getMinBalanceRentForExemptAccount(connection),
programId: TOKEN_PROGRAM_ID,
}),
/**... some other instruction*/
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'processed');
Hi i have similar issue,
There are two signers admin and user,
admin is signing the tx from node and serializing tx.
this i send to frontend
and user signs it.
But as initially the signature is null, so wallet.signTransaction(tx);
gives the Signature verification failed
You have to partially sign with the tokenAccount before sending the transaction.
const blockHash = await connection.getRecentBlockhash()
tx.feePayer = provider.publicKey
tx.recentBlockhash = await blockHash.blockhash
const signed = await provider.signTransaction(tx);
// now sign with the tokenAccount
signed.partialSign(tokenAccount);
import { WalletConnectConnector } from "#web3-react/walletconnect-connector";
I have used this for connecting walletconnect through QR code and used useWeb3React for connecting to wallet.
Metamask extension is working fine but not able to use walletconnect for transactions.
const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
var web3 = createAlchemyWeb3(alchemyKey);
const transactionParameters = [
{
method: "eth_sendTransaction",
params: [
{
to: contractAddress, // Required except during contract publications.
from: acct, // must match user's active address.
data: window.contract.methods.mintNFT(acct, tokenURI).encodeABI(), //make call to NFT smart contract
},
],
},
];
await web3.eth
.sendTransaction(transactionParameters)
.on("receipt", (receipt) => {
console.log(receipt, "receipt");
})
.on("transactionHash", (hash) => {
console.log(hash, "hash");
})
.on("error", (err) => {
console.log(err, "error");
});
The above works fine with metamask extension but not with Walletconnect.
I think the issue is with your web3 provider. Try to get web3 provider from useWeb3React itself.
eg:
const provider = connector.getProvider();
const web3 = new Web3(provider)
use this web3 to send transaction
I'm trying to send ethereum transaction that sends ERC20 tokens to someone with Ledger Nano S through Node.JS but I'm not able to successfully sign and send this transaction.
First of all, I signed the transaction through the method, signTransaction, of ledgerhq API and then after signing it, I sended it to the main net by using sendSignedTransaction. When I execute below code, Ledger receives request and shows details of a transaction. However, after pressing Ledger's confirm button, the console returns error 'Returned error: Invalid signature: Crypto error (Invalid EC signature)'.
import AppEth from "#ledgerhq/hw-app-eth";
import TransportU2F from "#ledgerhq/hw-transport-u2f";
import TransportNodeHid from "#ledgerhq/hw-transport-node-hid";
import EthereumTx from "ethereumjs-tx"
const Web3 = require('web3');
import { addHexPrefix, bufferToHex, toBuffer } from 'ethereumjs-util';
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var destAddresses = ['0xa6acFa18468786473269Dc1521fd4ff40F6481D9'];
var amount = 1000000000000;
var i=0;
var contract = new web3.eth.Contract([token contract ABI... ], '0x74a...');
const data1 = contract.methods.transfer(destAddresses[0], amount).encodeABI();
const exParams = {
gasLimit: 6e6,
gasPrice: 3e9,
from: '0x1A...',
data : data1,
to: '0x74a...',
value: '0x00',
nonce: "0x0",
chainId: 1,
v: "0x01",
r: "0x00",
s: "0x00"
}
async function makeSign(txParams) {
const tx = new EthereumTx(txParams);
const txHex = tx.serialize().toString("hex");
const signedTransaction = '0x' + txHex;
let transport;
try {
transport = await TransportNodeHid.create();
let eth2 = new AppEth(transport);
const result = await eth2.signTransaction("m/44'/60'/0'/0", txHex).then(result => {
web3.eth.sendSignedTransaction('0x' + txHex)
.then(res => {
console.log(res);
}).catch(err => {
console.log('sendSignedTransaction');
console.log(err);
});
}).catch(err => {
console.log('signTransaction');
console.log(err);
});
txParams.r = `0x${result.r, 'hex'}`;
txParams.s = `0x${result.s, 'hex'}`;
txParams.v = `0x${result.v, 'hex'}`;
return result;
} catch (e) {
console.log(e);
}
}
makeSign(exParams).then(function () {
console.log("Promise Resolved2");
}.catch(function () {
console.log("Promise Rejected2");
});
When I only use signTransaction function, I can confirm the transaction in the ledger device and return txhash on the console. However, ultimately I want to broadcast a transaction to the main net. Could you please give me any idea? I want any feedback. Also, if there are any examples of creating and broadcasting a raw transaction by using the ledger, notice me please.
Your code already sends the transaction to the network. However, just awaiting the "send" promise only gives you the transaction hash, not the receipt. You need to treat it as an event emitter and wait for the 'confirmation' event.
const serializedTx = tx.serialize();
web3.eth.sendSignedTransaction(serializedTx.toString('hex'))
.once('transactionHash', hash => console.log('Tx hash', hash))
.on('confirmation', (confNumber, receipt) => {
console.log(`Confirmation #${confNumber}`, receipt);
})
.on('error', console.error);
To send it to mainnet as you mention, you can either run a local geth node on port 8545 and use your code unchanged, or point web3 at infura or similar.
I am confused about how I should be executing a contract's method using the web3 1.0 library.
This code works (so long as I manually unlock the account first):
var contract = new web3.eth.Contract(contractJson, contractAddress);
contract.methods
.transfer("0x0e0479bC23a96F6d701D003c5F004Bb0f28e773C", 1000)
.send({
from: "0x2EBd0A4729129b45b23aAd4656b98026cf67650A"
})
.on('confirmation', (confirmationNumber, receipt) => {
io.emit('confirmation', confirmationNumber);
});
I get this error (if I don't unlock manually first):
Returned error: authentication needed: password or unlock
The above code is an API endpoint in node.js, so I want it to unlock or authenticate programmatically.
There is no method in web3.js 1.0 to unlock the account.
I also don't think this is necessary (at least that's what I am confused about). Since I am managing accounts, I know what the private key is.
I am thinking the transaction needs to be signed with the private key?? Is this correct? Is this effectively the same thing as "unlocking the account"?
I tried doing this:
var contract = new web3.eth.Contract(contractJson, contractAddress);
var tx = {
from: "...{fromAddress -- address that has the private key below}",
to: "...",
value: ...
};
var signed = web3.eth.accounts.signTransaction(tx,
"...{privateKey}");
console.log(signed);
var promise = web3.eth.sendSignedTransaction(signed);
I get this error:
Returned error: The method net_version does not exist/is not available
What is the easiest way to authenticate and submit a transaction?
Ideally, I want to use the first approach in my code sample, as it is the cleanest.
This code allows me to sign a transaction server-side (node.js) using the privateKey from the account I created (using web3.eth.accounts.create()), and send the signed transaction to the network without having to unlock the account.
I am using Geth 1.7.1
var contract = new web3.eth.Contract(contractJson, contractAddress);
var transfer = contract.methods.transfer("0x...", 490);
var encodedABI = transfer.encodeABI();
var tx = {
from: "0x...",
to: contractAddress,
gas: 2000000,
data: encodedABI
};
web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
var tran = web3.eth.sendSignedTransaction(signed.rawTransaction);
tran.on('confirmation', (confirmationNumber, receipt) => {
console.log('confirmation: ' + confirmationNumber);
});
tran.on('transactionHash', hash => {
console.log('hash');
console.log(hash);
});
tran.on('receipt', receipt => {
console.log('reciept');
console.log(receipt);
});
tran.on('error', console.error);
});
A way to be able to call your contract methods without having to sign the transaction explicitly is this (web3js 1.0.0):
const privateKey = 'e0f3440344e4814d0dea8a65c1b9c488bab4295571c72fb879f5c29c8c861937';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
web3.eth.defaultAccount = account.address;
// ...
contract = new web3.eth.Contract(JSON_INTERFACE, address);
contract.methods.myMethod(myParam1, myParam2)
.send({
from: this.web3.eth.defaultAccount,
gas: myConfig.gas,
gasPrice: myConfig.gasPrice
})
Here's a complete example of how to sign a transaction without a local wallet account. Especially useful if you are using infura for the transaction. This was written for
'use strict';
const Web3 = require('web3');
const wsAddress = 'wss://rinkeby.infura.io/ws';
const contractJson = '(taken from solc or remix online compiler)';
const privateKey = '0xOOOX';
const contractAddress = '0xOOOX';
const walletAddress = '0xOOOX';
const webSocketProvider = new Web3.providers.WebsocketProvider(wsAddress);
const web3 = new Web3(new Web3.providers.WebsocketProvider(webSocketProvider));
const contract = new web3.eth.Contract(
JSON.parse(contractJson),
contractAddress
);
// change this to whatever contract method you are trying to call, E.G. SimpleStore("Hello World")
const query = contract.methods.SimpleStore('Hello World');
const encodedABI = query.encodeABI();
const tx = {
from: walletAddress,
to: contractAddress,
gas: 2000000,
data: encodedABI,
};
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
console.log(account);
web3.eth.getBalance(walletAddress).then(console.log);
web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
const tran = web3.eth
.sendSignedTransaction(signed.rawTransaction)
.on('confirmation', (confirmationNumber, receipt) => {
console.log('=> confirmation: ' + confirmationNumber);
})
.on('transactionHash', hash => {
console.log('=> hash');
console.log(hash);
})
.on('receipt', receipt => {
console.log('=> reciept');
console.log(receipt);
})
.on('error', console.error);
});
Using
"web3": "1.0.0-beta.30"
This is my implementation using "#truffle/hdwallet-provider": "^2.0.3", "web3": "^1.6.1",
function getWeb3Provider() {
return new HDWalletProvider({
privateKeys: [NFT_MINTER_ACCOUNT_PRIVATE_KEY],
providerOrUrl: BSC_RPC_ENDPOINT,
});
}
const web3 = new Web3(BSC_RPC_ENDPOINT);
const contract = new web3.eth.Contract(
jsonContractABI as unknown as AbiItem[],
NFT_CONTRACT_ADDRESS
);
contract.setProvider(getWeb3Provider());
then in send methods
contract.methods.safeMint(receiverAddress, itemUri).send({
from: NFT_MINTER_ACCOUNT,
});
in call methods
contract.methods.balanceOf(address).call();