Send erc20 Tokens using Alchemy - react-native

I am using the Alchemy SDK to build an ethereum wallet app on react native. The docs (https://docs.alchemy.com/docs/how-to-send-transactions-on-ethereum) show me how to send Eth and I have already tested this and it works. However, I don't see anywhere in the docs on how to specify which token should be sent. I am wondering how I can set up my transaction object so that it will send the correct token. Our app handles Eth and all erc20 tokens currently so that the user can see their balances.
Here is the method for sending Eth using Alchemy's SDK
const { Alchemy, Network, Wallet, Utils } = require("alchemy-sdk");
const dotenv = require("dotenv");
dotenv.config();
const { API_KEY, PRIVATE_KEY } = process.env;
const settings = {
apiKey: API_KEY,
network: Network.ETH_GOERLI,
};
const alchemy = new Alchemy(settings);
let wallet = new Wallet(PRIVATE_KEY);
async function main() {
const nonce = await alchemy.core.getTransactionCount(
wallet.address,
"latest"
);
let transaction = {
to: "0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd",
value: Utils.parseEther("0.001"),
gasLimit: "21000",
maxPriorityFeePerGas: Utils.parseUnits("5", "gwei"),
maxFeePerGas: Utils.parseUnits("20", "gwei"),
nonce: nonce,
type: 2,
chainId: 5,
};
let rawTransaction = await wallet.signTransaction(transaction);
let tx = await alchemy.core.sendTransaction(rawTransaction);
console.log("Sent transaction", tx);
}
main();
I also found this article in the docs which explains the transaction object (https://docs.alchemy.com/docs/understanding-the-transaction-object-on-ethereum) but I still do not see where I would specify the token that I am sending.

The Alchemy SDK does not contain any CORE methods that you can use to connect to an interface of a deployed ERC20 contract with a view to using it to send transactions. However, you can connect with a deployed instance of a contract using a library like web3js or EthersJS
To send tokens from an ERC20 contract, you need to use a library like Ethersjs to connect to an instance of the deployed contract. An Ethereum is also required to connect to a deployed instance of the contract. A Provider is an abstraction of a connection to the Ethereum network, providing a concise, consistent interface to standard Ethereum node functionality. With a Provider, you can connect to an instance of a deployed contract and carry out transactions, track events, etc.
To be able to send transactions with an ERC20 token using the Alchemy SDK, you need the following:
The deployed contract address.
The deployed contract ABI.
The Contract Provider.
EtherJS
To connect to the EthersJS provider, use your Alchemy API KEY.
The following code is an example code which you can reference:
const { Wallet, Utils } = require("alchemy-sdk");
const dotenv = require("dotenv");
dotenv.config();
const { ALCHEMY_KEY, PRIVATE_KEY } = process.env;
const ethers = require("ethers");
const ABI = require("./ABI.json");
let wallet = new Wallet(PRIVATE_KEY);
const CONTRACT_ADDRESS = "0x...";
const provider = new ethers.providers.AlchemyProvider(
`https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_KEY}`
);
async function main() {
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider);
const amount = Utils.parseEther("0.001");
await contract.transfer(wallet.address, "<receiver-wallet-address>", amount);
console.log("Sent ", amount);
}
main();

Related

Connect to a Solana custom program without a wallet / frontend

I would like to be able to connect to my custom solana program without using any frontend object.
Currently, my provider method uses "window.solana" which I want to avoid.
The idea is to be able to sign transaction from a backend without having to retrieve object from a frontend. The transactions will be signed and paid directly by the program.
This how I am calling the my program now:
const network = clusterApiUrl("devnet");
const opts = {
preflightCommitment: "processed",
};
const { SystemProgram } = web3;
const getProvider = () => {
const connection = new Connection(network, opts.preflightCommitment);
const provider = new AnchorProvider(
connection,
window.solana,
opts.preflightCommitment
);
return provider;
};
const provider = getProvider();
const program = new Program(idl, programID, provider);
Anchor's Wallet class allows for exactly that form of implementation, as it is inherited from NodeWallet.
You need to instantiate an #solana/web3.js Keypair object, likely from your provided secret key, and then pass the keypair into the Anchor Wallet constructor. You can then pass the Wallet object into the AnchorProvider, no frontend adapters needed.
For your code, see below, where the Base58SecretKey comes from exporting private key of your desired signer on Phantom (or another wallet). You can also import the keypair using a uint8 array or Keypair.generate() for testing, if you prefer.
import * as anchor from "#project-serum/anchor";
const getProvider = () => {
const connection = new Connection(network, opts.preflightCommitment);
const keypair = new anchor.web3.Keypair.fromSecretKey(anchor.utils.bytes.bs58.decode("Base58SecretKey"))
const wallet = new Wallet(keypair);
const provider = new AnchorProvider(
connection,
wallet,
opts.preflightCommitment
);
return provider;
};

AAVE v3 - POLYGON - TEST <UnrecognizedContract>.<unknown> When running a script to deposit tokens to AAVE using a fork of the polygon mainnet

I'm testing v3 AAVE contracts on a fork of the polygon mainnet using harhat locally, but when I call de supply() function I get this error:
Error: Transaction reverted without a reason string
at <UnrecognizedContract>.<unknown> (0x794a61358d6845594f94dc1db02a252b5b4814ad)
at <UnrecognizedContract>.<unknown> (0x794a61358d6845594f94dc1db02a252b5b4814ad)
at <UnrecognizedContract>.<unknown> (0x794a61358d6845594f94dc1db02a252b5b4814ad)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at HardhatNode._mineBlockWithPendingTxs (/home/daniel/daniel/dev/chainlink/flowmi/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1802:23)
at HardhatNode.mineBlock (/home/daniel/daniel/dev/chainlink/flowmi/node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:491:16)
at EthModule._sendTransactionAndReturnHash (/home/daniel/daniel/dev/chainlink/flowmi/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1522:18)
at HardhatNetworkProvider.request (/home/daniel/daniel/dev/chainlink/flowmi/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
at EthersProviderWrapper.send (/home/daniel/daniel/dev/chainlink/flowmi/node_modules/#nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
The script I'm trying to run:
const { getNamedAccounts, ethers } = require("hardhat");
async function main() {
const { deployer } = await getNamedAccounts();
// Mainnet pool adready given by the deployment
// Deposit
// Aprove to get Matic
const AMOUNT = ethers.utils.parseEther("0.11");
//const maticTokenAddress = "0x0000000000000000000000000000000000001010"; //mainnet
const Pool = await getPool(deployer);
const maticTokenAddress = "0xD65d229951E94a7138F47Bd9e0Faff42A7aCe0c6"; // testnet matic address
await approveErc20(maticTokenAddress, Pool.address, AMOUNT, deployer);
console.log("Depositing...");
console.log("Address provided: ", Pool.address);
await Pool.supply(maticTokenAddress, AMOUNT, deployer, 0);
console.log("Deposited!");
}
async function getPool(account) {
const PoolAddressesProvider = await ethers.getContractAt(
"IPoolAddressesProvider",
"0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb", // mainnet pool addresses provider
//"0x5343b5bA672Ae99d627A1C87866b8E53F47Db2E6", // testnet pool addresses provider
account
);
const PoolAddress = await PoolAddressesProvider.getPool();
const Pool = await ethers.getContractAt("IPool", PoolAddress, account);
return Pool;
}
async function approveErc20(
erc20Address,
spenderAddress,
amountToSpend,
account
) {
const erc20Token = await ethers.getContractAt(
"IERC20",
erc20Address,
account
);
const tx = await erc20Token.approve(spenderAddress, amountToSpend);
await tx.wait(1);
console.log("Approved!");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
When I ask for which address was provided the answer is:
Address provided: 0x794a61358D6845594F94dc1DB02A252b5b4814aD
Which happens to be a polygon mainnet pool address according to documentation. Notice is the same address the error gives.
I'll be most thankful if someone points out my mistake
I've tried different combinations of "mainnet" and "testnet" addresses, for the maticToken, and the pool addresses provider
The problem was the matic address, It seems I misundertood documentation, thought the fact that matic is an ERC20 compliant implied it should not need to be wrapped to deposit.
But the script only works with the address of wrapped matic on mainnet.
Maybe is a problem of the mainnet fork, don't know but I moved on.

Error: unknown account #0 (operation="getAddress", code=UNSUPPORTED_OPERATION, version=providers/5.7.1)

I want to test my function withdraw of my Vuejs app.
If my wallet Metamask is connected, then I can click on a button withdraw to get the money of my contract. The function works. Now I want to test it with Jest.
withdraw: async function(){
if(typeof window.ethereum !== 'undefined') {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(this.contractAddress, NftContract.abi, signer);
try {
const transaction = await contract.withdraw();
await transaction.wait();
this.setSuccess('The withdrawal is successful');
}
catch(err) {
console.log(err);
this.setError('An error occured to withdraw');
}
}
}
I'm using eth-testing (https://www.npmjs.com/package/eth-testing?activeTab=readme) to mock the interaction with my smart contract. My test with Jest:
let wrapper;
const testingUtils = generateTestingUtils({ providerType: "MetaMask" });
beforeAll(() => {
// use this to check the state of anything in the view
wrapper = shallowMount(NFTMintComponent);
// Manually inject the mocked provider in the window as MetaMask does
global.window.ethereum = testingUtils.getProvider();
})
afterEach(() => {
// Clear all mocks between tests
testingUtils.clearAllMocks();
//jest.restoreAllMocks();
})
it('when the owner withdraw the amount of the contract, the balance of the contract should be 0 and a successful message should appear (withdraw function)', async () => {
// Start with not connected wallet
testingUtils.mockNotConnectedWallet();
// Mock the connection request of MetaMask
const account = testingUtils.mockRequestAccounts(["0xe14d2f7105f759a100eab6559282083e0d5760ff"]);
//allows to mock the chain ID / network to which the provider is connected --> 0x3 Ropsten network
testingUtils.mockChainId("0x3");
// Mock the network to Ethereum main net
testingUtils.mockBlockNumber("0x3");
const abi = NftContract.abi;
// An address may be optionally given as second argument, advised in case of multiple similar contracts
const contractTestingUtils = testingUtils.generateContractUtils(abi);
const transaction = await contractTestingUtils.mockTransaction("withdraw", '0x10Bc587867D87d1Ea1Cd62eac01b6DD027c182E9');
await wrapper.vm.withdraw();
});
I got the error: Error: unknown account #0 (operation="getAddress", code=UNSUPPORTED_OPERATION, version=providers/5.7.1) for my transaction contract.withdraw();
It's like the contract doesn't recognize my account even if I mocked my account at the beginning of the test with const account = testingUtils.mockRequestAccounts(["0xe14d2f7105f759a100eab6559282083e0d5760ff"]);
How can I fix that problem ?

How can do a contract to Approve user manipuler her tokens?

Like I have own token
And I develope an Dapp to transfer between us my own personal token.
To do that I have to Approve and then use transferFrom, aren't¿
I check some nft games and always, then force my to approve before play.
I have tryed to do that but if I have
Contrat MyToken
Contract MyDapp
When I save user address to Approve, I send Approve from MyDapp to MyToken, then approve no works.
How can I do that? or what is the good way to do that?
Thanks
Let's say you want to approve compound USDT with this contract address on Rinkeby
your JavaScript code with ethers.js library (it could be python or java too, library is important) (Note that I only use front-end and I personally know nothing about back-end)
const ethers = require('ethers');
const USDTInterface = ['function approve(address spender, uint256 amount) external returns (bool)'];
const USDTAddress = '0xD9BA894E0097f8cC2BBc9D24D308b98e36dc6D02';
const yourContractAddress = YOUR_DAPP_CONTRACT_ADDRESS;
let provider;
let signer;
let signerAddress;
let USDTContract;
const startFunction = async () => {
await ethereum.request({ method: 'eth_requestAccounts'});
await ethereum.request({ method: 'wallet_switchEthereumChain', params:[{chainId: '0x4'}]});
provider = new ethers.providers.Web3Provider(window.ethereum);
signer = provider.getSigner();
signerAddress = await signer.getAddress();
USDTContract = await new ethers.Contract(USDTAddress, USDTInterface, signer);
}
startFunction();
async function approveUSDT(){
USDTContract.approve(yourContractAddress, BigInt("9007199254740990")**3n);
}
//Whenever this function is called, a transaction request is sent to user's metamask and whenever
//user confirms it, it is approved!

TronWeb to send trc20 usdt

I want to use TronWeb to send trc20 token. Whether I need to use contract().at() to do this? It means I need to treat trc20 token just as smart contract?
first things first, to clarify every token on any network (not just tron) has its own smart contract that has been published to the network
here is the code to get your account balance and another to transfer USDT
don't forget to init the code with your private key and network endpoints
note that you need tron energy and bandwidth to perform a transaction
you can read about them using this link
const CONTRACT = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
async function getBalance(account) {
const {
abi
} = await tronWeb.trx.getContract(CONTRACT);
const contract = tronWeb.contract(abi.entrys, CONTRACT);
const balance = await contract.methods.balanceOf(account).call();
console.log("balance:", balance.toString());
}
async function transferUSDT(destination, amount) {
const {
abi
} = await tronWeb.trx.getContract(CONTRACT);
const contract = tronWeb.contract(abi.entrys, CONTRACT);
const resp = await contract.methods.transfer(destination, amount).send();
console.log("transfer:", resp);
}
When you init the tronweb compnent with private key ,you could use the contract().at()
tronWeb = new TronWeb(
'https://api.nileex.io/',
'https://api.nileex.io/',
'https://event.nileex.io/',
'your privateKey'
);