Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improve websocket logs #412

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fae1ef2
feat: addSend with optional utxos argument
r4mmer Aug 23, 2022
e1949a1
feat: calculate balance method
r4mmer Aug 23, 2022
547f28b
feat: calculate authority balance
r4mmer Aug 24, 2022
b41b114
fix: utxo selection
r4mmer Aug 24, 2022
a0d6423
fix: use base58 address
r4mmer Aug 24, 2022
1c180f0
tests: PartialTxProposal tests
r4mmer Aug 26, 2022
4be9aeb
tests: more partialTx proposal tests
r4mmer Aug 27, 2022
63d1b15
chore: increase code coverage
r4mmer Aug 29, 2022
34f4686
chore: change coverage
r4mmer Aug 29, 2022
a3d831b
feat: filter utxos
r4mmer Aug 30, 2022
8693816
feat: addressPath helper
r4mmer Aug 31, 2022
8c0caae
chore: use addressIndex to get addressPath
r4mmer Aug 31, 2022
ce01429
feat: expose bufferUtils
r4mmer Sep 2, 2022
88bb352
feat: track token authority with authorities property
r4mmer Sep 2, 2022
dc9530a
chore: add authorities to constructor
r4mmer Sep 5, 2022
92e2a33
tests: remove tokenData from partial tx constructor
r4mmer Sep 5, 2022
d2aa086
tests: remove tokenData from expected tests
r4mmer Sep 5, 2022
94cff9e
tests: change mock variables
r4mmer Sep 5, 2022
0c5eff3
tests: fix mock methods
r4mmer Sep 5, 2022
f821ef7
tests: integration tests
r4mmer Sep 12, 2022
0496a1c
tests: expect serialized string
r4mmer Sep 12, 2022
a85d068
tests: missing declaration
r4mmer Sep 12, 2022
99947e1
tests: remove expect
r4mmer Sep 12, 2022
b504c85
tests: setStore before signing
r4mmer Sep 12, 2022
0e2f16d
chore: use constants
r4mmer Sep 14, 2022
d3f1133
tests(integration): add balance check for atomic-swap
r4mmer Sep 14, 2022
701a06c
Merge pull request #408 from HathorNetwork/feat/partial-tx-facade
r4mmer Sep 14, 2022
b0dee84
chore: improve websocket logs
luislhl Sep 14, 2022
4dbbf57
chore: bump version v0.40.4 (#413)
r4mmer Sep 15, 2022
fd07dcd
Merge branch 'dev' into chore/improve-websocket-logs
luislhl Sep 15, 2022
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
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
"no-await-in-loop": "off",
"no-plusplus": "off",
"guard-for-in": "off"
"guard-for-in": "off",
"no-bitwise": "off",
},
"overrides": [
{
Expand Down
146 changes: 146 additions & 0 deletions __tests__/integration/atomic_swap.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { GenesisWalletHelper } from './helpers/genesis-wallet.helper';
import {
createTokenHelper,
DEFAULT_PIN_CODE,
generateWalletHelper,
stopAllWallets,
waitForTxReceived,
} from './helpers/wallet.helper';
import { loggers } from './utils/logger.util';
import { HATHOR_TOKEN_CONFIG } from '../../src/constants';
import SendTransaction from '../../src/new/sendTransaction';
import PartialTxProposal from '../../src/wallet/partialTxProposal';
import storage from '../../src/storage';

describe('partial tx proposal', () => {
afterEach(async () => {
await stopAllWallets();
await GenesisWalletHelper.clearListeners();
});

it('Should exchange tokens between wallets', async () => {
// Create the wallet
const hWallet1 = await generateWalletHelper();
const hWallet2 = await generateWalletHelper();
const network = hWallet1.getNetworkObject();

// Injecting funds and creating a new custom token
await GenesisWalletHelper.injectFunds(hWallet1.getAddressAtIndex(0), 103);
const { hash: token1Uid } = await createTokenHelper(
hWallet1,
'Token1',
'TK1',
200,
);

// Injecting funds and creating a new custom token
await GenesisWalletHelper.injectFunds(hWallet2.getAddressAtIndex(0), 10);
const { hash: token2Uid } = await createTokenHelper(
hWallet2,
'Token2',
'TK2',
1000,
);

// Get the balance states before the exchange
const w1HTRBefore = await hWallet1.getBalance(HATHOR_TOKEN_CONFIG.uid);
const w1Tk1Before = await hWallet1.getBalance(token1Uid);
const w1Tk2Before = await hWallet1.getBalance(token2Uid);

const w2HTRBefore = await hWallet2.getBalance(HATHOR_TOKEN_CONFIG.uid);
const w2Tk2Before = await hWallet2.getBalance(token2Uid);
const w2Tk1Before = await hWallet2.getBalance(token1Uid);
loggers.test.log('Balances before', {
wallet1: {
HTR: w1HTRBefore,
Tk1: w1Tk1Before,
Tk2: w1Tk2Before,
},
wallet2: {
HTR: w2HTRBefore,
Tk1: w2Tk1Before,
Tk2: w2Tk2Before,
},
});

/**
* The exchange will be:
*
* Wallet1 will send 100 HTR and 100 TK1
* Wallet2 will send 1000 TK2
*/
const proposal = new PartialTxProposal(network);
// Wallet1 side
proposal.addSend(hWallet1, HATHOR_TOKEN_CONFIG.uid, 100);
proposal.addSend(hWallet1, token1Uid, 100);
proposal.addReceive(hWallet1, token2Uid, 1000);
expect(proposal.partialTx.isComplete()).toBeFalsy();
// Wallet2 side
proposal.addSend(hWallet2, token2Uid, 1000);
proposal.addReceive(hWallet2, HATHOR_TOKEN_CONFIG.uid, 100);
proposal.addReceive(hWallet2, token1Uid, 100);
expect(proposal.partialTx.isComplete()).toBeTruthy();

const serialized = proposal.partialTx.serialize();
const proposal1 = PartialTxProposal.fromPartialTx(serialized, network);
storage.setStore(hWallet1.store);
await proposal1.signData(DEFAULT_PIN_CODE, true);
expect(proposal1.signatures.isComplete()).toBeFalsy();

const proposal2 = PartialTxProposal.fromPartialTx(serialized, network);
storage.setStore(hWallet2.store);
await proposal2.signData(DEFAULT_PIN_CODE, true);

expect(proposal2.signatures.isComplete()).toBeFalsy();

proposal2.signatures.addSignatures(proposal1.signatures.serialize());
expect(proposal2.signatures.isComplete()).toBeTruthy();

const transaction = proposal2.prepareTx();
const sendTransaction = new SendTransaction({ transaction, network });
const tx = await sendTransaction.runFromMining();
expect(tx.hash).toBeDefined();

await waitForTxReceived(hWallet1, tx.hash);

// Get the balance states before the exchange
const w1HTRAfter = await hWallet1.getBalance(HATHOR_TOKEN_CONFIG.uid);
const w1Tk1After = await hWallet1.getBalance(token1Uid);
const w1Tk2After = await hWallet1.getBalance(token2Uid);

const w2HTRAfter = await hWallet2.getBalance(HATHOR_TOKEN_CONFIG.uid);
const w2Tk2After = await hWallet2.getBalance(token2Uid);
const w2Tk1After = await hWallet2.getBalance(token1Uid);

loggers.test.log('Balances after', {
wallet1: {
HTR: w1HTRAfter,
Tk1: w1Tk1After,
Tk2: w1Tk2After,
},
wallet2: {
HTR: w2HTRAfter,
Tk1: w2Tk1After,
Tk2: w2Tk2After,
},
});

// Check balance HTR
expect(w1HTRAfter[0].balance.unlocked - w1HTRBefore[0].balance.unlocked).toEqual(-100);
expect(w1HTRAfter[0].balance.locked - w1HTRBefore[0].balance.locked).toEqual(0);
expect(w2HTRAfter[0].balance.unlocked - w2HTRBefore[0].balance.unlocked).toEqual(100);
expect(w2HTRAfter[0].balance.locked - w2HTRBefore[0].balance.locked).toEqual(0);

// Check balance token1
expect(w1Tk1After[0].balance.unlocked - w1Tk1Before[0].balance.unlocked).toEqual(-100);
expect(w1Tk1After[0].balance.locked - w1Tk1Before[0].balance.locked).toEqual(0);
expect(w2Tk1After[0].balance.unlocked - w2Tk1Before[0].balance.unlocked).toEqual(100);
expect(w2Tk1After[0].balance.locked - w2Tk1Before[0].balance.locked).toEqual(0);

// Check balance token2
expect(w1Tk2After[0].balance.unlocked - w1Tk2Before[0].balance.unlocked).toEqual(1000);
expect(w1Tk2After[0].balance.locked - w1Tk2Before[0].balance.locked).toEqual(0);
expect(w2Tk2After[0].balance.unlocked - w2Tk2Before[0].balance.unlocked).toEqual(-1000);
expect(w2Tk2After[0].balance.locked - w2Tk2Before[0].balance.locked).toEqual(0);
});
});
55 changes: 32 additions & 23 deletions __tests__/models/partial_tx.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ import dateFormatter from '../../src/date';


import { UnsupportedScriptError } from '../../src/errors';
import { HATHOR_TOKEN_CONFIG, DEFAULT_TX_VERSION, TOKEN_AUTHORITY_MASK } from '../../src/constants';
import {
HATHOR_TOKEN_CONFIG,
DEFAULT_TX_VERSION,
TOKEN_AUTHORITY_MASK,
TOKEN_MINT_MASK,
TOKEN_MELT_MASK,
} from '../../src/constants';
import helpers from '../../src/utils/helpers';
import txApi from '../../src/api/txApi';
import P2PKH from '../../src/models/p2pkh';
Expand Down Expand Up @@ -132,11 +138,11 @@ describe('PartialTx.isComplete', () => {
expect(partialTx.isComplete()).toBe(false);

// Outputs have less than inputs for 1 token
partialTx.outputs.push(new ProposalOutput(1, Buffer.from([]), { token: '1', tokenData: 1 }));
partialTx.outputs.push(new ProposalOutput(1, Buffer.from([]), { token: '1' }));
expect(partialTx.isComplete()).toBe(false);

// Outputs have more than inputs for 1 token
partialTx.outputs.push(new ProposalOutput(2, Buffer.from([]), { token: '2', tokenData: 2 }));
partialTx.outputs.push(new ProposalOutput(2, Buffer.from([]), { token: '2' }));
expect(partialTx.isComplete()).toBe(false);

// Missing token from inputs
Expand Down Expand Up @@ -178,7 +184,7 @@ describe('PartialTx.isComplete', () => {
new ProposalOutput(1, Buffer.from([])),
new ProposalOutput(1, Buffer.from([]), { token: '2' }),
// Add authority output for token 2
new ProposalOutput(1, Buffer.from([]), { token: '2', tokenData: TOKEN_AUTHORITY_MASK | 1 }),
new ProposalOutput(1, Buffer.from([]), { token: '2', authorities: TOKEN_MINT_MASK }),
];

expect(partialTx.isComplete()).toBe(true);
Expand All @@ -192,16 +198,19 @@ describe('PartialTx.addInput', () => {
const partialTx = new PartialTx(testnet);
const expected = []

expected.push(expect.objectContaining({ hash: 'hash1', index: 0, token: '1', tokenData: 1, value: 1, address: 'W123' }));
partialTx.addInput('hash1', 0, 1, 'W123', { token: '1', tokenData: 1 });
// Passing all optional arguments
expected.push(expect.objectContaining({ hash: 'hash1', index: 0, token: '1', authorities: 0, value: 1, address: 'W123' }));
partialTx.addInput('hash1', 0, 1, 'W123', { token: '1', authorities: 0 });
expect(partialTx.inputs).toEqual(expected);

expected.push(expect.objectContaining({ hash: 'hash2', index: 1, token: '00', tokenData: 0, value: 27, address: 'Wabc' }));
// Default options, HTR
expected.push(expect.objectContaining({ hash: 'hash2', index: 1, token: '00', authorities: 0, value: 27, address: 'Wabc' }));
partialTx.addInput('hash2', 1, 27, 'Wabc');
expect(partialTx.inputs).toEqual(expected);

expected.push(expect.objectContaining({ hash: 'hash3', index: 10, token: '1', tokenData: TOKEN_AUTHORITY_MASK | 3, value: 1056, address: 'W1b3' }));
partialTx.addInput('hash3', 10, 1056, 'W1b3', { token: '1', tokenData: TOKEN_AUTHORITY_MASK | 3 });
// Authority input
expected.push(expect.objectContaining({ hash: 'hash3', index: 10, token: '1', authorities: TOKEN_MINT_MASK | TOKEN_MELT_MASK, value: 1056, address: 'W1b3' }));
partialTx.addInput('hash3', 10, 1056, 'W1b3', { token: '1', authorities: TOKEN_MINT_MASK | TOKEN_MELT_MASK });
expect(partialTx.inputs).toEqual(expected);
});
});
Expand All @@ -220,17 +229,17 @@ describe('PartialTx.addOutput', () => {
isChange: true,
value: 27,
script: expect.toMatchBuffer(Buffer.from([230, 148, 32])),
tokenData: 128,
authorities: TOKEN_MELT_MASK,
}));
partialTx.addOutput(27, Buffer.from([230, 148, 32]), { token: '1', tokenData: 128, isChange: true});
partialTx.addOutput(27, Buffer.from([230, 148, 32]), { token: '1', authorities: TOKEN_MELT_MASK, isChange: true});
expect(partialTx.outputs).toEqual(expected);

expected.push(expect.objectContaining({
token: '2',
isChange: false,
value: 72,
script: expect.toMatchBuffer(Buffer.from([1, 2, 3])),
tokenData: 0,
authorities: 0,
}));
partialTx.addOutput(72, Buffer.from([1, 2, 3]), { token: '2' });
expect(partialTx.outputs).toEqual(expected);
Expand Down Expand Up @@ -272,14 +281,14 @@ describe('PartialTx serialization', () => {
};

it('should serialize a transaction correctly', async () => {
const expected = 'PartialTx|00010102030000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c00000d906babfa76b092f0088530a85f4d6bae5437304820f4c7a39540d87dd00000000000584ed8ad32b00e79e1c5cf26b5969ca7cd4d93ae39b776e71cfecf7c8c780400000000000f00001976a914729181c0f3f2e3f589cc10facbb9332e0c309a7788ac0000000d01001976a9146861143f7dc6b2f9c8525315efe6fcda160a795c88ac0000000c00001976a914486bc4f1e70f242a737d3866147c7f8335c2995f88ac0000000000000000000000010000000000|WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,00,0,1b:WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,0000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c,1,d|1:2';
const expected = 'PartialTx|00010102030000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c00000d906babfa76b092f0088530a85f4d6bae5437304820f4c7a39540d87dd00000000000584ed8ad32b00e79e1c5cf26b5969ca7cd4d93ae39b776e71cfecf7c8c780400000000000f00001976a914729181c0f3f2e3f589cc10facbb9332e0c309a7788ac0000000d01001976a9146861143f7dc6b2f9c8525315efe6fcda160a795c88ac0000000c00001976a914486bc4f1e70f242a737d3866147c7f8335c2995f88ac0000000000000000000000010000000000|WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,00,0,1b:WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,0000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c,0,d|1:2';

const partialTx = new PartialTx(testnet);

const address = 'WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi';
partialTx.inputs = [
new ProposalInput(txId1, 0, 27, address, { token: HATHOR_TOKEN_CONFIG.uid }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid }),
];
partialTx.outputs = [
new ProposalOutput(15, scriptFromAddressP2PKH('WZ7pDnkPnxbs14GHdUFivFzPbzitwNtvZo')),
Expand All @@ -292,7 +301,7 @@ describe('PartialTx serialization', () => {
});

it('should deserialize a transaction correctly', () => {
const serialized = 'PartialTx|00010102030000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c00000d906babfa76b092f0088530a85f4d6bae5437304820f4c7a39540d87dd00000000000584ed8ad32b00e79e1c5cf26b5969ca7cd4d93ae39b776e71cfecf7c8c780400000000000f00001976a914729181c0f3f2e3f589cc10facbb9332e0c309a7788ac0000000d01001976a9146861143f7dc6b2f9c8525315efe6fcda160a795c88ac0000000c00001976a914486bc4f1e70f242a737d3866147c7f8335c2995f88ac0000000000000000000000010000000000|WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,00,0,1b:WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,0000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c,1,d|1:2';
const serialized = 'PartialTx|00010102030000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c00000d906babfa76b092f0088530a85f4d6bae5437304820f4c7a39540d87dd00000000000584ed8ad32b00e79e1c5cf26b5969ca7cd4d93ae39b776e71cfecf7c8c780400000000000f00001976a914729181c0f3f2e3f589cc10facbb9332e0c309a7788ac0000000d01001976a9146861143f7dc6b2f9c8525315efe6fcda160a795c88ac0000000c00001976a914486bc4f1e70f242a737d3866147c7f8335c2995f88ac0000000000000000000000010000000000|WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,00,0,1b:WVGxdgZMHkWo2Hdrb1sEFedNdjTXzjvjPi,0000389deaf5557642e5a8a26656dcf360b608160f43e7ef79b9bde8ab69a18c,0,d|1:2';
const partialTx = PartialTx.deserialize(serialized, testnet);
expect(partialTx.serialize()).toBe(serialized);
});
Expand All @@ -306,7 +315,7 @@ describe('PartialTx serialization', () => {

partialTx.inputs = [
new ProposalInput(txId1, 0, 27, address, { token: HATHOR_TOKEN_CONFIG.uid }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid }),
];
const partialOnlyInputs = PartialTx.deserialize(partialTx.serialize(), testnet);
expect(partialOnlyInputs.serialize()).toEqual(partialTx.serialize());
Expand All @@ -322,7 +331,7 @@ describe('PartialTx serialization', () => {

partialTx.inputs = [
new ProposalInput(txId1, 0, 27, address, { token: HATHOR_TOKEN_CONFIG.uid }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, address, { token: testTokenConfig.uid }),
];
const partialFull = PartialTx.deserialize(partialTx.serialize(), testnet);
expect(partialFull.serialize()).toEqual(partialTx.serialize());
Expand Down Expand Up @@ -416,7 +425,7 @@ describe('PartialTx.validate', () => {
const partialTx = new PartialTx(testnet);
partialTx.inputs = [
new ProposalInput(txId1, 0, 27, addr1),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid }),
];
partialTx.outputs = [
new ProposalOutput(15, scriptFromAddressP2PKH(addr2)),
Expand All @@ -427,7 +436,7 @@ describe('PartialTx.validate', () => {
await expect(partialTx.validate()).resolves.toEqual(true);
});

it('should return false if an address, value, token or tokenData is wrong', async () => {
it('should return false if an address, value, token or authorities are wrong', async () => {
spy.mockImplementation(async (txId, cb) => {
return new Promise(resolve => {
process.nextTick(() => {
Expand All @@ -440,7 +449,7 @@ describe('PartialTx.validate', () => {
// Address of inputs[1] is wrong
partialTx.inputs = [
new ProposalInput(txId1, 0, 27, addr1),
new ProposalInput(txId2, 4, 13, addr1, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, addr1, { token: testTokenConfig.uid }),
];
partialTx.outputs = [
new ProposalOutput(15, scriptFromAddressP2PKH(addr2)),
Expand All @@ -453,23 +462,23 @@ describe('PartialTx.validate', () => {
// Value of inputs[0] is wrong
partialTx.inputs = [
new ProposalInput(txId1, 0, 28, addr1),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid }),
];

await expect(partialTx.validate()).resolves.toEqual(false);

// TokenData of inputs[1] is wrong
partialTx.inputs = [
new ProposalInput(txId1, 0, 27, addr1),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid, tokenData: 2 }),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid, authorities: TOKEN_MELT_MASK }),
];

await expect(partialTx.validate()).resolves.toEqual(false);

// Token of inputs[0] is wrong
partialTx.inputs = [
new ProposalInput(txId1, 0, 27, addr1, { token: testTokenConfig }),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid, tokenData: 1 }),
new ProposalInput(txId2, 4, 13, addr2, { token: testTokenConfig.uid }),
];

await expect(partialTx.validate()).resolves.toEqual(false);
Expand Down
File renamed without changes.
Loading