> giveCoinFullInfo = await this.sdk.getCoin(this.giveCoin.toLowerCase()) > giveAmount = Кол-во монет, которые отдают > getCoinFullInfo = await this.sdk.getCoin(this.getCoin.toLowerCase()) ```ts estimated = sell(this.giveCoinFullInfo, this.giveAmount, this.getCoinFullInfo) ``` > (process.env.baseCoin = 'DEL', если testnet, то 'tDEL') # Функция estimate (используется на странице) ```ts public estimate (field) : void { let estimated = { success: false, value: '0' } as IEstimated if (field === 'giveCoin' || field === 'sellAll') { if (field !== 'sellAll') { this.mode = 'sell' } if (this.getCoinFullInfo && this.giveCoinFullInfo && this.giveAmount && this.getCoin && this.giveCoin) { estimated = sell(this.giveCoinFullInfo, this.giveAmount, this.getCoinFullInfo) // @ts-ignore this.getAmount = estimated.success ? this.DecimalNumber(estimated.value).toFixed(18).replace(/^0+(?!\.)|(?:\.|(\..*?))0+$/gm, '$1') : '' } else if (!this.giveAmount) { this.getAmount = '' } // @ts-ignore this.estimatedGet = estimated } else if (field === 'getCoin') { this.mode = 'buy' if (this.getCoinFullInfo && this.giveCoinFullInfo && this.getAmount && this.getCoin && this.giveCoin) { estimated = buy(this.getCoinFullInfo, this.getAmount, this.giveCoinFullInfo) // @ts-ignore this.giveAmount = estimated.success ? this.DecimalNumber(estimated.value).toFixed(18).replace(/^0+(?!\.)|(?:\.|(\..*?))0+$/gm, '$1') : '' } else if (!this.getAmount) { this.giveAmount = '' } // @ts-ignore this.estimatedSpend = estimated } } ``` # math.ts ```ts import DecimalNumber from 'decimal.js' interface ICoin { crr: string; ticker: any; reserve: string ; maxSupply?: string; supply: string } DecimalNumber.set({ precision: 100 }) function getAmountFromSatoshi (amount: DecimalNumber.Value): string { return new DecimalNumber(amount).times(new DecimalNumber(10).pow(-18)).toFixed() } function getCoinFormatted (coinData: { volume: DecimalNumber.Value; reserve: DecimalNumber.Value; crr: DecimalNumber.Value; limitVolume: DecimalNumber.Value; symbol: any; }) : ICoin { return { supply: getAmountFromSatoshi(coinData.volume), reserve: getAmountFromSatoshi(coinData.reserve), crr: new DecimalNumber(coinData.crr).div(100).toFixed(), maxSupply: getAmountFromSatoshi(coinData.limitVolume), ticker: coinData.symbol } } /** * Sell: * Продажа монеты, подсчет получаемых del */ export const sellCoin = (coin: ICoin, coinAmount: DecimalNumber.Value): string | boolean => { const crr = new DecimalNumber(coin.crr).times(100).toNumber() if (new DecimalNumber(coinAmount).eq(new DecimalNumber(0))) { return '0' } if (new DecimalNumber(coinAmount).eq(new DecimalNumber(coin.supply))) { return coin.reserve } if (new DecimalNumber(crr).eq(new DecimalNumber(100))) { const ret = new DecimalNumber(coin.reserve).times(new DecimalNumber(coinAmount)) return ret.div(new DecimalNumber(coin.supply)).toFixed().toString() } const e1 = new DecimalNumber(coinAmount).div(coin.supply) const e2 = new DecimalNumber(1).minus(e1) if (e2 < new DecimalNumber(0)) { return false } const e3 = e2.pow(new DecimalNumber(100).div(crr)) const e4 = new DecimalNumber(1).minus(e3) return e4.times(coin.reserve).toFixed() } /** * Sell: * Продажа монеты, подсчет необходимых монет */ export const sellCoinByDel = (coin: ICoin, delAmount: DecimalNumber.Value): string => { // eslint-disable-next-line no-param-reassign delAmount = Math.min(parseFloat(coin.reserve), +delAmount) const e1 = new DecimalNumber(delAmount).div(coin.reserve) const e2 = new DecimalNumber(1).minus(e1).pow(coin.crr) const result = new DecimalNumber(1).minus(e2).times(coin.supply) // => coin return result.toFixed() } /** * Buy: * Покупка монеты, подсчет получаемых монет */ export const buyCoin = (coin: ICoin, delAmount: string | number | DecimalNumber.Value): string => { const e1 = new DecimalNumber(delAmount).div(coin.reserve).plus(1).pow(coin.crr) const result = new DecimalNumber(e1).minus(1).times(coin.supply) // => coin return result.toFixed() } /** * Buy: * Покупка монеты, подсчет необходимых del */ export const buyCoinByCoin = (coin: ICoin, coinAmount: number | string): string => { const e1 = new DecimalNumber(coinAmount).div(coin.supply).plus(1) const e2 = new DecimalNumber(1).div(coin.crr) const result = new DecimalNumber(e1).pow(e2).minus(1).times(coin.reserve) // => del return result.toFixed() } function isLessReserve (spendCoin: { reserve: DecimalNumber.Value; ticker: string; }, amount: DecimalNumber.Value): false | {key: string, coin:string} { // console.log('spend-coin', spendCoin); // console.log('amount', amount); const maxDelSpend = new DecimalNumber(spendCoin.reserve).minus(1000).toFixed() if (!amount || new DecimalNumber(amount).gt(maxDelSpend)) { return { key: 'reserve-limit', coin: spendCoin.ticker.toUpperCase() } } return false } function isMoreMaxSupply (getCoin:any, amount: DecimalNumber.Value):false | {key: string, coin:string} { const available = new DecimalNumber(getCoin.maxSupply).minus(getCoin.supply).toFixed() // => coin if (new DecimalNumber(amount).gt(available)) { return { key: 'more-limit-volume', coin: getCoin.ticker.toUpperCase() } } return false } // Todo export function buy (getCoinn: any, amount: string | number, spendCoinn: any) : {success:boolean, value?:string, key?: string, coin?:string} { const spendCoin = getCoinFormatted(spendCoinn) const getCoin = getCoinFormatted(getCoinn) // console.log('buy'); let estimated: any = '' let error: false | {key: string, coin:string} = false if ( // @ts-ignore getCoin.ticker.toLowerCase() === process.env.baseCoin.toLowerCase()) { estimated = sellCoinByDel(spendCoin, amount) // => coin error = isLessReserve(spendCoin, amount) } else if ( // @ts-ignore spendCoin.ticker.toLowerCase() === process.env.baseCoin.toLowerCase()) { estimated = buyCoinByCoin(getCoin, amount) // => tdel error = isMoreMaxSupply(getCoin, amount) } else { const needDel = buyCoinByCoin(getCoin, amount) // => tdel estimated = sellCoinByDel(spendCoin, needDel) // => coin error = isMoreMaxSupply(getCoin, amount) error = error || isLessReserve(spendCoin, needDel) } // error = error || isInfluentFunds(estimated, spendCoin); if (error) { return { success: false, ...error } } return { success: true, value: estimated } } export function sell (spendCoinn: any, amount: string | number | DecimalNumber, getCoinn: any) : {success?:boolean, value?:string, key?: string, coin?:string} { const spendCoin = getCoinFormatted(spendCoinn) const getCoin = getCoinFormatted(getCoinn) // console.log('sell'); let estimated: any = '' let error : any = false if ( // @ts-ignore spendCoin.ticker.toLowerCase() === process.env.baseCoin.toLowerCase()) { estimated = buyCoin(getCoin, amount) // => coin error = isMoreMaxSupply(getCoin, estimated) } else if ( // @ts-ignore getCoin.ticker.toLowerCase() === process.env.baseCoin.toLowerCase()) { estimated = sellCoin(spendCoin, amount) error = isLessReserve(spendCoin, estimated) } else { const needDel = String(sellCoin(spendCoin, amount)) // => tdel estimated = buyCoin(getCoin, needDel) // => coin error = isMoreMaxSupply(getCoin, amount) error = error || isLessReserve(spendCoin, needDel) } // error = error || isInfluentFunds(amount, spendCoin); if (error) { return { success: false, ...error } } return { success: true, value: estimated } } ```