Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortened amount props for ValueViewComponent #1915

Merged
merged 4 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-squids-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@penumbra-zone/types': minor
---

Adding shortify + round utilities
5 changes: 5 additions & 0 deletions .changeset/loud-beers-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@penumbra-zone/ui': minor
---

Updating ValueViewComponent to support shortening symbols
2 changes: 1 addition & 1 deletion apps/minifront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"devDependencies": {
"@chain-registry/types": "^0.45.38",
"@eslint/compat": "^1.1.0",
"@types/lodash": "^4.17.4",
"@types/lodash": "^4.17.7",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.11",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_p
import { SwapExecution_Trace } from '@penumbra-zone/protobuf/penumbra/core/component/dex/v1/dex_pb';
import { bech32mAssetId } from '@penumbra-zone/bech32m/passet';
import { getDisplayDenomExponent } from '@penumbra-zone/getters/metadata';
import { formatAmount, removeTrailingZeros } from '@penumbra-zone/types/amount';
import { formatAmount } from '@penumbra-zone/types/amount';
import { BigNumber } from 'bignumber.js';
import { removeTrailingZeros } from '@penumbra-zone/types/shortify';

export const Price = ({
trace,
Expand Down
4 changes: 3 additions & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@
"dependencies": {
"bignumber.js": "^9.1.2",
"idb": "^8.0.0",
"lodash": "^4.17.21",
"zod": "^3.23.8"
},
"devDependencies": {
"@bufbuild/protobuf": "^1.10.0",
"@penumbra-zone/bech32m": "workspace:*",
"@penumbra-zone/getters": "workspace:*",
"@penumbra-zone/protobuf": "workspace:*"
"@penumbra-zone/protobuf": "workspace:*",
"@types/lodash": "^4.17.7"
},
"peerDependencies": {
"@bufbuild/protobuf": "^1.10.0",
Expand Down
5 changes: 1 addition & 4 deletions packages/types/src/amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { fromBaseUnit, joinLoHi, splitLoHi, toBaseUnit } from './lo-hi.js';
import { BigNumber } from 'bignumber.js';
import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb';
import { getAmount, getDisplayDenomExponentFromValueView } from '@penumbra-zone/getters/value-view';
import { removeTrailingZeros } from './shortify.js';

export const joinLoHiAmount = (amount: Amount): bigint => {
return joinLoHi(amount.lo, amount.hi);
Expand Down Expand Up @@ -81,10 +82,6 @@ export const formatNumber = (number: number, options: FormatOptions): string =>
: parseFloat(number.toFixed(precision)).toString();
};

export const removeTrailingZeros = (strNum: string): string => {
return strNum.replace(/(\.\d*?[1-9])0+$|\.0*$/, '$1');
};

export const formatAmount = ({
amount,
exponent = 0,
Expand Down
124 changes: 124 additions & 0 deletions packages/types/src/round.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { describe, expect, it } from 'vitest';
import { round, RoundOptions } from './round.js';

describe('round function', () => {
const testCases: {
description: string;
options: RoundOptions;
expected: string;
}[] = [
// Default rounding mode ('round')
{
description: 'should round up using default rounding (round)',
options: { value: 1.2345, decimals: 3 },
expected: '1.235',
},
{
description: 'should round down using default rounding (round)',
options: { value: 1.2341, decimals: 3 },
expected: '1.234',
},
{
description: 'should round a negative number using default rounding (round)',
options: { value: -1.2345, decimals: 2 },
expected: '-1.23',
},
{
description: 'should round zero',
options: { value: 0, decimals: 2 },
expected: '0.00',
},
{
description: 'should round an integer with decimals',
options: { value: 5, decimals: 2 },
expected: '5.00',
},
// Rounding mode: 'ceil'
{
description: 'should ceil to 2 decimals',
options: { value: 1.2345, decimals: 2, roundingMode: 'ceil' },
expected: '1.24',
},
{
description: 'should ceil a negative number',
options: { value: -1.2345, decimals: 2, roundingMode: 'ceil' },
expected: '-1.23',
},
{
description: 'should ceil with zero decimals',
options: { value: 1.5, decimals: 0, roundingMode: 'ceil' },
expected: '2',
},
// Rounding mode: 'floor'
{
description: 'should floor to 2 decimals',
options: { value: 1.2399, decimals: 2, roundingMode: 'floor' },
expected: '1.23',
},
{
description: 'should floor a negative number',
options: { value: -1.2345, decimals: 2, roundingMode: 'floor' },
expected: '-1.24',
},
{
description: 'should floor with zero decimals',
options: { value: 1.9, decimals: 0, roundingMode: 'floor' },
expected: '1',
},
// Edge Cases
{
description: 'should handle very large numbers',
options: { value: 1.23456789e10, decimals: 2, roundingMode: 'round' },
expected: '12345678900.00',
},
{
description: 'should handle very small numbers',
options: { value: 0.000123456, decimals: 8, roundingMode: 'round' },
expected: '0.00012346',
},
{
description: 'should handle Infinity',
options: { value: Infinity, decimals: 2, roundingMode: 'round' },
expected: 'Infinity',
},
{
description: 'should handle -Infinity',
options: { value: -Infinity, decimals: 2, roundingMode: 'floor' },
expected: '-Infinity',
},
{
description: 'should handle NaN',
options: { value: NaN, decimals: 2, roundingMode: 'ceil' },
expected: 'NaN',
},
{
description: 'should handle decimals greater than available decimal places',
options: { value: 1.2, decimals: 5, roundingMode: 'floor' },
expected: '1.20000',
},
// Rounding to integer
{
description: 'should round to integer using round mode',
options: { value: 2.5, decimals: 0, roundingMode: 'round' },
expected: '3',
},
{
description: 'should ceil to integer',
options: { value: 2.1, decimals: 0, roundingMode: 'ceil' },
expected: '3',
},
{
description: 'should floor to integer',
options: { value: 2.9, decimals: 0, roundingMode: 'floor' },
expected: '2',
},
];

testCases.forEach(({ description, options, expected }) => {
// eslint-disable-next-line vitest/valid-title
it(description, () => {
const result = round(options);
expect(result).toBe(expected);
});
});
});
39 changes: 39 additions & 0 deletions packages/types/src/round.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ceil as lodashCeil, floor as lodashFloor, round as lodashRound } from 'lodash';

export type RoundingMode = 'round' | 'ceil' | 'floor';

export interface RoundOptions {
value: number;
decimals: number;
roundingMode?: RoundingMode;
}

const roundingStrategies = {
ceil: lodashCeil,
floor: lodashFloor,
round: lodashRound,
} as const;

/**
* Rounds a number based on the specified options.
*
* @param options - An object containing the properties:
* - value: The number to round.
* - decimals: The number of decimal places to round to.
* - roundingMode: The mode of rounding ('round', 'ceil', 'floor'). Defaults to 'round'.
*
* @returns A string representation of the rounded number.
*
* @example
*
* ```typescript
* round({ value: 1.2345, decimals: 2, roundingMode: 'ceil' }); // "1.24"
* round({ value: 1.2345, decimals: 2, roundingMode: 'floor' }); // "1.23"
* round({ value: 1.2345, decimals: 2 }); // "1.23" (default rounding)
* ```
*/
export function round({ value, decimals, roundingMode = 'round' }: RoundOptions): string {
const roundingFn = roundingStrategies[roundingMode];
const roundedNumber = roundingFn(value, decimals);
return roundedNumber.toFixed(decimals);
}
Comment on lines +35 to +39
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both round() and shortify() come from the dex explorer. However, expanded these quite a bit w/ testing as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this works, after publishing, will delete the local one in the dex explorer

Loading
Loading