I have a problem when running the following 4 lines of code from the main JS script (see below):
await uniswapFactory.getPair(daiAddress, wethAddress)
await sushiFactory.getPair(daiAddress, wethAddress),
const uniswapReserves = await uniswapDaiEth.getReserves();
const sushiReserves = await sushiEthDai.getReserves();
For the first two, if I substituted them with hardcoded token pair addresses from Etherscan into the code it works. If I run the first two directly into Truffle console it resolves the pair addresses but strangely enough it doesn´t resolve when I execute the JS script!
For the above two .getReserves() function calls it doesn´t retrieve any of the reserve values unless if I ran them as they are under Truffle console environment then it retrieves them OK.
I appreciate your assistance here as it´s been bugging me for the full last two days and am running out of options to resolve this.
Full JS script
require('dotenv').config();
const { INFURA_API_KEY, PRIVATE_KEY } = process.env;
const { ethers } = require('ethers');
const UniswapV2Pair = require(".././build/contracts/IUniswapV2Pair.json");
const UniswapV2Factory = require('.././build/contracts/IUniswapV2Factory.json');
const daiAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
const wethAddress = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const privateKey = process.env.PRIVATE_KEY;
const infuraProvider = new ethers.providers.InfuraProvider('mainnet', process.env.INFURA_API_KEY);
const wallet = new ethers.Wallet(privateKey, infuraProvider);
const testBasic = async () => {
const uniswapFactory = new ethers.Contract(
"0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
UniswapV2Factory.abi,
wallet
);
const sushiFactory = new ethers.Contract(
"0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac",
UniswapV2Factory.abi,
wallet
);
let uniswapDaiEth;
let sushiEthDai;
const loadPairs = async () => {
uniswapDaiEth = new ethers.Contract(
await uniswapFactory.getPair(daiAddress, wethAddress),
UniswapV2Pair.abi,
wallet
);
sushiEthDai = new ethers.Contract(
await sushiFactory.getPair(daiAddress, wethAddress),
UniswapV2Pair.abi,
wallet
);
};
await loadPairs();
infuraProvider.on('block', async (blockNumber) => {
try {
const uniswapReserves = await uniswapDaiEth.getReserves();
const sushiReserves = await sushiEthDai.getReserves();
} catch (err) {
console.error(err);
}
});
};
testBasic();
Thank you very much for your help!
Best, Samuel
how do you know it doesnt retrieve the values?
you’re defining uniswapReserves
inside a block, so it will cease to exist when you exit the block…
I have tried this.
See below code block once more
console.log("uniswapFactory.address: ", uniswapFactory.address);
console.log("sushiFactory.address: ", sushiFactory.address);
console.log("uniswapDaiEth: ", uniswapDaiEth.address);
console.log("sushiEthDai: ", sushiEthDai.address);
let uniswapReserves;
let sushiReserves;
console.log("step 1...");
uniswapReserves = await uniswapDaiEth.callStatic.getReserves();
console.log("step 2...");
const reserve0Uni = Number(ethers.utils.formatUnits(uniswapReserves[0], 18));
const reserve1Uni = Number(ethers.utils.formatUnits(uniswapReserves[1], 18));
console.log("step 3...");
sushiReserves = await sushiEthDai.callStatic.getReserves();
console.log("step 4...");
const reserve0Sushi = Number(ethers.utils.formatUnits(sushiReserves[0], 18));
const reserve1Sushi = Number(ethers.utils.formatUnits(sushiReserves[1], 18));
console.log("step 5...");
console.log("reserve0Uni: ", reserve0Uni);
console.log("reserve1Uni: ", reserve1Uni);
Output of Truffle console prompt
uniswapFactory.address: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
sushiFactory.address: 0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac
uniswapDaiEth: 0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11
sushiEthDai: 0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f
step 1…
TypeError: fn is not a function
at exec (C:\Users\samuel.sadek\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\require\dist\index.js:122:1) *
at node:internal/util:361:7*
at new Promise ()*
at exec (node:internal/util:347:12)*
at Object.module.exports [as run] (C:\Users\samuel.sadek\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\exec\run.js:43:1)*
at processTicksAndRejections (node:internal/process/task_queues:96:5)*
at runCommand (C:\Users\samuel.sadek\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\command-utils.js:201:1)*
truffle(mainnet_fork)>
As you can see from above it never reaches above console.log("step 2...");
code line which means it has trouble making the above uniswapReserves = await uniswapDaiEth.callStatic.getReserves();
call.
I now have an additional error to do with TypeError: fn is not a function .
Any help would be greatly appreciated!!!
BR
Do you have a documentation source for this function? It feels like it’s expecting to get handed a function but isnt?
The source JS script that I have tried to run
require('dotenv').config();
const { INFURA_API_KEY, PRIVATE_KEY } = process.env;
const { ethers, providers } = require('ethers');
// uni/sushiswap ABIs
const UniswapV2Pair = require("./build/contracts/IUniswapV2Pair.json");
const UniswapV2Factory = require('./build/contracts/IUniswapV2Factory.json');
const daiAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
const wethAddress = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
// use your own Infura node in production
providers.getDefaultProvider('mainnet'));
const infuraProvider = new ethers.providers.InfuraProvider('mainnet', process.env.INFURA_API_KEY);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, infuraProvider);
const BORROW_AMOUNT = 1000000 * 2; // 2M DAI
const testBasic = async () => {
console.log("starting...");
const INTERVAL = 5000; // ms
const uniswapFactory = new ethers.Contract(
"0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
UniswapV2Factory.abi,
wallet
);
const sushiFactory = new ethers.Contract(
"0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac",
UniswapV2Factory.abi,
wallet
);
let uniswapDaiEth;
let sushiEthDai;
const loadPairs = async () => {
uniswapDaiEth = new ethers.Contract(
await uniswapFactory.callStatic.getPair(daiAddress, wethAddress),
//"0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11",
UniswapV2Pair.abi,
wallet
);
console.log("step 1 done...........");
sushiEthDai = new ethers.Contract(
await sushiFactory.callStatic.getPair(daiAddress, wethAddress),
//"0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f",
UniswapV2Pair.abi,
wallet
);
console.log("step 2 done...........");
};
await loadPairs();
console.log("uniswapFactory.address: ", uniswapFactory.address);
console.log("sushiFactory.address: ", sushiFactory.address);
console.log("uniswapDaiEth: ", uniswapDaiEth.address);
console.log("sushiEthDai: ", sushiEthDai.address);
let uniswapReserves;
let sushiReserves;
console.log("step 1...");
uniswapReserves = await uniswapDaiEth.callStatic.getReserves();
console.log("step 2...");
const reserve0Uni = Number(ethers.utils.formatUnits(uniswapReserves[0], 18));
const reserve1Uni = Number(ethers.utils.formatUnits(uniswapReserves[1], 18));
console.log("step 3...");
sushiReserves = await sushiEthDai.callStatic.getReserves();
console.log("step 4...");
const reserve0Sushi = Number(ethers.utils.formatUnits(sushiReserves[0], 18));
const reserve1Sushi = Number(ethers.utils.formatUnits(sushiReserves[1], 18));
console.log("step 5...");
console.log("reserve0Uni: ", reserve0Uni);
console.log("reserve1Uni: ", reserve1Uni);
if (BORROW_AMOUNT <= 0) {
console.log('UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
return;
}
if (reserve0Uni <= 0 && reserve0Uni <= 0) {
console.log('UniswapV2Library: INSUFFICIENT_LIQUIDITY');
return;
}
const numerator = reserve0Uni * BORROW_AMOUNT * 1000;
const denominator = reserve1Uni - BORROW_AMOUNT * 997;
const amountRequired = (numerator / denominator) + 1;
const amounts = [];
amounts[0] = BORROW_AMOUNT;
if (BORROW_AMOUNT <= 0) {
console.log('UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
return;
}
if (reserve0Sushi <= 0 && reserve1Sushi <= 0) {
console.log('UniswapV2Library: INSUFFICIENT_LIQUIDITY');
return;
}
const amountInWithFee = BORROW_AMOUNT * 997;
const numerator2 = amountInWithFee * reserve1Sushi;
const denominator2 = reserve0Sushi * 1000 + amountInWithFee;
amounts[1] = numerator2 / denominator2;
if (amounts[amounts.length - 1] < amountRequired) {
console.log("amounts[1]: ", amounts[1], " < amountRequired: ", amountRequired);
console.log("amounts[1] / amountRequired: ", amounts[1] / amountRequired);
console.log('UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
return;
}
amountRequired, path, msg.sender, block.timestamp + 120)[1];
};
testBasic();
console.log('testBasic finished!');
Yeah, but do you have documentation about the functions - how they’re set up, what they expect, etc. From the people who made whatever module it is you’re using?
It refers to back-end solidity smart contract which I built using this documentation whereas the above front-end javascript attempts to mimic its very same execution with some output debugging incorporated due to an error UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT it spits out. This is because as you may know, Solidity does not have any console.log capability as javascript. That´s the main reason. In any case, still would like to get to the bottom of failing to return back with a token pair address based on await uniswapFactory.callStatic.getPair(daiAddress, wethAddress)
Here´s the link to the original JS script source for the above javascript code I attempted to replicate and test.
Node.js (forked) - StackBlitz
And lastly, I provide you a screendump of both contract instances of uniswapFactory and sushiFactory where I attempted to make calls to await uniswapFactory.callStatic.getPair(daiAddress, wethAddress)
and await sushiFactory.callStatic.getPair(daiAddress, wethAddress)
for uniswapDaiEth and sushiEthDai, respectively.
uniswapFactory: Contract {
interface: Interface {*
fragments: [*
[EventFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment]*
],*
_abiCoder: AbiCoder { coerceFunc: null },*
functions: {*
'getPair(address,address)': [FunctionFragment],*
'allPairs(uint256)': [FunctionFragment],*
'allPairsLength()': [FunctionFragment],*
'feeTo()': [FunctionFragment],*
'feeToSetter()': [FunctionFragment],*
'createPair(address,address)': [FunctionFragment]*
},*
errors: {},*
events: { ‘PairCreated(address,address,address,uint256)’: [EventFragment] },*
structs: {},*
deploy: ConstructorFragment {*
name: null,*
type: 'constructor',*
inputs: [],*
payable: false,*
stateMutability: 'nonpayable',*
gas: null,*
_isFragment: true*
},*
_isInterface: true*
},*
provider: InfuraProvider {*
_isProvider: true,*
_events: ,*
_emitted: { block: -2 },*
disableCcipRead: false,*
formatter: Formatter { formats: [Object] },*
anyNetwork: false,*
_network: {*
name: 'homestead',*
chainId: 1,*
ensAddress: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',*
_defaultProvider: [Function]*
},*
_maxInternalBlockNumber: -1024,*
_lastBlockNumber: -2,*
_maxFilterBlockRange: 10,*
_pollingInterval: 4000,*
_fastQueryDate: 0,*
connection: {*
allowGzip: true,*
url: 'https://mainnet.infura.io/v3/6021b8788d0648c285535dc157a95e6f',*
throttleCallback: [Function: throttleCallback]*
},*
_nextId: 42,*
apiKey: ‘6021b8788d0648c285535dc157a95e6f’,*
projectId: ‘6021b8788d0648c285535dc157a95e6f’,*
projectSecret: null*
},*
signer: Wallet {*
_isSigner: true,*
_signingKey: [Function (anonymous)],*
_mnemonic: [Function (anonymous)],*
address: ‘0x825c5e7d385F9f07e2312154B0Cf3CDd06396869’,*
provider: InfuraProvider {*
_isProvider: true,*
_events: [],*
_emitted: [Object],*
disableCcipRead: false,*
formatter: [Formatter],*
anyNetwork: false,*
_network: [Object],*
_maxInternalBlockNumber: -1024,*
_lastBlockNumber: -2,*
_maxFilterBlockRange: 10,*
_pollingInterval: 4000,*
_fastQueryDate: 0,*
connection: [Object],*
_nextId: 42,*
apiKey: '6021b8788d0648c285535dc157a95e6f',*
projectId: '6021b8788d0648c285535dc157a95e6f',*
projectSecret: null*
}*
},*
callStatic: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
estimateGas: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
functions: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
populateTransaction: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
filters: {*
‘PairCreated(address,address,address,uint256)’: [Function (anonymous)],*
PairCreated: [Function (anonymous)]*
},*
_runningEvents: {},*
_wrappedEmits: {},*
address: ‘0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f’,*
resolvedAddress: Promise { },*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
}
sushiFactory: Contract {
interface: Interface {*
fragments: [*
[EventFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment],*
[FunctionFragment]*
],*
_abiCoder: AbiCoder { coerceFunc: null },*
functions: {*
'getPair(address,address)': [FunctionFragment],*
'allPairs(uint256)': [FunctionFragment],*
'allPairsLength()': [FunctionFragment],*
'feeTo()': [FunctionFragment],*
'feeToSetter()': [FunctionFragment],*
'createPair(address,address)': [FunctionFragment]*
},*
errors: {},*
events: { ‘PairCreated(address,address,address,uint256)’: [EventFragment] },*
structs: {},*
deploy: ConstructorFragment {*
name: null,*
type: 'constructor',*
inputs: [],*
payable: false,*
stateMutability: 'nonpayable',*
gas: null,*
_isFragment: true*
},*
_isInterface: true*
},*
provider: InfuraProvider {*
_isProvider: true,*
_events: ,*
_emitted: { block: -2 },*
disableCcipRead: false,*
formatter: Formatter { formats: [Object] },*
anyNetwork: false,*
_network: {*
name: 'homestead',*
chainId: 1,*
ensAddress: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',*
_defaultProvider: [Function]*
},*
_maxInternalBlockNumber: -1024,*
_lastBlockNumber: -2,*
_maxFilterBlockRange: 10,*
_pollingInterval: 4000,*
_fastQueryDate: 0,*
connection: {*
allowGzip: true,*
url: 'https://mainnet.infura.io/v3/6021b8788d0648c285535dc157a95e6f',*
throttleCallback: [Function: throttleCallback]*
},*
_nextId: 42,*
apiKey: ‘6021b8788d0648c285535dc157a95e6f’,*
projectId: ‘6021b8788d0648c285535dc157a95e6f’,*
projectSecret: null*
},*
signer: Wallet {*
_isSigner: true,*
_signingKey: [Function (anonymous)],*
_mnemonic: [Function (anonymous)],*
address: ‘0x825c5e7d385F9f07e2312154B0Cf3CDd06396869’,*
provider: InfuraProvider {*
_isProvider: true,*
_events: [],*
_emitted: [Object],*
disableCcipRead: false,*
formatter: [Formatter],*
anyNetwork: false,*
_network: [Object],*
_maxInternalBlockNumber: -1024,*
_lastBlockNumber: -2,*
_maxFilterBlockRange: 10,*
_pollingInterval: 4000,*
_fastQueryDate: 0,*
connection: [Object],*
_nextId: 42,*
apiKey: '6021b8788d0648c285535dc157a95e6f',*
projectId: '6021b8788d0648c285535dc157a95e6f',*
projectSecret: null*
}*
},*
callStatic: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
estimateGas: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
functions: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
populateTransaction: {*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
},*
filters: {*
‘PairCreated(address,address,address,uint256)’: [Function (anonymous)],*
PairCreated: [Function (anonymous)]*
},*
_runningEvents: {},*
_wrappedEmits: {},*
address: ‘0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac’,*
resolvedAddress: Promise { },*
‘getPair(address,address)’: [Function (anonymous)],*
‘allPairs(uint256)’: [Function (anonymous)],*
‘allPairsLength()’: [Function (anonymous)],*
‘feeTo()’: [Function (anonymous)],*
‘feeToSetter()’: [Function (anonymous)],*
‘createPair(address,address)’: [Function (anonymous)],*
getPair: [Function (anonymous)],*
allPairs: [Function (anonymous)],*
allPairsLength: [Function (anonymous)],*
feeTo: [Function (anonymous)],*
feeToSetter: [Function (anonymous)],*
createPair: [Function (anonymous)]*
}
Hi, did you manage to look into the docs shared with you? Any ideas, please?
Could it be something to do with the await keyword? I´m seeing below post
javascript - await does not wait for Promise to finish - Salesforce Stack Exchange . Could this be the root cause of the problem do you think?
system
Closed
December 16, 2022, 9:14pm
15
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.