dnum icon indicating copy to clipboard operation
dnum copied to clipboard

Adding support to format roundDigits (for tokenDust)

Open yodlmeister opened this issue 1 year ago • 3 comments

Nice library.

We'd like to do a PR to add following functionality to better display token dust. E.g. when amounts are < 0.0

dnum.format([ 126, 8], roundDust: 1)
=> 0.00001

dnum.format([ 126, 8], roundDust: 2)
=> 0.000013

Would you accept a PR for that, any considerations?

yodlmeister avatar Jun 19 '24 09:06 yodlmeister

@yodlmeister I'm not familiar with your exact usecase, but a relatively simple helper function that leverages the existing digits and trailingZeros options could achieve what you're looking for:

import * as dn from 'dnum';

function roundDust(dnum: dn.Dnum, dustDigits: number): string {
  const sigZeros = Math.max(dnum[1] - dnum[0].toString().length, 0);
  return dn.format(dnum, { digits: sigZeros + dustDigits, trailingZeros: false });
}

console.log(dn.format([126n, 8]));     // 0.00000126
console.log(roundDust([126n, 8], 1));  // 0.000001
console.log(roundDust([126n, 8], 2));  // 0.0000013

carpntr avatar Jun 20 '24 00:06 carpntr

Nice solution @carpntr, thanks!

@yodlmeister I think it could be nice to have this in the library yes, especially if the implementation can be compact enough.

Some thoughts:


On naming, I think we could skip "round", as format() already rounds decimals with the other options. Some ideas:

  • dust
  • trail
  • leadingZeros, this one is weird because it doesn’t really mirror trailingZeros, but I’ve been wondering if having zeros in the name could make it more clear :thinking:

I wonder how the option would impact digits, and if it would be clear enough. I can see users setting dust and expecting it to work, but it would only do digits is set:

// digits defaults to 18, so dust does nothing
dn.format([123126n, 18], { dust: 2 })                  // "0.000000000000123126"

// digits is small enough for dust to take precedence
dn.format([123126n, 18], { digits: 2, dust: 2 })       // "0.00000000000012"

Is there a need for choosing the number of dust decimals, versus only having a boolean (= 1 digit)? The dust could be at any position in the decimals depending on the number, so choosing the dust digits doesn’t offer as much control as digit:

let dust1 = { digits: 0, dust: 1 }
let dust2 = { digits: 0, dust: 2 }

dn.format([126n, 18], dust1)                  // "0.0000000000000001"
dn.format([126n, 18], dust2)                  // "0.00000000000000013"

dn.format([126000000000000000n, 18], dust1)  // "0.1"
dn.format([126000000000000000n, 18], dust2)  // "0.13"

Or would it be useful for certain cases?


Another idea: what if the option was set to the number of digits until which the dust gets displayed?

It would basically take over digits when the number of leading zeros exceeds its value:

let o = { digits: 2, trailingZeros: true }

dn.format([126n, 8], { ...o, dust: 5 })  // "0.00013" (dust applies)
dn.format([126n, 8], { ...o, dust: 4 })  // "0.0001" (dust applies)
dn.format([126n, 8], { ...o, dust: 3 })  // "0.00" (digits applies)

@carpntr @yodlmeister what do you guys think?

bpierre avatar Jun 21 '24 01:06 bpierre

@carpntr @yodlmeister what do you guys think?

@carpntr your solution worked perfectly. I'll deploy this and a few small modifications and write a PR once this is running smoothly.

yodlmeister avatar Oct 29 '24 08:10 yodlmeister