Skip to content

Commit

Permalink
Move conversion logic to converters package.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibancioiu committed Mar 13, 2024
1 parent d19f4b0 commit 6a6a810
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 63 deletions.
1 change: 1 addition & 0 deletions src/converters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { TransactionsConverter } from "./transactionsConverter";
64 changes: 64 additions & 0 deletions src/converters/transactionsConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { IPlainTransactionObject, ITransaction } from "../interface";
import { Transaction } from "../transaction";

export class TransactionsConverter {
transactionToPlainObject(transaction: ITransaction): IPlainTransactionObject {
const plainObject = {
nonce: Number(transaction.nonce),
value: transaction.value.toString(),
receiver: transaction.receiver,
sender: transaction.sender,
senderUsername: this.toBase64OrUndefined(transaction.senderUsername),
receiverUsername: this.toBase64OrUndefined(transaction.receiverUsername),
gasPrice: Number(transaction.gasPrice),
gasLimit: Number(transaction.gasLimit),
data: this.toBase64OrUndefined(transaction.data),
chainID: transaction.chainID.valueOf(),
version: transaction.version,
options: transaction.options == 0 ? undefined : transaction.options,
guardian: transaction.guardian ? transaction.guardian : undefined,
signature: this.toHexOrUndefined(transaction.signature),
guardianSignature: this.toHexOrUndefined(transaction.guardianSignature),
};

return plainObject;
}

private toBase64OrUndefined(value?: string | Uint8Array) {
return value && value.length ? Buffer.from(value).toString("base64") : undefined;
}

private toHexOrUndefined(value?: Uint8Array) {
return value && value.length ? Buffer.from(value).toString("hex") : undefined;
}

public plainObjectToTransaction(object: IPlainTransactionObject): Transaction {
const transaction = new Transaction({
nonce: Number(object.nonce),
value: BigInt(object.value || ""),
receiver: object.receiver,
receiverUsername: this.bufferFromBase64(object.receiverUsername).toString(),
sender: object.sender,
senderUsername: this.bufferFromBase64(object.senderUsername).toString(),
guardian: object.guardian,
gasPrice: Number(object.gasPrice),
gasLimit: Number(object.gasLimit),
data: this.bufferFromBase64(object.data),
chainID: String(object.chainID),
version: object.version,
options: object.options,
signature: this.bufferFromHex(object.signature),
guardianSignature: this.bufferFromHex(object.guardianSignature),
});

return transaction;
}

private bufferFromBase64(value?: string) {
return Buffer.from(value || "", "base64");
}

private bufferFromHex(value?: string) {
return Buffer.from(value || "", "hex");
}
}
77 changes: 14 additions & 63 deletions src/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BigNumber } from "bignumber.js";
import { Address } from "./address";
import { TRANSACTION_MIN_GAS_PRICE, TRANSACTION_OPTIONS_DEFAULT, TRANSACTION_VERSION_DEFAULT } from "./constants";
import { TransactionsConverter } from "./converters/transactionsConverter";
import * as errors from "./errors";
import { Hash } from "./hash";
import {
Expand All @@ -20,7 +21,7 @@ import {
import { INetworkConfig } from "./interfaceOfNetwork";
import { TransactionOptions, TransactionVersion } from "./networkParams";
import { ProtoSerializer } from "./proto";
import { Signature, interpretSignatureAsBuffer } from "./signature";
import { interpretSignatureAsBuffer } from "./signature";
import { TransactionPayload } from "./transactionPayload";

const createTransactionHasher = require("blake2b");
Expand Down Expand Up @@ -141,16 +142,8 @@ export class Transaction {
this.options = options.options?.valueOf() || TRANSACTION_OPTIONS_DEFAULT;
this.guardian = options.guardian ? this.addressAsBech32(options.guardian) : "";

this.signature = Buffer.from([]);
this.guardianSignature = Buffer.from([]);

// Legacy logic, will be kept for some time, to avoid breaking changes in behavior.
if (options.signature?.length) {
this.applySignature(options.signature);
}
if (options.guardianSignature?.length) {
this.applyGuardianSignature(options.guardianSignature);
}
this.signature = options.signature || Buffer.from([]);
this.guardianSignature = options.guardianSignature || Buffer.from([]);
}

private addressAsBech32(address: IAddress | string): string {
Expand Down Expand Up @@ -370,74 +363,31 @@ export class Transaction {
}

/**
* Legacy method, use the "converters" package instead.
* Legacy method, use "TransactionsConverter.transactionToPlainObject()" instead.
*
* Converts the transaction object into a ready-to-serialize, plain JavaScript object.
* This function is called internally within the signing procedure.
*/
toPlainObject(): IPlainTransactionObject {
const plainObject = {
nonce: Number(this.nonce),
value: this.value.toString(),
receiver: this.receiver,
sender: this.sender,
senderUsername: this.senderUsername ? Buffer.from(this.senderUsername).toString("base64") : undefined,
receiverUsername: this.receiverUsername ? Buffer.from(this.receiverUsername).toString("base64") : undefined,
gasPrice: Number(this.gasPrice),
gasLimit: Number(this.gasLimit),
data: this.data.length == 0 ? undefined : Buffer.from(this.data).toString("base64"),
chainID: this.chainID.valueOf(),
version: this.getVersion().valueOf(),
options: this.getOptions().valueOf() == 0 ? undefined : this.getOptions().valueOf(),
guardian: this.guardian ? this.guardian : undefined,
signature: this.signature.length ? this.getSignature().toString("hex") : undefined,
guardianSignature: this.guardianSignature.length ? this.getGuardianSignature().toString("hex") : undefined,
};

return plainObject;
// Ideally, "converters" package should be outside of "core", and not referenced here.
const converter = new TransactionsConverter();
return converter.transactionToPlainObject(this);
}

/**
* Legacy method, use "TransactionsConverter.plainObjectToTransaction()" instead.
* Converts a plain object transaction into a Transaction Object.
*
* @param plainObjectTransaction Raw data of a transaction, usually obtained by calling toPlainObject()
*/
static fromPlainObject(plainObjectTransaction: IPlainTransactionObject): Transaction {
const tx = new Transaction({
nonce: Number(plainObjectTransaction.nonce),
value: new BigNumber(plainObjectTransaction.value).toFixed(0),
receiver: plainObjectTransaction.receiver,
receiverUsername: plainObjectTransaction.receiverUsername
? Buffer.from(plainObjectTransaction.receiverUsername, "base64").toString()
: undefined,
sender: plainObjectTransaction.sender,
senderUsername: plainObjectTransaction.senderUsername
? Buffer.from(plainObjectTransaction.senderUsername, "base64").toString()
: undefined,
guardian: plainObjectTransaction.guardian ? Address.fromString(plainObjectTransaction.guardian) : undefined,
gasPrice: Number(plainObjectTransaction.gasPrice),
gasLimit: Number(plainObjectTransaction.gasLimit),
data: new TransactionPayload(Buffer.from(plainObjectTransaction.data || "", "base64")),
chainID: String(plainObjectTransaction.chainID),
version: plainObjectTransaction.version,
options:
plainObjectTransaction.options != null
? new TransactionOptions(plainObjectTransaction.options)
: undefined,
});

if (plainObjectTransaction.signature) {
tx.applySignature(new Signature(plainObjectTransaction.signature));
}

if (plainObjectTransaction.guardianSignature) {
tx.applyGuardianSignature(new Signature(plainObjectTransaction.guardianSignature));
}

return tx;
// Ideally, "converters" package should be outside of "core", and not referenced here.
const converter = new TransactionsConverter();
return converter.plainObjectToTransaction(plainObjectTransaction);
}

/**
* Legacy method, use the "signature" property instead.
* Applies the signature on the transaction.
*
* @param signature The signature, as computed by a signer.
Expand All @@ -447,6 +397,7 @@ export class Transaction {
}

/**
* Legacy method, use the "guardianSignature" property instead.
* Applies the guardian signature on the transaction.
*
* @param guardianSignature The signature, as computed by a signer.
Expand Down

0 comments on commit 6a6a810

Please sign in to comment.