parsec-node
Version:
https://parseclabs.readthedocs.io/en/latest/
329 lines (306 loc) • 11.2 kB
JavaScript
const { Tx, Input, Outpoint, Output } = require('parsec-lib');
const {
checkOutpoints,
checkInsAndOuts,
addOutputs,
removeInputs,
} = require('./utils');
const ADDR_1 = '0x4436373705394267350db2c06613990d34621d69';
const PRIV_1 =
'0xad8e31c8862f5f86459e7cca97ac9302c5e1817077902540779eef66e21f394a';
const ADDR_2 = '0xc5a72c0bf9f59ed5a1d2ac9f29bd80c55279d2d3';
describe('applyTx utils', () => {
describe('checkInsAndOuts', () => {
test('ERC20', () => {
const deposit = Tx.deposit(12, 500, ADDR_1, 0);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
unspent: {
[outpoint.hex()]: deposit.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpoint)],
[new Output(500, ADDR_1, 0)]
).signAll(PRIV_1);
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
});
test('ERC721', () => {
const color = 2 ** 15 + 1;
const deposit = Tx.deposit(12, 500, ADDR_1, color);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
unspent: {
[outpoint.hex()]: deposit.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpoint)],
[new Output(500, ADDR_1, color)]
).signAll(PRIV_1);
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
});
test('ERC721 (big value)', () => {
const color = 2 ** 15 + 1;
const value =
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
const deposit = Tx.deposit(12, value, ADDR_1, color);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
unspent: {
[outpoint.hex()]: deposit.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpoint)],
[new Output(value, ADDR_1, color)]
).signAll(PRIV_1);
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
});
test('ERC20 + ERC721', () => {
const colorERC721 = 2 ** 15 + 1;
const colorERC20 = 0;
const depositERC20 = Tx.deposit(12, 500, ADDR_1, colorERC20);
const outpointERC20 = new Outpoint(depositERC20.hash(), 0);
const depositERC721 = Tx.deposit(12, 500, ADDR_1, colorERC721);
const outpointERC721 = new Outpoint(depositERC721.hash(), 0);
const state = {
unspent: {
[outpointERC20.hex()]: depositERC20.outputs[0].toJSON(),
[outpointERC721.hex()]: depositERC721.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpointERC721), new Input(outpointERC20)],
[
new Output(500, ADDR_1, colorERC721),
new Output(500, ADDR_1, colorERC20),
]
).signAll(PRIV_1);
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
});
test('Ins and outs mismatch ERC20', () => {
const colorERC721 = 2 ** 15 + 1;
const colorERC20 = 0;
const depositERC20 = Tx.deposit(12, 500, ADDR_1, colorERC20);
const outpointERC20 = new Outpoint(depositERC20.hash(), 0);
const depositERC721 = Tx.deposit(12, 500, ADDR_1, colorERC721);
const outpointERC721 = new Outpoint(depositERC721.hash(), 0);
const state = {
unspent: {
[outpointERC20.hex()]: depositERC20.outputs[0].toJSON(),
[outpointERC721.hex()]: depositERC721.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpointERC721), new Input(outpointERC20)],
[
new Output(500, ADDR_1, colorERC721),
new Output(400, ADDR_1, colorERC20),
]
).signAll(PRIV_1);
expect(() => {
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
}).toThrow(`Ins and outs values are mismatch for color ${colorERC20}`);
});
test('Ins and outs mismatch ERC721', () => {
const colorERC721 = 2 ** 15 + 1;
const colorERC20 = 0;
const depositERC20 = Tx.deposit(12, 500, ADDR_1, colorERC20);
const outpointERC20 = new Outpoint(depositERC20.hash(), 0);
const depositERC721 = Tx.deposit(12, 500, ADDR_1, colorERC721);
const outpointERC721 = new Outpoint(depositERC721.hash(), 0);
const state = {
unspent: {
[outpointERC20.hex()]: depositERC20.outputs[0].toJSON(),
[outpointERC721.hex()]: depositERC721.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpointERC721), new Input(outpointERC20)],
[
new Output(400, ADDR_1, colorERC721),
new Output(500, ADDR_1, colorERC20),
]
).signAll(PRIV_1);
expect(() => {
checkInsAndOuts(
transfer,
state,
({ address }, i) => address === transfer.inputs[i].signer
);
}).toThrow(`Ins and outs values are mismatch for color ${colorERC721}`);
});
});
describe('checkOutpoints', () => {
test('non-existent outpoint', () => {
const state = {
unspent: {},
};
const deposit = Tx.deposit(12, 500, ADDR_1, 0);
const transfer = Tx.transfer(
[new Input(new Outpoint(deposit.hash(), 0))],
[new Output(500, ADDR_1, 0)]
);
expect(() => {
checkOutpoints(state, transfer);
}).toThrow('Trying to spend non-existing output');
});
test('existent outpoint', () => {
const deposit = Tx.deposit(12, 500, ADDR_1, 0);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
unspent: {
[outpoint.hex()]: deposit.outputs[0].toJSON(),
},
};
const transfer = Tx.transfer(
[new Input(outpoint)],
[new Output(500, ADDR_1, 0)]
);
checkOutpoints(state, transfer);
});
});
describe('addOuputs', () => {
test('ERC20', () => {
const deposit = Tx.deposit(12, 500, ADDR_1, 0);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
balances: {},
owners: {},
unspent: {},
};
addOutputs(state, deposit);
expect(state.unspent[outpoint.hex()]).toBeDefined();
expect(state.balances[0][ADDR_1]).toBe(500);
});
test('ERC721', () => {
const color = 2 ** 15 + 1;
const value1 =
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
const value2 =
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa';
const value3 =
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe';
const deposit1 = Tx.deposit(12, value1, ADDR_1, color);
const deposit2 = Tx.deposit(12, value2, ADDR_1, color);
const deposit3 = Tx.deposit(12, value3, ADDR_2, color);
const outpoint1 = new Outpoint(deposit1.hash(), 0);
const outpoint2 = new Outpoint(deposit2.hash(), 0);
const outpoint3 = new Outpoint(deposit3.hash(), 0);
const state = {
balances: {},
owners: {},
unspent: {},
};
addOutputs(state, deposit1);
expect(state.unspent[outpoint1.hex()]).toBeDefined();
expect(state.balances[color][ADDR_1]).toEqual([value1]);
expect(state.owners[color][value1]).toBe(ADDR_1);
addOutputs(state, deposit2);
expect(state.unspent[outpoint2.hex()]).toBeDefined();
expect(state.balances[color][ADDR_1]).toEqual([value1, value2]);
expect(state.owners[color][value2]).toBe(ADDR_1);
addOutputs(state, deposit3);
expect(state.unspent[outpoint3.hex()]).toBeDefined();
expect(state.balances[color][ADDR_2]).toEqual([value3]);
expect(state.owners[color][value3]).toBe(ADDR_2);
});
});
describe('removeInputs', () => {
test('ERC20', () => {
const deposit = Tx.deposit(12, 500, ADDR_1, 0);
const outpoint = new Outpoint(deposit.hash(), 0);
const state = {
balances: {},
owners: {},
unspent: {},
};
addOutputs(state, deposit);
expect(state.unspent[outpoint.hex()]).toBeDefined();
const transfer = Tx.transfer(
[new Input(outpoint)],
[new Output(500, ADDR_1, 0)]
);
removeInputs(state, transfer);
expect(state.unspent[outpoint.hex()]).toBeUndefined();
expect(state.balances[0][ADDR_1]).toBe(0);
});
test('ERC721', () => {
const color = 2 ** 15 + 1;
const value1 =
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
const value2 =
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa';
const value3 =
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe';
const deposit1 = Tx.deposit(12, value1, ADDR_1, color);
const deposit2 = Tx.deposit(12, value2, ADDR_1, color);
const deposit3 = Tx.deposit(12, value3, ADDR_2, color);
const outpoint1 = new Outpoint(deposit1.hash(), 0);
const outpoint2 = new Outpoint(deposit2.hash(), 0);
const outpoint3 = new Outpoint(deposit3.hash(), 0);
const state = {
balances: {},
owners: {},
unspent: {},
};
addOutputs(state, deposit1);
expect(state.unspent[outpoint1.hex()]).toBeDefined();
expect(state.balances[color][ADDR_1]).toEqual([value1]);
expect(state.owners[color][value1]).toBe(ADDR_1);
addOutputs(state, deposit2);
expect(state.unspent[outpoint2.hex()]).toBeDefined();
expect(state.balances[color][ADDR_1]).toEqual([value1, value2]);
expect(state.owners[color][value2]).toBe(ADDR_1);
addOutputs(state, deposit3);
expect(state.unspent[outpoint3.hex()]).toBeDefined();
expect(state.balances[color][ADDR_2]).toEqual([value3]);
expect(state.owners[color][value3]).toBe(ADDR_2);
const transfer1 = Tx.transfer(
[new Input(outpoint1)],
[new Output(value1, ADDR_1, color)]
);
removeInputs(state, transfer1);
expect(state.unspent[outpoint1.hex()]).toBeUndefined();
expect(state.balances[color][ADDR_1]).toEqual([value2]);
expect(state.owners[color][value1]).toBeUndefined();
const transfer2 = Tx.transfer(
[new Input(outpoint2)],
[new Output(value2, ADDR_1, color)]
);
removeInputs(state, transfer2);
expect(state.unspent[outpoint2.hex()]).toBeUndefined();
expect(state.balances[color][ADDR_1]).toEqual([]);
expect(state.owners[color][value2]).toBeUndefined();
const transfer3 = Tx.transfer(
[new Input(outpoint3)],
[new Output(value3, ADDR_2, color)]
);
removeInputs(state, transfer3);
expect(state.unspent[outpoint3.hex()]).toBeUndefined();
expect(state.balances[color][ADDR_2]).toEqual([]);
expect(state.owners[color][value3]).toBeUndefined();
});
});
});