Skip to content

Commit

Permalink
[@dhealthdapps/backend] refactor(common): remove transaction's serial…
Browse files Browse the repository at this point in the history
…ized headers and reconstruct when decode
  • Loading branch information
nsonanh committed Jan 13, 2023
1 parent 8f89a95 commit dc880a8
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 32 deletions.
36 changes: 34 additions & 2 deletions runtime/backend/src/common/models/TransactionSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
*/
// external dependencies
import {
Convert,
NetworkType,
Transaction as SdkTransaction,
TransactionMapping,
TransactionType,
} from "@dhealth/sdk";
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Model } from "mongoose";
Expand Down Expand Up @@ -324,8 +327,37 @@ export class Transaction extends Transferable<TransactionDTO> {
* @returns {SdkTransaction} The `SdkTransaction` object with payload set.
*/
public toSDK(): SdkTransaction {
//XXX this assumes "encodedBody" contains the *full* payload.
return TransactionMapping.createFromPayload(this.encodedBody, false); // false for `isEmbedded`
const sizeBytes = Convert.numberToUint8Array(
(this.encodedBody.length + 256) / 2,
4,
);
const verifiableEntityHeader_Reserved4Bytes = Convert.numberToUint8Array(
0,
4,
);
const signatureBytes = Convert.hexToUint8(this.signature);
const signerPublicKeyBytes = Convert.hexToUint8(this.signerPublicKey);
const entityBody_Reserved4Bytes = Convert.numberToUint8Array(0, 4);
const versionBytes = Convert.numberToUint8Array(0, 1);
const networkBytes = Convert.numberToUint8Array(NetworkType.MAIN_NET, 1);
const typeBytes = Convert.numberToUint8Array(TransactionType.TRANSFER, 2);
const feeBytes = Convert.numberToUint8Array(0, 8);
const deadlineBytes = Convert.numberToUint8Array(0, 8);
const headersUint8Array = [
...sizeBytes,
...verifiableEntityHeader_Reserved4Bytes,
...signatureBytes,
...signerPublicKeyBytes,
...entityBody_Reserved4Bytes,
...versionBytes,
...networkBytes,
...typeBytes,
...feeBytes,
...deadlineBytes,
];
const fullEncodedBody =
Convert.uint8ToHex(headersUint8Array) + this.encodedBody;
return TransactionMapping.createFromPayload(fullEncodedBody, false); // false for `isEmbedded`
}

/**
Expand Down
30 changes: 20 additions & 10 deletions runtime/backend/src/discovery/models/TransactionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,28 @@
import { TransactionType } from "@dhealth/sdk";

/**
* @class TransactionDTO
* @description
* @class TransactionTypes
* @description A helper class that handle and process {@link TransactionType}.
*
* @todo Add relevant helper function documentation
* @todo Use the `@dhealth/contracts` abstraction and include in TransactionDTO if necessary.
* @since v0.2.0
*/
export const getTransactionType = (type: TransactionType): string => {
switch (type) {
case TransactionType.TRANSFER:
return "transfer";
default:
return "custom";
export class TransactionTypes {
/**
* A helper method that returns a string representation
* of a {@link TransactionType}.
*
* @access public
* @static
* @param {TransactionType} type The transaction type to get a string representation of.
* @returns {string}
*/
public static getTransactionType(type: TransactionType): string {
switch (type) {
case TransactionType.TRANSFER:
return "transfer";
default:
return "custom";
}
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { ConfigService } from "@nestjs/config";
import { InjectModel } from "@nestjs/mongoose";
import { Cron } from "@nestjs/schedule";
import {
Address,
AggregateTransactionInfo,
Order,
Page,
Expand All @@ -33,7 +32,7 @@ import { NetworkService } from "../../../common/services/NetworkService";
import { DiscoveryCommand, DiscoveryCommandOptions } from "../DiscoveryCommand";
import { AssetsService } from "../../../discovery/services/AssetsService";
import { TransactionsService } from "../../../discovery/services/TransactionsService";
import { getTransactionType } from "../../../discovery/models/TransactionTypes";
import { TransactionTypes } from "../../../discovery/models/TransactionTypes";
import {
Transaction,
TransactionDocument,
Expand Down Expand Up @@ -716,7 +715,7 @@ export class DiscoverTransactions extends DiscoveryCommand {
* @returns {string}
*/
protected extractTransactionType(transaction: SdkTransaction): string {
return getTransactionType(transaction.type);
return TransactionTypes.getTransactionType(transaction.type);
}

/**
Expand Down Expand Up @@ -745,19 +744,16 @@ export class DiscoverTransactions extends DiscoveryCommand {
// serializes transaction to get hexadecimal payload
const payload: string = transaction.serialize();

// @todo Move to the following implementation as this will
// @todo permit to save more than 100bytes of space for each
// @todo contract operation.
// @todo Note that this implementation would require also
// @todo a *transaction parser* that re-build transactions
// This will permit to save 128 bytes of space for each
// contract operation.
// Note that this implementation requires also
// a *transaction parser* that re-build transactions
// following transaction header applies here:
// size | r1 | sig | pub | r2 | ver | net | type
// 4b | 4b | 64b | 32b | 4b | 1b | 1b | 2b
// --> we are dropping 112 bytes as the header
// size | r1 | sig | pub | r2 | ver | net | type | fee | dl
// 4b | 4b | 64b | 32b | 4b | 1b | 1b | 2b | 8b | 8b
// --> we are dropping 128 bytes (256 hex characters) as the header
// and we return only the remaining body after
//return payload.substring(112);

return payload;
return payload.substring(256);
}

/**
Expand Down
13 changes: 11 additions & 2 deletions runtime/backend/tests/unit/common/models/TransactionSchema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
// external dependencies
import { TransactionDTO } from "@/discovery/models/TransactionDTO";
import { TransactionMapping } from "@dhealth/sdk";
import { Convert, TransactionMapping, Transaction as SdkTransaction } from "@dhealth/sdk";

// internal dependencies
import { Transaction, TransactionDocument } from "../../../../src/common/models/TransactionSchema";
Expand Down Expand Up @@ -51,13 +51,22 @@ describe("common/TransactionSchema", () => {
// prepare
let createFromPayloadCall = jest
.spyOn(TransactionMapping, "createFromPayload")
.mockReturnValue({} as any);
.mockReturnValue({} as SdkTransaction);
const transaction = new Transaction();
(transaction as any).encodedBody = "ABC";
const convertNumberToUint8ArrayCall = jest
.spyOn(Convert, "numberToUint8Array")
.mockReturnValue(new Uint8Array());
const convertHexToUint8Call = jest
.spyOn(Convert, "hexToUint8")
.mockReturnValue(new Uint8Array());

// act
const result = transaction.toSDK();

// assert
expect(convertNumberToUint8ArrayCall).toHaveBeenCalledTimes(8);
expect(convertHexToUint8Call).toHaveBeenCalledTimes(2);
expect(createFromPayloadCall).toHaveBeenCalledTimes(1);
expect(result).toStrictEqual({});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@
import { TransactionType } from "@dhealth/sdk";

// internal dependencies
import { getTransactionType } from "../../../../src/discovery/models/TransactionTypes";
import { TransactionTypes } from "../../../../src/discovery/models/TransactionTypes";

describe("discovery/TransactionType", () => {
describe("discovery/TransactionTypes", () => {
describe("getTransactionType()", () => {
it("should return transaction type: transfer", () => {
// act
const result = getTransactionType(TransactionType.TRANSFER);
const result = TransactionTypes.getTransactionType(TransactionType.TRANSFER);

// assert
expect(result).toBe("transfer");
});

it("should return transaction type: custom", () => {
// act
const result = getTransactionType(TransactionType.RESERVED);
const result = TransactionTypes.getTransactionType(TransactionType.RESERVED);

// assert
expect(result).toBe("custom");
Expand Down

0 comments on commit dc880a8

Please sign in to comment.