many changes sorry.
This commit is contained in:
parent
4fd993ad30
commit
0c07810d06
201
index.js
201
index.js
|
@ -1,4 +1,4 @@
|
||||||
// SPHRc Liquidity Harvester Pro 2000
|
// Ubiq Token Liquidity Harvester Pro 2000
|
||||||
// License: Public Domain
|
// License: Public Domain
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,8 +16,14 @@
|
||||||
* the terminal.
|
* the terminal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const account_number = 1; // Sparrow acct num, STARTS AT ZERO, CAN'T USE TREZOR
|
// Sparrow acct num, STARTS AT ZERO, CAN'T USE TREZOR/LEDGER.
|
||||||
const loop_delay = 7200 * 1000; // 2 hours
|
// Defaults to second account ("1"), or pass a number as the first parameter
|
||||||
|
// on the command line.
|
||||||
|
const account_number = process.argv.length >= 3 ? parseInt(process.argv[2]) : 1;
|
||||||
|
|
||||||
|
// Time between runs in milliseconds, or pass a number of hours as second
|
||||||
|
// argument on command line.
|
||||||
|
const loop_delay = ( process.argv.length >= 4 ? (parseFloat(process.argv[3]) * 3600) : 7200 ) * 1000;
|
||||||
|
|
||||||
const router_address = '0xf3ce4655a44146c8eefbf45651f6479f9d67a77a';
|
const router_address = '0xf3ce4655a44146c8eefbf45651f6479f9d67a77a';
|
||||||
|
|
||||||
|
@ -30,6 +36,12 @@ const ubiq_sphr_pool_address = '0x5130bc430Ed7cD252a18B724fBa40cd1078F8C75';
|
||||||
const ricks_sphr_pool_address = '0xB934A32F065a9db4B2Df565b901276c88dc31F3E';
|
const ricks_sphr_pool_address = '0xB934A32F065a9db4B2Df565b901276c88dc31F3E';
|
||||||
const sphrc_sphr_pool_address = '0x93CdC7AF7fa7CfA9E603Cf4406acD81171A7Cfaa';
|
const sphrc_sphr_pool_address = '0x93CdC7AF7fa7CfA9E603Cf4406acD81171A7Cfaa';
|
||||||
|
|
||||||
|
const tengrans_token_address = '0x0826180A4c981d5095Cb5c48BB2A098A44cf6f73';
|
||||||
|
const tengrans_ubiq_slpt_token_address = '0x6321C294f34C2CDAF61012Ac4f3588a527F4D990';
|
||||||
|
const tengrans_pool_address = '0x9969A0123c7e7553dac5390221e321C05630d102';
|
||||||
|
|
||||||
|
const wubq_token_address = '0x1FA6A37c64804C0D797bA6bC1955E50068FbF362';
|
||||||
|
|
||||||
const pool_addresses = [
|
const pool_addresses = [
|
||||||
grans_sphr_pool_address,
|
grans_sphr_pool_address,
|
||||||
ubiq_sphr_pool_address,
|
ubiq_sphr_pool_address,
|
||||||
|
@ -40,6 +52,8 @@ const pool_addresses = [
|
||||||
const deadline_seconds = 600;
|
const deadline_seconds = 600;
|
||||||
slippage_pct = .995;
|
slippage_pct = .995;
|
||||||
|
|
||||||
|
const one_eth = '1000000000000000000';
|
||||||
|
|
||||||
const HDWalletProvider = require('@truffle/hdwallet-provider');
|
const HDWalletProvider = require('@truffle/hdwallet-provider');
|
||||||
const Web3 = require("web3");
|
const Web3 = require("web3");
|
||||||
const Contract = require('web3-eth-contract');
|
const Contract = require('web3-eth-contract');
|
||||||
|
@ -48,6 +62,14 @@ BigNumber.set({ DECIMAL_PLACES: 18, ROUNDING_MODE: BigNumber.ROUND_FLOOR })
|
||||||
|
|
||||||
const mnemonic = process.env.MNEMONIC;
|
const mnemonic = process.env.MNEMONIC;
|
||||||
|
|
||||||
|
if (mnemonic) {
|
||||||
|
console.log("Mnemonic found.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("No mnemonic found, remember to do ' export MNEMONIC=\"your seed phrase\"' before running.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const provider = new HDWalletProvider({
|
const provider = new HDWalletProvider({
|
||||||
mnemonic: {
|
mnemonic: {
|
||||||
phrase: mnemonic
|
phrase: mnemonic
|
||||||
|
@ -59,8 +81,10 @@ Contract.setProvider(provider);
|
||||||
let web3 = new Web3(provider);
|
let web3 = new Web3(provider);
|
||||||
|
|
||||||
const erc20_abi = require('./IERC20.json').abi;
|
const erc20_abi = require('./IERC20.json').abi;
|
||||||
|
const pair_abi = require('./IUniswapV2Pair.json').abi;
|
||||||
const router_abi = require('./IUniswapV2Router02.json').abi;
|
const router_abi = require('./IUniswapV2Router02.json').abi;
|
||||||
|
const factory_abi = require('./IUniswapV2Factory.json').abi;
|
||||||
|
|
||||||
const router = new Contract(router_abi, router_address);
|
const router = new Contract(router_abi, router_address);
|
||||||
|
|
||||||
console.log("Starting loop");
|
console.log("Starting loop");
|
||||||
|
@ -71,80 +95,97 @@ console.log("Starting loop");
|
||||||
const factory_address = await router.methods.factory().call();
|
const factory_address = await router.methods.factory().call();
|
||||||
console.log(`factory address: ${factory_address}`);
|
console.log(`factory address: ${factory_address}`);
|
||||||
|
|
||||||
const factory_abi = require('./IUniswapV2Factory.json').abi;
|
|
||||||
const factory = new Contract(factory_abi, factory_address);
|
const factory = new Contract(factory_abi, factory_address);
|
||||||
|
|
||||||
const pool_abi = require('./ShinobiPool.json').abi;
|
const pool_abi = require('./ShinobiPool.json').abi;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
const reward_promises = [];
|
const reward_promises = [];
|
||||||
for (const pool_address of pool_addresses) {
|
for (const pool_address of pool_addresses) {
|
||||||
reward_promises.push(
|
reward_promises.push(
|
||||||
new Promise(resolve => {
|
new Promise(resolve => {
|
||||||
const pool = new Contract(pool_abi, pool_address);
|
const pool = new Contract(pool_abi, pool_address);
|
||||||
console.log(`Calling harvest for ${pool_address}`);
|
pool.methods.earned(account).call().then(earned => {
|
||||||
pool.methods.getReward().send({ from: account }).then(() => {
|
if (earned === '0') {
|
||||||
console.log(`Harvested rewards for ${pool_address}`);
|
console.log(`No rewards for ${pool_address}`);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Calling harvest for ${pool_address}`);
|
||||||
|
pool.methods.getReward().send({ from: account }).then(() => {
|
||||||
|
console.log(`Harvested rewards for ${pool_address}`);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`There are ${reward_promises.length} pools to harvest.`);
|
console.log(`There are ${reward_promises.length} SPHR pools to harvest.`);
|
||||||
|
|
||||||
console.log("Getting rewards from all pools.")
|
|
||||||
await Promise.all(reward_promises);
|
|
||||||
console.log("Done harvesting.")
|
|
||||||
|
|
||||||
|
console.log("Getting rewards from all SPHR pools.")
|
||||||
|
if (reward_promises.length) await Promise.all(reward_promises);
|
||||||
|
console.log("Done harvesting SPHRc.")
|
||||||
|
|
||||||
const sphr = new Contract(erc20_abi, sphr_token_address);
|
const sphr = new Contract(erc20_abi, sphr_token_address);
|
||||||
const sphr_balance = await sphr.methods.balanceOf(account).call();
|
const sphr_balance = new BigNumber(await sphr.methods.balanceOf(account).call());
|
||||||
const sphr_balance_pretty = new BigNumber(sphr_balance).div('1e+8');
|
console.log(`sphere balance: ${sphr_balance.div('1e+8')}`);
|
||||||
console.log(`sphere balance: ${sphr_balance_pretty}`);
|
|
||||||
|
|
||||||
const sphrc = new Contract(erc20_abi, sphrc_token_address);
|
const sphrc = new Contract(erc20_abi, sphrc_token_address);
|
||||||
const sphrc_balance = await sphrc.methods.balanceOf(account).call();
|
const sphrc_balance = new BigNumber(await sphrc.methods.balanceOf(account).call());
|
||||||
const sphrc_balance_pretty = new BigNumber(sphrc_balance).div('1e+18');
|
console.log(`spherec balance: ${sphrc_balance.div('1e+18')}`);
|
||||||
console.log(`spherec balance: ${sphrc_balance_pretty}`);
|
|
||||||
|
|
||||||
if (new BigNumber(sphr_balance).isZero() || new BigNumber(sphrc_balance).lt('1000000000000000000')) {
|
if (sphr_balance.isZero() || sphrc_balance.lt(one_eth)) {
|
||||||
console.log("sphere or spherec balance too low, skipping this step.")
|
console.log("sphere or spherec balance too low, skipping this step.")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const pair_address = await factory.methods.getPair(sphr_token_address, sphrc_token_address).call();
|
const pair_address = await factory.methods.getPair(sphr_token_address, sphrc_token_address).call();
|
||||||
const pair_abi = require('./IUniswapV2Pair.json').abi;
|
|
||||||
const pair = new Contract(pair_abi, pair_address);
|
const pair = new Contract(pair_abi, pair_address);
|
||||||
const reserves = await pair.methods.getReserves().call();
|
const reserves = await pair.methods.getReserves().call();
|
||||||
console.log(`reserve0: ${reserves.reserve0}, reserve1: ${reserves.reserve1}`);
|
// console.log(`reserve0: ${reserves.reserve0}, reserve1: ${reserves.reserve1}`);
|
||||||
|
|
||||||
const sphr_sphrc_ratio = new BigNumber(reserves.reserve0).div(reserves.reserve1);
|
const sphr_sphrc_ratio = new BigNumber(reserves.reserve0).div(reserves.reserve1);
|
||||||
console.log(`ratio of sphr to sphrc: ${sphr_sphrc_ratio}`);
|
console.log(`ratio of sphr to sphrc: ${sphr_sphrc_ratio}`);
|
||||||
const needed_sphr = new BigNumber(sphrc_balance).times(sphr_sphrc_ratio).integerValue().toString();
|
const needed_sphr = sphrc_balance.times(sphr_sphrc_ratio).integerValue();
|
||||||
console.log(`needed sphere: ${new BigNumber(needed_sphr).div('1e+8')}`);
|
// console.log(`needed sphere: ${needed_sphr.div('1e+8')}`);
|
||||||
|
|
||||||
if (new BigNumber(needed_sphr).gt(sphr_balance)) {
|
if (sphrc_balance.isZero() || sphr_balance.isZero()) {
|
||||||
console.log("Not enough sphr, skipping this step.");
|
console.log("Not enough SPHR/SPHRc, skipping this step.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
let usedSphr;
|
||||||
|
let usedSphrc;
|
||||||
|
|
||||||
|
const use_full_sphr_balance = needed_sphr.lte(sphr_balance);
|
||||||
|
if (use_full_sphr_balance) {
|
||||||
|
usedSphr = needed_sphr;
|
||||||
|
usedSphrc = sphrc_balance;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usedSphr = sphr_balance;
|
||||||
|
usedSphrc = sphr_balance.div(sphr_sphrc_ratio).integerValue();
|
||||||
|
}
|
||||||
|
console.log(`Will use ${usedSphr.div('1e+8')} SPHR, ${usedSphrc.div('1e+18')} SPHRc.`);
|
||||||
|
|
||||||
// account for slippage
|
// account for slippage
|
||||||
const sphr_min_desired = new BigNumber(needed_sphr).times(slippage_pct).integerValue().toString();
|
const sphr_min_desired = usedSphr.times(slippage_pct).integerValue().toString();
|
||||||
const sphrc_min_desired = new BigNumber(sphrc_balance).times(slippage_pct).integerValue().toString()
|
const sphrc_min_desired = usedSphrc.times(slippage_pct).integerValue().toString();
|
||||||
console.log(`desired: ${new BigNumber(sphr_min_desired).div('1e+8')} ${new BigNumber(sphrc_min_desired).div('1e+18')}`);
|
|
||||||
|
|
||||||
// make sure both tokens are approved for the amounts
|
// make sure both tokens are approved for the amounts
|
||||||
const approval_promises = [];
|
const approval_promises = [];
|
||||||
|
|
||||||
const sphr_allowance = await sphr.methods.allowance(account, router_address).call();
|
const sphr_allowance = new BigNumber(await sphr.methods.allowance(account, router_address).call());
|
||||||
if (new BigNumber(sphr_allowance).lt(needed_sphr)) {
|
if (sphr_allowance.lt(usedSphr)) {
|
||||||
console.log("Sphere allowance isn't big enough, approving now.");
|
console.log("SPHR allowance isn't big enough, approving now.");
|
||||||
approval_promises.push( sphr.methods.approve(router_address, needed_sphr).send({ from: account }) );
|
approval_promises.push( sphr.methods.approve(router_address, usedSphr.toString()).send({ from: account }) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const sphrc_allowance = await sphrc.methods.allowance(account, router_address).call()
|
const sphrc_allowance = new BigNumber(await sphrc.methods.allowance(account, router_address).call());
|
||||||
if (new BigNumber(sphrc_allowance).lt(sphrc_balance)) {
|
if (sphrc_allowance.lt(usedSphrc)) {
|
||||||
console.log("Sphere Cubed allowance isn't big enough, approving now.");
|
console.log("SPHRc allowance isn't big enough, approving now.");
|
||||||
approval_promises.push( sphrc.methods.approve(router_address, sphrc_balance).send({ from: account }) );
|
approval_promises.push( sphrc.methods.approve(router_address, usedSphrc.toString()).send({ from: account }) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (approval_promises.length) {
|
if (approval_promises.length) {
|
||||||
|
@ -153,12 +194,12 @@ console.log("Starting loop");
|
||||||
|
|
||||||
const deadline = Math.floor(Date.now() / 1000) + deadline_seconds;
|
const deadline = Math.floor(Date.now() / 1000) + deadline_seconds;
|
||||||
|
|
||||||
console.log('Adding liquidity to Shinobi.');
|
console.log('Adding SPHR/SPHRc liquidity to Shinobi in exchange for SLPT tokens.');
|
||||||
await router.methods.addLiquidity(
|
await router.methods.addLiquidity(
|
||||||
sphr_token_address,
|
sphr_token_address,
|
||||||
sphrc_token_address,
|
sphrc_token_address,
|
||||||
needed_sphr,
|
usedSphr.toString(),
|
||||||
sphrc_balance,
|
usedSphrc.toString(),
|
||||||
sphr_min_desired,
|
sphr_min_desired,
|
||||||
sphrc_min_desired,
|
sphrc_min_desired,
|
||||||
account,
|
account,
|
||||||
|
@ -171,7 +212,7 @@ console.log("Starting loop");
|
||||||
const slpt_balance = await slpt.methods.balanceOf(account).call();
|
const slpt_balance = await slpt.methods.balanceOf(account).call();
|
||||||
|
|
||||||
if ( new BigNumber(slpt_balance).isZero() ) {
|
if ( new BigNumber(slpt_balance).isZero() ) {
|
||||||
console.log("No new SLPT to stake.")
|
console.log("No new SPHR/SPHRc SLPT to stake.")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(`SLPT balance: ${new BigNumber(slpt_balance).div('1e+18')}`);
|
console.log(`SLPT balance: ${new BigNumber(slpt_balance).div('1e+18')}`);
|
||||||
|
@ -188,6 +229,80 @@ console.log("Starting loop");
|
||||||
await sphr_sphrc_pool.methods.stake(slpt_balance).send({ from: account });
|
await sphr_sphrc_pool.methods.stake(slpt_balance).send({ from: account });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tengrans = new Contract(erc20_abi, tengrans_token_address);
|
||||||
|
const tengrans_pool = new Contract(pool_abi, tengrans_pool_address);
|
||||||
|
console.log("Harvesting 10grans rewards");
|
||||||
|
await tengrans_pool.methods.getReward().send({ from: account });
|
||||||
|
const tengrans_balance = new BigNumber(await tengrans.methods.balanceOf(account).call());
|
||||||
|
const ubiq_balance = new BigNumber(await web3.eth.getBalance(account));
|
||||||
|
console.log(`10grans balance: ${tengrans_balance.div('1e+18')}`);
|
||||||
|
|
||||||
|
if (tengrans_balance.lt('1000000000000000')) {
|
||||||
|
console.log("Not enough 10grans to stake, skipping.");
|
||||||
|
}
|
||||||
|
else if (ubiq_balance.lt(one_eth)) {
|
||||||
|
console.log("Not enough ubiq to stake, skipping.")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const pair_address = await factory.methods.getPair(tengrans_token_address, wubq_token_address).call();
|
||||||
|
const pair = new Contract(pair_abi, pair_address);
|
||||||
|
const reserves = await pair.methods.getReserves().call();
|
||||||
|
console.log(`reserve0: ${reserves.reserve0}, reserve1: ${reserves.reserve1}`);
|
||||||
|
|
||||||
|
const grans_ubiq_ratio = new BigNumber(reserves.reserve1).div(reserves.reserve0);
|
||||||
|
console.log(`10grans/ubiq reserves ratio: ${grans_ubiq_ratio}`);
|
||||||
|
|
||||||
|
const needed_ubiq = new BigNumber(tengrans_balance).times(grans_ubiq_ratio).integerValue();
|
||||||
|
console.log(`needed ubiq: ${needed_ubiq.div('1e+18')}`);
|
||||||
|
|
||||||
|
if (ubiq_balance.lt(needed_ubiq)) {
|
||||||
|
console.log("Not enough ubiq to stake 10grans, skipping.")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// account for slippage
|
||||||
|
const grans_min_desired = tengrans_balance.times(slippage_pct).integerValue().toString();
|
||||||
|
const ubiq_min_desired = needed_ubiq.times(slippage_pct).integerValue().toString()
|
||||||
|
|
||||||
|
const grans_allowance = new BigNumber(await tengrans.methods.allowance(account, router_address).call());
|
||||||
|
console.log(`10grans allowance: ${grans_allowance.div('1e+18')}`);
|
||||||
|
if (grans_allowance.lt(tengrans_balance)) {
|
||||||
|
console.log("10grans allowance for Shinobi isn't big enough, approving now.");
|
||||||
|
await tengrans.methods.approve(router_address, tengrans_balance.toString()).send({from: account});
|
||||||
|
}
|
||||||
|
|
||||||
|
const deadline = Math.floor(Date.now() / 1000) + deadline_seconds;
|
||||||
|
|
||||||
|
console.log("Adding liquidity to Shinobi.");
|
||||||
|
await router.methods.addLiquidityETH(
|
||||||
|
tengrans_token_address,
|
||||||
|
tengrans_balance.toString(),
|
||||||
|
grans_min_desired,
|
||||||
|
ubiq_min_desired,
|
||||||
|
account,
|
||||||
|
deadline
|
||||||
|
).send({ from: account, value: needed_ubiq.toString() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const grans_slpt = new Contract(erc20_abi, tengrans_ubiq_slpt_token_address);
|
||||||
|
const grans_slpt_balance = new BigNumber(await grans_slpt.methods.balanceOf(account).call());
|
||||||
|
console.log(`SLPT balance: ${grans_slpt_balance.div('1e+18')}`);
|
||||||
|
|
||||||
|
if (grans_slpt_balance.isZero()) {
|
||||||
|
console.log("No 10grans/Ubiq SLPT to stake.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const grans_slpt_allowance = new BigNumber(await grans_slpt.methods.allowance(account, tengrans_pool_address).call());
|
||||||
|
|
||||||
|
if (grans_slpt_allowance.lt(grans_slpt_balance)) {
|
||||||
|
console.log("10grans staking pool allowance isn't big enough, approving now.");
|
||||||
|
await grans_slpt.methods.approve(tengrans_pool_address, grans_slpt_balance.toString()).send({ from: account });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Staking SLPT tokens.");
|
||||||
|
await tengrans_pool.methods.stake(grans_slpt_balance.toString()).send({ from: account });
|
||||||
|
}
|
||||||
|
|
||||||
console.log("Waiting for a while...");
|
console.log("Waiting for a while...");
|
||||||
await new Promise(resolve => setTimeout(resolve, loop_delay));
|
await new Promise(resolve => setTimeout(resolve, loop_delay));
|
||||||
console.log("Done waiting, resuming.");
|
console.log("Done waiting, resuming.");
|
||||||
|
|
Loading…
Reference in New Issue