NodeJS Uniswap USDC=>ETH交换

mrphzbgm  于 2023-02-08  发布在  Node.js
关注(0)|答案(1)|浏览(128)

尝试通过Uniswap和以太网将USDC交换到ETH,但一直出错。

async function swapUsdcToEth(amount, walledAddress) {
  const usdc = await Fetcher.fetchTokenData(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
  const eth = await Fetcher.fetchTokenData(chainId, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2');
  const pair = await Fetcher.fetchPairData(usdc, eth);
  const route = new Route([pair], usdc);
  const amountIn = new TokenAmount(usdc, amount);
  const trade = new Trade(route, amountIn, TradeType.EXACT_INPUT);
  const slippageTolerance = new Percent('50', '10000');
  const value = ethers.BigNumber.from(trade.inputAmount.raw.toString()).toHexString();
  const amountOutMin = ethers.BigNumber.from(trade.minimumAmountOut(slippageTolerance).raw.toString()).toHexString();
  const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
  const uniswapRouterV2Address = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';
  const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/b9fkdmkdkdv4937b52ea9637cf1d1bd');
  const signer = new ethers.Wallet(walledAddress, provider);
  const uniswap = new ethers.Contract(
    uniswapRouterV2Address,
    ['function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'],
    signer
  );
  try {
    const tx = await uniswap.swapExactTokensForETH(value, amountOutMin, [walledAddress], walledAddress, deadline);
    const receipt = await tx.wait();
    console.log('transaction was mined in block', receipt.blockNumber);
  } catch (e) {
    console.log(e);
  }
}

接收错误如下:'错误:无法估计气体;交易可能失败或可能需要手动气体限制“。我做错了什么?

nwsw7zdq

nwsw7zdq1#

所以看起来可能有几件事。你批准你的令牌被路由器使用了吗?而且我没有看到任何气体设置在那里
这是一个工作版本,我已经修改,使工作(这是设置测试在一个主网分支,但它使用的实时数据(作为阿尔法路由器是只为主网活,所以实时数据和分支数据将随着时间的推移而变化,并导致交易错误,所以重置分支使用前)
使主网只取出本地提供商,将所有提供商改为主网提供商。
谨慎使用,我不完美,不作任何保证:检查滑动和所有变量
这是作为TOKEN到TOKEN Exact_Input交换构建的,WETH存款为1 ETH。要使用ETH,您可以在批准中删除Weth存款和令牌,并使用BigNumber.from(typedValueParsed)作为事务的值,而不是0
由于我不知道EtherJS的天然气价格和天然气限额的存款和批准是一个单位100 gwei和300k的限制,并应修改为目前的网络天然气价格和估计的天然气限额。

import { AlphaRouter } from '@uniswap/smart-order-router'
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
import { JSBI, Percent } from "@uniswap/sdk";
import { ethers, BigNumber } from "ethers";

const V3_SWAP_ROUTER_ADDRESS = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45";

const TokenInput = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";

const TokenOutput = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

const web3Provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.alchemyapi.io/v2/");
const web3 = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545/");

const privateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
const wallet = new ethers.Wallet(privateKey,web3);
const address = wallet.address;

import * as fs from 'fs';

let UniV3RouterAbi = fs.readFileSync('NewUniRouter.json');
const V3routerAbi = JSON.parse(UniV3RouterAbi);

let ERC20Abi = fs.readFileSync('ERC20.json');
const ERC20 = JSON.parse(ERC20Abi);

let WETHAbij = fs.readFileSync('WETHAbi.json');
const WETHAbi = JSON.parse(WETHAbij);

async function log(inpt){
    console.log(inpt);
    console.log("");
}

async function TokBal(tokens){
    var ERC20contract =  new ethers.Contract(tokens, ERC20, web3);
    var myERC20bal = await ERC20contract.balanceOf(wallet.address);
    return myERC20bal;
}

async function Deposit(amt){
    var WethC =  new ethers.Contract(TokenInput, WETHAbi, web3);
    var datac = await WethC.populateTransaction["deposit"]();
    var ncn = await wallet.getTransactionCount();

    const transaction = {
      data: datac.data,
      nonce: ncn,
      to: TokenInput,
      value: BigNumber.from(amt),
      from: wallet.address,
      gasPrice: '0x174876e800',
      gasLimit: '0x493e0',
    };

    const signedTx = await wallet.signTransaction(transaction);
    const txHash =  await web3.sendTransaction(signedTx);
    log(txHash.hash);
}

async function Approve(Toked, amt){
    var WethC =  new ethers.Contract(Toked, ERC20, web3);
    var datac = await WethC.populateTransaction["approve"](V3_SWAP_ROUTER_ADDRESS, amt);
    var ncn = await wallet.getTransactionCount();

    const transaction = {
      data: datac.data,
      nonce: ncn,
      to: Toked,
      value: BigNumber.from("0"),
      from: wallet.address,
      gasPrice: '0x174876e800',
      gasLimit: '0x493e0',
    };

    const signedTx = await wallet.signTransaction(transaction);
    const txHash =  await web3.sendTransaction(signedTx);
    log(txHash.hash);
    var appFor = await WethC.callStatic.allowance(wallet.address, V3_SWAP_ROUTER_ADDRESS);
    log("Approved : "+appFor.toString());
}

const router = new AlphaRouter({ chainId: 1, provider: web3Provider });
const WETH = new Token(
  router.chainId,
  '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
  18,
  'WETH',
  'Wrapped Ether'
);

const USDC = new Token(
  router.chainId,
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  6,
  'USDC',
  'USD//C'
);

const typedValueParsed = '1000000000000000000';
const wethAmount = CurrencyAmount.fromRawAmount(WETH, JSBI.BigInt(typedValueParsed));

const IO = "Exact_Input"
const TradeType = IO == "Exact_Input" ? 0 : 1;

const route = await router.route(
  wethAmount,
  USDC,
  TradeType,
  {
    recipient: wallet.address,
    slippageTolerance: new Percent(5, 100),
    deadline: Math.floor(Date.now()/1000 +1800)
  }
);

var Ebal = await web3.getBalance(wallet.address);
log("Wallet Balance : "+Ebal.toString());

var tbal = await TokBal(TokenOutput);
log("Token Out Balance : "+tbal.toString());

await Deposit("1000000000000000000");
await Approve(TokenInput,"1000000000000000000");
var tbalW = await TokBal(TokenInput);
log("Token In Balance : "+tbalW.toString());

log(`Quote Exact In: ${route.quote.toFixed(wethAmount.currency === WETH ? USDC.decimals : WETH.decimals)}`);
log(`Gas Adjusted Quote In: ${route.quoteGasAdjusted.toFixed(wethAmount.currency === WETH ? USDC.decimals : WETH.decimals)}`);

var nc = await wallet.getTransactionCount();

const transaction = {
  data: route.methodParameters.calldata,
  nonce: nc,
  to: V3_SWAP_ROUTER_ADDRESS,
  value: BigNumber.from(0),
  from: wallet.address,
  gasPrice: BigNumber.from(route.gasPriceWei),
  gasLimit: BigNumber.from(route.estimatedGasUsed).add(BigNumber.from("50000")),
};

const signedTx = await wallet.signTransaction(transaction);

const PretxHash = ethers.utils.keccak256(signedTx);

const txHash =  await web3.sendTransaction(signedTx)
log(txHash.hash);

var Ebal = await web3.getBalance(wallet.address);
log("Wallet Balance : "+Ebal.toString());

var tbal = await TokBal(TokenOutput);
log("Token Out Balance : "+tbal.toString());

var tbalW = await TokBal(TokenInput);
log("Token In Balance : "+tbalW.toString());

要获取ETH,请使用此标记代替输出标记

outPutAddress === WETH9[chainId].address ? nativeOnChain(chainId) : outPutToken,

编辑〉〉〉〉〉〉〉〉〉〉修改为新版本

import { ethers } from 'ethers'
import {AlphaRouter, ChainId, SwapType, nativeOnChain} from '@uniswap/smart-order-router'
import { TradeType, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { TickMath } from '@uniswap/v3-sdk';
import JSBI from 'jsbi';
import bn from 'bignumber.js'

async function main() {
  const MY_ADDRESS = "<ADDRESS>";
  const web3Provider = new ethers.providers.JsonRpcProvider('https://eth-mainnet.alchemyapi.io/v2/<RPC_KEY>')

  const router = new AlphaRouter({ chainId: 1, provider: web3Provider });
  
  const WETH = new Token(
    1,
    '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
    18,
    'WETH',
    'Wrapped Ether'
  );

  const USDC = new Token(
    ChainId.MAINNET,
    '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
    6,
    'USDC',
    'USD//C'
  );

  const AAVE = new Token(
    ChainId.MAINNET,
    '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
    18,
    'AAVE',
    'AAVE'
  );

  const options = {
      recipient: MY_ADDRESS,
      slippageTolerance: new Percent(10, 1000),
      deadline: Math.floor(Date.now() / 1000 + 1800),
      type: SwapType.SWAP_ROUTER_02,
    }
  const typedValueParsed = '10000000000000000000'
  
  const route = await router.route(
      CurrencyAmount.fromRawAmount(
        AAVE,
        typedValueParsed.toString()
      ),
      nativeOnChain(ChainId.MAINNET),
      TradeType.EXACT_INPUT,
      options
    )

  console.log(`Quote Exact In: ${route.quote.toFixed(route.quote.currency.decimals)}`);
  console.log(`Gas Adjusted Quote In: ${route.quoteGasAdjusted.toFixed(route.quote.currency.decimals)}`);
  console.log(`Gas Used USD: ${route.estimatedGasUsedUSD.toFixed(2)}`);
  console.log(route.methodParameters.calldata);
}

main()

相关问题