Skip to content

Commit

Permalink
fix quote asset qty formatting (for total preview), group floating-po…
Browse files Browse the repository at this point in the history
…int operations to reduce the possibility of imprecise calculations
  • Loading branch information
norwnd committed Jan 19, 2025
1 parent b985e49 commit 0fb29cc
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 31 deletions.
8 changes: 4 additions & 4 deletions client/webserver/site/src/css/market.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,29 @@ div[data-handler=markets] {

#previewTotalBuy {
#orderTotalPreviewBuyLeft {
flex-basis: 42%;
flex-basis: 47%;
}

#orderTotalPreviewBuyDelimiter {
flex-basis: 6%;
}

#orderTotalPreviewBuyRight {
flex-basis: 42%;
flex-basis: 47%;
}
}

#previewTotalSell {
#orderTotalPreviewSellLeft {
flex-basis: 42%;
flex-basis: 47%;
}

#orderTotalPreviewSellDelimiter {
flex-basis: 6%;
}

#orderTotalPreviewSellRight {
flex-basis: 42%;
flex-basis: 47%;
}
}

Expand Down
13 changes: 13 additions & 0 deletions client/webserver/site/src/css/utilities.scss
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,16 @@ div.clear {
.text-sellcolor {
color: var(--sell-color);
}

.py-0-5 {
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}

.pt-0-5 {
padding-top: 0.125rem;
}

.pb-0-5 {
padding-bottom: 0.125rem;
}
16 changes: 8 additions & 8 deletions client/webserver/site/src/html/markets.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@
<option value="1"></option>
</datalist>
</div>
<div class="d-flex flex-grow-1 flex-stretch-row m-1 disabled" id="previewTotalBuy">
<div id="orderTotalPreviewBuyLeft" class="d-flex align-items-center justify-content-end mx-2 fs18"></div>
<span id="orderTotalPreviewBuyDelimiter" class="d-flex align-items-center mx-2 fs24">⇄</span>
<div id="orderTotalPreviewBuyRight" class="d-flex align-items-center justify-content-start mx-2 fs18"></div>
<div class="d-flex flex-stretch-row m-1 disabled" id="previewTotalBuy">
<div id="orderTotalPreviewBuyLeft" class="d-flex align-items-center justify-content-end me-1 fs18"></div>
<span id="orderTotalPreviewBuyDelimiter" class="d-flex align-items-center mx-1 pt-0-5 fs22">⇄</span>
<div id="orderTotalPreviewBuyRight" class="d-flex align-items-center justify-content-start ms-1 fs18"></div>
</div>
<button id="submitBttnBuy" type="button" class="flex-center border pointer hoverbg border-rounded3 m-1 submit fs18 text-center buygreen-bg"></button> {{/* textContent set by script */}}
<div class="m-1 fs17 pt-3 text-center d-hide text-danger text-break" id="orderErrBuy"></div>
Expand Down Expand Up @@ -187,10 +187,10 @@
<option value="1"></option>
</datalist>
</div>
<div class="d-flex flex-grow-1 flex-stretch-row m-1 disabled" id="previewTotalSell">
<div id="orderTotalPreviewSellLeft" class="d-flex align-items-center justify-content-end mx-2 fs18"></div>
<span id="orderTotalPreviewSellDelimiter" class="d-flex align-items-center mx-2 fs24">⇄</span>
<div id="orderTotalPreviewSellRight" class="d-flex align-items-center justify-content-start mx-2 fs18"></div>
<div class="d-flex flex-stretch-row m-1 disabled" id="previewTotalSell">
<div id="orderTotalPreviewSellLeft" class="d-flex align-items-center justify-content-end me-1 fs18"></div>
<span id="orderTotalPreviewSellDelimiter" class="d-flex align-items-center mx-1 pt-0-5 fs22">⇄</span>
<div id="orderTotalPreviewSellRight" class="d-flex align-items-center justify-content-start ms-1 fs18"></div>
</div>
<button id="submitBttnSell" type="button" class="flex-center border pointer hoverbg border-rounded3 m-1 submit fs18 text-center sellred-bg"></button> {{/* textContent set by script */}}
<div class="m-1 fs17 pt-3 text-center d-hide text-danger text-break" id="orderErrSell"></div>
Expand Down
2 changes: 1 addition & 1 deletion client/webserver/site/src/js/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function likelyTaker (ord: Order, rate: number): boolean {
const preparcelQuantity = (ord: Order, mkt?: Market, midGapAtom?: number) => {
const qty = ord.qty - ord.filled
if (ord.type === OrderTypeLimit) return qty
if (ord.sell) return qty * ord.rate / RateEncodingFactor
if (ord.sell) return qty * (ord.rate / RateEncodingFactor)
const rateAtom = midGapAtom || mkt?.spot?.rate || 0
// Caller should not call this for market orders without a mkt arg.
if (!mkt) return 0
Expand Down
2 changes: 1 addition & 1 deletion client/webserver/site/src/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,7 @@ export default class Application {
const [b, q] = [this.unitInfo(baseID, xc), this.unitInfo(quoteID, xc)]

const r = b.conventional.conversionFactor / q.conventional.conversionFactor
return encRate * r / RateEncodingFactor
return encRate * (r / RateEncodingFactor)
}

walletDefinition (assetID: number, walletType: string): WalletDefinition {
Expand Down
26 changes: 16 additions & 10 deletions client/webserver/site/src/js/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,9 @@ export default class Doc {
* formatCoinAtomToLotSizeBaseCurrency formats atomic coin value to represent it exactly
* at lot size precision (corresponds to base currency).
*/
static formatCoinAtomToLotSizeBaseCurrency (coinAtom: number, baseUnitInfo: UnitInfo, lotSizeAtom: number): string {
const [coin] = convertToConventional(coinAtom, baseUnitInfo)
const [lotSize] = convertToConventional(lotSizeAtom, baseUnitInfo)
static formatCoinAtomToLotSizeBaseCurrency (coinAtom: number, bui: UnitInfo, lotSizeAtom: number): string {
const [coin] = convertToConventional(coinAtom, bui)
const [lotSize] = convertToConventional(lotSizeAtom, bui) // lot size is in base units
const lotSizeDigits = -(Math.floor(Math.log10(lotSize)))
if (lotSizeDigits <= 0) {
// no decimals, display as integer then
Expand All @@ -367,12 +367,12 @@ export default class Doc {
}

/*
* formatCoinAtomToLotSizeQuoteCurrency formats atomic coin value to represent it exactly
* at lot size precision that would correspond to quote currency.
*/
* formatCoinAtomToLotSizeQuoteCurrency formats atomic coin value to represent it exactly
* at lot size precision that would correspond to quote currency.
*/
static formatCoinAtomToLotSizeQuoteCurrency (coinAtom: number, bui: UnitInfo, qui: UnitInfo, lotSizeAtom: number, rateStepAtom: number): string {
const [coin] = convertToConventional(coinAtom, qui)
const [lotSize] = convertToConventional(lotSizeAtom, qui)
const [lotSize] = convertToConventional(lotSizeAtom, bui) // lot size is in base units
const lotSizeDigits = -(Math.floor(Math.log10(lotSize)))
const rateStepDigits = log10RateEncodingFactor - Math.floor(Math.log10(rateStepAtom)) -
Math.floor(Math.log10(bui.conventional.conversionFactor) - Math.log10(qui.conventional.conversionFactor))
Expand Down Expand Up @@ -401,13 +401,13 @@ export default class Doc {
*/
static formatRateAtomToRateStep (rateAtom: number, bui: UnitInfo, qui: UnitInfo, rateStepAtom: number): string {
const r = bui.conventional.conversionFactor / qui.conventional.conversionFactor
const rateConv = rateAtom * r / RateEncodingFactor
const rateConv = rateAtom * (r / RateEncodingFactor)
return Doc.formatRateToRateStep(rateConv, bui, qui, rateStepAtom)
}

/*
* formatRateToRateStep formats conventional rate value to represent it exactly at rate step
* precision.
* precision (rounding down when necessary).
*/
static formatRateToRateStep (rateConv: number, bui: UnitInfo, qui: UnitInfo, rateStepAtom: number): string {
const rateStepDigits = log10RateEncodingFactor - Math.floor(Math.log10(rateStepAtom)) -
Expand All @@ -416,6 +416,12 @@ export default class Doc {
// no decimals, display as integer then
return intFormatter.format(rateConv)
}

// round down rateConv here explicitly so we don't leave rounding to "chance"
// const rateStepConv = Math.pow(10, -rateStepDigits)
// const rateConvAdj = rateConv - (rateConv % rateStepConv)

// return fullPrecisionFormatterWithPreservingZeroes(rateStepDigits).format(rateConvAdj)
return fullPrecisionFormatterWithPreservingZeroes(rateStepDigits).format(rateConv)
}

Expand Down Expand Up @@ -541,7 +547,7 @@ export default class Doc {

static conventionalRateStep (rateStepEnc: number, baseUnitInfo: UnitInfo, quoteUnitInfo: UnitInfo) {
const [qFactor, bFactor] = [quoteUnitInfo.conventional.conversionFactor, baseUnitInfo.conventional.conversionFactor]
return rateStepEnc / RateEncodingFactor * (bFactor / qFactor)
return (rateStepEnc / RateEncodingFactor) * (bFactor / qFactor)
}

/*
Expand Down
13 changes: 10 additions & 3 deletions client/webserver/site/src/js/markets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,11 @@ export default class MarketsPage extends BasePage {
page.orderTotalPreviewBuyRight.textContent = intl.prep(
intl.ID_LIMIT_ORDER_BUY_SELL_IN_TOTAL_PREVIEW,
{
total: Doc.formatCoinAtomToLotSizeBaseCurrency(totalIn, market.baseUnitInfo, market.cfg.lotsize),
total: Doc.formatCoinAtomToLotSizeBaseCurrency(
totalIn,
market.baseUnitInfo,
market.cfg.lotsize
),
asset: market.baseUnitInfo.conventional.unit
}
)
Expand All @@ -1459,7 +1463,11 @@ export default class MarketsPage extends BasePage {
page.orderTotalPreviewSellLeft.textContent = intl.prep(
intl.ID_LIMIT_ORDER_BUY_SELL_OUT_TOTAL_PREVIEW,
{
total: Doc.formatCoinAtomToLotSizeBaseCurrency(totalIn, market.baseUnitInfo, market.cfg.lotsize),
total: Doc.formatCoinAtomToLotSizeBaseCurrency(
totalIn,
market.baseUnitInfo,
market.cfg.lotsize
),
asset: market.baseUnitInfo.conventional.unit
}
)
Expand Down Expand Up @@ -3613,7 +3621,6 @@ class OrderTableRowManager {
this.redrawOrderRowEl()
} else {
let colorSellOrBuy = this.isSell() ? 'sellcolor' : 'buycolor'

page.rate.innerText = Doc.formatRateAtomToRateStep(this.msgRate, baseUnitInfo, quoteUnitInfo, rateStepAtom)
page.rate.classList.add(colorSellOrBuy)

Expand Down
6 changes: 3 additions & 3 deletions client/webserver/site/src/js/orderutil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function statusString (order: Order): string {
/* filled sums the quantities of non-cancel matches available. */
export function filled (order: Order): number {
if (!order.matches) return 0
const qty = isMarketBuy(order) ? (m: Match) => m.qty * m.rate / RateEncodingFactor : (m: Match) => m.qty
const qty = isMarketBuy(order) ? (m: Match) => m.qty * (m.rate / RateEncodingFactor) : (m: Match) => m.qty
return order.matches.reduce((filled, match) => {
if (match.isCancel) return filled
return filled + qty(match)
Expand All @@ -118,7 +118,7 @@ export function filled (order: Order): number {
/* settled sums the quantities of the matches that have completed. */
export function settled (order: Order): number {
if (!order.matches) return 0
const qty = isMarketBuy(order) ? (m: Match) => m.qty * m.rate / RateEncodingFactor : (m: Match) => m.qty
const qty = isMarketBuy(order) ? (m: Match) => m.qty * (m.rate / RateEncodingFactor) : (m: Match) => m.qty
return order.matches.reduce((settled, match) => {
if (match.isCancel) return settled
const redeemed = (match.side === Maker && match.status >= MakerRedeemed) ||
Expand Down Expand Up @@ -151,7 +151,7 @@ export function averageRate (ord: Order): number {

/* baseToQuote returns the quantity of the quote asset. */
export function baseToQuote (rate: number, base: number) : number {
return rate * base / RateEncodingFactor
return rate * (base / RateEncodingFactor)
}

/* orderPortion returns a string stating the percentage of the order a match
Expand Down
2 changes: 1 addition & 1 deletion dex/calc/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func ConventionalRate(msgRate uint64, baseInfo, quoteInfo dex.UnitInfo) float64
// conventional exchange rate using the base and quote assets' conventional
// conversion factors.
func ConventionalRateAlt(msgRate uint64, baseFactor, quoteFactor uint64) float64 {
return float64(msgRate) / RateEncodingFactor * float64(baseFactor) / float64(quoteFactor)
return (float64(msgRate) / RateEncodingFactor) * (float64(baseFactor) / float64(quoteFactor))
}

// MessageRate converts an exchange rate in conventional encoding to one
Expand Down

0 comments on commit 0fb29cc

Please sign in to comment.