-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add checking your top binance tokens using discord command
- Loading branch information
1 parent
5994355
commit b603a29
Showing
14 changed files
with
374 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Logger } from '@nestjs/common'; | ||
import Binance from 'binance-api-node'; | ||
import 'dotenv/config'; | ||
import { TickerPrice, TickerPriceType } from 'src/utils/dtos/binance.dto'; | ||
|
||
type Config = { | ||
BINANCE_API_KEY: string; | ||
BINANCE_SECRET_KEY: string; | ||
}; | ||
|
||
export class BinanceClient { | ||
private client: any; | ||
private logger: Logger; | ||
|
||
constructor(config: Config) { | ||
this.client = Binance({ | ||
apiKey: config.BINANCE_API_KEY, | ||
apiSecret: config.BINANCE_SECRET_KEY, | ||
}); | ||
this.logger = new Logger(BinanceClient.name); | ||
} | ||
|
||
public getBinanceAccountInfo = async () => { | ||
return await this.client.accountInfo(); | ||
}; | ||
|
||
public getSymbolTickerPrice = async ( | ||
symbol: string, | ||
): Promise<TickerPriceType> => { | ||
try { | ||
const tickerResponse: TickerPriceType = await this.client.prices({ | ||
symbol, | ||
}); | ||
|
||
const ticker: TickerPrice = { | ||
symbol: symbol, | ||
price: tickerResponse[symbol], | ||
}; | ||
return ticker; | ||
} catch (error) { | ||
this.logger.error(`Error when getting price for symbol ${symbol}`); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Controller, Get, UsePipes } from '@nestjs/common'; | ||
import { BinanceService } from './binance.service'; | ||
import { BinanceAccountInfo } from 'src/utils/dtos/binance.dto'; | ||
|
||
@Controller('binance') | ||
export class BinanceController { | ||
constructor(private readonly binanceService: BinanceService) {} | ||
|
||
@Get('/accountInfo') | ||
public async getBinanceAccountInfo() { | ||
return await this.binanceService.getAccountInfo(3); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { BinanceService } from './binance.service'; | ||
import { BinanceController } from './binance.controller'; | ||
|
||
@Module({ | ||
providers: [BinanceService], | ||
exports: [BinanceService], | ||
controllers: [BinanceController], | ||
}) | ||
export class BinanceModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import 'dotenv/config'; | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { BinanceClient } from './binance-client'; | ||
import { | ||
BinanceAccountInfo, | ||
BinanceAccountInfoSchema, | ||
BinanceBalance, | ||
BinanceBalanceWithTotalValueAndSymbol, | ||
TickerPriceType, | ||
} from 'src/utils/dtos/binance.dto'; | ||
|
||
const CURRENCY_FOR_TOKEN_PRICES = 'USDT'; | ||
|
||
@Injectable() | ||
export class BinanceService { | ||
private logger: Logger; | ||
private binanceClient: BinanceClient; | ||
|
||
constructor() { | ||
this.logger = new Logger(BinanceService.name); | ||
this.binanceClient = new BinanceClient({ | ||
BINANCE_API_KEY: process.env.BINANCE_API_KEY ?? '', | ||
BINANCE_SECRET_KEY: process.env.BINANCE_SECRET_KEY ?? '', | ||
}); | ||
} | ||
|
||
public getAccountInfo = async ( | ||
numberOfTopBalances: number, | ||
currencyName?: string, | ||
): Promise<BinanceBalanceWithTotalValueAndSymbol[]> => { | ||
try { | ||
const accountInfo = await this.binanceClient.getBinanceAccountInfo(); | ||
const parseResult = BinanceAccountInfoSchema.safeParse(accountInfo); | ||
if (parseResult.success) { | ||
const topBalances = this.mapBinanceAccountInfo( | ||
parseResult.data, | ||
numberOfTopBalances, | ||
currencyName, | ||
); | ||
return topBalances; | ||
} else if (parseResult.success === false) { | ||
this.logger.error( | ||
`Validation errors when parsing account info ${parseResult.error.errors}`, | ||
); | ||
} | ||
} catch (error) { | ||
this.logger.error( | ||
`Error when parsing binance account info ${error.message}`, | ||
); | ||
} | ||
}; | ||
|
||
private mapBinanceAccountInfo = async ( | ||
account: BinanceAccountInfo, | ||
numberOfTopBalances: number, | ||
currencyName?: string, | ||
) => { | ||
const accountBalancesWithMinValue = account.balances.filter( | ||
(balance) => parseFloat(balance.free) >= 0.1, | ||
); | ||
|
||
const balancesWithTotalValueCalculated: BinanceBalanceWithTotalValueAndSymbol[] = | ||
await this.addTotalValueAndCurrencySymbolToBalances( | ||
accountBalancesWithMinValue, | ||
currencyName, | ||
); | ||
|
||
const sortedBalances = this.sortBalancesByTotalValue( | ||
balancesWithTotalValueCalculated, | ||
); | ||
|
||
const revertedBalances = this.revertBalances(sortedBalances); | ||
|
||
const topBalances = revertedBalances.slice(0, numberOfTopBalances); | ||
|
||
return topBalances; | ||
}; | ||
|
||
private sortBalancesByTotalValue = ( | ||
balances: BinanceBalanceWithTotalValueAndSymbol[], | ||
) => { | ||
return balances.sort( | ||
(a, b) => parseFloat(b.totalValue) - parseFloat(a.totalValue), | ||
); | ||
}; | ||
|
||
private revertBalances = ( | ||
balances: BinanceBalanceWithTotalValueAndSymbol[], | ||
) => { | ||
return balances.map((balance) => ({ | ||
asset: balance.asset, | ||
free: balance.free, | ||
locked: balance.locked, | ||
symbol: balance.symbol, | ||
totalValue: balance.totalValue, | ||
})); | ||
}; | ||
|
||
private addTotalValueAndCurrencySymbolToBalances = async ( | ||
balances: BinanceBalance[], | ||
currencyName?: string, | ||
) => { | ||
return await Promise.all( | ||
balances.map(async (balance) => { | ||
const symbol = currencyName | ||
? `${balance.asset}${currencyName.toUpperCase()}` | ||
: `${balance.asset}${CURRENCY_FOR_TOKEN_PRICES}`; | ||
if (balance.asset === CURRENCY_FOR_TOKEN_PRICES) { | ||
return { | ||
asset: balance.asset, | ||
free: balance.free, | ||
locked: balance.locked, | ||
symbol: balance.asset, | ||
totalValue: balance.free, | ||
}; | ||
} | ||
const tickerResponse = | ||
await this.binanceClient.getSymbolTickerPrice(symbol); | ||
|
||
const totalValue = this.calculateTotalSymbolValue( | ||
balance, | ||
tickerResponse, | ||
); | ||
return { | ||
asset: balance.asset, | ||
free: balance.free, | ||
locked: balance.locked, | ||
symbol: symbol, | ||
totalValue: totalValue ?? 'Unavailable', | ||
}; | ||
}), | ||
); | ||
}; | ||
|
||
private calculateTotalSymbolValue = ( | ||
balance: BinanceBalance, | ||
tickerResponse: TickerPriceType, | ||
) => { | ||
if (!tickerResponse) { | ||
return ''; | ||
} | ||
const price = tickerResponse.price; | ||
const tokenAmount = balance.free; | ||
|
||
return (parseFloat(price) * parseFloat(tokenAmount)).toFixed(4); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.