UNPKG

@ellcrys/spell

Version:

The official JavaScript library for Ellcrys

289 lines (253 loc) 7.9 kB
import chai = require("chai"); import Decimal from "decimal.js"; import sinon = require("sinon"); import sinonChai = require("sinon-chai"); import { Transaction } from "../../../.."; import { Address, PrivateKey } from "../../../lib"; import { NumDecimals, TxBalanceBuilder, TxPayloadVersion, } from "../../../lib/builders/transaction_builder"; import errors from "../../../lib/errors"; import RPCClient from "../../../lib/rpcclient"; import Spell from "../../../lib/spell"; const b58 = require("bs58check"); const expect = chai.expect; chai.use(sinonChai); describe("#TransactionBuilder", () => { let spell: Spell; let client: RPCClient; let pk: PrivateKey; let testTx: Transaction; function makeClientStub(err: Error | null, resp: any) { return sinon.stub(client.client, "call" as never).callsArgWith(2, err, resp); } class WrappedTxBalanceBuilder extends TxBalanceBuilder { constructor(mClient?: RPCClient) { super(mClient); } public getClient(): RPCClient | undefined { return this.client; } public getData(): Transaction { return this.data; } public setData(tx: Transaction) { this.data = tx; } public finalize(sk?: PrivateKey): Promise<string> { return super.finalize(sk); } } beforeEach(() => { spell = new Spell(); client = spell.rpcClient; client.client = { call: (method: string, params: any, cb: (err: any, res: any) => {}): any => { cb(null, null); }, }; pk = PrivateKey.from( "wntaQsep5UAL3WAsThJx3jtJ2Ge79fjuzVvisKBhBrA4ps24o" + "stkmKA9egwH3o7nUYxB37Kn9Ac23UEym8u81AmgUn6Zuq", ); testTx = { from: "e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW", to: "e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW", type: 1, senderPubKey: pk.publicKey().toBase58(), value: "1", fee: "1", timestamp: 1547285790, nonce: 1, }; }); describe("TxBalanceBuilder", () => { describe(".constructor", () => { it("should set client", () => { const b = new WrappedTxBalanceBuilder(client); expect(b.getClient()).to.not.be.undefined; }); it("should set type to 0x1", () => { const b = new WrappedTxBalanceBuilder(client); expect(b.getData().type).to.eql(0x1); }); }); describe(".from", () => { it("should set `from` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = "e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW"; b.from(data); expect(b.getData().from).to.eq(data); }); specify("when Address is provided, it should set from field", () => { const b = new WrappedTxBalanceBuilder(client); const data = Address.from("e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW"); b.from(data.toString()); expect(b.getData().from).to.eq(data.toString()); }); }); describe(".to", () => { it("should set `to` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = "e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW"; b.to(data); expect(b.getData().to).to.eq(data); }); specify("when Address is provided, it should set to field", () => { const b = new WrappedTxBalanceBuilder(client); const data = Address.from("e4hbAT45QeddPj3XpJiSHxb9APhuQHcMUW"); b.to(data.toString()); expect(b.getData().to).to.eq(data.toString()); }); }); describe(".nonce", () => { it("should set `nonce` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = 10; b.nonce(data); expect(b.getData().nonce).to.eq(data); }); }); describe(".value", () => { it("should set `value` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = "10.40"; b.value(data); expect(b.getData().value).to.eq(data); }); specify("when Decimal is provided, it should set `value` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = new Decimal("10.40"); b.value(data); expect(b.getData().value).to.eq(data.toFixed(NumDecimals)); }); }); describe(".fee", () => { it("should set `fee` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = "10.40"; b.fee(data); expect(b.getData().fee).to.eq(data); }); specify("when Decimal is provided, it should set `fee` field", () => { const b = new WrappedTxBalanceBuilder(client); const data = new Decimal("10.40"); b.fee(data); expect(b.getData().fee).to.eq(data.toFixed(NumDecimals)); }); }); describe(".reset", () => { it("should set internal data to zero value (empty object)", () => { const b = new WrappedTxBalanceBuilder(client); const data = "10.40"; b.fee(data); b.value(data); expect(b.getData().fee).to.eq(data); expect(b.getData().value).to.eq(data); b.reset(); expect(b.getData()).to.be.empty; }); }); describe(".finalize", () => { it("should throw RequirePrivateKey error when private key is not provided", () => { const b = new WrappedTxBalanceBuilder(client); b.finalize().catch((e) => { expect(e).to.eq(errors.RequirePrivateKey); }); }); describe("when key is provided", () => { describe("when nonce field is not set", () => { it("should throw ClientNotInitialized error when client is not initialized", () => { const b = new WrappedTxBalanceBuilder(); delete testTx.nonce; b.setData(testTx); b.finalize(pk).catch((e) => { expect(e).to.eq(errors.ClientNotInitialized); }); }); it( "should throw UnknownSenderAccount error when sender " + "account is not known", async () => { const b = new WrappedTxBalanceBuilder(client); delete testTx.nonce; b.setData(testTx); makeClientStub( { data: `{ "error": { "code": 30001 }}`, statusCode: 400, } as any, null, ); b.finalize(pk).catch((e) => { expect(e).to.eq(errors.UnknownSenderAccount); }); }, ); it("should successfully call finalize()", async () => { makeClientStub(null, 2); const b = new WrappedTxBalanceBuilder(client); delete testTx.nonce; b.setData(testTx); const hash = await b.finalize(pk); const data = b.getData(); expect(data.timestamp).to.not.be.undefined; expect(data.nonce).to.eq(2); expect(data.hash).to.not.undefined; expect(data.sig).to.not.undefined; expect(data.hash).to.eq(hash); }); }); }); }); describe(".payload", () => { it("should return object", async () => { const b = new WrappedTxBalanceBuilder(client); expect(b.getData().timestamp).to.be.undefined; const data = await b.payload(); expect(data.timestamp).to.not.be.undefined; }); }); describe(".send", () => { it( "should throw ClientNotInitialized error when client is" + " not initialized", (done) => { const b = new WrappedTxBalanceBuilder(); b.setData(testTx); b.send(pk).catch((e) => { expect(e.message).to.equal(errors.ClientNotInitialized.message); done(); }); }, ); it("should successfully send signed transaction data", async () => { const b = new WrappedTxBalanceBuilder(client); b.setData(testTx); const mock = makeClientStub(null, { id: "0x000", }); const res = await b.send(pk); expect(res.id).to.equal("0x000"); expect(mock).to.have.been.calledWith("ell_send", b.getData()); }); }); describe(".packed", () => { it( "should successfully return a valid base58 serialized " + "version of the transaction", async () => { const b = new WrappedTxBalanceBuilder(client); b.setData(testTx); const res = await b.packed(pk); const decoded = b58.decode(res); expect(decoded[0]).to.eql(TxPayloadVersion[0]); const tx = JSON.parse(decoded.slice(1).toString()); expect(b.getData()).to.deep.eq(tx); }, ); }); }); });