Skip to content

Instantly share code, notes, and snippets.

@cswiger
Last active October 4, 2022 23:13
Show Gist options
  • Save cswiger/6faf9aeb1b5973f1d5b72126f6682820 to your computer and use it in GitHub Desktop.
Save cswiger/6faf9aeb1b5973f1d5b72126f6682820 to your computer and use it in GitHub Desktop.
uniswapv3_goerli_swap-add
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "subtractedValue",
"type": "uint256"
}
],
"name": "decreaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":true,"internalType":"int24","name":"tickSpacing","type":"int24"}],"name":"FeeAmountEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolCreated","type":"event"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"}],"name":"createPool","outputs":[{"internalType":"address","name":"pool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickSpacing","type":"int24"}],"name":"enableFeeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"","type":"uint24"}],"name":"feeAmountTickSpacing","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint24","name":"","type":"uint24"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parameters","outputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickSpacing","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"}]
require('dotenv').config();
const { ethers } = require('ethers');
const { Token, CurrencyAmount, TradeType, Percent, Fraction } = require('@uniswap/sdk-core');
const { BigNumber } = require('ethers');
const { Pool, Position, nearestUsableTick } = require('@uniswap/v3-sdk');
const { abi: IUniswapV3PoolABI } = require('@uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json');
const { abi: INonfungiblePositionManagerABI } = require('@uniswap/v3-periphery/artifacts/contracts/interfaces/INonfungiblePositionManager.sol/INonfungiblePositionManager.json');
const ERC20ABI = require('./abi.json');
const factoryABI = require('./factory.json');
const { AlphaRouter } = require('@uniswap/smart-order-router');
const { SwapToRatioStatus } = require('@uniswap/smart-order-router');
const WALLET_ADDRESS=process.env.WALLET_ADDRESS
const WALLET_SECRET=process.env.WALLET_SECRET;
const provider = new ethers.providers.JsonRpcProvider(process.env.INFURA_URL_GOERLI);
const positionManagerAddress = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
const factoryAddress = '0x1F98431c8aD98523631AE4a59f267346ea31F984';
const factoryContract = new ethers.Contract(factoryAddress,factoryABI,provider);
const WETHAddress = '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6';
const UNIAddress = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984';
const fee = 500;
var poolAddress = await factoryContract.getPool(WETHAddress,UNIAddress,fee);
const name0 = 'Wrapped Ether';
const symbol0 = 'WETH';
const decimals0 = 18;
const address0 = WETHAddress;
const name1 = 'UNI';
const symbol1 = 'UNI';
const decimals1 = 18;
const address1 = UNIAddress;
const chainId = provider.network.chainId;
const WethToken = new Token(chainId,address0,decimals0,symbol0,name0);
const UNIToken = new Token(chainId,address1,decimals1,symbol1,name1);
const nonfungiblePositionManagerContract = new ethers.Contract(positionManagerAddress,INonfungiblePositionManagerABI,provider);
const poolContract = new ethers.Contract(poolAddress,IUniswapV3PoolABI,provider);
const getPoolData = async (poolContract) => {
const [tickSpacing, fee, liquidity, slot0] = await Promise.all([
poolContract.tickSpacing(),
poolContract.fee(),
poolContract.liquidity(),
poolContract.slot0()
])
return {
tickSpacing: tickSpacing,
fee: fee,
liquidity: liquidity,
sqrtPriceX96: slot0[0],
tick: slot0[1],
}
}
var poolData = await getPoolData(poolContract);
const WETH_UNI_POOL = new Pool(
WethToken,
UNIToken,
poolData.fee,
poolData.sqrtPriceX96.toString(),
poolData.liquidity.toString(),
poolData.tick)
const position = new Position({
pool: WETH_UNI_POOL,
liquidity: ethers.utils.parseUnits('1',18),
tickLower: nearestUsableTick(poolData.tick, poolData.tickSpacing) - poolData.tickSpacing * 10,
tickUpper: nearestUsableTick(poolData.tick, poolData.tickSpacing) + poolData.tickSpacing * 10,
});
const wallet = new ethers.Wallet(WALLET_SECRET);
const connectedWallet = wallet.connect(provider);
const approvalAmount = ethers.utils.parseUnits('10',18);
const tokenContract0 = new ethers.Contract(address0,ERC20ABI,provider);
const tokenContract1 = new ethers.Contract(address1,ERC20ABI,provider);
// mebbe we need to approve THIS instead of the position manager?
// to submit a transaction based on above results
const V3_SWAP_ROUTER_ADDRESS = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45";
var res = await tokenContract0.connect(connectedWallet).approve(
V3_SWAP_ROUTER_ADDRESS,
approvalAmount);
var res = await tokenContract1.connect(connectedWallet).approve(
V3_SWAP_ROUTER_ADDRESS,
approvalAmount);
const router = new AlphaRouter({ chainId: provider.network.chainId, provider: provider });
var token0Balance = CurrencyAmount.fromRawAmount(WethToken, ethers.utils.parseUnits('.1',WethToken.decimals));
var token1Balance = CurrencyAmount.fromRawAmount(UNIToken, '0');
var response = await router.routeToRatio(
token0Balance,
token1Balance,
position,
{
ratioErrorTolerance: new Fraction(1, 100),
maxIterations: 6,
},
{
addLiquidityOptions: {
recipient: WALLET_ADDRESS,
},
swapOptions: {
deadline: Math.floor( Date.now() / 1000 + (10 * 60)),
recipient: WALLET_ADDRESS,
slippageTolerance: new Percent(5, 100),
},
},
);
// to submit a transaction based on above results
var route = response.result;
var transaction = {
data: route.methodParameters.calldata,
to: V3_SWAP_ROUTER_ADDRESS,
value: BigNumber.from(route.methodParameters.value),
from: WALLET_ADDRESS,
gasPrice: BigNumber.from(route.gasPriceWei),
gasLimit: ethers.utils.hexlify(1000000)
};
var tradeTransaction = await connectedWallet.sendTransaction(transaction);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment