Home Reference Source Test

test/specs/generic/consensus/base/transaction/index/TransactionStore.spec.js

describe('TransactionStore', () => {
    /** @type {TransactionStore} */
    let transactionStore;
    /** @type {Array.<Transaction>} */
    let transactions;
    let block, senderAddress, recipientAddress1, recipientAddress2;
    let testBlockchain;

    beforeAll((done) => {
        (async () => {
            transactionStore = TransactionStore.createVolatile();

            testBlockchain = await TestBlockchain.createVolatileTest(0, 3);
            const senderPubKey = testBlockchain.users[0].publicKey;
            senderAddress = testBlockchain.users[0].address;
            recipientAddress1 = testBlockchain.users[1].address;
            recipientAddress2 = testBlockchain.users[2].address;
            const signature = Signature.unserialize(BufferUtils.fromBase64(Dummy.signature1));
            const proof = BufferUtils.fromAscii('ABCD');
            const tx1 = new BasicTransaction(senderPubKey, recipientAddress1, 1, 1, 1, signature);
            const tx2 = new ExtendedTransaction(senderAddress, Account.Type.BASIC, recipientAddress2, Account.Type.BASIC, 1, 1, 1, Transaction.Flag.NONE, new Uint8Array(0), proof);
            const tx3 = new ExtendedTransaction(senderAddress, Account.Type.BASIC, recipientAddress1, Account.Type.BASIC, 100, 0, 1, Transaction.Flag.NONE, new Uint8Array(0), proof);

            /** @type {Array.<Transaction>} */
            transactions = [tx1, tx2, tx3];
            transactions.sort((a, b) => a.compareBlockOrder(b));

            block = await testBlockchain.createBlock({transactions});
        })().then(done, done.fail);
    });

    it('can store and remove transactions', (done) => {
        (async () => {
            await transactionStore.put(block);
            expect((await transactionStore.getBySender(senderAddress)).length).toBe(3);
            await transactionStore.remove(block);
            expect((await transactionStore.getBySender(senderAddress)).length).toBe(0);
        })().then(done, done.fail);
    });

    it('can retrieve transactions by senderAddress', (done) => {
        (async () => {
            await transactionStore.put(block);
            const results = await transactionStore.getBySender(senderAddress);
            expect(results.length).toBe(3);

            for (const entry of results) {
                expect(entry.sender.equals(senderAddress)).toBeTruthy();
            }

            await transactionStore.truncate();
        })().then(done, done.fail);
    });

    it('can retrieve transactions by recipientAddress', (done) => {
        (async () => {
            await transactionStore.put(block);
            let results = await transactionStore.getByRecipient(recipientAddress1);
            expect(results.length).toBe(2);

            for (const entry of results) {
                expect(entry.recipient.equals(recipientAddress1)).toBeTruthy();
            }

            results = await transactionStore.getByRecipient(recipientAddress2);
            expect(results.length).toBe(1);

            for (const entry of results) {
                expect(entry.recipient.equals(recipientAddress2)).toBeTruthy();
            }

            await transactionStore.truncate();
        })().then(done, done.fail);
    });

    it('can retrieve transactions by hash', (done) => {
        (async () => {
            await transactionStore.put(block);
            const blockHash = await block.hash();

            for (let i=0; i<transactions.length; ++i) {
                const hash = transactions[i].hash();
                const entry = await transactionStore.get(hash);
                expect(entry.transactionHash.equals(hash)).toBeTruthy('wrong transactionHash');
                expect(entry.sender.equals(transactions[i].sender)).toBeTruthy('wrong sender');
                expect(entry.recipient.equals(transactions[i].recipient)).toBeTruthy('wrong recipient');
                expect(entry.blockHeight).toBe(block.height, 'wrong block height');
                expect(entry.index).toBe(i, 'wrong index');
                expect(entry.blockHash.equals(blockHash)).toBeTruthy('wrong block hash');
            }
            await transactionStore.truncate();
        })().then(done, done.fail);
    });

    it('can rebranch', (done) => {
        (async () => {
            await transactionStore.put(block);

            const rebranchedBlock1 = await testBlockchain.createBlock({nonce: 1, transactions: [transactions[2]]});
            const rebranchedBlock2 = await testBlockchain.createBlock({nonce: 1, transactions: [transactions[0]]});

            const tx = transactionStore.transaction();
            await tx.remove(block);
            await tx.put(rebranchedBlock1);
            await tx.put(rebranchedBlock2);
            await tx.commit();

            for (let i=0; i<transactions.length; ++i) {
                const hash = transactions[i].hash();
                const entry = await transactionStore.get(hash);
                if (i == 1) {
                    expect(entry).toBe(null);
                    continue;
                }
                expect(entry.transactionHash.equals(hash)).toBeTruthy('wrong transactionHash');
                expect(entry.sender.equals(transactions[i].sender)).toBeTruthy('wrong sender');
                expect(entry.recipient.equals(transactions[i].recipient)).toBeTruthy('wrong recipient');
                expect(entry.blockHeight).toBe(block.height, 'wrong block height');
                expect(entry.index).toBe(0, 'wrong index');
            }
            await transactionStore.truncate();
        })().then(done, done.fail);
    });
});