Skip to content

Commit

Permalink
feat: RPC_URL support (#330)
Browse files Browse the repository at this point in the history
  • Loading branch information
valiafetisov authored Jul 4, 2022
1 parent f618ecd commit 948f56f
Show file tree
Hide file tree
Showing 47 changed files with 407 additions and 313 deletions.
14 changes: 5 additions & 9 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ data:
build_args:
- key: PRODUCTION_DOMAIN
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/production_domain
- key: INFURA_PROJECT_ID
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/infura_project_id
- key: RPC_URL
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/rpc_url
- key: CONTACT_EMAIL
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/contact_email
- key: STAGING_BANNER_URL
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/staging_banner_url
- key: DEFAULT_ETHEREUM_NETWORK
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/default_etherum_network
- key: HEAPIO_ID
value_from_secret: auction-ui/main.auction-ui.k8s.sidestream.tech/frontend/heapio_id
tags_to_cache_from:
Expand Down Expand Up @@ -59,7 +57,7 @@ data:
build_args:
- key: PRODUCTION_DOMAIN
value: "null.sidestream.tech"
- key: INFURA_PROJECT_ID
- key: RPC_URL
value: "key-not-provided"
- key: CONTACT_EMAIL
value: "[email protected]"
Expand All @@ -82,12 +80,10 @@ data:
build_args:
- key: PRODUCTION_DOMAIN
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/production_domain
- key: INFURA_PROJECT_ID
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/infura_project_id
- key: RPC_URL
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/rpc_url
- key: CONTACT_EMAIL
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/contact_email
- key: DEFAULT_ETHEREUM_NETWORK
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/default_etherum_network
- key: HEAPIO_ID
value_from_secret: auction-ui/production.auction-ui.k8s.sidestream.tech/frontend/heapio_id
tags_to_cache_from:
Expand Down
5 changes: 1 addition & 4 deletions bot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ $ npm run start

## Environment variables

- `INFURA_PROJECT_ID`: (required) [infura](https://infura.io/) project id (can be found in: dashboard -> ethereum ->
create new project -> settings -> keys). Note: this project can not be restricted by the origin.
- `ETHEREUM_NETWORK`: (optional, default `kovan`) – internal network name on which the bot poll for auctions. Available
- `RPC_URL`: (required) Etherium RPC url used for fetching data from the blockchain and participating in the auctions
- `WHITELISTED_COLLATERALS`: (optional) a comma-separated list of collaterals the bot will fetch. Example: `MATIC-A, UNI-A`
- `MAX_PRIORITY_FEE_PER_GAS_WEI`: (optional, default can be found in core/src/gas.ts) – [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) `max_priority_fee_per_gas` value
options can be found in [constants/NETWORKS](../core/src/constants/NETWORKS.ts)
- `REFETCH_INTERVAL`: (optional, default 60 seconds) – interval between auction fetching requests
- `KEEPER_*`: (optional) set of env variables to enable keeper bot:
- `KEEPER_WALLET_PRIVATE_KEY`: (required) The wallet private key (https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key)
Expand Down
2 changes: 1 addition & 1 deletion bot/src/auctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const getNewAuctionsFromActiveAuctions = function (activeActions: Auction
};

export const getAllAuctions = async function (network: string): Promise<AuctionInitialInfo[]> {
const collaterals = await getWhitelistedCollaterals();
const collaterals = await getWhitelistedCollaterals(network);
const auctions = await fetchAllInitialAuctions(network, collaterals);

const auctionIds = auctions.map(auction => `"${auction.id}"`).join(', ');
Expand Down
33 changes: 16 additions & 17 deletions bot/src/authorisation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,30 @@ import {
getCollateralAuthorizationStatus,
getWalletAuthorizationStatus,
} from 'auctions-core/src/authorizations';
import { ETHEREUM_NETWORK, KEEPER_PREAUTHORIZE } from './variables';
import { KEEPER_PREAUTHORIZE } from './variables';
import { getWhitelistedCollaterals } from './whitelist';

export async function checkAndAuthorizeWallet(walletAddress: string): Promise<boolean> {
const isWalletAuth = await getWalletAuthorizationStatus(ETHEREUM_NETWORK, walletAddress);
export async function checkAndAuthorizeWallet(network: string, walletAddress: string): Promise<boolean> {
const isWalletAuth = await getWalletAuthorizationStatus(network, walletAddress);

if (isWalletAuth) {
console.info(`keeper: wallet "${walletAddress}" has already been authorized`);
return false;
}

console.info(`keeper: wallet "${walletAddress}" has not been authorized yet. Attempting authorization now...`);
const transactionHash = await authorizeWallet(ETHEREUM_NETWORK, walletAddress, false);
const transactionHash = await authorizeWallet(network, walletAddress, false);
console.info(`keeper: wallet "${walletAddress}" successfully authorized via "${transactionHash}" transaction`);
return true;
}

export async function checkAndAuthorizeCollateral(walletAddress: string, collateralType: string): Promise<boolean> {
export async function checkAndAuthorizeCollateral(
network: string,
walletAddress: string,
collateralType: string
): Promise<boolean> {
// get collateral authorization status
const isCollateralAuth = await getCollateralAuthorizationStatus(ETHEREUM_NETWORK, collateralType, walletAddress);
const isCollateralAuth = await getCollateralAuthorizationStatus(network, collateralType, walletAddress);

// try to authorize the collateral then return
if (isCollateralAuth) {
Expand All @@ -37,33 +41,28 @@ export async function checkAndAuthorizeCollateral(walletAddress: string, collate
console.info(
`keeper: collateral "${collateralType}" has not been authorized on wallet "${walletAddress}" yet. Attempting authorization now...`
);
const collateralTransactionHash = await authorizeCollateral(
ETHEREUM_NETWORK,
walletAddress,
collateralType,
false
);
const collateralTransactionHash = await authorizeCollateral(network, walletAddress, collateralType, false);
console.info(
`keeper: collateral "${collateralType}" successfully authorized on wallet "${walletAddress}" via "${collateralTransactionHash}" transaction`
);
return true;
}

export async function executePreAuthorizationsIfRequested() {
export async function executePreAuthorizationsIfRequested(network: string) {
if (KEEPER_PREAUTHORIZE !== true) {
return;
}

const collaterals = await getWhitelistedCollaterals();
const collaterals = await getWhitelistedCollaterals(network);
console.info(
`keeper: "KEEPER_PREAUTHORIZE" is true. Attempting to authorize wallet and collaterals: "${collaterals.join(
', '
)}"`
);
const signer = await getSigner(ETHEREUM_NETWORK);
const signer = await getSigner(network);
const walletAddress = await signer.getAddress();
await checkAndAuthorizeWallet(walletAddress);
await checkAndAuthorizeWallet(network, walletAddress);
for (const collateral of collaterals) {
await checkAndAuthorizeCollateral(walletAddress, collateral);
await checkAndAuthorizeCollateral(network, walletAddress, collateral);
}
}
23 changes: 13 additions & 10 deletions bot/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { setTimeout as delay } from 'timers/promises';
import { getNetworkConfigByType } from 'auctions-core/src/constants/NETWORKS';
import { setupRpcUrlAndGetNetworks } from 'auctions-core/src/rpc';
import { getAllAuctions, getNewAuctionsFromActiveAuctions } from './auctions';
import notify from './notify';
import participate, { setupKeeper } from './keeper';
import { ETHEREUM_NETWORK } from './variables';
import { RPC_URL } from './variables';
import { setupTwitter } from './twitter';
import { setupWhitelist } from './whitelist';
import { executePreAuthorizationsIfRequested } from './authorisation';
Expand All @@ -12,29 +12,32 @@ const DEFAULT_REFETCH_INTERVAL = 60 * 1000;
const SETUP_DELAY = 3 * 1000;
const REFETCH_INTERVAL = parseInt(process.env.REFETCH_INTERVAL ?? '') || DEFAULT_REFETCH_INTERVAL;

const loop = async function (): Promise<void> {
const loop = async function (network: string): Promise<void> {
try {
const activeAuctions = await getAllAuctions(ETHEREUM_NETWORK);
const activeAuctions = await getAllAuctions(network);
if (activeAuctions.length === 0) {
return;
}
const newAuctions = getNewAuctionsFromActiveAuctions(activeAuctions);
newAuctions.map(notify);
participate(activeAuctions);
participate(network, activeAuctions);
} catch (error) {
console.error('loop error:', error);
}
};

const start = async function (): Promise<void> {
if (!RPC_URL) {
throw new Error('Required `RPC_URL` env variable was not provided, please refer to the readme');
}
await delay(SETUP_DELAY);
getNetworkConfigByType(ETHEREUM_NETWORK);
const { defaultNetwork: network } = await setupRpcUrlAndGetNetworks(RPC_URL);
setupWhitelist();
await setupTwitter();
await setupKeeper();
await executePreAuthorizationsIfRequested();
loop();
setInterval(loop, REFETCH_INTERVAL);
await setupKeeper(network);
await executePreAuthorizationsIfRequested(network);
loop(network);
setInterval(() => loop(network), REFETCH_INTERVAL);
};

start().catch(error => {
Expand Down
31 changes: 16 additions & 15 deletions bot/src/keeper.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { AuctionInitialInfo } from 'auctions-core/src/types';
import getSigner, { createSigner, setSigner } from 'auctions-core/src/signer';
import { bidWithCallee, enrichAuction } from 'auctions-core/src/auctions';
import { ETHEREUM_NETWORK, KEEPER_MINIMUM_NET_PROFIT_DAI, KEEPER_WALLET_PRIVATE_KEY } from './variables';
import { KEEPER_MINIMUM_NET_PROFIT_DAI, KEEPER_WALLET_PRIVATE_KEY } from './variables';
import { checkAndAuthorizeCollateral, checkAndAuthorizeWallet } from './authorisation';

let isSetupCompleted = false;
const currentlyExecutedAuctions = new Set();

export const setupKeeper = async function () {
export const setupKeeper = async function (network: string) {
if (!KEEPER_WALLET_PRIVATE_KEY) {
console.warn('keeper: KEEPER_WALLET_PRIVATE_KEY variable is not set, keeper will not run');
return;
Expand All @@ -17,8 +17,8 @@ export const setupKeeper = async function () {
return;
}
try {
setSigner(ETHEREUM_NETWORK, createSigner(ETHEREUM_NETWORK, KEEPER_WALLET_PRIVATE_KEY));
const signer = await getSigner(ETHEREUM_NETWORK);
setSigner(network, createSigner(network, KEEPER_WALLET_PRIVATE_KEY));
const signer = await getSigner(network);
const address = await signer.getAddress();
isSetupCompleted = true;
console.info(
Expand All @@ -29,16 +29,16 @@ export const setupKeeper = async function () {
}
};

const checkAndParticipateIfPossible = async function (auction: AuctionInitialInfo) {
const checkAndParticipateIfPossible = async function (network: string, auction: AuctionInitialInfo) {
// check if setupKeeper hasn't run
if (!isSetupCompleted) {
return;
}

const signer = await getSigner(ETHEREUM_NETWORK);
const signer = await getSigner(network);

// enrich the auction with more numbers
const auctionTransaction = await enrichAuction(ETHEREUM_NETWORK, auction);
const auctionTransaction = await enrichAuction(network, auction);

// check if auction became inactive or finished
if (auctionTransaction.isFinished) {
Expand Down Expand Up @@ -85,31 +85,32 @@ const checkAndParticipateIfPossible = async function (auction: AuctionInitialInf
const walletAddress = await signer.getAddress();

// try to authorize the wallet then return
const wasWalletNewlyAuthorized = await checkAndAuthorizeWallet(walletAddress);
const wasWalletNewlyAuthorized = await checkAndAuthorizeWallet(network, walletAddress);
if (wasWalletNewlyAuthorized) {
// restart auction evaluation in case authorization was executed
await checkAndParticipateIfPossible(auction);
await checkAndParticipateIfPossible(network, auction);
return;
}

// check the collateral authorization status and authorize if needed
const wasCollateralNewlyAuthorized = await checkAndAuthorizeCollateral(
network,
walletAddress,
auctionTransaction.collateralType
);
if (wasCollateralNewlyAuthorized) {
// restart auction evaluation in case authorization was executed
await checkAndParticipateIfPossible(auction);
await checkAndParticipateIfPossible(network, auction);
return;
}

// bid on the Auction
console.info(`keeper: auction "${auctionTransaction.id}": attempting swap execution`);
const bidHash = await bidWithCallee(ETHEREUM_NETWORK, auctionTransaction, walletAddress);
const bidHash = await bidWithCallee(network, auctionTransaction, walletAddress);
console.info(`keeper: auction "${auctionTransaction.id}" was succesfully executed via "${bidHash}" transaction`);
};

const participateInAuction = async function (auction: AuctionInitialInfo) {
const participateInAuction = async function (network: string, auction: AuctionInitialInfo) {
// check if this auction is currently executed to avoid double execution
if (currentlyExecutedAuctions.has(auction.id)) {
return;
Expand All @@ -118,7 +119,7 @@ const participateInAuction = async function (auction: AuctionInitialInfo) {

// execute
try {
await checkAndParticipateIfPossible(auction);
await checkAndParticipateIfPossible(network, auction);
} catch (error) {
console.error(`keeper: unexpected error: ${(error instanceof Error && error.message) || 'unknown'}`);
}
Expand All @@ -127,9 +128,9 @@ const participateInAuction = async function (auction: AuctionInitialInfo) {
currentlyExecutedAuctions.delete(auction.id);
};

export const participate = async function (auctions: AuctionInitialInfo[]) {
export const participate = async function (network: string, auctions: AuctionInitialInfo[]) {
for (const auction of auctions) {
await participateInAuction(auction);
await participateInAuction(network, auction);
}
};

Expand Down
2 changes: 1 addition & 1 deletion bot/src/variables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const ETHEREUM_NETWORK = process.env.ETHEREUM_NETWORK || 'kovan';
export const RPC_URL = process.env.RPC_URL;
export const KEEPER_MINIMUM_NET_PROFIT_DAI = parseInt(process.env.KEEPER_MINIMUM_NET_PROFIT_DAI || '');
export const KEEPER_WALLET_PRIVATE_KEY = process.env.KEEPER_WALLET_PRIVATE_KEY;
export const WHITELISTED_COLLATERALS = process.env.WHITELISTED_COLLATERALS;
Expand Down
8 changes: 4 additions & 4 deletions bot/src/whitelist.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getCollateralConfigByType } from 'auctions-core/src/constants/COLLATERALS';
import { getSupportedCollateralTypes } from 'auctions-core/dist/src/addresses';
import { ETHEREUM_NETWORK, WHITELISTED_COLLATERALS } from './variables';
import { getSupportedCollateralTypes } from 'auctions-core/src/addresses';
import { WHITELISTED_COLLATERALS } from './variables';

const validateWhitelist = function (whitelist: string[]) {
const unsupportedCollateralTypes: string[] = [];
Expand All @@ -22,11 +22,11 @@ const parseCollateralWhitelist = function (whitelist: string): string[] {
return whitelist.split(',').map(item => item.trim());
};

export const getWhitelistedCollaterals = async function () {
export const getWhitelistedCollaterals = async function (network: string) {
if (WHITELISTED_COLLATERALS) {
return parseCollateralWhitelist(WHITELISTED_COLLATERALS);
}
return await getSupportedCollateralTypes(ETHEREUM_NETWORK);
return await getSupportedCollateralTypes(network);
};

export const setupWhitelist = function () {
Expand Down
2 changes: 1 addition & 1 deletion core/src/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import memoizee from 'memoizee';
import COLLATERALS, { getAllCollateralTypes } from './constants/COLLATERALS';
import getProvider from './provider';
import CHAINLOG from './abis/CHAINLOG.json';
import { CHAINLOG_ADDRESS } from './constants/NETWORKS';

const CHAINLOG_ADDRESS = '0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F';
const CHAINLOG_CACHE = 24 * 60 * 60 * 1000;

const getChainLogContract = async function (network: string): Promise<Contract> {
Expand Down
2 changes: 1 addition & 1 deletion core/src/calleeFunctions/helpers/uniswapV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import memoizee from 'memoizee';
import { Fetcher, Token, Pair, Route, TokenAmount, Trade, TradeType } from '@uniswap/sdk';
import { abi as uniswapV2PairABI } from '@uniswap/v2-core/build/UniswapV2Pair.json';
import BigNumber from '../../bignumber';
import { getDecimalChainIdByNetworkType } from '../../constants/NETWORKS';
import { getDecimalChainIdByNetworkType } from '../../network';
import getProvider from '../../provider';
import { getTokenAddressByNetworkAndSymbol, getTokenDecimalsBySymbol } from '../../tokens';
import { getCollateralConfigBySymbol } from '../../constants/COLLATERALS';
Expand Down
4 changes: 2 additions & 2 deletions core/src/constants/CALLEES.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CalleeAddresses } from '../types';
import { getCollateralConfigByType } from './COLLATERALS';
import { getNetworkConfigByType } from './NETWORKS';
import { getNetworkConfigByType } from '../network';

const CALLEES: Record<string, CalleeAddresses | undefined> = {
'0x1': {
Expand All @@ -24,7 +24,7 @@ const CALLEES: Record<string, CalleeAddresses | undefined> = {

export const getCalleesByNetworkType = function (network: string): CalleeAddresses {
const networkConfig = getNetworkConfigByType(network);
const chainId = network === 'localhost' ? '0x1' : networkConfig.chainId;
const chainId = networkConfig.isFork ? '0x1' : networkConfig.chainId;
const networkCallees = CALLEES[chainId];
if (!networkCallees) {
throw new Error(`Can not find callee addresses for the "${network}" network`);
Expand Down
Loading

0 comments on commit 948f56f

Please sign in to comment.