diff --git a/docs/lib/modules/lumconstants.md b/docs/lib/modules/lumconstants.md index 6fcc445..d423134 100644 --- a/docs/lib/modules/lumconstants.md +++ b/docs/lib/modules/lumconstants.md @@ -16,7 +16,9 @@ - [LumBech32PrefixValAddr](lumconstants.md#lumbech32prefixvaladdr) - [LumBech32PrefixValPub](lumconstants.md#lumbech32prefixvalpub) - [LumDenom](lumconstants.md#lumdenom) +- [LumExponent](lumconstants.md#lumexponent) - [LumWalletSigningVersion](lumconstants.md#lumwalletsigningversion) +- [MicroLumDenom](lumconstants.md#microlumdenom) - [PrivateKeyLength](lumconstants.md#privatekeylength) ### Functions @@ -93,6 +95,15 @@ Lum Coin denomination ___ +### LumExponent + +• `Const` **LumExponent**: *6*= 6 + +Lum Exponent +1 lum = 10^6 ulum + +___ + ### LumWalletSigningVersion • `Const` **LumWalletSigningVersion**: *1*= '1' @@ -101,6 +112,14 @@ Signing version of the SDK ___ +### MicroLumDenom + +• `Const` **MicroLumDenom**: *ulum*= 'ulum' + +Micro Lum Coin denomination + +___ + ### PrivateKeyLength • `Const` **PrivateKeyLength**: *32*= 32 diff --git a/docs/lib/modules/lumutils.md b/docs/lib/modules/lumutils.md index d83a2ea..efcff6d 100644 --- a/docs/lib/modules/lumutils.md +++ b/docs/lib/modules/lumutils.md @@ -10,6 +10,7 @@ - [broadcastTxCommitSuccess](lumutils.md#broadcasttxcommitsuccess) - [broadcastTxSyncSuccess](lumutils.md#broadcasttxsyncsuccess) +- [convertUnit](lumutils.md#convertunit) - [generateAuthInfoBytes](lumutils.md#generateauthinfobytes) - [generateKeyStore](lumutils.md#generatekeystore) - [generateMnemonic](lumutils.md#generatemnemonic) @@ -78,6 +79,28 @@ Name | Type | ___ +### convertUnit + +▸ `Const`**convertUnit**(`coin`: [*Coin*](../interfaces/lumtypes.coin.md), `toDenom`: *string*): *string* + +Converts the Coin amount into the destination denom. +This method does not do any actual math and only "move" the floating precision of the amoun in order to avoid any +possible floating point precision issue. +It does nothing if src denom = dst denom. + +#### Parameters: + +Name | Type | Description | +:------ | :------ | :------ | +`coin` | [*Coin*](../interfaces/lumtypes.coin.md) | Coin to convert into toDenom | +`toDenom` | *string* | destination denom to convert into | + +**Returns:** *string* + +the amount converted + +___ + ### generateAuthInfoBytes ▸ `Const`**generateAuthInfoBytes**(`publicKey`: *Uint8Array*, `fee`: [*Fee*](../interfaces/lumtypes.fee.md), `sequence`: *number*, `signMode`: SignMode): *Uint8Array* diff --git a/package.json b/package.json index cc71334..65c65b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lum-network/sdk-javascript", - "version": "0.3.4", + "version": "0.3.5", "license": "Apache-2.0", "description": "Javascript SDK library for NodeJS and Web browsers to interact with the Lum Network.", "homepage": "https://github.com/lum-network/sdk-javascript#readme", diff --git a/src/constants/index.ts b/src/constants/index.ts index 2d2e2c6..24b36a8 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,8 +1,19 @@ +/** + * Lum Exponent + * 1 lum = 10^6 ulum + */ +export const LumExponent = 6; + /** * Lum Coin denomination */ export const LumDenom = 'lum'; +/** + * Micro Lum Coin denomination + */ +export const MicroLumDenom = 'ulum'; + /** * Lum Network Bech32 prefix of an account's address */ diff --git a/src/utils/index.ts b/src/utils/index.ts index 292207a..631b023 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -6,3 +6,4 @@ export * from './transactions'; export * from './broadcast'; export * from './search'; export * from './txlogs'; +export * from './units'; diff --git a/src/utils/units.ts b/src/utils/units.ts new file mode 100644 index 0000000..102def0 --- /dev/null +++ b/src/utils/units.ts @@ -0,0 +1,42 @@ +import { LumTypes, LumConstants } from '..'; + +/** + * Converts the Coin amount into the destination denom. + * This method does not do any actual math and only "move" the floating precision of the amoun in order to avoid any + * possible floating point precision issue. + * It does nothing if src denom = dst denom. + * + * @param coin Coin to convert into toDenom + * @param toDenom destination denom to convert into + * @returns the amount converted + */ +export const convertUnit = (coin: LumTypes.Coin, toDenom: string): string => { + const parts = coin.amount.split('.'); + if (parts.length > 2) { + throw new Error('More than one separator found'); + } + + if (coin.denom.startsWith('u') && coin.denom.endsWith(toDenom)) { + // from micro to base + if (parts.length !== 1) { + throw new Error('Micro units cannot have floating precision'); + } + let res = parts[0]; + for (let i = res.length; res.length <= LumConstants.LumExponent; i++) { + res = '0' + res; + } + const floatIdx = res.length - LumConstants.LumExponent; + return (res.substring(0, floatIdx) + '.' + res.substring(floatIdx)).replace(/0+$/, ''); + } else if (toDenom.startsWith('u') && toDenom.endsWith(coin.denom)) { + // form base to micro + if (parts.length === 2 && parts[1].length > LumConstants.LumExponent) { + throw new Error(`Floating precision cannot exceed ${LumConstants.LumExponent} digits`); + } + let res = parts[0] + (parts[1] || ''); + for (let i = parts.length === 2 ? parts[1].length : 0; i < LumConstants.LumExponent; i++) { + res += '0'; + } + return res.replace(/^0+/, ''); + } + return coin.amount; +}; diff --git a/tests/client.test.ts b/tests/client.test.ts index 7fa1bfb..de2233b 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -40,7 +40,7 @@ describe('LumClient', () => { const supplies = await clt.queryClient.bank.unverified.totalSupply(); expect(supplies).toBeTruthy(); expect(supplies.length).toBeGreaterThan(0); - const lumSupply = supplies.filter((c) => c.denom === LumConstants.LumDenom)[0]; + const lumSupply = supplies.filter((c) => c.denom === LumConstants.MicroLumDenom)[0]; expect(lumSupply).toBeTruthy(); expect(parseFloat(lumSupply.amount)).toBeGreaterThan(0); }); @@ -80,7 +80,7 @@ describe('LumClient', () => { const balances = await clt.getAllBalancesUnverified(account.address); expect(balances).toBeTruthy(); expect(balances.length).toBeGreaterThan(0); - const lumBalance = balances.filter((b) => b.denom === LumConstants.LumDenom)[0]; + const lumBalance = balances.filter((b) => b.denom === LumConstants.MicroLumDenom)[0]; expect(lumBalance).toBeTruthy(); expect(parseFloat(lumBalance.amount)).toBeGreaterThan(0); }); diff --git a/tests/faucet.test.ts b/tests/faucet.test.ts index ac9984d..acf7c1a 100644 --- a/tests/faucet.test.ts +++ b/tests/faucet.test.ts @@ -17,7 +17,7 @@ describe('Faucet', () => { // WIP // const mintMsg = LumMessages.BuildMsgMintAndSend(w1.getAddress(), new Date()); // const fee = { - // amount: [{ denom: LumConstants.LumDenom, amount: '0' }], + // amount: [{ denom: LumConstants.MicroLumDenom, amount: '0' }], // gas: '100000', // }; // const chainId = await clt.getChainId(); diff --git a/tests/ledger.test.ts b/tests/ledger.test.ts index 5e2ca43..273a77f 100644 --- a/tests/ledger.test.ts +++ b/tests/ledger.test.ts @@ -27,7 +27,7 @@ describe('Ledger', () => { // const chainId = await clt.getChainId(); // const sendMsg = LumMessages.BuildMsgSend(w1.getAddress(), 'lum1lsagfzrm4gz28he4wunt63sts5xzmczwjttsr9', [{ denom: 'lum', amount: '3' }]); // const fee = { - // amount: [{ denom: LumConstants.LumDenom, amount: '1' }], + // amount: [{ denom: LumConstants.MicroLumDenom, amount: '1' }], // gas: '100000', // }; // const doc = { diff --git a/tests/utils.test.ts b/tests/utils.test.ts new file mode 100644 index 0000000..5946e93 --- /dev/null +++ b/tests/utils.test.ts @@ -0,0 +1,15 @@ +import { LumConstants, LumUtils } from '../src'; + +describe('Utils', () => { + it('Unit conversion should output consistent results', () => { + expect(LumUtils.convertUnit({ denom: LumConstants.LumDenom, amount: '23.456789' }, LumConstants.LumDenom)).toEqual('23.456789'); + expect(LumUtils.convertUnit({ denom: LumConstants.LumDenom, amount: '23.456789' }, LumConstants.MicroLumDenom)).toEqual('23456789'); + expect(LumUtils.convertUnit({ denom: LumConstants.LumDenom, amount: '23456789' }, LumConstants.MicroLumDenom)).toEqual('23456789000000'); + expect(LumUtils.convertUnit({ denom: LumConstants.MicroLumDenom, amount: '123456789000' }, LumConstants.LumDenom)).toEqual('123456.789'); + expect(LumUtils.convertUnit({ denom: LumConstants.MicroLumDenom, amount: '123456789111' }, LumConstants.LumDenom)).toEqual('123456.789111'); + expect(LumUtils.convertUnit({ denom: LumConstants.MicroLumDenom, amount: '123456' }, LumConstants.LumDenom)).toEqual('0.123456'); + expect(LumUtils.convertUnit({ denom: LumConstants.MicroLumDenom, amount: '23456' }, LumConstants.LumDenom)).toEqual('0.023456'); + expect(LumUtils.convertUnit({ denom: LumConstants.LumDenom, amount: '0.000001' }, LumConstants.MicroLumDenom)).toEqual('1'); + expect(LumUtils.convertUnit({ denom: LumConstants.MicroLumDenom, amount: '1' }, LumConstants.LumDenom)).toEqual('0.000001'); + }); +});