Skip to content

Commit

Permalink
Merge pull request #479 from NEMStudios/mosaicNonceImprovements
Browse files Browse the repository at this point in the history
Changed dto mappers to map nonce as a decimal int.
  • Loading branch information
rg911 committed Mar 4, 2020
2 parents d2c502d + 963db2d commit 49fb08c
Show file tree
Hide file tree
Showing 18 changed files with 272 additions and 176 deletions.
6 changes: 4 additions & 2 deletions e2e/infrastructure/AccountHttp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,12 @@ describe('AccountHttp', () => {
describe('transactions', () => {
it('should call transactions successfully by type', async () => {
const transactions = await accountRepository.getAccountTransactions(
publicAccount.address, new QueryParams(), new TransactionFilter({ types: [TransactionType.TRANSFER] })).toPromise();
publicAccount.address, new QueryParams(), new TransactionFilter({
types: [TransactionType.TRANSFER, TransactionType.AGGREGATE_COMPLETE],
})).toPromise();
expect(transactions.length).to.be.greaterThan(0);
transactions.forEach((t) => {
expect(t.type).to.be.eq(TransactionType.TRANSFER);
expect((t.type === TransactionType.TRANSFER || t.type === TransactionType.AGGREGATE_COMPLETE)).to.be.eq(true);
});
});
});
Expand Down
18 changes: 14 additions & 4 deletions e2e/infrastructure/MosaicHttp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,32 @@ describe('MosaicHttp', () => {
*/
describe('Setup test MosaicId', () => {

it('Announce MosaicDefinitionTransaction', () => {
const nonce = MosaicNonce.createRandom();
it('Announce MosaicDefinitionTransaction', async () => {
const nonce = MosaicNonce.createFromNumber(-1501238750);
expect(nonce.toDTO()).to.be.equals(2793728546);
expect(nonce.toHex()).to.be.equals('22EA84A6');
mosaicId = MosaicId.createFromNonce(nonce, account.publicAccount);
const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
Deadline.create(),
nonce,
mosaicId,
MosaicFlags.create(true, true, false),
3,
UInt64.fromUint(0),
UInt64.fromUint(100),
networkType,
helper.maxFee,
);
const signedTransaction = mosaicDefinitionTransaction.signWith(account, generationHash);

return helper.announce(signedTransaction);
const listenedTransaction = await helper.announce(signedTransaction) as MosaicDefinitionTransaction;
expect(mosaicDefinitionTransaction.nonce.toHex()).to.be.equal(listenedTransaction.nonce.toHex());
expect(mosaicDefinitionTransaction.nonce).to.deep.equal(listenedTransaction.nonce);
expect(mosaicDefinitionTransaction.getMosaicNonceIntValue()).to.be.equal(listenedTransaction.getMosaicNonceIntValue());

const savedTransaction = await helper.repositoryFactory.createTransactionRepository().getTransaction(signedTransaction.hash).toPromise() as MosaicDefinitionTransaction;
expect(mosaicDefinitionTransaction.nonce.toHex()).to.be.equal(savedTransaction.nonce.toHex());
expect(mosaicDefinitionTransaction.nonce).to.deep.equal(savedTransaction.nonce);
expect(mosaicDefinitionTransaction.getMosaicNonceIntValue()).to.be.equal(savedTransaction.getMosaicNonceIntValue());
});
});

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions src/core/format/Convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,31 @@ export class Convert {
}
return Convert.uint8ToHex(Uint8Array.from(delta));
}

/**
* It splits the number's bytes into a an array.
* @param number the number
* @param arraySize the expected size of the array.
*/
public static numberToUint8Array(number: number, arraySize: number): Uint8Array {
const uint8Array = new Uint8Array(arraySize);
for (let index = 0; index < uint8Array.length; index++) {
const byte = number & 0xff;
uint8Array [index] = byte;
number = (number - byte) / 256;
}
return uint8Array;
}

/**
* It creates a number from the bytes in the array.
* @param array the number from the bytes.
*/
public static uintArray8ToNumber(array: Uint8Array): number {
let value = 0;
for (let index = 0; index < array.length; index++) {
value += array[index] << (index * 8);
}
return value >>> 0;
}
}
4 changes: 2 additions & 2 deletions src/infrastructure/Http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ export abstract class Http {
}

errorHandling(error: any): Error {
if (error.response && error.response.statusCode && error.body) {
if (error.response && error.response.statusCode && error.response.body) {
const formattedError = {
statusCode: error.response.statusCode,
errorDetails: {
statusCode: error.response.statusCode,
statusMessage: error.response.statusMessage,
},
body: error.body,
body: error.response.body,
};
return new Error(JSON.stringify(formattedError));
}
Expand Down
63 changes: 31 additions & 32 deletions src/infrastructure/transaction/CreateTransactionFromDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Convert as convert} from '../../core/format';
import { Convert as convert } from '../../core/format';
import { UnresolvedMapping } from '../../core/utils/UnresolvedMapping';
import {Address} from '../../model/account/Address';
import {PublicAccount} from '../../model/account/PublicAccount';
import {NetworkType} from '../../model/blockchain/NetworkType';
import { Address } from '../../model/account/Address';
import { PublicAccount } from '../../model/account/PublicAccount';
import { EncryptedMessage } from '../../model/message/EncryptedMessage';
import { MessageType } from '../../model/message/MessageType';
import { PersistentHarvestingDelegationMessage } from '../../model/message/PersistentHarvestingDelegationMessage';
import {EmptyMessage, PlainMessage} from '../../model/message/PlainMessage';
import {Mosaic} from '../../model/mosaic/Mosaic';
import {MosaicFlags} from '../../model/mosaic/MosaicFlags';
import {MosaicId} from '../../model/mosaic/MosaicId';
import { EmptyMessage, PlainMessage } from '../../model/message/PlainMessage';
import { Mosaic } from '../../model/mosaic/Mosaic';
import { MosaicFlags } from '../../model/mosaic/MosaicFlags';
import { MosaicId } from '../../model/mosaic/MosaicId';
import { MosaicNonce } from '../../model/mosaic/MosaicNonce';
import {NamespaceId} from '../../model/namespace/NamespaceId';
import {AccountAddressRestrictionTransaction} from '../../model/transaction/AccountAddressRestrictionTransaction';
import { NamespaceId } from '../../model/namespace/NamespaceId';
import { AccountAddressRestrictionTransaction } from '../../model/transaction/AccountAddressRestrictionTransaction';
import { AccountLinkTransaction } from '../../model/transaction/AccountLinkTransaction';
import { AccountMetadataTransaction } from '../../model/transaction/AccountMetadataTransaction';
import {AccountMosaicRestrictionTransaction} from '../../model/transaction/AccountMosaicRestrictionTransaction';
import {AccountOperationRestrictionTransaction} from '../../model/transaction/AccountOperationRestrictionTransaction';
import {AddressAliasTransaction} from '../../model/transaction/AddressAliasTransaction';
import {AggregateTransaction} from '../../model/transaction/AggregateTransaction';
import {AggregateTransactionCosignature} from '../../model/transaction/AggregateTransactionCosignature';
import {AggregateTransactionInfo} from '../../model/transaction/AggregateTransactionInfo';
import {Deadline} from '../../model/transaction/Deadline';
import {LockFundsTransaction} from '../../model/transaction/LockFundsTransaction';
import { AccountMosaicRestrictionTransaction } from '../../model/transaction/AccountMosaicRestrictionTransaction';
import { AccountOperationRestrictionTransaction } from '../../model/transaction/AccountOperationRestrictionTransaction';
import { AddressAliasTransaction } from '../../model/transaction/AddressAliasTransaction';
import { AggregateTransaction } from '../../model/transaction/AggregateTransaction';
import { AggregateTransactionCosignature } from '../../model/transaction/AggregateTransactionCosignature';
import { AggregateTransactionInfo } from '../../model/transaction/AggregateTransactionInfo';
import { Deadline } from '../../model/transaction/Deadline';
import { LockFundsTransaction } from '../../model/transaction/LockFundsTransaction';
import { MosaicAddressRestrictionTransaction } from '../../model/transaction/MosaicAddressRestrictionTransaction';
import {MosaicAliasTransaction} from '../../model/transaction/MosaicAliasTransaction';
import {MosaicDefinitionTransaction} from '../../model/transaction/MosaicDefinitionTransaction';
import { MosaicAliasTransaction } from '../../model/transaction/MosaicAliasTransaction';
import { MosaicDefinitionTransaction } from '../../model/transaction/MosaicDefinitionTransaction';
import { MosaicGlobalRestrictionTransaction } from '../../model/transaction/MosaicGlobalRestrictionTransaction';
import { MosaicMetadataTransaction } from '../../model/transaction/MosaicMetadataTransaction';
import {MosaicSupplyChangeTransaction} from '../../model/transaction/MosaicSupplyChangeTransaction';
import {MultisigAccountModificationTransaction} from '../../model/transaction/MultisigAccountModificationTransaction';
import { MosaicSupplyChangeTransaction } from '../../model/transaction/MosaicSupplyChangeTransaction';
import { MultisigAccountModificationTransaction } from '../../model/transaction/MultisigAccountModificationTransaction';
import { NamespaceMetadataTransaction } from '../../model/transaction/NamespaceMetadataTransaction';
import {NamespaceRegistrationTransaction} from '../../model/transaction/NamespaceRegistrationTransaction';
import {SecretLockTransaction} from '../../model/transaction/SecretLockTransaction';
import {SecretProofTransaction} from '../../model/transaction/SecretProofTransaction';
import {SignedTransaction} from '../../model/transaction/SignedTransaction';
import {Transaction} from '../../model/transaction/Transaction';
import {TransactionInfo} from '../../model/transaction/TransactionInfo';
import {TransactionType} from '../../model/transaction/TransactionType';
import {TransferTransaction} from '../../model/transaction/TransferTransaction';
import {UInt64} from '../../model/UInt64';
import { NamespaceRegistrationTransaction } from '../../model/transaction/NamespaceRegistrationTransaction';
import { SecretLockTransaction } from '../../model/transaction/SecretLockTransaction';
import { SecretProofTransaction } from '../../model/transaction/SecretProofTransaction';
import { SignedTransaction } from '../../model/transaction/SignedTransaction';
import { Transaction } from '../../model/transaction/Transaction';
import { TransactionInfo } from '../../model/transaction/TransactionInfo';
import { TransactionType } from '../../model/transaction/TransactionType';
import { TransferTransaction } from '../../model/transaction/TransferTransaction';
import { UInt64 } from '../../model/UInt64';

// tslint:disable: no-use-before-declare
/**
Expand Down Expand Up @@ -161,7 +160,7 @@ const CreateStandaloneTransactionFromDTO = (transactionDTO, transactionInfo): Tr
transactionDTO.version,
Deadline.createFromDTO(transactionDTO.deadline),
UInt64.fromNumericString(transactionDTO.maxFee || '0'),
MosaicNonce.createFromHex(transactionDTO.nonce.toString(16)),
MosaicNonce.createFromNumber(transactionDTO.nonce),
new MosaicId(transactionDTO.id),
new MosaicFlags(transactionDTO.flags),
transactionDTO.divisibility,
Expand Down
10 changes: 5 additions & 5 deletions src/model/mosaic/MosaicId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
*/
import { Convert as convert, RawUInt64 as uint64_t } from '../../core/format';
import {NamespaceMosaicIdGenerator} from '../../infrastructure/transaction/NamespaceMosaicIdGenerator';
import {PublicAccount} from '../account/PublicAccount';
import {Id} from '../Id';
import {MosaicNonce} from '../mosaic/MosaicNonce';
import { NamespaceMosaicIdGenerator } from '../../infrastructure/transaction/NamespaceMosaicIdGenerator';
import { PublicAccount } from '../account/PublicAccount';
import { Id } from '../Id';
import { MosaicNonce } from '../mosaic/MosaicNonce';

/**
* The mosaic id structure describes mosaic id
Expand All @@ -39,7 +39,7 @@ export class MosaicId {
* @return {MosaicId}
*/
public static createFromNonce(nonce: MosaicNonce, owner: PublicAccount): MosaicId {
const mosaicId = NamespaceMosaicIdGenerator.mosaicId(nonce.nonce, convert.hexToUint8(owner.publicKey));
const mosaicId = NamespaceMosaicIdGenerator.mosaicId(nonce.toUint8Array(), convert.hexToUint8(owner.publicKey));
return new MosaicId(mosaicId);
}

Expand Down
63 changes: 42 additions & 21 deletions src/model/mosaic/MosaicNonce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Crypto} from '../../core/crypto';
import { Convert as convert} from '../../core/format';
import { Crypto } from '../../core/crypto';
import { Convert as convert } from '../../core/format';

/**
* The mosaic nonce structure
*
* @since 1.0
*/
export class MosaicNonce {

/**
* Create MosaicNonce from int
*
* @param nonce nonce
*/
constructor(nonce: Uint8Array) {
if (nonce.length !== 4) {
throw Error('Invalid byte size for nonce, should be 4 bytes but received ' + nonce.length);
}
this.nonce = nonce;
}

/**
* Mosaic nonce
*/
Expand All @@ -35,49 +48,57 @@ export class MosaicNonce {
public static createRandom(): MosaicNonce {
const bytes = Crypto.randomBytes(4);
const nonce = new Uint8Array(bytes);
return this.createFromUint8Array(nonce);
}

/**
* Create a MosaicNonce from a Uint8Array notation.
*
* @param nonce {number}
* @return {MosaicNonce}
*/
public static createFromUint8Array(nonce: Uint8Array): MosaicNonce {
return new MosaicNonce(nonce);
}

/**
* Create a MosaicNonce from a number notation.
*
* @param nonce {number}
* @return {MosaicNonce}
*/
public static createFromNumber(nonce: number): MosaicNonce {
return new MosaicNonce(convert.numberToUint8Array(nonce, 4));
}

/**
* Create a MosaicNonce from hexadecimal notation.
*
* @param hex {string}
* @return {MosaicNonce}
*/
public static createFromHex(hex: string): MosaicNonce {
const uint8 = convert.hexToUint8(hex.padStart(8, '0'));

if (uint8.length !== 4) {
throw new Error('Expected 4 bytes for Nonce and got ' + hex.length + ' instead.');
}

return new MosaicNonce(uint8);
return new MosaicNonce(convert.hexToUint8(hex));
}

/**
* Create MosaicNonce from Uint8Array
*
* @param id
* @returns the nonce as an array of 4 digits
*/
constructor(nonce: Uint8Array) {
if (nonce.length !== 4) {
throw Error('Invalid byte size for nonce, should be 4 bytes but received ' + nonce.length);
}

this.nonce = nonce;
public toUint8Array(): Uint8Array {
return this.nonce;
}

/**
* @internal
* @returns {[number,number,number,number]}
* @returns the nonce as number
*/
public toDTO(): number {
return (this.nonce[0] + (this.nonce[1] << 8) + (this.nonce[2] << 16) + (this.nonce[3] << 24)) >>> 0;
return convert.uintArray8ToNumber(this.nonce);
}

/**
* Get string value of nonce
* @returns {string}
* @returns the nonce as hex
*/
public toHex(): string {
return convert.uint8ToHex(this.nonce);
Expand Down
3 changes: 1 addition & 2 deletions src/model/transaction/MosaicDefinitionTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
BlockDurationDto,
EmbeddedMosaicDefinitionTransactionBuilder,
EmbeddedTransactionBuilder,
GeneratorUtils,
KeyDto,
MosaicDefinitionTransactionBuilder,
MosaicIdDto,
Expand Down Expand Up @@ -138,7 +137,7 @@ export class MosaicDefinitionTransaction extends Transaction {
const transaction = MosaicDefinitionTransaction.create(
isEmbedded ? Deadline.create() : Deadline.createFromDTO(
(builder as MosaicDefinitionTransactionBuilder).getDeadline().timestamp),
new MosaicNonce(builder.getNonce().serialize()),
MosaicNonce.createFromUint8Array(builder.getNonce().serialize()),
new MosaicId(builder.getId().mosaicId),
MosaicFlags.create(
(builder.getFlags() & 1) === 1,
Expand Down
7 changes: 3 additions & 4 deletions src/service/TransactionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,9 @@ export class TransactionService implements ITransactionService {
*/
public announce(signedTransaction: SignedTransaction, listener: IListener): Observable<Transaction> {
const signerAddress = signedTransaction.getSignerAddress();
const transactionObservable = this.transactionRepository.announce(signedTransaction).pipe(
flatMap(() => listener.confirmed(signerAddress, signedTransaction.hash)),
);
return this.getTransactionOrRaiseError(listener, signerAddress, signedTransaction.hash, transactionObservable);
this.transactionRepository.announce(signedTransaction);
return this.getTransactionOrRaiseError(listener,
signerAddress, signedTransaction.hash, listener.confirmed(signerAddress, signedTransaction.hash));
}

/**
Expand Down
Loading

0 comments on commit 49fb08c

Please sign in to comment.