Skip to content

Commit 49fb08c

Browse files
authored
Merge pull request #479 from NEMStudios/mosaicNonceImprovements
Changed dto mappers to map nonce as a decimal int.
2 parents d2c502d + 963db2d commit 49fb08c

18 files changed

+272
-176
lines changed

e2e/infrastructure/AccountHttp.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,12 @@ describe('AccountHttp', () => {
228228
describe('transactions', () => {
229229
it('should call transactions successfully by type', async () => {
230230
const transactions = await accountRepository.getAccountTransactions(
231-
publicAccount.address, new QueryParams(), new TransactionFilter({ types: [TransactionType.TRANSFER] })).toPromise();
231+
publicAccount.address, new QueryParams(), new TransactionFilter({
232+
types: [TransactionType.TRANSFER, TransactionType.AGGREGATE_COMPLETE],
233+
})).toPromise();
232234
expect(transactions.length).to.be.greaterThan(0);
233235
transactions.forEach((t) => {
234-
expect(t.type).to.be.eq(TransactionType.TRANSFER);
236+
expect((t.type === TransactionType.TRANSFER || t.type === TransactionType.AGGREGATE_COMPLETE)).to.be.eq(true);
235237
});
236238
});
237239
});

e2e/infrastructure/MosaicHttp.spec.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,32 @@ describe('MosaicHttp', () => {
6565
*/
6666
describe('Setup test MosaicId', () => {
6767

68-
it('Announce MosaicDefinitionTransaction', () => {
69-
const nonce = MosaicNonce.createRandom();
68+
it('Announce MosaicDefinitionTransaction', async () => {
69+
const nonce = MosaicNonce.createFromNumber(-1501238750);
70+
expect(nonce.toDTO()).to.be.equals(2793728546);
71+
expect(nonce.toHex()).to.be.equals('22EA84A6');
7072
mosaicId = MosaicId.createFromNonce(nonce, account.publicAccount);
7173
const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
7274
Deadline.create(),
7375
nonce,
7476
mosaicId,
7577
MosaicFlags.create(true, true, false),
7678
3,
77-
UInt64.fromUint(0),
79+
UInt64.fromUint(100),
7880
networkType,
7981
helper.maxFee,
8082
);
8183
const signedTransaction = mosaicDefinitionTransaction.signWith(account, generationHash);
8284

83-
return helper.announce(signedTransaction);
85+
const listenedTransaction = await helper.announce(signedTransaction) as MosaicDefinitionTransaction;
86+
expect(mosaicDefinitionTransaction.nonce.toHex()).to.be.equal(listenedTransaction.nonce.toHex());
87+
expect(mosaicDefinitionTransaction.nonce).to.deep.equal(listenedTransaction.nonce);
88+
expect(mosaicDefinitionTransaction.getMosaicNonceIntValue()).to.be.equal(listenedTransaction.getMosaicNonceIntValue());
89+
90+
const savedTransaction = await helper.repositoryFactory.createTransactionRepository().getTransaction(signedTransaction.hash).toPromise() as MosaicDefinitionTransaction;
91+
expect(mosaicDefinitionTransaction.nonce.toHex()).to.be.equal(savedTransaction.nonce.toHex());
92+
expect(mosaicDefinitionTransaction.nonce).to.deep.equal(savedTransaction.nonce);
93+
expect(mosaicDefinitionTransaction.getMosaicNonceIntValue()).to.be.equal(savedTransaction.getMosaicNonceIntValue());
8494
});
8595
});
8696

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/format/Convert.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,31 @@ export class Convert {
229229
}
230230
return Convert.uint8ToHex(Uint8Array.from(delta));
231231
}
232+
233+
/**
234+
* It splits the number's bytes into a an array.
235+
* @param number the number
236+
* @param arraySize the expected size of the array.
237+
*/
238+
public static numberToUint8Array(number: number, arraySize: number): Uint8Array {
239+
const uint8Array = new Uint8Array(arraySize);
240+
for (let index = 0; index < uint8Array.length; index++) {
241+
const byte = number & 0xff;
242+
uint8Array [index] = byte;
243+
number = (number - byte) / 256;
244+
}
245+
return uint8Array;
246+
}
247+
248+
/**
249+
* It creates a number from the bytes in the array.
250+
* @param array the number from the bytes.
251+
*/
252+
public static uintArray8ToNumber(array: Uint8Array): number {
253+
let value = 0;
254+
for (let index = 0; index < array.length; index++) {
255+
value += array[index] << (index * 8);
256+
}
257+
return value >>> 0;
258+
}
232259
}

src/infrastructure/Http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ export abstract class Http {
6565
}
6666

6767
errorHandling(error: any): Error {
68-
if (error.response && error.response.statusCode && error.body) {
68+
if (error.response && error.response.statusCode && error.response.body) {
6969
const formattedError = {
7070
statusCode: error.response.statusCode,
7171
errorDetails: {
7272
statusCode: error.response.statusCode,
7373
statusMessage: error.response.statusMessage,
7474
},
75-
body: error.body,
75+
body: error.response.body,
7676
};
7777
return new Error(JSON.stringify(formattedError));
7878
}

src/infrastructure/transaction/CreateTransactionFromDTO.ts

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,47 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import {Convert as convert} from '../../core/format';
16+
import { Convert as convert } from '../../core/format';
1717
import { UnresolvedMapping } from '../../core/utils/UnresolvedMapping';
18-
import {Address} from '../../model/account/Address';
19-
import {PublicAccount} from '../../model/account/PublicAccount';
20-
import {NetworkType} from '../../model/blockchain/NetworkType';
18+
import { Address } from '../../model/account/Address';
19+
import { PublicAccount } from '../../model/account/PublicAccount';
2120
import { EncryptedMessage } from '../../model/message/EncryptedMessage';
2221
import { MessageType } from '../../model/message/MessageType';
2322
import { PersistentHarvestingDelegationMessage } from '../../model/message/PersistentHarvestingDelegationMessage';
24-
import {EmptyMessage, PlainMessage} from '../../model/message/PlainMessage';
25-
import {Mosaic} from '../../model/mosaic/Mosaic';
26-
import {MosaicFlags} from '../../model/mosaic/MosaicFlags';
27-
import {MosaicId} from '../../model/mosaic/MosaicId';
23+
import { EmptyMessage, PlainMessage } from '../../model/message/PlainMessage';
24+
import { Mosaic } from '../../model/mosaic/Mosaic';
25+
import { MosaicFlags } from '../../model/mosaic/MosaicFlags';
26+
import { MosaicId } from '../../model/mosaic/MosaicId';
2827
import { MosaicNonce } from '../../model/mosaic/MosaicNonce';
29-
import {NamespaceId} from '../../model/namespace/NamespaceId';
30-
import {AccountAddressRestrictionTransaction} from '../../model/transaction/AccountAddressRestrictionTransaction';
28+
import { NamespaceId } from '../../model/namespace/NamespaceId';
29+
import { AccountAddressRestrictionTransaction } from '../../model/transaction/AccountAddressRestrictionTransaction';
3130
import { AccountLinkTransaction } from '../../model/transaction/AccountLinkTransaction';
3231
import { AccountMetadataTransaction } from '../../model/transaction/AccountMetadataTransaction';
33-
import {AccountMosaicRestrictionTransaction} from '../../model/transaction/AccountMosaicRestrictionTransaction';
34-
import {AccountOperationRestrictionTransaction} from '../../model/transaction/AccountOperationRestrictionTransaction';
35-
import {AddressAliasTransaction} from '../../model/transaction/AddressAliasTransaction';
36-
import {AggregateTransaction} from '../../model/transaction/AggregateTransaction';
37-
import {AggregateTransactionCosignature} from '../../model/transaction/AggregateTransactionCosignature';
38-
import {AggregateTransactionInfo} from '../../model/transaction/AggregateTransactionInfo';
39-
import {Deadline} from '../../model/transaction/Deadline';
40-
import {LockFundsTransaction} from '../../model/transaction/LockFundsTransaction';
32+
import { AccountMosaicRestrictionTransaction } from '../../model/transaction/AccountMosaicRestrictionTransaction';
33+
import { AccountOperationRestrictionTransaction } from '../../model/transaction/AccountOperationRestrictionTransaction';
34+
import { AddressAliasTransaction } from '../../model/transaction/AddressAliasTransaction';
35+
import { AggregateTransaction } from '../../model/transaction/AggregateTransaction';
36+
import { AggregateTransactionCosignature } from '../../model/transaction/AggregateTransactionCosignature';
37+
import { AggregateTransactionInfo } from '../../model/transaction/AggregateTransactionInfo';
38+
import { Deadline } from '../../model/transaction/Deadline';
39+
import { LockFundsTransaction } from '../../model/transaction/LockFundsTransaction';
4140
import { MosaicAddressRestrictionTransaction } from '../../model/transaction/MosaicAddressRestrictionTransaction';
42-
import {MosaicAliasTransaction} from '../../model/transaction/MosaicAliasTransaction';
43-
import {MosaicDefinitionTransaction} from '../../model/transaction/MosaicDefinitionTransaction';
41+
import { MosaicAliasTransaction } from '../../model/transaction/MosaicAliasTransaction';
42+
import { MosaicDefinitionTransaction } from '../../model/transaction/MosaicDefinitionTransaction';
4443
import { MosaicGlobalRestrictionTransaction } from '../../model/transaction/MosaicGlobalRestrictionTransaction';
4544
import { MosaicMetadataTransaction } from '../../model/transaction/MosaicMetadataTransaction';
46-
import {MosaicSupplyChangeTransaction} from '../../model/transaction/MosaicSupplyChangeTransaction';
47-
import {MultisigAccountModificationTransaction} from '../../model/transaction/MultisigAccountModificationTransaction';
45+
import { MosaicSupplyChangeTransaction } from '../../model/transaction/MosaicSupplyChangeTransaction';
46+
import { MultisigAccountModificationTransaction } from '../../model/transaction/MultisigAccountModificationTransaction';
4847
import { NamespaceMetadataTransaction } from '../../model/transaction/NamespaceMetadataTransaction';
49-
import {NamespaceRegistrationTransaction} from '../../model/transaction/NamespaceRegistrationTransaction';
50-
import {SecretLockTransaction} from '../../model/transaction/SecretLockTransaction';
51-
import {SecretProofTransaction} from '../../model/transaction/SecretProofTransaction';
52-
import {SignedTransaction} from '../../model/transaction/SignedTransaction';
53-
import {Transaction} from '../../model/transaction/Transaction';
54-
import {TransactionInfo} from '../../model/transaction/TransactionInfo';
55-
import {TransactionType} from '../../model/transaction/TransactionType';
56-
import {TransferTransaction} from '../../model/transaction/TransferTransaction';
57-
import {UInt64} from '../../model/UInt64';
48+
import { NamespaceRegistrationTransaction } from '../../model/transaction/NamespaceRegistrationTransaction';
49+
import { SecretLockTransaction } from '../../model/transaction/SecretLockTransaction';
50+
import { SecretProofTransaction } from '../../model/transaction/SecretProofTransaction';
51+
import { SignedTransaction } from '../../model/transaction/SignedTransaction';
52+
import { Transaction } from '../../model/transaction/Transaction';
53+
import { TransactionInfo } from '../../model/transaction/TransactionInfo';
54+
import { TransactionType } from '../../model/transaction/TransactionType';
55+
import { TransferTransaction } from '../../model/transaction/TransferTransaction';
56+
import { UInt64 } from '../../model/UInt64';
5857

5958
// tslint:disable: no-use-before-declare
6059
/**
@@ -161,7 +160,7 @@ const CreateStandaloneTransactionFromDTO = (transactionDTO, transactionInfo): Tr
161160
transactionDTO.version,
162161
Deadline.createFromDTO(transactionDTO.deadline),
163162
UInt64.fromNumericString(transactionDTO.maxFee || '0'),
164-
MosaicNonce.createFromHex(transactionDTO.nonce.toString(16)),
163+
MosaicNonce.createFromNumber(transactionDTO.nonce),
165164
new MosaicId(transactionDTO.id),
166165
new MosaicFlags(transactionDTO.flags),
167166
transactionDTO.divisibility,

src/model/mosaic/MosaicId.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
* limitations under the License.
1515
*/
1616
import { Convert as convert, RawUInt64 as uint64_t } from '../../core/format';
17-
import {NamespaceMosaicIdGenerator} from '../../infrastructure/transaction/NamespaceMosaicIdGenerator';
18-
import {PublicAccount} from '../account/PublicAccount';
19-
import {Id} from '../Id';
20-
import {MosaicNonce} from '../mosaic/MosaicNonce';
17+
import { NamespaceMosaicIdGenerator } from '../../infrastructure/transaction/NamespaceMosaicIdGenerator';
18+
import { PublicAccount } from '../account/PublicAccount';
19+
import { Id } from '../Id';
20+
import { MosaicNonce } from '../mosaic/MosaicNonce';
2121

2222
/**
2323
* The mosaic id structure describes mosaic id
@@ -39,7 +39,7 @@ export class MosaicId {
3939
* @return {MosaicId}
4040
*/
4141
public static createFromNonce(nonce: MosaicNonce, owner: PublicAccount): MosaicId {
42-
const mosaicId = NamespaceMosaicIdGenerator.mosaicId(nonce.nonce, convert.hexToUint8(owner.publicKey));
42+
const mosaicId = NamespaceMosaicIdGenerator.mosaicId(nonce.toUint8Array(), convert.hexToUint8(owner.publicKey));
4343
return new MosaicId(mosaicId);
4444
}
4545

src/model/mosaic/MosaicNonce.ts

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,28 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import {Crypto} from '../../core/crypto';
17-
import { Convert as convert} from '../../core/format';
16+
import { Crypto } from '../../core/crypto';
17+
import { Convert as convert } from '../../core/format';
18+
1819
/**
1920
* The mosaic nonce structure
2021
*
2122
* @since 1.0
2223
*/
2324
export class MosaicNonce {
2425

26+
/**
27+
* Create MosaicNonce from int
28+
*
29+
* @param nonce nonce
30+
*/
31+
constructor(nonce: Uint8Array) {
32+
if (nonce.length !== 4) {
33+
throw Error('Invalid byte size for nonce, should be 4 bytes but received ' + nonce.length);
34+
}
35+
this.nonce = nonce;
36+
}
37+
2538
/**
2639
* Mosaic nonce
2740
*/
@@ -35,49 +48,57 @@ export class MosaicNonce {
3548
public static createRandom(): MosaicNonce {
3649
const bytes = Crypto.randomBytes(4);
3750
const nonce = new Uint8Array(bytes);
51+
return this.createFromUint8Array(nonce);
52+
}
53+
54+
/**
55+
* Create a MosaicNonce from a Uint8Array notation.
56+
*
57+
* @param nonce {number}
58+
* @return {MosaicNonce}
59+
*/
60+
public static createFromUint8Array(nonce: Uint8Array): MosaicNonce {
3861
return new MosaicNonce(nonce);
3962
}
4063

64+
/**
65+
* Create a MosaicNonce from a number notation.
66+
*
67+
* @param nonce {number}
68+
* @return {MosaicNonce}
69+
*/
70+
public static createFromNumber(nonce: number): MosaicNonce {
71+
return new MosaicNonce(convert.numberToUint8Array(nonce, 4));
72+
}
73+
4174
/**
4275
* Create a MosaicNonce from hexadecimal notation.
4376
*
4477
* @param hex {string}
4578
* @return {MosaicNonce}
4679
*/
4780
public static createFromHex(hex: string): MosaicNonce {
48-
const uint8 = convert.hexToUint8(hex.padStart(8, '0'));
49-
50-
if (uint8.length !== 4) {
51-
throw new Error('Expected 4 bytes for Nonce and got ' + hex.length + ' instead.');
52-
}
53-
54-
return new MosaicNonce(uint8);
81+
return new MosaicNonce(convert.hexToUint8(hex));
5582
}
5683

5784
/**
58-
* Create MosaicNonce from Uint8Array
59-
*
60-
* @param id
85+
* @returns the nonce as an array of 4 digits
6186
*/
62-
constructor(nonce: Uint8Array) {
63-
if (nonce.length !== 4) {
64-
throw Error('Invalid byte size for nonce, should be 4 bytes but received ' + nonce.length);
65-
}
66-
67-
this.nonce = nonce;
87+
public toUint8Array(): Uint8Array {
88+
return this.nonce;
6889
}
6990

7091
/**
7192
* @internal
72-
* @returns {[number,number,number,number]}
93+
* @returns the nonce as number
7394
*/
7495
public toDTO(): number {
75-
return (this.nonce[0] + (this.nonce[1] << 8) + (this.nonce[2] << 16) + (this.nonce[3] << 24)) >>> 0;
96+
return convert.uintArray8ToNumber(this.nonce);
7697
}
7798

7899
/**
79100
* Get string value of nonce
80-
* @returns {string}
101+
* @returns the nonce as hex
81102
*/
82103
public toHex(): string {
83104
return convert.uint8ToHex(this.nonce);

src/model/transaction/MosaicDefinitionTransaction.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
BlockDurationDto,
2020
EmbeddedMosaicDefinitionTransactionBuilder,
2121
EmbeddedTransactionBuilder,
22-
GeneratorUtils,
2322
KeyDto,
2423
MosaicDefinitionTransactionBuilder,
2524
MosaicIdDto,
@@ -138,7 +137,7 @@ export class MosaicDefinitionTransaction extends Transaction {
138137
const transaction = MosaicDefinitionTransaction.create(
139138
isEmbedded ? Deadline.create() : Deadline.createFromDTO(
140139
(builder as MosaicDefinitionTransactionBuilder).getDeadline().timestamp),
141-
new MosaicNonce(builder.getNonce().serialize()),
140+
MosaicNonce.createFromUint8Array(builder.getNonce().serialize()),
142141
new MosaicId(builder.getId().mosaicId),
143142
MosaicFlags.create(
144143
(builder.getFlags() & 1) === 1,

src/service/TransactionService.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ export class TransactionService implements ITransactionService {
7171
*/
7272
public announce(signedTransaction: SignedTransaction, listener: IListener): Observable<Transaction> {
7373
const signerAddress = signedTransaction.getSignerAddress();
74-
const transactionObservable = this.transactionRepository.announce(signedTransaction).pipe(
75-
flatMap(() => listener.confirmed(signerAddress, signedTransaction.hash)),
76-
);
77-
return this.getTransactionOrRaiseError(listener, signerAddress, signedTransaction.hash, transactionObservable);
74+
this.transactionRepository.announce(signedTransaction);
75+
return this.getTransactionOrRaiseError(listener,
76+
signerAddress, signedTransaction.hash, listener.confirmed(signerAddress, signedTransaction.hash));
7877
}
7978

8079
/**

0 commit comments

Comments
 (0)