Skip to content

Commit cc8bf8a

Browse files
committed
[@dhealthdapps/backend] refactor(common): remove transaction's serialized headers and reconstruct when decode
1 parent f1f8bed commit cc8bf8a

File tree

5 files changed

+79
-32
lines changed

5 files changed

+79
-32
lines changed

runtime/backend/src/common/models/TransactionSchema.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
*/
1010
// external dependencies
1111
import {
12+
Convert,
13+
NetworkType,
1214
Transaction as SdkTransaction,
1315
TransactionMapping,
16+
TransactionType,
1417
} from "@dhealth/sdk";
1518
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
1619
import { Model } from "mongoose";
@@ -324,8 +327,37 @@ export class Transaction extends Transferable<TransactionDTO> {
324327
* @returns {SdkTransaction} The `SdkTransaction` object with payload set.
325328
*/
326329
public toSDK(): SdkTransaction {
327-
//XXX this assumes "encodedBody" contains the *full* payload.
328-
return TransactionMapping.createFromPayload(this.encodedBody, false); // false for `isEmbedded`
330+
const sizeBytes = Convert.numberToUint8Array(
331+
(this.encodedBody.length + 256) / 2,
332+
4,
333+
);
334+
const verifiableEntityHeader_Reserved4Bytes = Convert.numberToUint8Array(
335+
0,
336+
4,
337+
);
338+
const signatureBytes = Convert.hexToUint8(this.signature);
339+
const signerPublicKeyBytes = Convert.hexToUint8(this.signerPublicKey);
340+
const entityBody_Reserved4Bytes = Convert.numberToUint8Array(0, 4);
341+
const versionBytes = Convert.numberToUint8Array(0, 1);
342+
const networkBytes = Convert.numberToUint8Array(NetworkType.MAIN_NET, 1);
343+
const typeBytes = Convert.numberToUint8Array(TransactionType.TRANSFER, 2);
344+
const feeBytes = Convert.numberToUint8Array(0, 8);
345+
const deadlineBytes = Convert.numberToUint8Array(0, 8);
346+
const headersUint8Array = [
347+
...sizeBytes,
348+
...verifiableEntityHeader_Reserved4Bytes,
349+
...signatureBytes,
350+
...signerPublicKeyBytes,
351+
...entityBody_Reserved4Bytes,
352+
...versionBytes,
353+
...networkBytes,
354+
...typeBytes,
355+
...feeBytes,
356+
...deadlineBytes,
357+
];
358+
const fullEncodedBody =
359+
Convert.uint8ToHex(headersUint8Array) + this.encodedBody;
360+
return TransactionMapping.createFromPayload(fullEncodedBody, false); // false for `isEmbedded`
329361
}
330362

331363
/**

runtime/backend/src/discovery/models/TransactionTypes.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,28 @@
1111
import { TransactionType } from "@dhealth/sdk";
1212

1313
/**
14-
* @class TransactionDTO
15-
* @description
14+
* @class TransactionTypes
15+
* @description A helper class that handle and process {@link TransactionType}.
1616
*
17-
* @todo Add relevant helper function documentation
1817
* @todo Use the `@dhealth/contracts` abstraction and include in TransactionDTO if necessary.
1918
* @since v0.2.0
2019
*/
21-
export const getTransactionType = (type: TransactionType): string => {
22-
switch (type) {
23-
case TransactionType.TRANSFER:
24-
return "transfer";
25-
default:
26-
return "custom";
20+
export class TransactionTypes {
21+
/**
22+
* A helper method that returns a string representation
23+
* of a {@link TransactionType}.
24+
*
25+
* @access public
26+
* @static
27+
* @param {TransactionType} type The transaction type to get a string representation of.
28+
* @returns {string}
29+
*/
30+
public static getTransactionType(type: TransactionType): string {
31+
switch (type) {
32+
case TransactionType.TRANSFER:
33+
return "transfer";
34+
default:
35+
return "custom";
36+
}
2737
}
28-
};
38+
}

runtime/backend/src/discovery/schedulers/DiscoverTransactions/DiscoverTransactions.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { ConfigService } from "@nestjs/config";
1313
import { InjectModel } from "@nestjs/mongoose";
1414
import { Cron } from "@nestjs/schedule";
1515
import {
16-
Address,
1716
AggregateTransactionInfo,
1817
Order,
1918
Page,
@@ -33,7 +32,7 @@ import { NetworkService } from "../../../common/services/NetworkService";
3332
import { DiscoveryCommand, DiscoveryCommandOptions } from "../DiscoveryCommand";
3433
import { AssetsService } from "../../../discovery/services/AssetsService";
3534
import { TransactionsService } from "../../../discovery/services/TransactionsService";
36-
import { getTransactionType } from "../../../discovery/models/TransactionTypes";
35+
import { TransactionTypes } from "../../../discovery/models/TransactionTypes";
3736
import {
3837
Transaction,
3938
TransactionDocument,
@@ -716,7 +715,7 @@ export class DiscoverTransactions extends DiscoveryCommand {
716715
* @returns {string}
717716
*/
718717
protected extractTransactionType(transaction: SdkTransaction): string {
719-
return getTransactionType(transaction.type);
718+
return TransactionTypes.getTransactionType(transaction.type);
720719
}
721720

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

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

763759
/**

runtime/backend/tests/unit/common/models/TransactionSchema.spec.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
// external dependencies
1111
import { TransactionDTO } from "@/discovery/models/TransactionDTO";
12-
import { TransactionMapping } from "@dhealth/sdk";
12+
import { Convert, TransactionMapping, Transaction as SdkTransaction } from "@dhealth/sdk";
1313

1414
// internal dependencies
1515
import { Transaction, TransactionDocument } from "../../../../src/common/models/TransactionSchema";
@@ -51,13 +51,22 @@ describe("common/TransactionSchema", () => {
5151
// prepare
5252
let createFromPayloadCall = jest
5353
.spyOn(TransactionMapping, "createFromPayload")
54-
.mockReturnValue({} as any);
54+
.mockReturnValue({} as SdkTransaction);
5555
const transaction = new Transaction();
56+
(transaction as any).encodedBody = "ABC";
57+
const convertNumberToUint8ArrayCall = jest
58+
.spyOn(Convert, "numberToUint8Array")
59+
.mockReturnValue(new Uint8Array());
60+
const convertHexToUint8Call = jest
61+
.spyOn(Convert, "hexToUint8")
62+
.mockReturnValue(new Uint8Array());
5663

5764
// act
5865
const result = transaction.toSDK();
5966

6067
// assert
68+
expect(convertNumberToUint8ArrayCall).toHaveBeenCalledTimes(8);
69+
expect(convertHexToUint8Call).toHaveBeenCalledTimes(2);
6170
expect(createFromPayloadCall).toHaveBeenCalledTimes(1);
6271
expect(result).toStrictEqual({});
6372
});

runtime/backend/tests/unit/discovery/models/TransactionType.spec.ts renamed to runtime/backend/tests/unit/discovery/models/TransactionTypes.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@
1111
import { TransactionType } from "@dhealth/sdk";
1212

1313
// internal dependencies
14-
import { getTransactionType } from "../../../../src/discovery/models/TransactionTypes";
14+
import { TransactionTypes } from "../../../../src/discovery/models/TransactionTypes";
1515

16-
describe("discovery/TransactionType", () => {
16+
describe("discovery/TransactionTypes", () => {
1717
describe("getTransactionType()", () => {
1818
it("should return transaction type: transfer", () => {
1919
// act
20-
const result = getTransactionType(TransactionType.TRANSFER);
20+
const result = TransactionTypes.getTransactionType(TransactionType.TRANSFER);
2121

2222
// assert
2323
expect(result).toBe("transfer");
2424
});
2525

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

3030
// assert
3131
expect(result).toBe("custom");

0 commit comments

Comments
 (0)