Skip to content

Commit

Permalink
fix: LegacyDec transactions (#3868)
Browse files Browse the repository at this point in the history
* fix: unbond from pool tx

* fix: create pools tx

* feat: use decimals patch

* feat: add decimal patch to codegen

* feat: fix legacy decs txs

* fix: build

* fix: amino type

* feat: fix quote asset

* fix: create cl pool tx

* improvement: remove console log

* fix: tests
  • Loading branch information
JoseRFelix authored Oct 8, 2024
1 parent 2291cff commit 44e7356
Show file tree
Hide file tree
Showing 63 changed files with 783 additions and 286 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/jest-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ jobs:
matrix:
node-version: [20.x]
package:
["web", "utils", "server", "stores", "pools", "math", "bridge", "tx"]
[
"web",
"utils",
"server",
"stores",
"pools",
"math",
"bridge",
"tx",
"proto-codecs",
]

steps:
- name: Checkout Repo
Expand Down
25 changes: 25 additions & 0 deletions packages/proto-codecs/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
preset: "ts-jest",
roots: ["<rootDir>/src/", "<rootDir>/scripts/"],
testMatch: ["**/__tests__/?(*.)+(spec|test).[jt]s?(x)"],
testTimeout: 100000,
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
transform: {
"^.+\\.(js|jsx)?$": [
"babel-jest",
{ configFile: "../../babel.config.json" },
],
"^.+\\.(ts|tsx)?$": [
"ts-jest",
{
useESM: true,
},
],
},
watchPlugins: [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname",
],
};
5 changes: 3 additions & 2 deletions packages/proto-codecs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"clean": "rm -rf node_modules; rm -rf build; rm -f tsconfig.tsbuildinfo",
"build": "tsc",
"dev": "tsc --watch",
"test:regression": "jest --passWithNoTests --runInBand",
"test": "jest",
"lint": "eslint \"src/**/*\" && prettier --check \"src/**/*\"",
"lint:fix": "eslint --fix \"src/**/*\" && prettier --write \"src/**/*\"",
"pre-commit": "lint-staged",
Expand All @@ -43,10 +43,11 @@
},
"devDependencies": {
"@cosmology/proto-parser": "^1.5.0",
"@cosmology/telescope": "^1.8.4",
"@cosmology/telescope": "^1.10.0",
"@types/node": "^20.14.1",
"regenerator-runtime": "^0.13.11",
"rimraf": "^5.0.0",
"ts-jest": "^29.1.2",
"tsx": "^4.6.2"
},
"dependencies": {
Expand Down
54 changes: 54 additions & 0 deletions packages/proto-codecs/scripts/__tests__/decimal-patch.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// decimal.test.ts
import { Decimal as CodegenDecimal } from "../../src/codegen/decimals";
import { Decimal as DecimalPatch } from "../decimals-patch";

/**
* Run the tests for both the codegen and the patch
* to ensure that the patch is correctly applied.
*/
[DecimalPatch, CodegenDecimal].forEach((Decimal) => {
test("should create a Decimal from user input", () => {
const decimal = Decimal.fromUserInput("123.456", 3);
expect(decimal.atomics).toBe("123456");
expect(decimal.fractionalDigits).toBe(3);
});

test("should throw an error for invalid user input", () => {
expect(() => Decimal.fromUserInput("123.45.6", 3)).toThrow(
"More than one separator found"
);
expect(() => Decimal.fromUserInput("123a.456", 3)).toThrow(
"Invalid character at position 4"
);
expect(() => Decimal.fromUserInput("123.4567", 3)).toThrow(
"Got more fractional digits than supported"
);
});

test("should create a Decimal from atomics", () => {
const decimal = Decimal.fromAtomics("123456", 3);
expect(decimal.atomics).toBe("123456");
expect(decimal.fractionalDigits).toBe(3);
});

test("should convert Decimal to string", () => {
const decimal = Decimal.fromUserInput("123.456", 3);
expect(decimal.toString()).toBe("123456");

const decimalNoFraction = Decimal.fromUserInput("123", 3);
expect(decimalNoFraction.toString()).toBe("123000");
});

test("should handle edge cases", () => {
const decimal = Decimal.fromUserInput("0.000", 3);
expect(decimal.toString()).toBe("0");

const decimalMaxFraction = Decimal.fromUserInput("1.999", 3);
expect(decimalMaxFraction.toString()).toBe("1999");
});

test("toString should return the atomics", () => {
const decimal = Decimal.fromUserInput("0.01", 18);
expect(decimal.toString()).toBe("10000000000000000");
});
});
26 changes: 17 additions & 9 deletions packages/proto-codecs/scripts/codegen.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import * as fs from "node:fs";

import { ProtoStore } from "@cosmology/proto-parser";
import telescope from "@cosmology/telescope";
import { join } from "path";
Expand Down Expand Up @@ -69,9 +71,6 @@ telescope({
decode: true,
fromPartial: true,

// toSDK: true,
// fromSDK: true,

toAmino: true,
fromAmino: true,
fromProto: true,
Expand All @@ -88,17 +87,12 @@ telescope({
num64: "bigint",
customTypes: {
useCosmosSDKDec: true,
usePatchedDecimal: true,
},
},
},
aminoEncoding: {
enabled: true,
exceptions: {
// '/cosmos-sdk/MsgWithdrawValCommission': {
// aminoType: 'cosmos-sdk/MsgWithdrawValidatorCommission'
// },
},
// useRecursiveV2encoding: true,
},
interfaces: {
enabled: true,
Expand All @@ -113,6 +107,20 @@ telescope({
},
})
.then(() => {
/**
* Read the content of the decimals-patch.ts file and write it to
* the decimals.ts file in the codegen directory This is to patch
* the decimals.ts file to fix the Decimal class
*/
const decimalsPatchContent = fs.readFileSync(
join(__dirname, "./decimals-patch.ts"),
"utf8"
);
fs.writeFileSync(
join(__dirname, "../src/codegen/decimals.ts"),
decimalsPatchContent
);

console.info("✨ all done!");
})
.catch((e) => {
Expand Down
98 changes: 98 additions & 0 deletions packages/proto-codecs/scripts/decimals-patch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* This class patch is required to override Telescope number handling.
* Following Osmosis v26, which includes the new Cosmos SDK, we need to handle
* numbers in a different way. Specifically, we need to omit periods in the
* number representation to ensure compatibility with the updated SDK.
* This patch ensures that the Decimal class processes numbers correctly
* according to the new requirements.
*/

const maxFractionalDigits = 30;
export class Decimal {
public static fromUserInput(
input: string,
fractionalDigits: number
): Decimal {
Decimal.verifyFractionalDigits(fractionalDigits);
const badCharacter = input.match(/[^0-9.]/);
if (badCharacter) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
throw new Error(
`Invalid character at position ${badCharacter.index! + 1}`
);
}
let whole: string;
let fractional: string;
if (input === "") {
whole = "0";
fractional = "";
} else if (input.search(/\./) === -1) {
// integer format, no separator
whole = input;
fractional = "";
} else {
const parts = input.split(".");
switch (parts.length) {
case 0:
case 1:
throw new Error(
"Fewer than two elements in split result. This must not happen here."
);
case 2:
if (!parts[1]) throw new Error("Fractional part missing");
whole = parts[0];
fractional = parts[1].replace(/0+$/, "");
break;
default:
throw new Error("More than one separator found");
}
}
if (fractional.length > fractionalDigits) {
throw new Error("Got more fractional digits than supported");
}
const quantity = `${whole}${fractional.padEnd(fractionalDigits, "0")}`;
return new Decimal(quantity, fractionalDigits);
}
public static fromAtomics(
atomics: string,
fractionalDigits: number
): Decimal {
Decimal.verifyFractionalDigits(fractionalDigits);
return new Decimal(atomics, fractionalDigits);
}
private static verifyFractionalDigits(fractionalDigits: number): void {
if (!Number.isInteger(fractionalDigits))
throw new Error("Fractional digits is not an integer");
if (fractionalDigits < 0)
throw new Error("Fractional digits must not be negative");
if (fractionalDigits > maxFractionalDigits) {
throw new Error(
`Fractional digits must not exceed ${maxFractionalDigits}`
);
}
}
public get atomics(): string {
return this.data.atomics.toString();
}
public get fractionalDigits(): number {
return this.data.fractionalDigits;
}
private readonly data: {
readonly atomics: bigint;
readonly fractionalDigits: number;
};
private constructor(atomics: string, fractionalDigits: number) {
if (!atomics.match(/^[0-9]+$/)) {
throw new Error(
"Invalid string format. Only non-negative integers in decimal representation supported."
);
}
this.data = {
atomics: BigInt(atomics),
fractionalDigits: fractionalDigits,
};
}
public toString(): string {
return this.atomics;
}
}
2 changes: 1 addition & 1 deletion packages/proto-codecs/src/codegen/binary.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@ts-nocheck
/**
* This file and any referenced files were automatically generated by @cosmology/telescope@1.8.4
* This file and any referenced files were automatically generated by @cosmology/telescope@1.10.0
* DO NOT MODIFY BY HAND. Instead, download the latest proto files for your chain
* and run the transpile command or npm scripts command that is used to regenerate this bundle.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//@ts-nocheck
import { Pubkey } from "@cosmjs/amino";
import { Decimal } from "@cosmjs/math";
import { decodePubkey, encodePubkey } from "@cosmjs/proto-signing";

import { BinaryReader, BinaryWriter } from "../../../binary";
import { Decimal } from "../../../decimals";
import {
Any,
AnyAmino,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//@ts-nocheck
import { Pubkey } from "@cosmjs/amino";
import { Decimal } from "@cosmjs/math";
import { decodePubkey, encodePubkey } from "@cosmjs/proto-signing";

import { BinaryReader, BinaryWriter } from "../../../binary";
import { Decimal } from "../../../decimals";
import {
Any,
AnyAmino,
Expand Down
Loading

0 comments on commit 44e7356

Please sign in to comment.