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

Commit 6417099

Browse files
authored
Merge pull request #144 from CoinAlpha/development
release / development -> master
2 parents eb051cb + ddf2db7 commit 6417099

35 files changed

+3684
-9393
lines changed

Dockerfile

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
FROM node:12.13.0-alpine
2-
3-
# Add timezone database
4-
RUN apk add --no-cache tzdata
1+
FROM node:12.13.0
52

63
# Set labels
74
LABEL application="gateway-api"

package-lock.json

Lines changed: 2019 additions & 5762 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"prebuild": "rimraf dist && mkdir dist",
1010
"build": "tsc --project ./",
1111
"format": "prettier . --write",
12-
"lint": "eslint src test --format table --fix",
12+
"lint": "eslint src tests --format table --fix",
1313
"debug": "DEBUG=*router nodemon --ext 'ts,js,json' --exec 'ts-node' src/index.ts",
1414
"start": "pm2 start dist/index.js --no-daemon",
1515
"status": "pm2 monit",
@@ -40,6 +40,7 @@
4040
"capture-console": "^1.0.1",
4141
"cross-fetch": "^3.0.6",
4242
"debug": "^4.2.0",
43+
"esm": "^3.2.25",
4344
"ethers": "^5.3.1",
4445
"express": "^4.17.1",
4546
"express-ipfilter": "^1.1.2",
@@ -49,18 +50,20 @@
4950
"lodash": "^4.17.20",
5051
"mathjs": "^9.3.0",
5152
"moment": "^2.29.1",
53+
"pm2": "^4.5.6",
5254
"util": "^0.12.3",
5355
"winston": "^3.3.3",
5456
"winston-daily-rotate-file": "^4.5.4",
55-
"yaml": "^1.10.2",
56-
"pm2": "^4.5.6"
57+
"yaml": "^1.10.2"
5758
},
5859
"devDependencies": {
60+
"@types/chai": "^4.2.10",
5961
"@types/express": "^4.17.12",
6062
"@types/jest": "^26.0.24",
6163
"@types/mathjs": "^9.4.2",
6264
"@typescript-eslint/eslint-plugin": "^4.26.1",
6365
"@typescript-eslint/parser": "^4.26.1",
66+
"chai": "^4.2.0",
6467
"eslint": "^7.25.0",
6568
"eslint-config-prettier": "^8.3.0",
6669
"eslint-config-standard": "^16.0.3",

src/routes/ethereum.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { EthereumConfigService } from '../services/ethereum_config';
77
// import { EthereumGasService } from '../services/ethereum_gas';
88
import Fees from '../services/fees';
99

10+
import { getNonceManager } from '../services/utils';
11+
1012
import { logger } from '../services/logger';
1113
import { Router, Request, Response } from 'express';
1214
import { ethers } from 'ethers';
@@ -136,15 +138,19 @@ router.post('/approve', async (req: Request, res: Response) => {
136138
}
137139
// Getting Wallet
138140
try {
139-
const wallet = ethereumService.getWallet(req.body.privateKey);
141+
const wallet = await getNonceManager(
142+
ethereumService.getWallet(req.body.privateKey)
143+
);
140144

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

144148
if (!token) {
145149
res.status(500).send(`Token "${req.body.token}" is not supported`);
146150
} else {
147-
const amount = ethers.utils.parseUnits(req.body.amount, token.decimals);
151+
const amount = req.body.amount
152+
? ethers.utils.parseUnits(req.body.amount, token.decimals)
153+
: ethers.constants.MaxUint256;
148154
// call approve function
149155
let approval;
150156
try {
@@ -179,6 +185,9 @@ router.post('/poll', async (req: Request, res: Response) => {
179185
const initTime = Date.now();
180186
const receipt = await ethereumService.getTransactionReceipt(req.body.txHash);
181187
const confirmed = receipt && receipt.blockNumber ? true : false;
188+
if (receipt.gasUsed) {
189+
receipt.gasUsed = receipt.gasUsed.toNumber();
190+
}
182191

183192
res.status(200).json({
184193
network: config.networkName,

src/routes/uniswap.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import { EthereumConfigService } from '../services/ethereum_config';
1010

1111
import Uniswap from '../services/uniswap';
1212
import { EthereumGasService } from '../services/ethereum_gas';
13+
import Fees from '../services/fees';
1314

1415
const debug = require('debug')('router');
1516
const router = express.Router();
1617
const ethConfig = new EthereumConfigService();
1718
const eth = new EthereumService(ethConfig);
1819
const uniswap = new Uniswap();
1920
const fees = new EthereumGasService(ethConfig);
21+
const feesOld = new Fees();
2022

2123
const swapMoreThanMaxPriceError = 'Price too high';
2224
const swapLessThanMaxPriceError = 'Price too low';
@@ -85,7 +87,10 @@ router.get('/start', async (req: Request, res: Response) => {
8587
return;
8688
}
8789
}
88-
const gasCost = await fees.getGasCost(uniswap.gasLimit);
90+
const gasCost = await feesOld.getGasCost(
91+
fees.getGasPrice(),
92+
uniswap.gasLimit
93+
);
8994
const result = {
9095
network: eth.networkName,
9196
timestamp: initTime,
@@ -122,7 +127,10 @@ router.post('/trade', async (req: Request, res: Response) => {
122127
if (baseToken && quoteToken) {
123128
const side = req.body.side.toUpperCase();
124129
const limitPrice = req.body.limitPrice || null;
125-
const gasCost = await fees.getGasCost(uniswap.gasLimit);
130+
const gasCost = await feesOld.getGasCost(
131+
fees.getGasPrice(),
132+
uniswap.gasLimit
133+
);
126134
try {
127135
// fetch the optimal pool mix from uniswap
128136
const result: any =
@@ -250,7 +258,10 @@ router.post('/price', async (req: Request, res: Response) => {
250258
const quoteToken = eth.getERC20Token(req.body.quote);
251259
if (baseToken && quoteToken) {
252260
const side = req.body.side.toUpperCase();
253-
const gasCost = await fees.getGasCost(uniswap.gasLimit);
261+
const gasCost = await feesOld.getGasCost(
262+
fees.getGasPrice(),
263+
uniswap.gasLimit
264+
);
254265

255266
try {
256267
const result: any =
@@ -294,7 +305,11 @@ router.post('/price', async (req: Request, res: Response) => {
294305
trade: trade,
295306
};
296307
debug(
297-
`Price ${side} ${baseToken.symbol}-${quoteToken.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${uniswap.gasLimit} estimated fee:${gasCost} ETH`
308+
`Price ${side} ${baseToken.symbol}-${
309+
quoteToken.symbol
310+
} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${
311+
uniswap.gasLimit
312+
} estimated fee:${gasCost} ETH`
298313
);
299314
res.status(200).json(result);
300315
} else {

src/routes/uniswap_v3.ts

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ const eth = new EthereumService(ethConfig);
2424

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

27-
uniswap.generate_tokens();
28-
setTimeout(uniswap.update_pairs.bind(uniswap), 2000);
29-
3027
const fees = new Fees();
3128

32-
const swapMoreThanMaxPriceError = 'Price too high';
33-
const swapLessThanMaxPriceError = 'Price too low';
29+
// const swapMoreThanMaxPriceError = 'Price too high';
30+
// const swapLessThanMaxPriceError = 'Price too low';
3431

3532
const estimateGasLimit = () => {
3633
return uniswap.gasLimit;
@@ -135,12 +132,6 @@ router.get('/start', async (req, res) => {
135132
error: 'pairs query param required',
136133
});
137134
}
138-
let gasPrice;
139-
if (typeof req.query.gasPrice === 'string') {
140-
gasPrice = parseFloat(req.query.gasPrice);
141-
} else {
142-
gasPrice = fees.ethGasPrice;
143-
}
144135

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

162-
uniswap.extend_update_pairs([
163-
baseTokenContractInfo,
164-
quoteTokenContractInfo,
165-
]);
166-
167-
const gasLimit = estimateGasLimit();
168-
const gasCost = await fees.getGasCost(gasPrice, gasLimit);
169-
170153
const result = {
171154
network: eth.networkName,
172155
timestamp: initTime,
173156
latency: latency(initTime, Date.now()),
174157
success: true,
175158
pairs: orderedPairs,
176-
gasPrice: gasPrice,
177-
gasLimit: gasLimit,
178-
gasCost: gasCost,
179159
};
180160
res.status(200).json(result);
181161
} else {
@@ -191,8 +171,8 @@ router.get('/start', async (req, res) => {
191171
}
192172
});
193173

194-
router.post('/trade', async (req: Request, res: Response) => {
195-
/*
174+
/*router.post('/trade', async (req: Request, res: Response) => {
175+
196176
POST: /trade
197177
x-www-form-urlencoded: {
198178
"quote":"BAT"
@@ -204,7 +184,7 @@ router.post('/trade', async (req: Request, res: Response) => {
204184
"privateKey":{{privateKey}}
205185
"side":{buy|sell}
206186
}
207-
*/
187+
208188
const initTime = Date.now();
209189
// params: privateKey (required), base (required), quote (required), amount (required), maxPrice (required), gasPrice (required)
210190
const privateKey = req.body.privateKey;
@@ -250,7 +230,7 @@ router.post('/trade', async (req: Request, res: Response) => {
250230
);
251231
252232
if (side === 'BUY') {
253-
const price = trade.executionPrice.invert().toFixed(8);
233+
const price = parseFloat(trade.executionPrice.invert().toSignificant(8));
254234
logger.info(`uniswap.route - Price: ${price.toString()}`);
255235
if (!limitPrice || price <= limitPrice) {
256236
// pass swaps to exchange-proxy to complete trade
@@ -286,7 +266,7 @@ router.post('/trade', async (req: Request, res: Response) => {
286266
}
287267
} else {
288268
// sell
289-
const price = trade.executionPrice.toFixed(8);
269+
const price = parseFloat(trade.executionPrice.toSignificant(8));
290270
logger.info(`Price: ${price.toString()}`);
291271
if (!limitPrice || price >= limitPrice) {
292272
// pass swaps to exchange-proxy to complete trade
@@ -304,8 +284,8 @@ router.post('/trade', async (req: Request, res: Response) => {
304284
base: baseTokenAddress,
305285
quote: quoteTokenAddress,
306286
amount: parseFloat(req.body.amount),
307-
expectedOut: expectedAmount.toFixed(8),
308-
price: parseFloat(price),
287+
expectedOut: expectedAmount.toSignificant(8),
288+
price: price,
309289
gasPrice: gasPrice,
310290
gasLimit,
311291
gasCost: gasCost,
@@ -338,7 +318,7 @@ router.post('/trade', async (req: Request, res: Response) => {
338318
});
339319
}
340320
});
341-
321+
*/
342322
router.post('/price', async (req: Request, res: Response) => {
343323
/*
344324
POST: /price
@@ -368,8 +348,9 @@ router.post('/price', async (req: Request, res: Response) => {
368348
const gasCost = await fees.getGasCost(gasPrice, gasLimit);
369349
try {
370350
// fetch pools for all tiers
371-
let priceResult, price;
351+
let priceResult; // , price;
372352
if (req.body.amount) {
353+
/*
373354
// get price at this depth
374355
const amount = req.body.amount;
375356
const side = req.body.side.toUpperCase();
@@ -398,6 +379,7 @@ router.post('/price', async (req: Request, res: Response) => {
398379
expectedAmount: parseFloat(expectedAmount.toFixed(8)),
399380
};
400381
}
382+
*/
401383
} else {
402384
// get mid price for all tiers
403385
priceResult = await uniswap.currentPrice(
@@ -419,7 +401,7 @@ router.post('/price', async (req: Request, res: Response) => {
419401
gasLimit: gasLimit,
420402
gasCost: gasCost,
421403
};
422-
debug(
404+
logger.info(
423405
`Mid Price ${baseTokenContractInfo.symbol}-${
424406
quoteTokenContractInfo.symbol
425407
} | (rate:${JSON.stringify(

src/services/ethereum.ts

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import abi from '../assets/abi.json';
33
import { BigNumber, Contract, providers, Wallet } from 'ethers';
44
import { EthereumConfigService } from './ethereum_config';
55
import { default as kovanErc20TokenList } from '../assets/erc20_tokens_kovan.json';
6+
import { logger } from '../services/logger';
7+
68
export enum GasStationLevel {
79
FAST = 'fast',
810
FASTEST = 'fastest',
@@ -20,13 +22,13 @@ export enum Network {
2022
ROPSTEN = 'ropsten',
2123
}
2224

23-
export interface EthTransactionReceipt {
24-
gasUsed: number;
25-
blockNumber: number;
26-
confirmations: number;
27-
status: number;
28-
logs: Array<providers.Log>;
29-
}
25+
// export interface EthTransactionReceipt {
26+
// gasUsed: number;
27+
// blockNumber: number;
28+
// confirmations: number;
29+
// status: number;
30+
// logs: Array<providers.Log>;
31+
// }
3032

3133
export interface TokenERC20Info {
3234
symbol: string;
@@ -40,12 +42,12 @@ export interface ERC20TokensList {
4042
tokens: TokenERC20Info[];
4143
}
4244

43-
export interface EthTransactionReceipt {
44-
gasUsed: number;
45-
blockNumber: number;
46-
confirmations: number;
47-
status: number;
48-
}
45+
// export interface EthTransactionReceipt {
46+
// gasUsed: number;
47+
// blockNumber: number;
48+
// confirmations: number;
49+
// status: number;
50+
// }
4951

5052
const stringInsert = (str: string, val: string, index: number) => {
5153
if (index > 0) {
@@ -81,7 +83,8 @@ export class EthereumService {
8183
this.chainId = 42;
8284
this.erc20TokenList = kovanErc20TokenList;
8385
break;
84-
default: // MAINNET
86+
default:
87+
// MAINNET
8588
(async () => {
8689
const { data } = await axios.get(this.config.tokenListUrl);
8790
this.erc20TokenList = data;
@@ -272,24 +275,28 @@ export class EthereumService {
272275
/**
273276
* Get transaction receipt for a transaction hash.
274277
* @param {string} txHash
275-
* @return {Promise<EthTransactionReceipt>}
278+
* @return {Promise<any>}
276279
*/
277-
async getTransactionReceipt(txHash: string): Promise<EthTransactionReceipt> {
280+
async getTransactionReceipt(txHash: string): Promise<any> {
278281
const transaction = await this.provider.getTransactionReceipt(txHash);
279-
280-
let gasUsed;
281-
if (transaction.gasUsed) {
282-
gasUsed = transaction.gasUsed.toNumber();
282+
logger.info(transaction);
283+
if (transaction) {
284+
return {
285+
gasUsed: transaction.gasUsed || 0,
286+
blockNumber: transaction.blockNumber,
287+
confirmations: transaction.confirmations,
288+
status: transaction.status || 0,
289+
logs: transaction.logs,
290+
};
283291
} else {
284-
gasUsed = 0;
292+
// transaction is yet to be indexed
293+
return {
294+
gasUsed: 0,
295+
blockNumber: 0,
296+
confirmations: 0,
297+
status: 0,
298+
logs: [],
299+
};
285300
}
286-
287-
return {
288-
gasUsed: gasUsed,
289-
blockNumber: transaction.blockNumber,
290-
confirmations: transaction.confirmations,
291-
status: transaction.status || 0,
292-
logs: transaction.logs,
293-
};
294301
}
295302
}

0 commit comments

Comments
 (0)