Skip to content

Commit

Permalink
cleaning up
Browse files Browse the repository at this point in the history
  • Loading branch information
Strernd committed Feb 1, 2021
1 parent 7580ce3 commit dffe1dc
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 61 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "MIT",
"scripts": {
"start": "ts-node src/index.ts",
"test": "ts-node src/test.ts"
"sign": "ts-node src/sign.ts"
},
"dependencies": {
"apex-logs-winston": "^1.1.0",
Expand Down
11 changes: 11 additions & 0 deletions src/common/eth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Eth from 'ethjs';
import converter from 'hex2dec';
const erc20abi = require('./erc20abi.json');
import axios from 'axios';
import { BigNumber } from 'ethers';

const eth = new Eth(new Eth.HttpProvider(process.env.INFURA));

Expand Down Expand Up @@ -64,3 +66,12 @@ export function createErc20TransferData(toHex: string, value: string) {
const valueHex = pad32Bytes(converter.decToHex(value, { prefix: false }));
return '0x' + method + address + valueHex;
}

export async function getGasPrice(): Promise<BigNumber | null> {
const gasInfo = await axios.get(
`https://ethgasstation.info/api/ethgasAPI.json?api-key=${process.env.ETHGASSTATION_APIKEY}`,
);
if (gasInfo && gasInfo.data) {
return BigNumber.from(gasInfo.data.average).mul(BigNumber.from('100000000'));
} else return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@ export async function getTransactionInformation(
if (!symbol) return { status: 'ERROR' };
try {
const res = await axios.get(`${process.env.ERC20_API}/${symbol}/hash/${txReference}`);
if (res.data) {
if (!res.data.transaction) {
return { status: 'NOT_ACCEPTED' };
} else {
const receivedAmount = res.data.transaction.receiver === poolAddress ? res.data.transaction.amount : 0;
return { status: 'ACCEPTED', receivedAmount, sender: [res.data.transaction.sender] };
}
if (res.data && res.data.transaction) {
const receivedAmount =
res.data.transaction.receiver.toLowerCase() === poolAddress.toLowerCase() ? res.data.transaction.amount : 0;
return { status: 'ACCEPTED', receivedAmount, sender: [res.data.transaction.sender] };
} else {
return { status: 'ERROR' };
return { status: 'NOT_ACCEPTED' };
}
} catch (error) {
logger.info('Error getTransactionInformation', { error });
logger.warn('Error ERC20 getTransactionInformation', { error });
return { status: 'ERROR' };
}
}
53 changes: 28 additions & 25 deletions src/implementations/erc20/handlers/tx/createTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,59 @@ import { utils, BigNumber } from 'ethers';
import * as eth from '../../../../common/eth';
import keccak256 from 'keccak256';
import { logger } from '../../../../log';
import axios from 'axios';

export async function createTransaction(
transactionData: AssetTransactionData[],
symbol?: string,
): Promise<{ status: CreateTransactionStatus; partialTx?: object; tosign?: string[] }> {
if (!symbol) {
logger.error('Missing token symbol');
return { status: 'ERROR' };
}
try {
const gasInfo = await axios.get(
`https://ethgasstation.info/api/ethgasAPI.json?api-key=${process.env.ETHGASSTATION_APIKEY}`,
);
if (!gasInfo) {
logger.warn('Missing gas info');
const gasPrice = await eth.getGasPrice();
if (!gasPrice) {
logger.warn('Missing gas price');
return { status: 'ERROR' };
}
const gasPrice = BigNumber.from(gasInfo.data.average).mul(BigNumber.from('100000000'));
const txCount = await eth.getTransactionCount(transactionData[0].fromAddress);
if (isNaN(txCount)) {
logger.warn('Invalid nonce', { nonce: txCount });
return { status: 'ERROR' };
}
const transactions = await Promise.all(
transactionData.map((data, i) => createSingleTransaction(data, Number(txCount) + i, gasPrice)),
transactionData.map((data, i) => createSingleTransaction(data, Number(txCount) + i, gasPrice, symbol)),
);
return { status: 'OK', partialTx: transactions.map((x) => x.partialTx), tosign: transactions.map((x) => x.tosign) };
} catch (error) {
logger.warn('Error in create transaction', { error });
if (error === 'INSUFFICIENT_AMOUNT') {
return { status: 'INSUFFICIENT_FUNDS' };
}
logger.warn('Error in ERC20 createTransaction', { error });
return { status: 'ERROR' };
}
}

async function createSingleTransaction(txData: AssetTransactionData, nonce: number, gasPrice: BigNumber) {
async function createSingleTransaction(
txData: AssetTransactionData,
nonce: number,
gasPrice: BigNumber,
contract: string,
) {
const gasLimit = BigNumber.from('41395');
const data = await eth.createErc20TransferData(txData.toAddress, txData.amount);
const opts = {
// gas: BigNumber.from('80000').toHexString(),
to: '0xaFF4481D10270F50f203E0763e2597776068CBc5',
data,
// gasPrice: gasPrice.toHexString(),
value: BigNumber.from('0').toHexString(),
};
const estimate = await eth.estimateGas(opts);
console.log(JSON.stringify(opts));
console.log(estimate);
// TODO: ESTIMATE GAS
// const opts = {
// gas: BigNumber.from('80000').toHexString(),
// to: contract,
// data,
// gasPrice: gasPrice.toHexString(),
// value: BigNumber.from('0').toHexString(),
// };
// const estimate = await eth.estimateGas(opts);
// console.log(JSON.stringify(opts));
// console.log(estimate);

try {
const tx: utils.UnsignedTransaction = {
to: '0xaFF4481D10270F50f203E0763e2597776068CBc5',
to: contract,
nonce,
gasLimit: gasLimit.toHexString(),
gasPrice: gasPrice.toHexString(),
Expand All @@ -64,7 +68,6 @@ async function createSingleTransaction(txData: AssetTransactionData, nonce: numb
return { partialTx: tx, tosign: hash };
} catch (error) {
logger.warn('Error in create single Transaction ERC20', { error });
console.log(error);
throw error;
}
}
10 changes: 8 additions & 2 deletions src/implementations/erc20/handlers/tx/signAndSendTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SignAndSendResponse } from '../../../../types';
import * as eth from '../../../../common/eth';
import { utils } from 'ethers';
import { logger } from '../../../../log';

export async function signAndSendTransaction(
partialTx: Array<utils.UnsignedTransaction>,
Expand All @@ -15,6 +16,11 @@ export async function signAndSendTransaction(
const withSignature = utils.serializeTransaction(partialTx, signature);
return withSignature;
});
const hashes = await Promise.all(txs.map(eth.sendRawTransaction));
return { status: 'OK', hash: hashes };
try {
const hashes = await Promise.all(txs.map(eth.sendRawTransaction));
return { status: 'OK', hash: hashes };
} catch (error) {
logger.warn('Error in ERC20 signAndSendTransaction', { error });
return { status: 'ERROR' };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function getTransactionInformation(
const receivedAmount = txInfo.to.toLowerCase() === poolAddress.toLowerCase() ? txInfo.amount : '0';
return { status: 'ACCEPTED', receivedAmount, sender: [txInfo.from] };
} catch (error) {
logger.info('Error getTransactionInformation', { error });
logger.info('Error ETH getTransactionInformation', { error });
return { status: 'ERROR' };
}
}
12 changes: 4 additions & 8 deletions src/implementations/eth/handlers/tx/createTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@ import { utils, BigNumber } from 'ethers';
import * as eth from '../../../../common/eth';
import keccak256 from 'keccak256';
import { logger } from '../../../../log';
import axios from 'axios';

export async function createTransaction(
transactionData: AssetTransactionData[],
): Promise<{ status: CreateTransactionStatus; partialTx?: object; tosign?: string[] }> {
try {
const gasInfo = await axios.get(
`https://ethgasstation.info/api/ethgasAPI.json?api-key=${process.env.ETHGASSTATION_APIKEY}`,
);
if (!gasInfo) {
logger.warn('Missing gas info');
const gasPrice = await eth.getGasPrice();
if (!gasPrice) {
logger.warn('ETH Missing gas price');
return { status: 'ERROR' };
}
const gasPrice = BigNumber.from(gasInfo.data.average).mul(BigNumber.from('100000000'));
const txCount = await eth.getTransactionCount(transactionData[0].fromAddress);
if (isNaN(txCount)) {
logger.warn('Invalid nonce', { nonce: txCount });
Expand Down Expand Up @@ -56,7 +52,7 @@ async function createSingleTransaction(data: AssetTransactionData, nonce: number
const hash = '0x' + keccak256(serialized).toString('hex');
return { partialTx: tx, tosign: hash };
} catch (error) {
logger.warn('Error in create single Transaction', { error });
logger.warn('Error in ETH create single Transaction', { error });
throw error;
}
}
10 changes: 8 additions & 2 deletions src/implementations/eth/handlers/tx/signAndSendTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SignAndSendResponse } from '../../../../types';
import * as eth from '../../../../common/eth';
import { utils } from 'ethers';
import { logger } from '../../../../log';

export async function signAndSendTransaction(
partialTx: Array<utils.UnsignedTransaction>,
Expand All @@ -15,6 +16,11 @@ export async function signAndSendTransaction(
const withSignature = utils.serializeTransaction(partialTx, signature);
return withSignature;
});
const hashes = await Promise.all(txs.map(eth.sendRawTransaction));
return { status: 'OK', hash: hashes };
try {
const hashes = await Promise.all(txs.map(eth.sendRawTransaction));
return { status: 'OK', hash: hashes };
} catch (error) {
logger.warn('Error in ETH signAndSendTransaction', { error });
return { status: 'ERROR' };
}
}
33 changes: 27 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'local_wit
const app = express();
app.use(express.json());

// TODO: Fill whitelist
const tokenWhitelist = new Map<string, boolean>();
tokenWhitelist.set('WEENUS', true);

const supportedTokensFromEnv = process.env.SUPPORTED_TOKENS;
if (supportedTokensFromEnv) {
supportedTokensFromEnv.split(',').forEach((token) => tokenWhitelist.set(token.toLowerCase(), true));
}

function getHandlerForSymbol(symbol: string): FullServiceHandlers | null {
if (symbol === 'ETH') return ethHandler;
else if (tokenWhitelist.has(symbol)) return erc20Handler;
else if (tokenWhitelist.has(symbol.toLowerCase())) return erc20Handler;
else return null;
}

Expand All @@ -37,7 +40,14 @@ app.get('/:symbol/oracle/transactionInfo', async (req, res) => {
const { reference, poolAddress } = req.query;
logger.info('Called /oracle/transactionInfo', { reference, poolAddress });
if (!reference || !poolAddress) return res.status(400).json({ status: 'MISSING_PARAMS' });
const result = await handler.oracle.getTransactionInformation(reference as string, poolAddress as string, req.params.symbol);
const result = await handler.oracle.getTransactionInformation(
reference as string,
poolAddress as string,
req.params.symbol,
);
if (result.status === 'ERROR') {
return res.status(500).json(result);
}
return res.json(result);
});

Expand All @@ -61,8 +71,13 @@ app.post('/:symbol/tx/create', async (req, res) => {
if (!transactionData) {
return res.status(400).json({ status: 'MISSING_BODY' });
}
const result = await handler.transactionService.createTransaction(transactionData);
// TODO: Use correct status codes
const result = await handler.transactionService.createTransaction(transactionData, req.params.symbol);
if (result.status === 'ERROR') {
return res.status(500).json(result);
}
if (result.status !== 'OK') {
return res.status(400).json(result);
}
return res.json(result);
});

Expand All @@ -75,6 +90,12 @@ app.post('/:symbol/tx/signAndSend', async (req, res) => {
return res.status(400).json({ status: 'MISSING_BODY' });
}
const result = await handler.transactionService.signAndSendTransaction(partialTx, tosign, signatures);
if (result.status === 'ERROR') {
return res.status(500).json(result);
}
if (result.status === 'INVALID_SIGNATURES') {
return res.status(400).json(result);
}
return res.json(result);
});

Expand Down
11 changes: 5 additions & 6 deletions src/test.ts → src/sign.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
require('dotenv').config();
// import { sendErc20Token } from './common/eth';
import { Wallet } from 'ethers';
import { joinSignature } from '@ethersproject/bytes';

// Used to sign things manually
(async () => {
const w = Wallet.fromMnemonic(process.env.MNEMONIC!);

console.log('Wallet address', await w.getAddress());
const tosign = '0xb0fbca2fa177026d39ab2155155237573fbd130fab9eead32217043f78963101';
console.log('Wallet address: ', await w.getAddress());
const tosign = process.argv[2];
console.log('Tosign: ', tosign);
const signature = await w._signingKey().signDigest(tosign);
console.log('signature', joinSignature(signature));

console.log('Signature: ', joinSignature(signature));
})();
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type CreateTransactionResponse = {
tosign?: string[];
};
export interface TransactionServiceHandlers {
createTransaction: (transactionData: AssetTransactionData[]) => Promise<CreateTransactionResponse>;
createTransaction: (transactionData: AssetTransactionData[], symbol?: string) => Promise<CreateTransactionResponse>;
signAndSendTransaction: (
partialTx: any,
tosign: string[],
Expand Down

0 comments on commit dffe1dc

Please sign in to comment.