Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
026d2fa
added #357 transaction service for resolving alias
rg911 Nov 28, 2019
96a7513
restore missing tests
rg911 Nov 29, 2019
01d48ee
Changed to resolve alias from receipts
rg911 Nov 30, 2019
865bb0b
Added resolveAliases for AggregateTransaction
rg911 Nov 30, 2019
638f143
Updated e2e tests with aggregated tx
rg911 Nov 30, 2019
b5b20e1
Fixed jsdoc issues
rg911 Nov 30, 2019
903db08
- Fixed primary source id as confirmed by Jag
rg911 Dec 2, 2019
404e016
Fixed bug in transaction service
rg911 Dec 2, 2019
c9415f9
Sort aggregate inner transactions to original order
rg911 Dec 2, 2019
7aa54cb
added #357 transaction service for resolving alias
rg911 Nov 28, 2019
ffc5581
restore missing tests
rg911 Nov 29, 2019
e0df5c2
Changed to resolve alias from receipts
rg911 Nov 30, 2019
8da5886
Added resolveAliases for AggregateTransaction
rg911 Nov 30, 2019
d1b4b1a
Updated e2e tests with aggregated tx
rg911 Nov 30, 2019
7f3886b
Fixed jsdoc issues
rg911 Nov 30, 2019
4f497ae
- Fixed primary source id as confirmed by Jag
rg911 Dec 2, 2019
510a648
Fixed bug in transaction service
rg911 Dec 2, 2019
e484c93
Sort aggregate inner transactions to original order
rg911 Dec 2, 2019
aa558b7
Merge branch 'task/g357_standardize_transaction_service' of github.co…
rg911 Dec 2, 2019
a2e0dd4
Added transactionService interface
rg911 Dec 3, 2019
58dd436
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
afb2be1
get most recent resolution entry
rg911 Dec 3, 2019
20aa6a6
expose getResolvedFromReceipt
rg911 Dec 3, 2019
341badb
Added unit tests for getResolutionEntryById
rg911 Dec 4, 2019
fe7028a
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
c006f3b
Merge branch 'task/g352_aggregate_bonded_announcing' of github.com:NE…
rg911 Dec 4, 2019
c1bf3ec
Moved listener to method
rg911 Dec 4, 2019
d1c4675
Refactored
rg911 Dec 4, 2019
c34cdcd
Fixed unit test
rg911 Dec 4, 2019
2997e4f
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
835ba0b
Moved listener to method
rg911 Dec 4, 2019
b218d25
Merge branch 'task/g352_aggregate_bonded_announcing' of github.com:NE…
rg911 Dec 5, 2019
2567479
Added more e2e tests
rg911 Dec 5, 2019
a06a4e4
Bug fixed on resolutionStatement
rg911 Dec 5, 2019
a7890a6
Fixed bug and added scenarior unit test which not covered in e2e
rg911 Dec 5, 2019
e295b5a
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
e4234d1
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
7392764
Moved listener to method
rg911 Dec 4, 2019
1e3ebe1
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
fc2dc92
Moved listener to method
rg911 Dec 4, 2019
98d0e79
Added more e2e tests
rg911 Dec 5, 2019
aac0275
Merge branch 'task/g352_aggregate_bonded_announcing' of github.com:NE…
rg911 Dec 6, 2019
5c8c183
Fixed typos in comments
rg911 Dec 6, 2019
8996a72
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
81ff792
Moved listener to method
rg911 Dec 4, 2019
c547dd2
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
5bc520d
Moved listener to method
rg911 Dec 4, 2019
1be9cec
Added more e2e tests
rg911 Dec 5, 2019
519b0de
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
c2adec6
Moved listener to method
rg911 Dec 4, 2019
1fe8b95
Added #352 aggregate bonded announcing
rg911 Dec 3, 2019
5a515c5
Moved listener to method
rg911 Dec 4, 2019
ddb8d24
Added more e2e tests
rg911 Dec 5, 2019
600d14a
Merge branch 'task/g352_aggregate_bonded_announcing' of github.com:NE…
rg911 Dec 6, 2019
0d21737
Fixed typo
rg911 Dec 6, 2019
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
561 changes: 561 additions & 0 deletions e2e/service/TransactionService.spec.ts

Large diffs are not rendered by default.

292 changes: 292 additions & 0 deletions e2e/service/TransactionService_AggregateBonded.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
/*
* Copyright 2019 NEM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { expect } from 'chai';
import { Listener } from '../../src/infrastructure/Listener';
import { NamespaceHttp } from '../../src/infrastructure/NamespaceHttp';
import { TransactionHttp } from '../../src/infrastructure/TransactionHttp';
import { Account } from '../../src/model/account/Account';
import { Address } from '../../src/model/account/Address';
import { NetworkType } from '../../src/model/blockchain/NetworkType';
import { PlainMessage } from '../../src/model/message/PlainMessage';
import { Mosaic } from '../../src/model/mosaic/Mosaic';
import { MosaicId } from '../../src/model/mosaic/MosaicId';
import { NetworkCurrencyMosaic } from '../../src/model/mosaic/NetworkCurrencyMosaic';
import { NamespaceId } from '../../src/model/namespace/NamespaceId';
import { AggregateTransaction } from '../../src/model/transaction/AggregateTransaction';
import { Deadline } from '../../src/model/transaction/Deadline';
import { LockFundsTransaction } from '../../src/model/transaction/LockFundsTransaction';
import { MultisigAccountModificationTransaction } from '../../src/model/transaction/MultisigAccountModificationTransaction';
import { TransactionType } from '../../src/model/transaction/TransactionType';
import { TransferTransaction } from '../../src/model/transaction/TransferTransaction';
import { UInt64 } from '../../src/model/UInt64';
import { TransactionService } from '../../src/service/TransactionService';
import { TransactionUtils } from '../infrastructure/TransactionUtils';

describe('TransactionService', () => {
let account: Account;
let account2: Account;
let multisigAccount: Account;
let cosignAccount1: Account;
let cosignAccount2: Account;
let cosignAccount3: Account;
let networkCurrencyMosaicId: MosaicId;
let url: string;
let generationHash: string;
let transactionHttp: TransactionHttp;
let transactionService: TransactionService;
let namespaceHttp: NamespaceHttp;
let config;

before((done) => {
const path = require('path');
require('fs').readFile(path.resolve(__dirname, '../conf/network.conf'), (err, data) => {
if (err) {
throw err;
}
const json = JSON.parse(data);
config = json;
account = Account.createFromPrivateKey(json.testAccount.privateKey, NetworkType.MIJIN_TEST);
account2 = Account.createFromPrivateKey(json.testAccount2.privateKey, NetworkType.MIJIN_TEST);
multisigAccount = Account.createFromPrivateKey(json.multisigAccount.privateKey, NetworkType.MIJIN_TEST);
cosignAccount1 = Account.createFromPrivateKey(json.cosignatoryAccount.privateKey, NetworkType.MIJIN_TEST);
cosignAccount2 = Account.createFromPrivateKey(json.cosignatory2Account.privateKey, NetworkType.MIJIN_TEST);
cosignAccount3 = Account.createFromPrivateKey(json.cosignatory3Account.privateKey, NetworkType.MIJIN_TEST);
url = json.apiUrl;
generationHash = json.generationHash;
transactionHttp = new TransactionHttp(url);
namespaceHttp = new NamespaceHttp(url);
transactionService = new TransactionService(url);
done();
});
});

/**
* =========================
* Setup test data
* =========================
*/
describe('Get network currency mosaic id', () => {
it('get mosaicId', (done) => {
namespaceHttp.getLinkedMosaicId(new NamespaceId('cat.currency')).subscribe((networkMosaicId) => {
networkCurrencyMosaicId = networkMosaicId;
done();
});
});
});

describe('Setup test multisig account', () => {
let listener: Listener;
before (() => {
listener = new Listener(config.apiUrl);
return listener.open();
});
after(() => {
return listener.close();
});
it('Announce MultisigAccountModificationTransaction', (done) => {
const modifyMultisigAccountTransaction = MultisigAccountModificationTransaction.create(
Deadline.create(),
2,
1,
[
cosignAccount1.publicAccount,
cosignAccount2.publicAccount,
cosignAccount3.publicAccount,
],
[],
NetworkType.MIJIN_TEST,
);

const aggregateTransaction = AggregateTransaction.createComplete(Deadline.create(),
[modifyMultisigAccountTransaction.toAggregate(multisigAccount.publicAccount)],
NetworkType.MIJIN_TEST,
[]);
const signedTransaction = aggregateTransaction
.signTransactionWithCosignatories(multisigAccount, [cosignAccount1, cosignAccount2, cosignAccount3], generationHash);

listener.confirmed(multisigAccount.address).subscribe(() => {
done();
});
listener.status(multisigAccount.address).subscribe((error) => {
console.log('Error:', error);
done();
});
transactionHttp.announce(signedTransaction);
});
});

/**
* =========================
* Test
* =========================
*/

describe('should announce transaction', () => {
let listener: Listener;
before (() => {
listener = new Listener(config.apiUrl);
return listener.open();
});
after(() => {
return listener.close();
});
it('announce', (done) => {
const transferTransaction = TransferTransaction.create(
Deadline.create(),
account2.address,
[
NetworkCurrencyMosaic.createAbsolute(1),
],
PlainMessage.create('test-message'),
NetworkType.MIJIN_TEST,
);
const signedTransaction = transferTransaction.signWith(account, generationHash);
transactionService.announce(signedTransaction, listener).subscribe((tx: TransferTransaction) => {
expect(tx.signer!.publicKey).to.be.equal(account.publicKey);
expect((tx.recipientAddress as Address).equals(account2.address)).to.be.true;
expect(tx.message.payload).to.be.equal('test-message');
done();
});
});
});

describe('should announce aggregate bonded with hashlock', () => {
let listener: Listener;
before (() => {
listener = new Listener(config.apiUrl);
return listener.open();
});
after(() => {
return listener.close();
});
it('announce', (done) => {
const signedAggregatedTransaction =
TransactionUtils.createSignedAggregatedBondTransaction(multisigAccount, account, account2.address, generationHash);
const lockFundsTransaction = LockFundsTransaction.create(
Deadline.create(),
new Mosaic(networkCurrencyMosaicId, UInt64.fromUint(10 * Math.pow(10, NetworkCurrencyMosaic.DIVISIBILITY))),
UInt64.fromUint(1000),
signedAggregatedTransaction,
NetworkType.MIJIN_TEST,
);
const signedLockFundsTransaction = lockFundsTransaction.signWith(account, generationHash);
transactionService
.announceHashLockAggregateBonded(signedLockFundsTransaction, signedAggregatedTransaction, listener).subscribe((tx) => {
expect(tx.signer!.publicKey).to.be.equal(account.publicKey);
expect(tx.type).to.be.equal(TransactionType.AGGREGATE_BONDED);
done();
});
});
});

describe('should announce aggregate bonded transaction', () => {
let listener: Listener;
before (() => {
listener = new Listener(config.apiUrl);
return listener.open();
});
after(() => {
return listener.close();
});
it('announce', (done) => {
const signedAggregatedTransaction =
TransactionUtils.createSignedAggregatedBondTransaction(multisigAccount, account, account2.address, generationHash);
const lockFundsTransaction = LockFundsTransaction.create(
Deadline.create(),
new Mosaic(networkCurrencyMosaicId, UInt64.fromUint(10 * Math.pow(10, NetworkCurrencyMosaic.DIVISIBILITY))),
UInt64.fromUint(1000),
signedAggregatedTransaction,
NetworkType.MIJIN_TEST,
);
const signedLockFundsTransaction = lockFundsTransaction.signWith(account, generationHash);
transactionService.announce(signedLockFundsTransaction, listener).subscribe(() => {
transactionService.announceAggregateBonded(signedAggregatedTransaction, listener).subscribe((tx) => {
expect(tx.signer!.publicKey).to.be.equal(account.publicKey);
expect(tx.type).to.be.equal(TransactionType.AGGREGATE_BONDED);
done();
});
});
});
});

/**
* =========================
* House Keeping
* =========================
*/

describe('Restore test multisig Accounts', () => {
let listener: Listener;
before (() => {
listener = new Listener(config.apiUrl);
return listener.open();
});
after(() => {
return listener.close();
});
it('Announce MultisigAccountModificationTransaction', (done) => {
const removeCosigner1 = MultisigAccountModificationTransaction.create(
Deadline.create(),
-1,
0,
[],
[ cosignAccount1.publicAccount,
],
NetworkType.MIJIN_TEST,
);
const removeCosigner2 = MultisigAccountModificationTransaction.create(
Deadline.create(),
0,
0,
[],
[
cosignAccount2.publicAccount,
],
NetworkType.MIJIN_TEST,
);

const removeCosigner3 = MultisigAccountModificationTransaction.create(
Deadline.create(),
-1,
-1,
[],
[
cosignAccount3.publicAccount,
],
NetworkType.MIJIN_TEST,
);

const aggregateTransaction = AggregateTransaction.createComplete(Deadline.create(),
[removeCosigner1.toAggregate(multisigAccount.publicAccount),
removeCosigner2.toAggregate(multisigAccount.publicAccount),
removeCosigner3.toAggregate(multisigAccount.publicAccount)],
NetworkType.MIJIN_TEST,
[]);
const signedTransaction = aggregateTransaction
.signTransactionWithCosignatories(cosignAccount1, [cosignAccount2, cosignAccount3], generationHash);

listener.confirmed(cosignAccount1.address).subscribe(() => {
done();
});
listener.status(cosignAccount1.address).subscribe((error) => {
console.log('Error:', error);
done();
});
transactionHttp.announce(signedTransaction);
});
});
});
1 change: 0 additions & 1 deletion src/core/utils/TransactionMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { CreateTransactionFromDTO } from '../../infrastructure/transaction/Creat
import { CreateTransactionFromPayload } from '../../infrastructure/transaction/CreateTransactionFromPayload';
import { InnerTransaction } from '../../model/transaction/InnerTransaction';
import { Transaction } from '../../model/transaction/Transaction';
import { SignSchema } from '../crypto/SignSchema';

export class TransactionMapping {

Expand Down
2 changes: 1 addition & 1 deletion src/core/utils/UnresolvedMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
* limitations under the License.
*/
import { Address } from '../../model/account/Address';
import { NetworkType } from '../../model/blockchain/NetworkType';
import { MosaicId } from '../../model/mosaic/MosaicId';
import { NamespaceId } from '../../model/namespace/NamespaceId';
import { Convert } from '../format/Convert';
import { RawAddress } from '../format/RawAddress';
import { NetworkType } from "../../model/blockchain/NetworkType";

/**
* @internal
Expand Down
14 changes: 10 additions & 4 deletions src/infrastructure/Listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,18 @@ export class Listener {
* it emits a new Transaction in the event stream.
*
* @param address address we listen when a transaction is in confirmed state
* @param transactionHash transactionHash for filtering multiple transactions
* @return an observable stream of Transaction with state confirmed
*/
public confirmed(address: Address): Observable<Transaction> {
public confirmed(address: Address, transactionHash?: string): Observable<Transaction> {
this.subscribeTo(`confirmedAdded/${address.plain()}`);
return this.messageSubject.asObservable().pipe(
filter((_) => _.channelName === ListenerChannelName.confirmedAdded),
filter((_) => _.message instanceof Transaction),
map((_) => _.message as Transaction),
filter((_) => this.transactionFromAddress(_, address)));
filter((_) => this.transactionFromAddress(_, address)),
filter((_) => transactionHash === undefined || _.transactionInfo!.hash === transactionHash),
);
}

/**
Expand Down Expand Up @@ -289,15 +292,18 @@ export class Listener {
* it emits a new {@link AggregateTransaction} in the event stream.
*
* @param address address we listen when a transaction with missing signatures state
* @param transactionHash transactionHash for filtering multiple transactions
* @return an observable stream of AggregateTransaction with missing signatures state
*/
public aggregateBondedAdded(address: Address): Observable<AggregateTransaction> {
public aggregateBondedAdded(address: Address, transactionHash?: string): Observable<AggregateTransaction> {
this.subscribeTo(`partialAdded/${address.plain()}`);
return this.messageSubject.asObservable().pipe(
filter((_) => _.channelName === ListenerChannelName.aggregateBondedAdded),
filter((_) => _.message instanceof AggregateTransaction),
map((_) => _.message as AggregateTransaction),
filter((_) => this.transactionFromAddress(_, address)));
filter((_) => this.transactionFromAddress(_, address)),
filter((_) => transactionHash === undefined || _.transactionInfo!.hash === transactionHash),
);
}

/**
Expand Down
Loading