Skip to content
This repository has been archived by the owner on Feb 25, 2023. It is now read-only.

Commit

Permalink
Merge pull request #144 from CoinAlpha/development
Browse files Browse the repository at this point in the history
release / development -> master
  • Loading branch information
dennisocana authored Sep 3, 2021
2 parents eb051cb + ddf2db7 commit 6417099
Show file tree
Hide file tree
Showing 35 changed files with 3,684 additions and 9,393 deletions.
5 changes: 1 addition & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
FROM node:12.13.0-alpine

# Add timezone database
RUN apk add --no-cache tzdata
FROM node:12.13.0

# Set labels
LABEL application="gateway-api"
Expand Down
7,781 changes: 2,019 additions & 5,762 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"prebuild": "rimraf dist && mkdir dist",
"build": "tsc --project ./",
"format": "prettier . --write",
"lint": "eslint src test --format table --fix",
"lint": "eslint src tests --format table --fix",
"debug": "DEBUG=*router nodemon --ext 'ts,js,json' --exec 'ts-node' src/index.ts",
"start": "pm2 start dist/index.js --no-daemon",
"status": "pm2 monit",
Expand Down Expand Up @@ -40,6 +40,7 @@
"capture-console": "^1.0.1",
"cross-fetch": "^3.0.6",
"debug": "^4.2.0",
"esm": "^3.2.25",
"ethers": "^5.3.1",
"express": "^4.17.1",
"express-ipfilter": "^1.1.2",
Expand All @@ -49,18 +50,20 @@
"lodash": "^4.17.20",
"mathjs": "^9.3.0",
"moment": "^2.29.1",
"pm2": "^4.5.6",
"util": "^0.12.3",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.4",
"yaml": "^1.10.2",
"pm2": "^4.5.6"
"yaml": "^1.10.2"
},
"devDependencies": {
"@types/chai": "^4.2.10",
"@types/express": "^4.17.12",
"@types/jest": "^26.0.24",
"@types/mathjs": "^9.4.2",
"@typescript-eslint/eslint-plugin": "^4.26.1",
"@typescript-eslint/parser": "^4.26.1",
"chai": "^4.2.0",
"eslint": "^7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.3",
Expand Down
13 changes: 11 additions & 2 deletions src/routes/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { EthereumConfigService } from '../services/ethereum_config';
// import { EthereumGasService } from '../services/ethereum_gas';
import Fees from '../services/fees';

import { getNonceManager } from '../services/utils';

import { logger } from '../services/logger';
import { Router, Request, Response } from 'express';
import { ethers } from 'ethers';
Expand Down Expand Up @@ -136,15 +138,19 @@ router.post('/approve', async (req: Request, res: Response) => {
}
// Getting Wallet
try {
const wallet = ethereumService.getWallet(req.body.privateKey);
const wallet = await getNonceManager(
ethereumService.getWallet(req.body.privateKey)
);

// Getting token info
const token = ethereumService.getERC20Token(req.body.token);

if (!token) {
res.status(500).send(`Token "${req.body.token}" is not supported`);
} else {
const amount = ethers.utils.parseUnits(req.body.amount, token.decimals);
const amount = req.body.amount
? ethers.utils.parseUnits(req.body.amount, token.decimals)
: ethers.constants.MaxUint256;
// call approve function
let approval;
try {
Expand Down Expand Up @@ -179,6 +185,9 @@ router.post('/poll', async (req: Request, res: Response) => {
const initTime = Date.now();
const receipt = await ethereumService.getTransactionReceipt(req.body.txHash);
const confirmed = receipt && receipt.blockNumber ? true : false;
if (receipt.gasUsed) {
receipt.gasUsed = receipt.gasUsed.toNumber();
}

res.status(200).json({
network: config.networkName,
Expand Down
23 changes: 19 additions & 4 deletions src/routes/uniswap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import { EthereumConfigService } from '../services/ethereum_config';

import Uniswap from '../services/uniswap';
import { EthereumGasService } from '../services/ethereum_gas';
import Fees from '../services/fees';

const debug = require('debug')('router');
const router = express.Router();
const ethConfig = new EthereumConfigService();
const eth = new EthereumService(ethConfig);
const uniswap = new Uniswap();
const fees = new EthereumGasService(ethConfig);
const feesOld = new Fees();

const swapMoreThanMaxPriceError = 'Price too high';
const swapLessThanMaxPriceError = 'Price too low';
Expand Down Expand Up @@ -85,7 +87,10 @@ router.get('/start', async (req: Request, res: Response) => {
return;
}
}
const gasCost = await fees.getGasCost(uniswap.gasLimit);
const gasCost = await feesOld.getGasCost(
fees.getGasPrice(),
uniswap.gasLimit
);
const result = {
network: eth.networkName,
timestamp: initTime,
Expand Down Expand Up @@ -122,7 +127,10 @@ router.post('/trade', async (req: Request, res: Response) => {
if (baseToken && quoteToken) {
const side = req.body.side.toUpperCase();
const limitPrice = req.body.limitPrice || null;
const gasCost = await fees.getGasCost(uniswap.gasLimit);
const gasCost = await feesOld.getGasCost(
fees.getGasPrice(),
uniswap.gasLimit
);
try {
// fetch the optimal pool mix from uniswap
const result: any =
Expand Down Expand Up @@ -250,7 +258,10 @@ router.post('/price', async (req: Request, res: Response) => {
const quoteToken = eth.getERC20Token(req.body.quote);
if (baseToken && quoteToken) {
const side = req.body.side.toUpperCase();
const gasCost = await fees.getGasCost(uniswap.gasLimit);
const gasCost = await feesOld.getGasCost(
fees.getGasPrice(),
uniswap.gasLimit
);

try {
const result: any =
Expand Down Expand Up @@ -294,7 +305,11 @@ router.post('/price', async (req: Request, res: Response) => {
trade: trade,
};
debug(
`Price ${side} ${baseToken.symbol}-${quoteToken.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${uniswap.gasLimit} estimated fee:${gasCost} ETH`
`Price ${side} ${baseToken.symbol}-${
quoteToken.symbol
} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${
uniswap.gasLimit
} estimated fee:${gasCost} ETH`
);
res.status(200).json(result);
} else {
Expand Down
46 changes: 14 additions & 32 deletions src/routes/uniswap_v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@ const eth = new EthereumService(ethConfig);

const uniswap = new UniswapV3(globalConfig.getConfig('ETHEREUM_CHAIN'));

uniswap.generate_tokens();
setTimeout(uniswap.update_pairs.bind(uniswap), 2000);

const fees = new Fees();

const swapMoreThanMaxPriceError = 'Price too high';
const swapLessThanMaxPriceError = 'Price too low';
// const swapMoreThanMaxPriceError = 'Price too high';
// const swapLessThanMaxPriceError = 'Price too low';

const estimateGasLimit = () => {
return uniswap.gasLimit;
Expand Down Expand Up @@ -135,12 +132,6 @@ router.get('/start', async (req, res) => {
error: 'pairs query param required',
});
}
let gasPrice;
if (typeof req.query.gasPrice === 'string') {
gasPrice = parseFloat(req.query.gasPrice);
} else {
gasPrice = fees.ethGasPrice;
}

// get token contract address and cache paths
for (let pair of pairs) {
Expand All @@ -159,23 +150,12 @@ router.get('/start', async (req, res) => {
orderedPairs.push(pair.reverse().join('-'));
}

uniswap.extend_update_pairs([
baseTokenContractInfo,
quoteTokenContractInfo,
]);

const gasLimit = estimateGasLimit();
const gasCost = await fees.getGasCost(gasPrice, gasLimit);

const result = {
network: eth.networkName,
timestamp: initTime,
latency: latency(initTime, Date.now()),
success: true,
pairs: orderedPairs,
gasPrice: gasPrice,
gasLimit: gasLimit,
gasCost: gasCost,
};
res.status(200).json(result);
} else {
Expand All @@ -191,8 +171,8 @@ router.get('/start', async (req, res) => {
}
});

router.post('/trade', async (req: Request, res: Response) => {
/*
/*router.post('/trade', async (req: Request, res: Response) => {
POST: /trade
x-www-form-urlencoded: {
"quote":"BAT"
Expand All @@ -204,7 +184,7 @@ router.post('/trade', async (req: Request, res: Response) => {
"privateKey":{{privateKey}}
"side":{buy|sell}
}
*/
const initTime = Date.now();
// params: privateKey (required), base (required), quote (required), amount (required), maxPrice (required), gasPrice (required)
const privateKey = req.body.privateKey;
Expand Down Expand Up @@ -250,7 +230,7 @@ router.post('/trade', async (req: Request, res: Response) => {
);
if (side === 'BUY') {
const price = trade.executionPrice.invert().toFixed(8);
const price = parseFloat(trade.executionPrice.invert().toSignificant(8));
logger.info(`uniswap.route - Price: ${price.toString()}`);
if (!limitPrice || price <= limitPrice) {
// pass swaps to exchange-proxy to complete trade
Expand Down Expand Up @@ -286,7 +266,7 @@ router.post('/trade', async (req: Request, res: Response) => {
}
} else {
// sell
const price = trade.executionPrice.toFixed(8);
const price = parseFloat(trade.executionPrice.toSignificant(8));
logger.info(`Price: ${price.toString()}`);
if (!limitPrice || price >= limitPrice) {
// pass swaps to exchange-proxy to complete trade
Expand All @@ -304,8 +284,8 @@ router.post('/trade', async (req: Request, res: Response) => {
base: baseTokenAddress,
quote: quoteTokenAddress,
amount: parseFloat(req.body.amount),
expectedOut: expectedAmount.toFixed(8),
price: parseFloat(price),
expectedOut: expectedAmount.toSignificant(8),
price: price,
gasPrice: gasPrice,
gasLimit,
gasCost: gasCost,
Expand Down Expand Up @@ -338,7 +318,7 @@ router.post('/trade', async (req: Request, res: Response) => {
});
}
});

*/
router.post('/price', async (req: Request, res: Response) => {
/*
POST: /price
Expand Down Expand Up @@ -368,8 +348,9 @@ router.post('/price', async (req: Request, res: Response) => {
const gasCost = await fees.getGasCost(gasPrice, gasLimit);
try {
// fetch pools for all tiers
let priceResult, price;
let priceResult; // , price;
if (req.body.amount) {
/*
// get price at this depth
const amount = req.body.amount;
const side = req.body.side.toUpperCase();
Expand Down Expand Up @@ -398,6 +379,7 @@ router.post('/price', async (req: Request, res: Response) => {
expectedAmount: parseFloat(expectedAmount.toFixed(8)),
};
}
*/
} else {
// get mid price for all tiers
priceResult = await uniswap.currentPrice(
Expand All @@ -419,7 +401,7 @@ router.post('/price', async (req: Request, res: Response) => {
gasLimit: gasLimit,
gasCost: gasCost,
};
debug(
logger.info(
`Mid Price ${baseTokenContractInfo.symbol}-${
quoteTokenContractInfo.symbol
} | (rate:${JSON.stringify(
Expand Down
65 changes: 36 additions & 29 deletions src/services/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import abi from '../assets/abi.json';
import { BigNumber, Contract, providers, Wallet } from 'ethers';
import { EthereumConfigService } from './ethereum_config';
import { default as kovanErc20TokenList } from '../assets/erc20_tokens_kovan.json';
import { logger } from '../services/logger';

export enum GasStationLevel {
FAST = 'fast',
FASTEST = 'fastest',
Expand All @@ -20,13 +22,13 @@ export enum Network {
ROPSTEN = 'ropsten',
}

export interface EthTransactionReceipt {
gasUsed: number;
blockNumber: number;
confirmations: number;
status: number;
logs: Array<providers.Log>;
}
// export interface EthTransactionReceipt {
// gasUsed: number;
// blockNumber: number;
// confirmations: number;
// status: number;
// logs: Array<providers.Log>;
// }

export interface TokenERC20Info {
symbol: string;
Expand All @@ -40,12 +42,12 @@ export interface ERC20TokensList {
tokens: TokenERC20Info[];
}

export interface EthTransactionReceipt {
gasUsed: number;
blockNumber: number;
confirmations: number;
status: number;
}
// export interface EthTransactionReceipt {
// gasUsed: number;
// blockNumber: number;
// confirmations: number;
// status: number;
// }

const stringInsert = (str: string, val: string, index: number) => {
if (index > 0) {
Expand Down Expand Up @@ -81,7 +83,8 @@ export class EthereumService {
this.chainId = 42;
this.erc20TokenList = kovanErc20TokenList;
break;
default: // MAINNET
default:
// MAINNET
(async () => {
const { data } = await axios.get(this.config.tokenListUrl);
this.erc20TokenList = data;
Expand Down Expand Up @@ -272,24 +275,28 @@ export class EthereumService {
/**
* Get transaction receipt for a transaction hash.
* @param {string} txHash
* @return {Promise<EthTransactionReceipt>}
* @return {Promise<any>}
*/
async getTransactionReceipt(txHash: string): Promise<EthTransactionReceipt> {
async getTransactionReceipt(txHash: string): Promise<any> {
const transaction = await this.provider.getTransactionReceipt(txHash);

let gasUsed;
if (transaction.gasUsed) {
gasUsed = transaction.gasUsed.toNumber();
logger.info(transaction);
if (transaction) {
return {
gasUsed: transaction.gasUsed || 0,
blockNumber: transaction.blockNumber,
confirmations: transaction.confirmations,
status: transaction.status || 0,
logs: transaction.logs,
};
} else {
gasUsed = 0;
// transaction is yet to be indexed
return {
gasUsed: 0,
blockNumber: 0,
confirmations: 0,
status: 0,
logs: [],
};
}

return {
gasUsed: gasUsed,
blockNumber: transaction.blockNumber,
confirmations: transaction.confirmations,
status: transaction.status || 0,
logs: transaction.logs,
};
}
}
Loading

0 comments on commit 6417099

Please sign in to comment.