From 736aefb7e0d082c670c61aaf3d951469d4f79b44 Mon Sep 17 00:00:00 2001 From: Zahrun <10415894+Zahrun@users.noreply.github.com> Date: Sun, 18 Dec 2022 23:16:12 +0100 Subject: [PATCH] feat: support aax trades import --- components/TradesTable/index.tsx | 2 + src/parsers/trades/aax/index.ts | 82 ++++++++++++++++++++++++++++++++ src/parsers/trades/index.ts | 2 + src/types/locations.ts | 2 + src/types/trade.ts | 2 + 5 files changed, 90 insertions(+) create mode 100644 src/parsers/trades/aax/index.ts diff --git a/components/TradesTable/index.tsx b/components/TradesTable/index.tsx index c92de882..d244c28d 100644 --- a/components/TradesTable/index.tsx +++ b/components/TradesTable/index.tsx @@ -55,6 +55,7 @@ export class TradesTable extends React.Component [ @@ -66,6 +67,7 @@ export class TradesTable extends React.Component{trade.boughtCurrency}, {(trade.amountSold / trade.rate).toFixed(8)}, {`${trade.transactionFee} ${trade.transactionFeeCurrency}`}, + {`${trade.tradeFee} ${trade.tradeFeeCurrency}`}, , ])} /> diff --git a/src/parsers/trades/aax/index.ts b/src/parsers/trades/aax/index.ts new file mode 100644 index 00000000..fb02e945 --- /dev/null +++ b/src/parsers/trades/aax/index.ts @@ -0,0 +1,82 @@ +import { getCSVData } from '../../'; +import { EXCHANGES, IImport, IPartialTrade, ITrade } from '../../../types'; +import { createDateAsUTC, createID } from '../../utils'; + +interface IAAX { + Coin: string; + Quantity: string; + Type: string; + Details: string; + Time: string; +} + +interface IAAXGroup { + [key: string]: IAAX[]; +} + +function groupByType(group: IAAXGroup, line: IAAX) { + group[line.Type] = group[line.Type] ?? []; + group[line.Type].push(line); + return group; +} + +export default async function processData(importDetails: IImport): Promise { + const data: IAAX[] = (await getCSVData(importDetails.data) as IAAX[]); + const internalFormat: ITrade[] = []; + for (let i = 0; i < data.length; i++) { + const tradeToAdd: IPartialTrade = { + date : createDateAsUTC(new Date(data[i].Time)).getTime(), + exchange : EXCHANGES.AAX, + }; + switch (data[i].Type) { + case 'Trading': { + const trades = [data[i], data[++i], data[++i]]; + const groupedTrades = trades.reduce(groupByType, {}); + internalFormat.push(addTrade(tradeToAdd, groupedTrades['Trading'][0], groupedTrades['Trading'][1], groupedTrades['Trading Fee'][0])); + break; + } + case 'Convert': { + internalFormat.push(addTrade(tradeToAdd, data[i], data[++i])); + break; + } + // TODO: Withdrawal, Deposit, System Deposit, Fixed Interest, Flexible Interest + default: { + console.log(`Ignored ${tradeToAdd.exchange} trade of type ${data[i].Type}`); + } + } + } + return internalFormat; +} + +function addTrade( + tradeToAdd: IPartialTrade, + firstHalf: IAAX, + secondHalf: IAAX, + feeTrade?: IAAX, +): ITrade { + let firstHalfDirection = parseFloat(firstHalf.Quantity) > 0; + let secondHalfDirection = parseFloat(secondHalf.Quantity) > 0; + if (firstHalfDirection && !secondHalfDirection) { + tradeToAdd.boughtCurrency = firstHalf.Coin; + tradeToAdd.soldCurrency = secondHalf.Coin; + tradeToAdd.amountSold = Math.abs(parseFloat(secondHalf.Quantity)); + tradeToAdd.rate = Math.abs(parseFloat(secondHalf.Quantity) / parseFloat(firstHalf.Quantity)); + } else if (!firstHalfDirection && secondHalfDirection) { + tradeToAdd.soldCurrency = firstHalf.Coin; + tradeToAdd.boughtCurrency = secondHalf.Coin; + tradeToAdd.amountSold = Math.abs(parseFloat(firstHalf.Quantity)); + tradeToAdd.rate = Math.abs(parseFloat(firstHalf.Quantity) / parseFloat(secondHalf.Quantity)); + } else { + console.info(firstHalf); + console.info(secondHalf); + throw new Error(`Error parsing ${tradeToAdd.exchange} firstHalf.direction=${firstHalfDirection} + and secondHalf.direction=${secondHalfDirection}`); + } + if (feeTrade !== undefined) { + tradeToAdd.tradeFee = Math.abs(parseFloat(feeTrade.Quantity)); + tradeToAdd.tradeFeeCurrency = feeTrade.Coin; + } + tradeToAdd.ID = createID(tradeToAdd); + tradeToAdd.exchangeID = tradeToAdd.ID; + return tradeToAdd as ITrade; +} diff --git a/src/parsers/trades/index.ts b/src/parsers/trades/index.ts index 30b720d4..e341ca30 100644 --- a/src/parsers/trades/index.ts +++ b/src/parsers/trades/index.ts @@ -1,5 +1,6 @@ import { EXCHANGES, ExchangesTradeHeaders, IImport, ITrade } from '@types'; import * as crypto from 'crypto'; +import aaxParser from './aax' import binanceParser from './binance'; import bittrexParser from './bittrex'; import geminiParser from './gemini'; @@ -8,6 +9,7 @@ import poloniexParser from './poloniex'; import revolutParser from './revolut'; const parserMapping: {[key in EXCHANGES]: any} = { + [EXCHANGES.AAX]: aaxParser, [EXCHANGES.Binance]: binanceParser, [EXCHANGES.Bittrex]: bittrexParser, [EXCHANGES.Gemini]: geminiParser, diff --git a/src/types/locations.ts b/src/types/locations.ts index c0053d4b..8fc43afd 100644 --- a/src/types/locations.ts +++ b/src/types/locations.ts @@ -1,6 +1,7 @@ export type Location = EXCHANGES | string; export enum EXCHANGES { + AAX = 'AAX', Bittrex = 'BITTREX', Gemini= 'GEMINI', Poloniex = 'POLONIEX', @@ -14,6 +15,7 @@ export enum IncomeImportTypes { } export enum ExchangesTradeHeaders { + AAX = '5aaccf9d0910e5c227f7590bfd39c8baa883bde920c5da39f06c29447b78d80f', BITTREX = '07230399aaa8d1f15e88e38bd43a01c5ef1af6c1f9131668d346e196ff090d80', GEMINI = '996edee25db7f3d1dd16c83c164c6cff8c6d0f5d6b3aafe6d1700f2a830f6c9e', POLONIEX = 'd7484d726e014edaa059c0137ac91183a7eaa9ee5d52713aa48bb4104b01afb0', diff --git a/src/types/trade.ts b/src/types/trade.ts index 07731197..1de8b25b 100644 --- a/src/types/trade.ts +++ b/src/types/trade.ts @@ -13,6 +13,8 @@ export interface ITrade { ID: string; transactionFee: number; transactionFeeCurrency: string; + tradeFee?: number; + tradeFeeCurrency?: string; } export interface ITradeWithFiatRate extends ITrade {