Skip to content

Commit

Permalink
feat: add bigdecimal class
Browse files Browse the repository at this point in the history
  • Loading branch information
trungbach committed Oct 26, 2023
1 parent 4a2870b commit 99cd75a
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 0 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/publish_decimal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: publish_bigdecimal

# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [feat/bigdecimal]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
node-version: ["18"]

steps:
- name: Cancel Previous Runs
uses: styfle/[email protected]
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
with:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
./node_modules/
key: ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Build
run: yarn build packages/bigdecimal
- name: Authenticate with private NPM package
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
- name: Publish
id: publish
continue-on-error: false
run: yarn deploy packages/bigdecimal
env:
CI: false
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
10 changes: 10 additions & 0 deletions packages/bigdecimal/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@oraichain/bigdecimal",
"version": "1.0.0",
"main": "build/index.js",
"files": [
"build/"
],
"license": "MIT",
"devDependencies": {}
}
106 changes: 106 additions & 0 deletions packages/bigdecimal/src/bigdecimal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
type DecimalLike = string | number | bigint | BigDecimal;

class BigDecimal {
private bigInt: bigint;

constructor(value: DecimalLike, protected decimals: number = 6) {
if (typeof value === "string") {
const [ints, decis] = value.split(".");
const padding = decis ? decis.padEnd(decimals, "0").substring(0, decimals) : "0".repeat(decimals);
this.bigInt = BigInt(ints + padding);
} else if (typeof value === "number") {
return new BigDecimal(value.toString(), decimals);
} else if (typeof value === "bigint") {
this.bigInt = value;
} else {
this.bigInt = value.bigInt;
this.decimals = value.decimals;
}
}

private processDecimal = (value: DecimalLike): BigDecimal => {
if (value instanceof BigDecimal) {
if (value.decimals > this.decimals) {
this.bigInt *= 10n ** BigInt(value.decimals - this.decimals);
this.decimals = value.decimals;
} else if (this.decimals > value.decimals) {
value.bigInt *= 10n ** BigInt(this.decimals - value.decimals);
value.decimals = this.decimals;
}
// same decimal
return value;
}
return new BigDecimal(value, this.decimals);
};

toString() {
const str = this.bigInt.toString();
let ret = str.slice(0, -this.decimals);
const denominator = str.slice(-this.decimals).replace(/0+$/, "");
if (denominator) {
ret += "." + denominator;
}
return ret;
}

toNumber() {
return Number(this.toString());
}

clone(): BigDecimal {
return new BigDecimal(this);
}

private iadd(other: DecimalLike) {
const otherDecimal = this.processDecimal(other);
this.bigInt += otherDecimal.bigInt;
return this;
}

private isub(other: BigDecimal) {
const otherDecimal = this.processDecimal(other);
this.bigInt -= otherDecimal.bigInt;
return this;
}

private idiv(other: BigDecimal) {
const otherDecimal = this.processDecimal(other);
this.bigInt = (this.bigInt * 10n ** BigInt(this.decimals)) / otherDecimal.bigInt;
return this;
}

private imul(other: BigDecimal) {
const otherDecimal = this.processDecimal(other);
this.bigInt *= otherDecimal.bigInt;
this.bigInt /= 10n ** BigInt(this.decimals);
return this;
}

add(other: BigDecimal) {
return this.clone().iadd(other);
}

sub(other: BigDecimal) {
return this.clone().isub(other);
}

div(other: BigDecimal) {
return this.clone().idiv(other);
}

mul(other: BigDecimal) {
return this.clone().imul(other);
}

valueOf() {
return this.toNumber();
}
}

/**
* Example
* const a = new BigDecimal("12345.6789", 10);
* const b = new BigDecimal("2345");
* // @ts-ignore
* console.log(a.sub(b).toNumber(), a.add(b).toNumber(), a.mul(b).toNumber(), a.div(b).mul(2).add(2.78).toNumber());
*/
1 change: 1 addition & 0 deletions packages/bigdecimal/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./bigdecimal";

Check failure on line 1 in packages/bigdecimal/src/index.ts

View workflow job for this annotation

GitHub Actions / build (18)

File '/home/runner/work/oraidex-sdk/oraidex-sdk/packages/bigdecimal/src/bigdecimal.ts' is not a module.
8 changes: 8 additions & 0 deletions packages/bigdecimal/tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"isolatedModules": false,
"strict": false,
"strictNullChecks": false
},
}
15 changes: 15 additions & 0 deletions packages/bigdecimal/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "build",
"declaration": true,
"rootDir": "src"
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules/"
]
}

0 comments on commit 99cd75a

Please sign in to comment.