diff --git a/integration_tests/Rpc.spec.ts b/integration_tests/Rpc.spec.ts index 8243b0e8..acbf7a7f 100644 --- a/integration_tests/Rpc.spec.ts +++ b/integration_tests/Rpc.spec.ts @@ -417,7 +417,6 @@ describe("rpc", () => { }); test("getAssetScheme", async () => { - const shardId = 0; expect( await sdk.rpc.chain.getAssetSchemeByHash( mintTransaction.hash(), diff --git a/src/core/Asset.ts b/src/core/Asset.ts index f077f079..70f82a73 100644 --- a/src/core/Asset.ts +++ b/src/core/Asset.ts @@ -9,6 +9,17 @@ import { AssetTransferTransaction } from "./transaction/AssetTransferTransaction import { NetworkId } from "./types"; import { U256 } from "./U256"; +export interface AssetJSON { + assetType: string; + lockScriptHash: string; + parameters: number[][]; + amount: string; + // The `hash` and the `index` are not included in an RPC response. See + // getAsset() in chain.ts for more details. + transactionHash: string; + transactionOutputIndex: number; +} + export interface AssetData { assetType: H256; lockScriptHash: H160; @@ -21,7 +32,7 @@ export interface AssetData { * Object created as an AssetMintTransaction or AssetTransferTransaction. */ export class Asset { - public static fromJSON(data: any) { + public static fromJSON(data: AssetJSON) { const { assetType, lockScriptHash, @@ -71,7 +82,7 @@ export class Asset { }); } - public toJSON() { + public toJSON(): AssetJSON { const { assetType, lockScriptHash, @@ -83,8 +94,8 @@ export class Asset { return { assetType: assetType.value, lockScriptHash: lockScriptHash.value, - parameters, - amount: amount.toEncodeObject(), + parameters: parameters.map(p => [...p]), + amount: `0x${amount.toString(16)}`, transactionHash: transactionHash.value, transactionOutputIndex: index }; diff --git a/src/core/AssetScheme.ts b/src/core/AssetScheme.ts index b6698af9..85adbb76 100644 --- a/src/core/AssetScheme.ts +++ b/src/core/AssetScheme.ts @@ -9,11 +9,21 @@ import { AssetMintTransaction } from "./transaction/AssetMintTransaction"; import { NetworkId } from "./types"; import { U256 } from "./U256"; +export interface AssetSchemeJSON { + metadata: string; + amount: string; + registrar: string | null; + pool: { + assetType: string; + amount: string; + }[]; +} + /** * Object that contains information about the Asset when performing AssetMintTransaction. */ export class AssetScheme { - public static fromJSON(data: any) { + public static fromJSON(data: AssetSchemeJSON) { const { metadata, amount, registrar, pool } = data; return new AssetScheme({ metadata, @@ -50,15 +60,15 @@ export class AssetScheme { this.pool = data.pool; } - public toJSON() { + public toJSON(): AssetSchemeJSON { const { metadata, amount, registrar, pool } = this; return { metadata, - amount: amount.toEncodeObject(), + amount: `0x${amount.toString(16)}`, registrar: registrar === null ? null : registrar.toString(), pool: pool.map(a => ({ assetType: a.assetType.value, - amount: a.amount.toEncodeObject() + amount: `0x${a.amount.toString(16)}` })) }; } diff --git a/src/core/transaction/AssetComposeTransaction.ts b/src/core/transaction/AssetComposeTransaction.ts index 2651c1c7..6fa2de4d 100644 --- a/src/core/transaction/AssetComposeTransaction.ts +++ b/src/core/transaction/AssetComposeTransaction.ts @@ -17,11 +17,26 @@ import { Asset } from "../Asset"; import { AssetScheme } from "../AssetScheme"; import { NetworkId } from "../types"; import { U256 } from "../U256"; -import { AssetMintOutput } from "./AssetMintOutput"; -import { AssetTransferInput } from "./AssetTransferInput"; +import { AssetMintOutput, AssetMintOutputJSON } from "./AssetMintOutput"; +import { + AssetTransferInput, + AssetTransferInputJSON +} from "./AssetTransferInput"; const RLP = require("rlp"); +export interface AssetComposeTransactionJSON { + type: "assetCompose"; + data: { + networkId: NetworkId; + shardId: number; + metadata: string; + inputs: AssetTransferInputJSON[]; + output: AssetMintOutputJSON; + registrar: string | null; + }; +} + /** * Compose assets. */ @@ -31,7 +46,7 @@ export class AssetComposeTransaction { * @param obj An AssetComposeTransaction JSON object. * @returns An AssetComposeTransaction. */ - public static fromJSON(obj: any) { + public static fromJSON(obj: AssetComposeTransactionJSON) { const { data: { networkId, shardId, metadata, inputs, output, registrar } } = obj; @@ -41,9 +56,7 @@ export class AssetComposeTransaction { metadata, registrar: registrar === null ? null : PlatformAddress.ensure(registrar), - inputs: inputs.map((input: any) => - AssetTransferInput.fromJSON(input) - ), + inputs: inputs.map(input => AssetTransferInput.fromJSON(input)), output: AssetMintOutput.fromJSON(output) }); } @@ -93,14 +106,15 @@ export class AssetComposeTransaction { * Convert to an AssetComposeTransaction JSON object. * @returns An AssetComposeTransaction JSON object. */ - public toJSON() { + public toJSON(): AssetComposeTransactionJSON { return { type: this.type, data: { networkId: this.networkId, shardId: this.shardId, metadata: this.metadata, - registrar: this.registrar, + registrar: + this.registrar === null ? null : this.registrar.toString(), output: this.output.toJSON(), inputs: this.inputs.map(input => input.toJSON()) } diff --git a/src/core/transaction/AssetDecomposeTransaction.ts b/src/core/transaction/AssetDecomposeTransaction.ts index 7ba07905..aadfe6b8 100644 --- a/src/core/transaction/AssetDecomposeTransaction.ts +++ b/src/core/transaction/AssetDecomposeTransaction.ts @@ -10,11 +10,26 @@ import * as _ from "lodash"; import { Asset } from "../Asset"; import { AssetTransferOutputValue, NetworkId } from "../types"; import { U256 } from "../U256"; -import { AssetTransferInput } from "./AssetTransferInput"; -import { AssetTransferOutput } from "./AssetTransferOutput"; +import { + AssetTransferInput, + AssetTransferInputJSON +} from "./AssetTransferInput"; +import { + AssetTransferOutput, + AssetTransferOutputJSON +} from "./AssetTransferOutput"; const RLP = require("rlp"); +export interface AssetDecomposeTransactionJSON { + type: "assetDecompose"; + data: { + input: AssetTransferInputJSON; + outputs: AssetTransferOutputJSON[]; + networkId: NetworkId; + }; +} + /** * Decompose assets. The sum of inputs must be whole supply of the asset. */ @@ -24,13 +39,13 @@ export class AssetDecomposeTransaction { * @param obj An AssetDecomposeTransaction JSON object. * @returns An AssetDecomposeTransaction. */ - public static fromJSON(obj: any) { + public static fromJSON(obj: AssetDecomposeTransactionJSON) { const { data: { input, outputs, networkId } } = obj; return new this({ input: AssetTransferInput.fromJSON(input), - outputs: outputs.map((o: any) => AssetTransferInput.fromJSON(o)), + outputs: outputs.map(o => AssetTransferOutput.fromJSON(o)), networkId }); } @@ -59,7 +74,7 @@ export class AssetDecomposeTransaction { * Convert to an AssetDecomposeTransaction JSON object. * @returns An AssetDecomposeTransaction JSON object. */ - public toJSON() { + public toJSON(): AssetDecomposeTransactionJSON { const { type, input, outputs, networkId } = this; return { type, diff --git a/src/core/transaction/AssetMintOutput.ts b/src/core/transaction/AssetMintOutput.ts index 2af06306..1efcfb51 100644 --- a/src/core/transaction/AssetMintOutput.ts +++ b/src/core/transaction/AssetMintOutput.ts @@ -5,17 +5,19 @@ import { P2PKH } from "../../key/P2PKH"; import { P2PKHBurn } from "../../key/P2PKHBurn"; import { U256 } from "../U256"; +export interface AssetMintOutputJSON { + lockScriptHash: string; + parameters: number[][]; + amount?: string | null; +} + export class AssetMintOutput { /** * Create an AssetMintOutput from an AssetMintOutput JSON object. * @param data An AssetMintOutput JSON object. * @returns An AssetMintOutput. */ - public static fromJSON(data: { - lockScriptHash: string; - parameters: Buffer[]; - amount?: string | null; - }) { + public static fromJSON(data: AssetMintOutputJSON) { const { lockScriptHash, parameters, amount } = data; return new this({ lockScriptHash: H160.ensure(lockScriptHash), @@ -83,12 +85,14 @@ export class AssetMintOutput { * Convert to an AssetMintOutput JSON object. * @returns An AssetMintOutput JSON object. */ - public toJSON() { + public toJSON(): AssetMintOutputJSON { return { lockScriptHash: this.lockScriptHash.value, parameters: this.parameters.map(p => [...p]), amount: - this.amount == null ? undefined : this.amount.toEncodeObject() + this.amount == null + ? undefined + : `0x${this.amount.toString(16)}` }; } } diff --git a/src/core/transaction/AssetMintTransaction.ts b/src/core/transaction/AssetMintTransaction.ts index 602196b9..6b35b0ef 100644 --- a/src/core/transaction/AssetMintTransaction.ts +++ b/src/core/transaction/AssetMintTransaction.ts @@ -6,10 +6,21 @@ import { Asset } from "../Asset"; import { AssetScheme } from "../AssetScheme"; import { H256 } from "../H256"; import { NetworkId } from "../types"; -import { AssetMintOutput } from "./AssetMintOutput"; +import { AssetMintOutput, AssetMintOutputJSON } from "./AssetMintOutput"; const RLP = require("rlp"); +export interface AssetMintTransactionJSON { + type: "assetMint"; + data: { + networkId: NetworkId; + shardId: number; + metadata: string; + output: AssetMintOutputJSON; + registrar: string | null; + }; +} + /** * Creates a new asset type and that asset itself. * @@ -26,7 +37,7 @@ export class AssetMintTransaction { * @param data An AssetMintTransaction JSON object. * @returns An AssetMintTransaction. */ - public static fromJSON(data: any) { + public static fromJSON(data: AssetMintTransactionJSON) { const { data: { networkId, shardId, metadata, output, registrar } } = data; @@ -68,7 +79,7 @@ export class AssetMintTransaction { this.networkId = networkId; this.shardId = shardId; this.metadata = metadata; - this.output = new AssetMintOutput(output); + this.output = output; this.registrar = registrar; } @@ -76,7 +87,7 @@ export class AssetMintTransaction { * Convert to an AssetMintTransaction JSON object. * @returns An AssetMintTransaction JSON object. */ - public toJSON() { + public toJSON(): AssetMintTransactionJSON { const { networkId, shardId, metadata, output, registrar } = this; return { type: this.type, diff --git a/src/core/transaction/AssetOutPoint.ts b/src/core/transaction/AssetOutPoint.ts index fccff499..b43adaa1 100644 --- a/src/core/transaction/AssetOutPoint.ts +++ b/src/core/transaction/AssetOutPoint.ts @@ -2,6 +2,13 @@ import { H160 } from "../H160"; import { H256 } from "../H256"; import { U256 } from "../U256"; +export interface AssetOutPointJSON { + transactionHash: string; + index: number; + assetType: string; + amount: string; +} + export interface AssetOutPointData { transactionHash: H256; index: number; @@ -24,7 +31,7 @@ export class AssetOutPoint { * @param data An AssetOutPoint JSON object. * @returns An AssetOutPoint. */ - public static fromJSON(data: any) { + public static fromJSON(data: AssetOutPointJSON) { const { transactionHash, index, assetType, amount } = data; return new this({ transactionHash: new H256(transactionHash), @@ -82,13 +89,13 @@ export class AssetOutPoint { * Convert to an AssetOutPoint JSON object. * @returns An AssetOutPoint JSON object. */ - public toJSON() { + public toJSON(): AssetOutPointJSON { const { transactionHash, index, assetType, amount } = this; return { transactionHash: transactionHash.value, index, assetType: assetType.value, - amount: amount.toEncodeObject() + amount: `0x${amount.toString(16)}` }; } } diff --git a/src/core/transaction/AssetTransferInput.ts b/src/core/transaction/AssetTransferInput.ts index f171fde7..8d57b53d 100644 --- a/src/core/transaction/AssetTransferInput.ts +++ b/src/core/transaction/AssetTransferInput.ts @@ -1,6 +1,6 @@ import { Buffer } from "buffer"; -import { AssetOutPoint } from "./AssetOutPoint"; +import { AssetOutPoint, AssetOutPointJSON } from "./AssetOutPoint"; export type TimelockType = "block" | "blockAge" | "time" | "timeAge"; export interface Timelock { @@ -9,6 +9,13 @@ export interface Timelock { value: number; } +export interface AssetTransferInputJSON { + prevOut: AssetOutPointJSON; + timelock: Timelock | null; + lockScript: number[]; + unlockScript: number[]; +} + /** * An AssetTransferInput consists of the following: * - An AssetOutPoint, which points to the asset to be spent. @@ -22,13 +29,13 @@ export class AssetTransferInput { * @param data An AssetTransferInput JSON object. * @returns An AssetTransferInput. */ - public static fromJSON(data: any) { + public static fromJSON(data: AssetTransferInputJSON) { const { prevOut, timelock, lockScript, unlockScript } = data; return new this({ prevOut: AssetOutPoint.fromJSON(prevOut), timelock, - lockScript, - unlockScript + lockScript: Buffer.from(lockScript), + unlockScript: Buffer.from(unlockScript) }); } public readonly prevOut: AssetOutPoint; @@ -76,7 +83,7 @@ export class AssetTransferInput { * Convert to an AssetTransferInput JSON object. * @returns An AssetTransferInput JSON object. */ - public toJSON() { + public toJSON(): AssetTransferInputJSON { const { prevOut, timelock, lockScript, unlockScript } = this; return { prevOut: prevOut.toJSON(), diff --git a/src/core/transaction/AssetTransferOutput.ts b/src/core/transaction/AssetTransferOutput.ts index c361f204..f90ffb4d 100644 --- a/src/core/transaction/AssetTransferOutput.ts +++ b/src/core/transaction/AssetTransferOutput.ts @@ -7,6 +7,13 @@ import { P2PKHBurn } from "../../key/P2PKHBurn"; import { H256 } from "../H256"; import { U256 } from "../U256"; +export interface AssetTransferOutputJSON { + lockScriptHash: string; + parameters: number[][]; + assetType: string; + amount: string; +} + export interface AssetTransferOutputData { lockScriptHash: H160; parameters: Buffer[]; @@ -31,7 +38,7 @@ export class AssetTransferOutput { * @param data An AssetTransferOutput JSON object. * @returns An AssetTransferOutput. */ - public static fromJSON(data: AssetTransferOutputData) { + public static fromJSON(data: AssetTransferOutputJSON) { const { lockScriptHash, parameters, assetType, amount } = data; return new this({ lockScriptHash: H160.ensure(lockScriptHash), @@ -109,13 +116,13 @@ export class AssetTransferOutput { * Convert to an AssetTransferOutput JSON object. * @returns An AssetTransferOutput JSON object. */ - public toJSON() { + public toJSON(): AssetTransferOutputJSON { const { lockScriptHash, parameters, assetType, amount } = this; return { lockScriptHash: lockScriptHash.value, parameters: parameters.map(parameter => [...parameter]), assetType: assetType.value, - amount: amount.toEncodeObject() + amount: `0x${amount.toString(16)}` }; } diff --git a/src/core/transaction/AssetTransferTransaction.ts b/src/core/transaction/AssetTransferTransaction.ts index b6225427..9b557595 100644 --- a/src/core/transaction/AssetTransferTransaction.ts +++ b/src/core/transaction/AssetTransferTransaction.ts @@ -12,11 +12,27 @@ import { Asset } from "../Asset"; import { H256 } from "../H256"; import { AssetTransferOutputValue, NetworkId } from "../types"; import { U256 } from "../U256"; -import { AssetTransferInput } from "./AssetTransferInput"; -import { AssetTransferOutput } from "./AssetTransferOutput"; +import { + AssetTransferInput, + AssetTransferInputJSON +} from "./AssetTransferInput"; +import { + AssetTransferOutput, + AssetTransferOutputJSON +} from "./AssetTransferOutput"; const RLP = require("rlp"); +export interface AssetTransferTransactionJSON { + type: "assetTransfer"; + data: { + burns: AssetTransferInputJSON[]; + inputs: AssetTransferInputJSON[]; + outputs: AssetTransferOutputJSON[]; + networkId: NetworkId; + }; +} + export interface AssetTransferTransactionData { burns: AssetTransferInput[]; inputs: AssetTransferInput[]; @@ -42,7 +58,7 @@ export class AssetTransferTransaction { * @param obj An AssetTransferTransaction JSON object. * @returns An AssetTransferTransaction. */ - public static fromJSON(obj: any) { + public static fromJSON(obj: AssetTransferTransactionJSON) { const { data: { networkId, burns, inputs, outputs } } = obj; @@ -321,7 +337,7 @@ export class AssetTransferTransaction { * Convert to an AssetTransferTransaction JSON object. * @returns An AssetTransferTransaction JSON object. */ - public toJSON() { + public toJSON(): AssetTransferTransactionJSON { const { networkId, burns, inputs, outputs } = this; return { type: this.type, diff --git a/src/core/transaction/Transaction.ts b/src/core/transaction/Transaction.ts index df9bbcb8..0e04d611 100644 --- a/src/core/transaction/Transaction.ts +++ b/src/core/transaction/Transaction.ts @@ -1,7 +1,25 @@ -import { AssetComposeTransaction } from "./AssetComposeTransaction"; -import { AssetDecomposeTransaction } from "./AssetDecomposeTransaction"; -import { AssetMintTransaction } from "./AssetMintTransaction"; -import { AssetTransferTransaction } from "./AssetTransferTransaction"; +import { + AssetComposeTransaction, + AssetComposeTransactionJSON +} from "./AssetComposeTransaction"; +import { + AssetDecomposeTransaction, + AssetDecomposeTransactionJSON +} from "./AssetDecomposeTransaction"; +import { + AssetMintTransaction, + AssetMintTransactionJSON +} from "./AssetMintTransaction"; +import { + AssetTransferTransaction, + AssetTransferTransactionJSON +} from "./AssetTransferTransaction"; + +export type TransactionJSON = + | AssetMintTransactionJSON + | AssetTransferTransactionJSON + | AssetComposeTransactionJSON + | AssetDecomposeTransactionJSON; export type Transaction = | AssetMintTransaction @@ -15,21 +33,17 @@ export type Transaction = * @param params Either an AssetMintTransaction JSON object or an AssetTransferTransaction JSON object. * @returns A Transaction. */ -export const getTransactionFromJSON = (params: { - type: string; - data: object; -}) => { - const { type } = params; - switch (type) { +export const getTransactionFromJSON = (json: TransactionJSON): Transaction => { + switch (json.type) { case "assetMint": - return AssetMintTransaction.fromJSON(params); + return AssetMintTransaction.fromJSON(json); case "assetTransfer": - return AssetTransferTransaction.fromJSON(params); + return AssetTransferTransaction.fromJSON(json); case "assetCompose": - return AssetComposeTransaction.fromJSON(params); + return AssetComposeTransaction.fromJSON(json); case "assetDecompose": - return AssetDecomposeTransaction.fromJSON(params); + return AssetDecomposeTransaction.fromJSON(json); default: - throw Error(`Unexpected transaction type: ${type}`); + throw Error(`Unexpected transaction type: ${(json as any).type}`); } }; diff --git a/src/core/transaction/__test__/AssetMintTransaction.spec.ts b/src/core/transaction/__test__/AssetMintTransaction.spec.ts index 01d61c52..5cdee361 100644 --- a/src/core/transaction/__test__/AssetMintTransaction.spec.ts +++ b/src/core/transaction/__test__/AssetMintTransaction.spec.ts @@ -1,5 +1,6 @@ import { H160 } from "../../H160"; import { U256 } from "../../U256"; +import { AssetMintOutput } from "../AssetMintOutput"; import { AssetMintTransaction } from "../AssetMintTransaction"; test("AssetMintTransaction toJSON", () => { @@ -7,13 +8,13 @@ test("AssetMintTransaction toJSON", () => { networkId: "cc", shardId: 0, metadata: "", - output: { + output: new AssetMintOutput({ lockScriptHash: new H160( "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" ), parameters: [], amount: new U256(0) - }, + }), registrar: null }); expect(AssetMintTransaction.fromJSON(t.toJSON())).toEqual(t);