Skip to content

Commit eb7fecf

Browse files
authored
Merge branch 'master' into feat/leb128-util-improvements
2 parents 60617a2 + 7a0b839 commit eb7fecf

24 files changed

+1002
-258
lines changed

__tests__/integration/configuration/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66

77
fullnode:
88
image:
9-
${HATHOR_LIB_INTEGRATION_TESTS_FULLNODE_IMAGE:-hathornetwork/hathor-core:experimental-nano-testnet-v1.7.3}
9+
${HATHOR_LIB_INTEGRATION_TESTS_FULLNODE_IMAGE:-hathornetwork/hathor-core:experimental-nano-preview-20250428}
1010
command: [
1111
"run_node",
1212
"--listen", "tcp:40404",

__tests__/integration/nanocontracts/bet.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { NATIVE_TOKEN_UID, NANO_CONTRACTS_INITIALIZE_METHOD } from '../../../src
1212
import ncApi from '../../../src/api/nano';
1313
import dateFormatter from '../../../src/utils/date';
1414
import { bufferToHex } from '../../../src/utils/buffer';
15+
import helpersUtils from '../../../src/utils/helpers';
1516
import Address from '../../../src/models/address';
1617
import P2PKH from '../../../src/models/p2pkh';
1718
import P2SH from '../../../src/models/p2sh';
@@ -55,7 +56,15 @@ describe('full cycle of bet nano contract', () => {
5556
await GenesisWalletHelper.clearListeners();
5657
});
5758

58-
const checkTxValid = async (wallet, txId) => {
59+
const checkTxValid = async (wallet, tx) => {
60+
const txId = tx.hash;
61+
// Check that serialization and deserialization match
62+
const network = wallet.getNetworkObject();
63+
const txBytes = tx.toBytes();
64+
const deserializedTx = helpersUtils.createTxFromBytes(txBytes, network);
65+
const deserializedTxBytes = deserializedTx.toBytes();
66+
expect(bufferToHex(txBytes)).toBe(bufferToHex(deserializedTxBytes));
67+
5968
expect(txId).toBeDefined();
6069
await waitForTxReceived(wallet, txId);
6170
// We need to wait for the tx to get a first block, so we guarantee it was executed
@@ -93,7 +102,7 @@ describe('full cycle of bet nano contract', () => {
93102
args: [bufferToHex(oracleData), NATIVE_TOKEN_UID, dateLastBet],
94103
}
95104
);
96-
await checkTxValid(wallet, tx1.hash);
105+
await checkTxValid(wallet, tx1);
97106
const tx1Data = await wallet.getFullTxById(tx1.hash);
98107
expect(isNanoContractCreateTx(tx1Data.tx)).toBe(true);
99108

@@ -165,7 +174,7 @@ describe('full cycle of bet nano contract', () => {
165174
},
166175
],
167176
});
168-
await checkTxValid(wallet, txBet.hash);
177+
await checkTxValid(wallet, txBet);
169178
const txBetData = await wallet.getFullTxById(txBet.hash);
170179
expect(isNanoContractCreateTx(txBetData.tx)).toBe(false);
171180

@@ -213,7 +222,7 @@ describe('full cycle of bet nano contract', () => {
213222
},
214223
],
215224
});
216-
await checkTxValid(wallet, txBet2.hash);
225+
await checkTxValid(wallet, txBet2);
217226
const txBet2Data = await wallet.getFullTxById(txBet2.hash);
218227
expect(isNanoContractCreateTx(txBet2Data.tx)).toBe(false);
219228

@@ -291,7 +300,7 @@ describe('full cycle of bet nano contract', () => {
291300
ncId: tx1.hash,
292301
args: [`${bufferToHex(inputData)},${result},str`],
293302
});
294-
await checkTxValid(wallet, txSetResult.hash);
303+
await checkTxValid(wallet, txSetResult);
295304
txIds.push(txSetResult.hash);
296305
const txSetResultData = await wallet.getFullTxById(txSetResult.hash);
297306
expect(isNanoContractCreateTx(txSetResultData.tx)).toBe(false);
@@ -330,7 +339,7 @@ describe('full cycle of bet nano contract', () => {
330339
},
331340
],
332341
});
333-
await checkTxValid(wallet, txWithdrawal.hash);
342+
await checkTxValid(wallet, txWithdrawal);
334343
txIds.push(txWithdrawal.hash);
335344

336345
const txWithdrawalData = await wallet.getFullTxById(txWithdrawal.hash);

__tests__/wallet/connection.test.ts

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,67 @@ describe('WalletConnection', () => {
4747

4848
describe('websocket transaction events', () => {
4949
const validTransaction = {
50-
tx_id: '00003eeb2ce22e80e0fa72d8afb0b8b01f8919faac94cb3a3b4900782d0f399f',
51-
nonce: 123,
52-
timestamp: Date.now(),
53-
version: 1,
54-
weight: 1,
55-
parents: ['parent1', 'parent2'],
50+
tx_id: '00000e0e193894909fc85dad8a778a8e7904de30362f53b4839e93cc315648e6',
51+
nonce: 16488190,
52+
timestamp: 1745940424,
53+
version: 2,
54+
voided: false,
55+
weight: 17.43270481128759,
56+
parents: [
57+
'000000003a90c27be4093663ef1e1eb1564aa5462f282d86fc062add717b059a',
58+
'0000762414270482d75b7c759d1b8bc7341a884084004042fb70eafe11a01eb6',
59+
],
5660
inputs: [
5761
{
58-
address: 'HH5As5aLtzFkcbmbXZmE65wSd22GqPWq2T',
59-
timelock: null,
60-
type: 'P2PKH',
62+
tx_id: '0000762414270482d75b7c759d1b8bc7341a884084004042fb70eafe11a01eb6',
63+
index: 0,
64+
value: 1n,
65+
token_data: 0,
66+
script: {
67+
type: 'Buffer' as const,
68+
data: [
69+
118, 169, 20, 107, 97, 132, 123, 120, 0, 1, 243, 13, 222, 197, 107, 73, 138, 22, 138,
70+
241, 2, 209, 72, 136, 172,
71+
],
72+
},
73+
token: '00',
74+
decoded: {
75+
type: 'P2PKH',
76+
address: 'HGJuWWGgRQ2roCfcmt5MCBJZx3yMYRz8dq',
77+
timelock: null,
78+
},
6179
},
6280
],
6381
outputs: [
6482
{
65-
address: 'HH5As5aLtzFkcbmbXZmE65wSd22GqPWq2T',
66-
timelock: null,
67-
type: 'P2PKH',
83+
value: 100n,
84+
token_data: 1,
85+
script: {
86+
type: 'Buffer' as const,
87+
data: [
88+
118, 169, 20, 69, 227, 122, 171, 130, 223, 106, 158, 121, 173, 64, 26, 133, 156, 27,
89+
199, 10, 82, 191, 81, 136, 172,
90+
],
91+
},
92+
decodedScript: null,
93+
token: '00000e0e193894909fc85dad8a778a8e7904de30362f53b4839e93cc315648e6',
94+
locked: false,
95+
index: 0,
96+
decoded: {
97+
type: 'P2PKH',
98+
address: 'HCtfX7Pz98ihXjPKCEugFHduVeuHgSXRcy',
99+
timelock: null,
100+
},
68101
},
69102
],
70-
height: 100,
71-
token_name: 'Test Token',
103+
height: 0,
104+
token_name: 'Test',
72105
token_symbol: 'TST',
73-
signal_bits: 1,
74-
voided: false,
106+
signal_bits: 0,
75107
};
76108

77109
const invalidTransaction = {
78-
// Missing required fields
110+
// Missing required fields, this remains a simple invalid object
79111
tx_id: '00003eeb2ce22e80e0fa72d8afb0b8b01f8919faac94cb3a3b4900782d0f399f',
80112
};
81113

__tests__/wallet/wallet.test.ts

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import Mnemonic from 'bitcore-mnemonic';
1010
import { mockAxiosAdapter } from '../__mock_helpers__/axios-adapter.mock';
1111
import HathorWalletServiceWallet from '../../src/wallet/wallet';
1212
import Network from '../../src/models/network';
13-
import { GetAddressesObject, WsTransaction, CreateWalletAuthData } from '../../src/wallet/types';
13+
import {
14+
GetAddressesObject,
15+
WsTransaction,
16+
CreateWalletAuthData,
17+
AddressInfoObject,
18+
} from '../../src/wallet/types';
1419
import config from '../../src/config';
1520
import {
1621
buildSuccessTxByIdTokenDataResponse,
@@ -102,6 +107,106 @@ test('getAddressAtIndex', async () => {
102107
await expect(wallet.getAddressAtIndex(0)).rejects.toThrow('Error getting wallet addresses.');
103108
});
104109

110+
describe('onNewTx', () => {
111+
const requestPassword = jest.fn();
112+
const network = new Network('testnet');
113+
const seed = defaultWalletSeed;
114+
115+
it('should call getNewAddresses if an output address is in newAddresses', async () => {
116+
const wallet = new HathorWalletServiceWallet({
117+
requestPassword,
118+
seed,
119+
network,
120+
});
121+
122+
const testAddress = 'testAddress1';
123+
// @ts-expect-error: Monkey-patching wallet instance
124+
wallet.newAddresses = [
125+
{ address: testAddress, index: 0, addressPath: "m/0'/0/0" },
126+
] as AddressInfoObject[];
127+
128+
const getNewAddressesSpy = jest
129+
// @ts-expect-error: Monkey-patching wallet instance
130+
.spyOn(wallet, 'getNewAddresses')
131+
.mockResolvedValue(undefined);
132+
133+
const newTx: WsTransaction = {
134+
tx_id: 'tx1',
135+
nonce: 0,
136+
timestamp: 0,
137+
signal_bits: 0,
138+
version: 1,
139+
weight: 1,
140+
parents: [],
141+
inputs: [],
142+
outputs: [
143+
{
144+
value: 100n,
145+
token_data: 0,
146+
script: { type: 'Buffer', data: [] },
147+
token: 'HTR',
148+
decoded: {
149+
type: 'P2PKH',
150+
address: testAddress,
151+
timelock: null,
152+
},
153+
locked: false,
154+
index: 0,
155+
},
156+
],
157+
};
158+
159+
await wallet.onNewTx(newTx);
160+
161+
expect(getNewAddressesSpy).toHaveBeenCalled();
162+
});
163+
164+
it('should not call getNewAddresses if no output address is in newAddresses', async () => {
165+
const wallet = new HathorWalletServiceWallet({
166+
requestPassword,
167+
seed,
168+
network,
169+
});
170+
171+
// @ts-expect-error: Monkey-patching newAddresses
172+
wallet.newAddresses = [
173+
{ address: 'otherAddress', index: 0, addressPath: "m/0'/0/0" },
174+
] as AddressInfoObject[];
175+
176+
const getNewAddressesSpy = jest.spyOn(wallet, 'getNewAddresses').mockResolvedValue(undefined);
177+
178+
const newTx: WsTransaction = {
179+
tx_id: 'tx2',
180+
nonce: 0,
181+
timestamp: 0,
182+
signal_bits: 0,
183+
version: 1,
184+
weight: 1,
185+
parents: [],
186+
inputs: [],
187+
outputs: [
188+
{
189+
value: 100n,
190+
token_data: 0,
191+
script: { type: 'Buffer', data: [] },
192+
token: 'HTR',
193+
decoded: {
194+
type: 'P2PKH',
195+
address: 'someRandomAddress',
196+
timelock: null,
197+
},
198+
locked: false,
199+
index: 0,
200+
},
201+
],
202+
};
203+
204+
await wallet.onNewTx(newTx);
205+
206+
expect(getNewAddressesSpy).not.toHaveBeenCalled();
207+
});
208+
});
209+
105210
test('getTxBalance', async () => {
106211
const requestPassword = jest.fn();
107212
const network = new Network('testnet');

0 commit comments

Comments
 (0)