Skip to content

Commit

Permalink
Merge pull request #496 from HathorNetwork/release-candidate
Browse files Browse the repository at this point in the history
v0.32.0
  • Loading branch information
r4mmer authored Sep 27, 2024
2 parents c24cde5 + 018aac1 commit de5b233
Show file tree
Hide file tree
Showing 16 changed files with 604 additions and 34 deletions.
1 change: 1 addition & 0 deletions __tests__/__fixtures__/ws-fixtures.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
capabilities: { capabilities: ['history-streaming'] },
dashboard: {
transactions: 2,
blocks: 1537,
Expand Down
7 changes: 5 additions & 2 deletions __tests__/history-sync.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { initializedWallets } from '../src/services/wallets.service';
const walletId = 'stub_history_sync';

describe('history sync', () => {
beforeEach(() => {
settings._resetConfig();
});

afterEach(async () => {
await TestUtils.stopWallet({ walletId });
});
Expand All @@ -27,11 +31,11 @@ describe('history sync', () => {
const response = await TestUtils.request
.post('/start')
.send({ seedKey: TestUtils.seedKey, 'wallet-id': walletId });
settings._resetConfig();
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
const wallet = initializedWallets.get(walletId);
expect(wallet.historySyncMode).toEqual(hathorLib.HistorySyncMode.MANUAL_STREAM_WS);
await TestUtils.stopWallet({ walletId });
});

it('should use the history sync from the request when provided', async () => {
Expand All @@ -45,7 +49,6 @@ describe('history sync', () => {
'wallet-id': walletId,
history_sync_mode: 'xpub_stream_ws',
});
settings._resetConfig();
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
const wallet = initializedWallets.get(walletId);
Expand Down
179 changes: 179 additions & 0 deletions __tests__/mark_utxos_selected_as_input.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { Storage, Transaction, Input, Output } from '@hathor/wallet-lib';
import TestUtils from './test-utils';

const walletId = 'stub_mark_inputs_as_used';

function createCustomTxHex() {
const txId0 = '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74';
const txId1 = 'fb2fbe0385bc0bc8e9a255a8d530f7b3bdcebcd5ccdae5e154e6c3d57cbcd143';
const txId2 = '11835fae291c60fc58314c61d27dc644b9e029c363bbe458039b2b0186144275';
const tx = new Transaction(
[new Input(txId0, 0), new Input(txId1, 1), new Input(txId2, 2)],
[new Output(100, Buffer.from('0463616665ac', 'hex'))],
{
timestamp: 123,
parents: ['f6c83e3641a08ec21aebc01296ff12f5a46780f0fbadb1c8101309123b95d2c6'],
},
);

return tx.toHex();
}

describe('mark utxos selected_as_input api', () => {
let selectSpy;
const txHex = createCustomTxHex();

beforeAll(async () => {
selectSpy = jest.spyOn(Storage.prototype, 'utxoSelectAsInput');
await TestUtils.startWallet({ walletId });
});

beforeEach(() => {
selectSpy.mockReset();
selectSpy.mockImplementation(jest.fn(async () => {}));
});

afterAll(async () => {
selectSpy.mockRestore();
await TestUtils.stopWallet({ walletId });
});

it('should fail if txHex is not a hex string', async () => {
let response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex: 123 })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);

response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex: '0123g' })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);
expect(selectSpy).toHaveBeenCalledTimes(0);
});

it('should fail if mark is not a boolean', async () => {
let response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: '123' })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);

response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: 123 })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);

response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: 'abc' })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);
});

it('should fail if ttl is not a number', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, ttl: '123a' })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);
});

it('should fail if txHex is an invalid transaction', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex: '0123456789abcdef' })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(false);
expect(selectSpy).toHaveBeenCalledTimes(0);
});

it('should mark the inputs as selected on the storage', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);

expect(selectSpy).toHaveBeenCalledTimes(3);
expect(selectSpy).toHaveBeenCalledWith(
{ index: 0, txId: '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74' },
true,
null,
);
});

it('should mark the inputs as selected on the storage with ttl', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, ttl: 123 })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);

expect(selectSpy).toHaveBeenCalledTimes(3);
expect(selectSpy).toHaveBeenCalledWith(
{ index: 0, txId: '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74' },
true,
123,
);
});

it('should mark the inputs as selected on the storage with mark false', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: false })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);

expect(selectSpy).toHaveBeenCalledTimes(3);
expect(selectSpy).toHaveBeenCalledWith(
{ index: 0, txId: '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74' },
false,
null,
);
});

it('should mark the inputs as selected on the storage with mark true', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: true })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);

expect(selectSpy).toHaveBeenCalledTimes(3);
expect(selectSpy).toHaveBeenCalledWith(
{ index: 0, txId: '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74' },
true,
null,
);
});

it('should mark the inputs as selected on the storage with all options', async () => {
const response = await TestUtils.request
.put('/wallet/utxos-selected-as-input')
.send({ txHex, mark_as_used: false, ttl: 456 })
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);

expect(selectSpy).toHaveBeenCalledTimes(3);
expect(selectSpy).toHaveBeenCalledWith(
{ index: 0, txId: '5db0a8c77f818c51cb107532fc1a36785adfa700d81d973fd1f23438b2f3dd74' },
false,
456,
);
});
});
26 changes: 26 additions & 0 deletions __tests__/p2sh/tx-proposal-create.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,30 @@ describe('create tx-proposal api', () => {
expect(response.status).toBe(200);
expect(response.body.success).toBe(false);
});

it('should mark utxos as used when sending mark_inputs_as_used', async () => {
const markSpy = jest.spyOn(hathorLib.Storage.prototype, 'utxoSelectAsInput').mockImplementation(jest.fn(async () => {}));
try {
const response = await TestUtils.request
.post('/wallet/p2sh/tx-proposal')
.send({
outputs: [
{ address: 'WPynsVhyU6nP7RSZAkqfijEutC88KgAyFc', value: 1 },
{ address: 'wcUZ6J7t2B1s8bqRYiyuZAftcdCGRSiiau', value: 1 },
],
mark_inputs_as_used: true,
})
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.txHex).toBeDefined();
expect(response.body.success).toBe(true);
const tx = hathorLib.helpersUtils.createTxFromHex(response.body.txHex, new hathorLib.Network('testnet'));
expect(tx.outputs.map(o => o.decodedScript.address.base58))
.toEqual(expect.arrayContaining(['WPynsVhyU6nP7RSZAkqfijEutC88KgAyFc', 'wcUZ6J7t2B1s8bqRYiyuZAftcdCGRSiiau']));

expect(markSpy).toHaveBeenCalledTimes(1);
} finally {
markSpy.mockRestore();
}
});
});
25 changes: 25 additions & 0 deletions __tests__/p2sh/tx-proposal-melt-tokens.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,29 @@ describe('melt-tokens tx-proposal api', () => {
});
}
});

it('should mark utxos as used when sending mark_inputs_as_used', async () => {
const markSpy = jest.spyOn(hathorLib.Storage.prototype, 'utxoSelectAsInput').mockImplementation(jest.fn(async () => {}));
try {
const response = await TestUtils.request
.post('/wallet/p2sh/tx-proposal/melt-tokens')
.send({
token: '0000073b972162f70061f61cf0082b7a47263cc1659a05976aca5cd01b3351ee',
amount: 1,
mark_inputs_as_used: true,
})
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.txHex).toBeDefined();
const tx = hathorLib.helpersUtils
.createTxFromHex(response.body.txHex, new hathorLib.Network('testnet'));
expect(tx.outputs.map(o => o.decodedScript.address.base58))
.toEqual(expect.arrayContaining(['wbe2eJdyZVimA7nJjmBQnKYJSXmpnpMKgG']));

expect(markSpy).toHaveBeenCalledTimes(2);
} finally {
markSpy.mockRestore();
}
});
});
30 changes: 30 additions & 0 deletions __tests__/p2sh/tx-proposal-mint-tokens.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,34 @@ describe('mint-tokens tx-proposal api', () => {
expect(authorityOutputs).toHaveLength(1);
expect(authorityOutputs[0].value).toBe(AUTHORITY_VALUE.MINT);
});

it('should mark utxos as used when sending mark_inputs_as_used', async () => {
const markSpy = jest.spyOn(hathorLib.Storage.prototype, 'utxoSelectAsInput').mockImplementation(jest.fn(async () => {}));
try {
const response = await TestUtils.request
.post('/wallet/p2sh/tx-proposal/mint-tokens')
.send({
token: '0000073b972162f70061f61cf0082b7a47263cc1659a05976aca5cd01b3351ee',
amount: 1,
mark_inputs_as_used: true,
})
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.txHex).toBeDefined();
const tx = hathorLib.helpersUtils
.createTxFromHex(response.body.txHex, new hathorLib.Network('testnet'));
expect(tx.outputs.map(o => o.decodedScript.address.base58))
.toEqual(expect.arrayContaining(['wbe2eJdyZVimA7nJjmBQnKYJSXmpnpMKgG']));
expect(tx.inputs).toEqual(expect.not.arrayContaining([
expect.objectContaining({
data: expect.any(Object),
}),
]));

expect(markSpy).toHaveBeenCalledTimes(2);
} finally {
markSpy.mockRestore();
}
});
});
30 changes: 30 additions & 0 deletions __tests__/p2sh/tx-proposal-new-token.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -440,4 +440,34 @@ describe('create-token tx-proposal api', () => {
expect(authorityOutputs[0].value).toBe(AUTHORITY_VALUE.MINT);
expect(authorityOutputs[1].value).toBe(AUTHORITY_VALUE.MELT);
});

it('should mark utxos as used when sending mark_inputs_as_used', async () => {
const markSpy = jest.spyOn(hathorLib.Storage.prototype, 'utxoSelectAsInput').mockImplementation(jest.fn(async () => {}));
try {
const response = await TestUtils.request
.post('/wallet/p2sh/tx-proposal/create-token')
.send({
name: 'My Custom Token',
symbol: 'MCT',
amount: 1,
mark_inputs_as_used: true,
})
.set({ 'x-wallet-id': walletId });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.txHex).toBeDefined();
const tx = hathorLib.helpersUtils.createTxFromHex(response.body.txHex, new hathorLib.Network('testnet'));
expect(tx.outputs.map(o => o.decodedScript.address.base58))
.toEqual(expect.arrayContaining([TestUtils.multisigAddresses[1]]));
expect(tx.inputs).toEqual(expect.not.arrayContaining([
expect.objectContaining({
data: expect.any(Object),
}),
]));

expect(markSpy).toHaveBeenCalledTimes(1);
} finally {
markSpy.mockRestore();
}
});
});
Loading

0 comments on commit de5b233

Please sign in to comment.