Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import "jest-extended";

import { BlockCommand } from "../../../../../packages/core-tester-cli/dist/commands/make/block";

describe("make:block", () => {
it("should generate 1 block with default flags", async () => {
const blocks = await BlockCommand.run(["--network=unitnet"]);

expect(blocks).toHaveLength(1);

expect(blocks[0].generatorPublicKey).toBe("03287bfebba4c7881a0509717e71b34b63f31e40021c321f89ae04f84be6d6ac37");
});

it("should generate 1 block with 10 transactions", async () => {
const blocks = await BlockCommand.run(["--network=unitnet", "--transactions=10"]);

expect(blocks[0].transactions).toHaveLength(10);
});

it("should generate 10 blocks", async () => {
const blocks = await BlockCommand.run(["--network=unitnet", "--number=10"]);

expect(blocks).toHaveLength(10);
});

it("should generate 10 blocks with 10 transactions", async () => {
const blocks = await BlockCommand.run(["--network=unitnet", "--transactions=10"]);

for (const block of blocks) {
expect(block.transactions).toHaveLength(10);
}
});

it("should generate a block with a custom passphrase", async () => {
const blocks = await BlockCommand.run(["--network=unitnet", "--passphrase=123"]);

expect(blocks[0].generatorPublicKey).toBe("03be686ed7f0539affbaf634f3bcc2b235e8e220e7be57e9397ab1c14c39137eb4");
});
});
12 changes: 11 additions & 1 deletion packages/core-tester-cli/src/commands/command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { bignumify } from "@arkecosystem/core-utils";
import { Address, Bignum, formatSatoshi } from "@arkecosystem/crypto";
import { Address, Bignum, configManager, formatSatoshi, NetworkName } from "@arkecosystem/crypto";
import Command, { flags } from "@oclif/command";
import delay from "delay";
import { satoshiFlag } from "../flags";
Expand Down Expand Up @@ -86,6 +86,16 @@ export abstract class BaseCommand extends Command {
return { args, flags };
}

protected makeOffline(command): any {
const { args, flags } = this.parse(command);

configManager.setFromPreset(flags.network as NetworkName);

this.signer = new Signer(configManager.all());

return { args, flags };
}

protected async sendTransaction(transactions: any[]): Promise<Record<string, any>> {
if (!Array.isArray(transactions)) {
transactions = [transactions];
Expand Down
105 changes: 105 additions & 0 deletions packages/core-tester-cli/src/commands/make/block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { configManager, models, slots } from "@arkecosystem/crypto";
import { flags } from "@oclif/command";
import { writeFileSync } from "fs";
import { satoshiFlag } from "../../flags";
import { copyToClipboard } from "../../utils";
import { BaseCommand } from "../command";

export class BlockCommand extends BaseCommand {
public static description: string = "create new blocks";

public static flags = {
...BaseCommand.flagsConfig,
...BaseCommand.flagsDebug,
number: flags.integer({
description: "number of blocks to generate",
default: 1,
}),
transactions: flags.integer({
description: "number of transactions to generate",
default: 0,
}),
transactionAmount: satoshiFlag({
description: "initial wallet token amount",
default: 2,
}),
transactionFee: satoshiFlag({
description: "transfer fee",
default: 0.1,
}),
passphrase: flags.string({
description: "passphrase of the forger",
default: "clay harbor enemy utility margin pretty hub comic piece aerobic umbrella acquire",
}),
previousBlock: flags.string({
description: `Previous block to base the generated block(s) on. For example: '{ "height": 50, "id": "123", "idHex": "7b" }'`,
}),
write: flags.boolean({
description: "write the blocks to the disk",
}),
log: flags.boolean({
description: "log the data to the console",
default: true,
}),
};

public async run(): Promise<models.IBlockData[]> {
const { flags } = this.makeOffline(BlockCommand);

const genesisBlock = configManager.get("genesisBlock");
const genesisWallets = genesisBlock.transactions.map(t => t.recipientId).filter(a => !!a);

let previousBlock = flags.previousBlock ? JSON.parse(flags.previousBlock) : genesisBlock;

const blocks: models.IBlockData[] = [];

for (let i = 0; i < flags.number; i++) {
const milestone = configManager.getMilestone(previousBlock.height);
const delegate = new models.Delegate(flags.passphrase, configManager.get("pubKeyHash"));

const transactions = [];
for (let i = 0; i < flags.transactions; i++) {
transactions.push(
this.signer.makeTransfer({
...flags,
...{
amount: flags.transactionAmount + i,
transferFee: flags.transactionFee,
recipient: genesisWallets[Math.floor(Math.random() * genesisWallets.length)],
},
}),
);
}

const newBlock = await delegate.forge(transactions, {
previousBlock,
timestamp: slots.getSlotNumber(slots.getTime()) * milestone.blocktime,
reward: milestone.reward,
});

const blockPayload = newBlock.data;
blockPayload.transactions = newBlock.transactions.map(tx => ({
...tx.toJson(),
serialized: tx.serialized.toString("hex"),
}));
blockPayload.serialized = newBlock.serialized;
previousBlock = blockPayload;

blocks.push(blockPayload);
}

if (flags.log) {
console.log(JSON.stringify(blocks, null, 4));
}

if (flags.copy) {
copyToClipboard(JSON.stringify(blocks, null, 4));
}

if (flags.write) {
writeFileSync("./blocks.json", JSON.stringify(blocks));
}

return blocks;
}
}
2 changes: 1 addition & 1 deletion packages/core-tester-cli/src/commands/make/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { copyToClipboard } from "../../utils";
import { BaseCommand } from "../command";

export class WalletCommand extends BaseCommand {
public static description: string = "send multiple transactions";
public static description: string = "create new wallets";

public static flags = {
...BaseCommand.flagsConfig,
Expand Down