Reputation: 335
The Dapp sends Bep20 token from a remote wallet(My wallet) to users after they perform a certain activity such as accepting BNB to be sent to ICO, it works well on a desktop in which metamask is installed. The code that executes this is:
var amountTosend = amount;
var privateKey = 'PRIVATE_KEY';
var accountFrom = web3provider.eth.accounts.privateKeyToAccount(privateKey).address;
var contractCall = contractInstance.methods.transfer(addressTo, "0x"+amountTosend.toString(16));
var icoAccount = web3provider.eth.accounts.privateKeyToAccount(privateKey);
web3provider.eth.accounts.wallet.add(icoAccount);
contractCall.send({ from: accountFrom, gas: 2000000 }).then(function(hashdata) {
console.log(hashdata);
var rawTransaction = {
"from": accountFrom,
"nonce": nonce,
"gasPrice": 20000000000,
"gas": gas,
"to": SmartContractAddress,
"value": "0x" + amountTosend.toString(16),
"data": hashdata.events.Transfer.raw.data,
"chainId": chainid
};
var privKey = new ethereumjs.Buffer.Buffer(privateKey, 'hex');
let tx = new ethereumjs.Tx(rawTransaction);
tx.sign(privKey)
let serializedTx = tx.serialize();
console.log('serializedTx:', serializedTx);
web3provider.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'), function(err, receipt) {
if (!err) {
console.log('success token sent to user: ' + receipt);
alert('You have received your Tokens in your Wallet');
} else {
console.log('error: ' + err);
alert("An error Occured: " + err);
}
});
})
On mobile wallets such as trust and metamask mobile connected with web3modal using wallet connect as provider, I successfully interacted with the wallet, prompt user to send BNB but
contractCall.send({ from: accountFrom, gas: 2000000 })
which is used to change the state of the smart contract to send user Bep20 token fails with Unknown account error after adding remote wallet to local using:
web3provider.eth.accounts.wallet.add(icoAccount);
Note: If I try skipping
contractCall.send({ from: accountFrom, gas: 2000000 })
and use contractCall.encodeABI() for data parameter, it works fine but no token is actually sent to the user and I guess is because the smart contact state needs to be changed/altered with
myContract.methods.myMethod([param1[, param2[, ...]]]).send
Please I need any useful help/tip to make this work on mobile wallet, I have been on this bug for a few days now, thanks
Upvotes: 0
Views: 3238
Reputation: 335
I finally fixed this error, and I will like to answer comprehensively for future visitors. The short answer will come first to implement the solution, and the long comprehensive answer afterward to help you understand better and learn the technicalities of fixing the bug
Note: I am using walletconnect and web3modal under the hood for my DAPP on Mobile browser and Metamask for Desktop and I'm using vanilla javascript for web3 implemenation
Short Answer: I had to set givenProvider to the currentProvider which was initialized on web3 instance and that was my RPC URL provider, for me my RPC URL provider is: https://getblock.io/ which was passed in walletconnect/web3modal provider options paramater
I'm connecting to BSC so my RPC URL is: https://bsc.getblock.io/mainnet/?api_key=API_KEY
You may use other RPC URL providers of your choice
So the givenProvider is set like this:
web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;
read walletconnect docs on setting provider(s) here: https://docs.walletconnect.com/quick-start/dapps/web3-provider
Setting the web3.givenProvider to web3.currentProvider fixed the issue as web3.givenProvider was null
Long Answer:
You need to understand what is currentProvider and givenProvider are, as the bug resolves around the web3 provider. In my understanding as of writting this answer givenProvider is the provider injected in an Ethereum enabled browser while currentProvider is the provider that you passed in on the initialization of web3.
The error is: Unknown account
This problem doesn't appear on a desktop browser where metamask is installed because injects the givenProvider, except of course is a remote account that doesn't exist on the provider node
You have to add the account to the provider node using:
var account= web3provider.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3provider.eth.accounts.wallet.add(account);
This solves the error on desktop browser without having to configure or set up much and that is because masks makes your browser Ethereum enabled and injects givenProvider
But for mobile browsers, you will face this issue because mobile browsers aren't Ethereum enabled environment. You will have to set givenProvider to a valid provider after initializing web3 through walletconenct.
Note: givenProvider talks to the blockchain through the web and it is null on mobile browsers. Console.log(web3) will show you the values of web3 instance
Putting all together your code should look like this:
import WalletConnectProvider from "@walletconnect/web3-provider";
import Web3 from "web3";
// Create WalletConnect Provider
const provider = new WalletConnectProvider({
rpc: {
1: "https://mainnet.mycustomnode.com",
3: "https://ropsten.mycustomnode.com",
100: "https://dai.poa.network",
// ...
},
});
await provider.enable();
// Create Web3 instance
const web3 = new Web3(provider);
//FIX STARTS HERE
//set givenProvider to currentProvider
web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;
//add wallet to provider node
var account= web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3.eth.accounts.wallet.add(account);
var accountFrom = account.address;
var gas = contractCall.estimateGas({ from: accountFrom });
gas.then(function(gasTouse) {
contractCall.send({
from: accountFrom, gas: gasTouse }).then(function(hashdata){
console.log(hashdata);
});
});
Note: Be sure you estimate gas and include it, as without it you may encounter some gas-related errors.
Happy coding :)
Upvotes: 1