Oriok
Oriok

Reputation: 55

Hardhat, ether.js. TypeError: deployer.sendTransaction is not a function error. Trying to execute exactInput UniswapV3 function

Im trying to execute a swap to buy Uni using UniswapV3 interface. It sends me this error related to the sendTransaction() function and I dont understand why as a lot of examples that I have seen use it this way.

Im using hardhat as you can see and calling the getToken() from another script and deploying on goerli network. Function to check UNI wallet balnceOf() at the end works fine.

Also what advice would you recommend me to improve my code?

This is the code:

const { ethers, getNamedAccounts, network } = require("hardhat")
const {abi: V3SwapRouterABI} = require('@uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')

const FEE_SIZE = 3

function encodePath(path, fees) {
    if (path.length != fees.length + 1) {
        throw new Error('path/fee lengths do not match')
    }

    let encoded = '0x'
    for (let i = 0; i < fees.length; i++) {
        // 20 byte encoding of the address
        encoded += path[i].slice(2)
        // 3 byte encoding of the fee
        encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
    }
    // encode the final token
    encoded += path[path.length - 1].slice(2)

    return encoded.toLowerCase()
    }

async function getToken() {

    // const signer = provider.getSigner()
    const deadline = Math.floor(Date.now()/1000) + (60*10)
    const wethToken= "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
    const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
    const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    const path = encodePath([wethToken, Uni], [3000])
    console.log(path)
    
    const { deployer } = await getNamedAccounts()
    const UniV3Contract = await ethers.getContractAt(
        V3SwapRouterABI,
        UniswapRouter,
        deployer
    )

    const params = {
        path: path,
        recipient:deployer,
        deadline: deadline,
        amountIn: ethers.utils.parseEther('0.01'),
        amountOutMinimum: 0
    }

    const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])

    const txArg = {
        to: UniswapRouter,
        from: deployer,
        data: encodedData,
        gasLimit: ethers.utils.hexlify(1000000)
    }

    const tx = await deployer.sendTransaction(txArg)
    console.log('tx: ', tx)

    const IUni = await ethers.getContractAt(
        "IERC20",
        Uni,
        deployer
    )
    const UniBlance = await IUni.balanceOf(deployer)
    console.log(`Got ${UniBlance.toString()} UNI`)
}

module.exports = { getToken }

Without using the hardhat enviorment:

const {abi: V3SwapRouterABI} = require('@uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const { ethers } = require("ethers")
require("dotenv").config()

const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET
const PRIVATE_KEY = process.env.PRIVATE_KEY
const WALLET_ADDRESS = process.env.WALLET_ADDRESS
// now you can call sendTransaction 


const wethToken= "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
const UniV3Contract = new ethers.Contract(
    UniswapRouter,
    V3SwapRouterABI
)

const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET)
const wallet = new ethers.Wallet(PRIVATE_KEY)
const signer = wallet.connect(provider)


const FEE_SIZE = 3

function encodePath(path, fees) {
    if (path.length != fees.length + 1) {
        throw new Error('path/fee lengths do not match')
    }

    let encoded = '0x'
    for (let i = 0; i < fees.length; i++) {
        // 20 byte encoding of the address
        encoded += path[i].slice(2)
        // 3 byte encoding of the fee
        encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
    }
    // encode the final token
    encoded += path[path.length - 1].slice(2)

    return encoded.toLowerCase()
    }

async function getToken() {

    const path = encodePath([wethToken, Uni], [3000])
    const deadline = Math.floor(Date.now()/1000) + (60*10)  

    const params = {
        path: path,
        recipient: WALLET_ADDRESS,
        deadline: deadline,
        amountIn: ethers.utils.parseEther('0.01'),
        amountOutMinimum: 0
    }

    const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])

    const txArg = {
        to: UniswapRouter,
        from: WALLET_ADDRESS,
        data: encodedData,
        gasLimit: ethers.utils.hexlify(1000000)
    }

    const tx = await signer.sendTransaction(txArg)
    console.log('tx: ', tx)
    const receipt = tx.wait()
    console.log('receipt: ', receipt)

}

module.exports = { getToken }

Upvotes: 0

Views: 1083

Answers (1)

Yilmaz
Yilmaz

Reputation: 49263

I could not find documentation for getNamedAccounts but when I check the source code, I get this signature

getNamedAccounts: () => Promise<{
      [name: string]: Address;
    }>;

this just returns an array of account addresses and used in hardhat.config.js

namedAccounts: {
    deployer: {
        default: 0, // by default take the first account as deployer
        1: 0,
    },
},

to send the transaction programmatically:

const { ethers } = require("ethers");

const provider = new ethers.providers.JsonRpcProvider(INFURA_TEST_URL);

const wallet = new ethers.Wallet(WALLET_SECRET);
const signer = wallet.connect(provider);
// now you can call sendTransaction
const tx = await signer.sendTransaction(txArg);

Upvotes: 1

Related Questions