Skip to content

Commit

Permalink
feat: add vechain family [LIVE-9715] (#332)
Browse files Browse the repository at this point in the history
* feat: add vechain family

* test: add serializers test for vechain
  • Loading branch information
Justkant committed Mar 29, 2024
1 parent b4b5886 commit 1f5bd03
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/polite-melons-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/wallet-api-core": minor
---

feat: add vechain family
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"eslint": "^8.56.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"thor-devkit": "^2.0.9",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/families/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const FAMILIES = [
"elrond",
"cardano",
"solana",
"vechain",
] as const;

export const schemaFamilies = z.enum(FAMILIES);
1 change: 1 addition & 0 deletions packages/core/src/families/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from "./tron/types";
export * from "./elrond/types";
export * from "./cardano/types";
export * from "./solana/types";
export * from "./vechain/types";

export * from "./common";
export * from "./serializer";
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/families/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ import {
deserializeSolanaTransaction,
serializeSolanaTransaction,
} from "./solana/serializer";
import {
deserializeVechainTransaction,
serializeVechainTransaction,
} from "./vechain/serializer";
import type { RawTransaction, Transaction } from "./types";

/**
Expand Down Expand Up @@ -111,6 +115,8 @@ export function serializeTransaction(transaction: Transaction): RawTransaction {
return serializeCardanoTransaction(transaction);
case "solana":
return serializeSolanaTransaction(transaction);
case "vechain":
return serializeVechainTransaction(transaction);
default: {
const exhaustiveCheck: never = transaction; // https://www.typescriptlang.org/docs/handbook/2/narrowing.html#exhaustiveness-checking
return exhaustiveCheck;
Expand Down Expand Up @@ -166,6 +172,8 @@ export function deserializeTransaction(
return deserializeCardanoTransaction(rawTransaction);
case "solana":
return deserializeSolanaTransaction(rawTransaction);
case "vechain":
return deserializeVechainTransaction(rawTransaction);
default: {
const exhaustiveCheck: never = rawTransaction; // https://www.typescriptlang.org/docs/handbook/2/narrowing.html#exhaustiveness-checking
return exhaustiveCheck;
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/families/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type { SolanaTransaction } from "./solana/types";
import type { StellarTransaction } from "./stellar/types";
import type { TezosTransaction } from "./tezos/types";
import type { TronTransaction } from "./tron/types";
import type { VechainTransaction } from "./vechain/types";
import type { schemaRawTransaction } from "./validation";

/**
Expand Down Expand Up @@ -79,4 +80,5 @@ export type Transaction =
| NeoTransaction
| ElrondTransaction
| CardanoTransaction
| SolanaTransaction;
| SolanaTransaction
| VechainTransaction;
2 changes: 2 additions & 0 deletions packages/core/src/families/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { schemaRawHederaTransaction } from "./hedera/validation";
import { schemaRawFilecoinTransaction } from "./filecoin/validation";
import { schemaRawElrondTransaction } from "./elrond/validation";
import { schemaRawCardanoTransaction } from "./cardano/validation";
import { schemaRawVechainTransaction } from "./vechain/validation";

export const schemaRawTransaction = z.discriminatedUnion("family", [
schemaRawAlgorandTransaction,
Expand All @@ -37,4 +38,5 @@ export const schemaRawTransaction = z.discriminatedUnion("family", [
schemaRawElrondTransaction,
schemaRawCardanoTransaction,
schemaRawSolanaTransaction,
schemaRawVechainTransaction,
]);
30 changes: 30 additions & 0 deletions packages/core/src/families/vechain/serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import BigNumber from "bignumber.js";
import type { RawVechainTransaction, VechainTransaction } from "./types";

export const serializeVechainTransaction = ({
amount,
recipient,
family,
estimatedFees,
body,
}: VechainTransaction): RawVechainTransaction => ({
amount: amount.toString(),
recipient,
family,
estimatedFees,
body,
});

export const deserializeVechainTransaction = ({
amount,
recipient,
family,
estimatedFees,
body,
}: RawVechainTransaction): VechainTransaction => ({
amount: new BigNumber(amount),
recipient,
family,
estimatedFees,
body,
});
12 changes: 12 additions & 0 deletions packages/core/src/families/vechain/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Transaction as ThorTransaction } from "thor-devkit";
import type { z } from "zod";
import type { TransactionCommon } from "../index";
import type { schemaRawVechainTransaction } from "./validation";

export type VechainTransaction = TransactionCommon & {
readonly family: RawVechainTransaction["family"];
estimatedFees: string;
body: ThorTransaction.Body;
};

export type RawVechainTransaction = z.infer<typeof schemaRawVechainTransaction>;
34 changes: 34 additions & 0 deletions packages/core/src/families/vechain/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { z } from "zod";
import { schemaFamilies, schemaTransactionCommon } from "../common";

// Generated from VeChain Thor Transaction types
export const schemaThorTransactionClause = z.object({
to: z.string().nullable(),
value: z.union([z.string(), z.number()]),
data: z.string(),
});

// Generated from VeChain Thor Transaction types
// with Buffer type removed for `reserved.unused`
export const schemaThorTransactionBody = z.object({
chainTag: z.number(),
blockRef: z.string(),
expiration: z.number(),
clauses: z.array(schemaThorTransactionClause),
gasPriceCoef: z.number(),
gas: z.union([z.string(), z.number()]),
dependsOn: z.string().nullable(),
nonce: z.union([z.string(), z.number()]),
reserved: z
.object({
features: z.number().optional(),
unused: z.array(z.any()).optional(),
})
.optional(),
});

export const schemaRawVechainTransaction = schemaTransactionCommon.extend({
family: z.literal(schemaFamilies.enum.vechain),
estimatedFees: z.string(),
body: schemaThorTransactionBody,
});
85 changes: 85 additions & 0 deletions packages/core/tests/serializers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import {
RawCardanoTransaction,
RawSolanaTransaction,
SolanaTransaction,
VechainTransaction,
RawVechainTransaction,
} from "../src";

const date = new Date();
Expand Down Expand Up @@ -773,6 +775,47 @@ describe("serializers.ts", () => {
});
});
});

describe("vechain", () => {
const family = schemaFamilies.enum.vechain;

it("should serialize a Vechain transaction", () => {
const transaction: VechainTransaction = {
family,
amount: new BigNumber(100),
recipient: "recipient",
estimatedFees: "0",
body: {
chainTag: 0,
blockRef: "",
expiration: 0,
clauses: [],
gasPriceCoef: 0,
gas: 0,
dependsOn: null,
nonce: 0,
},
};
const serializedTransaction = serializeTransaction(transaction);

expect(serializedTransaction).toEqual({
family,
amount: "100",
recipient: "recipient",
estimatedFees: "0",
body: {
chainTag: 0,
blockRef: "",
expiration: 0,
clauses: [],
gasPriceCoef: 0,
gas: 0,
dependsOn: null,
nonce: 0,
},
});
});
});
});

describe("deserializeTransaction", () => {
Expand Down Expand Up @@ -1444,6 +1487,48 @@ describe("serializers.ts", () => {
});
});
});

describe("vechain", () => {
const family = schemaFamilies.enum.vechain;

it("should deserialize a Solana transaction", () => {
const serializedTransaction: RawVechainTransaction = {
family,
amount: "100",
recipient: "recipient",
estimatedFees: "0",
body: {
chainTag: 0,
blockRef: "",
expiration: 0,
clauses: [],
gasPriceCoef: 0,
gas: 0,
dependsOn: null,
nonce: 0,
},
};

const transaction = deserializeTransaction(serializedTransaction);

expect(transaction).toEqual({
family,
amount: new BigNumber(100),
recipient: "recipient",
estimatedFees: "0",
body: {
chainTag: 0,
blockRef: "",
expiration: 0,
clauses: [],
gasPriceCoef: 0,
gas: 0,
dependsOn: null,
nonce: 0,
},
});
});
});
});

describe("Serialize -> Deserialize flow", () => {
Expand Down

0 comments on commit 1f5bd03

Please sign in to comment.