From b0d250575dbcbbc43ae7f238cf98cf45aa6173e3 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 14:58:42 +0100 Subject: [PATCH 01/13] Added #204 - Fixed signTransactionGivenSignatures bug - Added e2e test for signTransactionGivenSignatures - Improved unit test for signTransactionGivenSignatures - Fixed typo --- e2e/infrastructure/TransactionHttp.spec.ts | 63 +++++++++++++++++++ .../transaction/CosignatureTransaction.ts | 11 ++-- .../transaction/AggregateTransaction.spec.ts | 22 ++++--- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/e2e/infrastructure/TransactionHttp.spec.ts b/e2e/infrastructure/TransactionHttp.spec.ts index dbee30b256..5aed1c6810 100644 --- a/e2e/infrastructure/TransactionHttp.spec.ts +++ b/e2e/infrastructure/TransactionHttp.spec.ts @@ -19,6 +19,7 @@ import {ChronoUnit} from 'js-joda'; import {keccak_256, sha3_256} from 'js-sha3'; import {Crypto} from '../../src/core/crypto'; import { Convert as convert } from '../../src/core/format'; +import { TransactionMapping } from '../../src/core/utils/TransactionMapping'; import {AccountHttp} from '../../src/infrastructure/AccountHttp'; import { NamespaceHttp } from '../../src/infrastructure/infrastructure'; import {Listener} from '../../src/infrastructure/Listener'; @@ -44,6 +45,7 @@ import { AccountRestrictionTransaction } from '../../src/model/transaction/Accou import { AddressAliasTransaction } from '../../src/model/transaction/AddressAliasTransaction'; import {AggregateTransaction} from '../../src/model/transaction/AggregateTransaction'; import {CosignatureSignedTransaction} from '../../src/model/transaction/CosignatureSignedTransaction'; +import { CosignatureTransaction } from '../../src/model/transaction/CosignatureTransaction'; import {Deadline} from '../../src/model/transaction/Deadline'; import { HashLockTransaction } from '../../src/model/transaction/HashLockTransaction'; import {HashType} from '../../src/model/transaction/HashType'; @@ -1641,6 +1643,67 @@ describe('TransactionHttp', () => { }); }); + describe('SignTransactionGivenSignatures', () => { + let listener: Listener; + before (() => { + listener = new Listener(config.apiUrl); + return listener.open(); + }); + after(() => { + return listener.close(); + }); + it('Announce cosign signatures given', (done) => { + + /** + * @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 + */ + // AliceAccount: account + // BobAccount: account + + const sendAmount = NetworkCurrencyMosaic.createRelative(1000); + const backAmount = NetworkCurrencyMosaic.createRelative(1); + + const aliceTransferTransaction = TransferTransaction.create(Deadline.create(), account2.address, [sendAmount], + PlainMessage.create('payout'), NetworkType.MIJIN_TEST); + const bobTransferTransaction = TransferTransaction.create(Deadline.create(), account.address, [backAmount], + PlainMessage.create('payout'), NetworkType.MIJIN_TEST); + + // 01. Alice creates the aggregated tx and sign it. Then payload send to Bob + const aggregateTransaction = AggregateTransaction.createComplete( + Deadline.create(), + [ + aliceTransferTransaction.toAggregate(account.publicAccount), + bobTransferTransaction.toAggregate(account2.publicAccount), + ], + NetworkType.MIJIN_TEST, + [], + ); + + const aliceSignedTransaction = aggregateTransaction.signWith(account, generationHash); + + // 02 Bob cosigns the tx and sends it back to Alice + const signedTxBob = CosignatureTransaction.signTransactionPayload(account2, aliceSignedTransaction.payload, generationHash); + + // 03. Alice collects the cosignatures, recreate, sign, and announces the transaction + const cosignatureSignedTransactions = [ + new CosignatureSignedTransaction(signedTxBob.parentHash, signedTxBob.signature, signedTxBob.signer), + ]; + const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction; + + const signedTransaction = recreatedTx.signTransactionGivenSignatures(account, cosignatureSignedTransactions, generationHash); + + listener.confirmed(account.address).subscribe(() => { + done(); + }); + listener.status(account.address).subscribe((error) => { + console.log('Error:', error); + assert(false); + done(); + }); + transactionHttp.announce(signedTransaction); + }); + }); + describe('transactions', () => { it('should call transactions successfully', (done) => { accountHttp.transactions(account.publicAccount).subscribe((transactions) => { diff --git a/src/model/transaction/CosignatureTransaction.ts b/src/model/transaction/CosignatureTransaction.ts index 1eb021e01a..2f37079c9f 100644 --- a/src/model/transaction/CosignatureTransaction.ts +++ b/src/model/transaction/CosignatureTransaction.ts @@ -15,11 +15,12 @@ */ import { SignSchema } from '../../core/crypto'; +import { Convert } from '../../core/format/Convert'; import {CosignatureTransaction as CosignaturetransactionLibrary} from '../../infrastructure/builders/CosignatureTransaction'; +import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction'; import {Account} from '../account/Account'; import {AggregateTransaction} from './AggregateTransaction'; import {CosignatureSignedTransaction} from './CosignatureSignedTransaction'; -import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction'; /** * Cosignature transaction is used to sign an aggregate transactions with missing cosignatures. @@ -52,14 +53,14 @@ export class CosignatureTransaction { * Creating a new CosignatureSignedTransaction * @param account - The signing account * @param payload - off transaction payload (aggregated transaction is unannounced) - * @param gernationHash - Network generation hash + * @param generationHash - Network generation hash * @returns {CosignatureSignedTransaction} */ - public static signTransactionPayload(account: Account, payload: string, gernationHash: string): CosignatureSignedTransaction { + public static signTransactionPayload(account: Account, payload: string, generationHash: string): CosignatureSignedTransaction { /** * For aggregated complete transaction, cosignatories are gathered off chain announced. */ - const transactionHash = VerifiableTransaction.createTransactionHash(payload, gernationHash); + const transactionHash = VerifiableTransaction.createTransactionHash(payload, Array.from(Convert.hexToUint8(generationHash))); const aggregateSignatureTransaction = new CosignaturetransactionLibrary(transactionHash); const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account); return new CosignatureSignedTransaction(signedTransactionRaw.parentHash, @@ -81,4 +82,4 @@ export class CosignatureTransaction { signedTransactionRaw.signature, signedTransactionRaw.signer); } -} \ No newline at end of file +} diff --git a/test/model/transaction/AggregateTransaction.spec.ts b/test/model/transaction/AggregateTransaction.spec.ts index 571df9defe..fa204a7500 100644 --- a/test/model/transaction/AggregateTransaction.spec.ts +++ b/test/model/transaction/AggregateTransaction.spec.ts @@ -388,7 +388,7 @@ describe('AggregateTransaction', () => { it('Should create signed transaction with cosignatories - Aggregated Complete', () => { /** - * https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 + * @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 */ const accountAlice = TestingAccount; const accountBob = CosignatoryAccount; @@ -410,8 +410,8 @@ describe('AggregateTransaction', () => { PlainMessage.create('c to a'), NetworkType.MIJIN_TEST); - // 01. Alice creates the aggregated tx and serialize it, Then payload send to Bob & Carol - const aggregateTransactionPayload = AggregateTransaction.createComplete( + // 01. Alice creates the aggregated tx and sign it, Then payload send to Bob & Carol + const aggregateTransaction = AggregateTransaction.createComplete( Deadline.create(), [ AtoBTx.toAggregate(accountAlice.publicAccount), @@ -419,13 +419,15 @@ describe('AggregateTransaction', () => { CtoATx.toAggregate(accountCarol.publicAccount)], NetworkType.MIJIN_TEST, [], - ).serialize(); + ); + + const aliceSignedTransaction = aggregateTransaction.signWith(accountAlice, generationHash); // 02.1 Bob cosigns the tx and sends it back to Alice - const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aggregateTransactionPayload, generationHash); + const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aliceSignedTransaction.payload, generationHash); // 02.2 Carol cosigns the tx and sends it back to Alice - const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aggregateTransactionPayload, generationHash); + const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aliceSignedTransaction.payload, generationHash); // 03. Alice collects the cosignatures, recreate, sign, and announces the transaction @@ -435,7 +437,7 @@ describe('AggregateTransaction', () => { new CosignatureSignedTransaction(signedTxCarol.parentHash, signedTxCarol.signature, signedTxCarol.signer), ]; - const recreatedTx = TransactionMapping.createFromPayload(aggregateTransactionPayload) as AggregateTransaction; + const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction; const signedTransaction = recreatedTx.signTransactionGivenSignatures(accountAlice, cosignatureSignedTransactions, generationHash); @@ -443,6 +445,12 @@ describe('AggregateTransaction', () => { expect(signedTransaction.signer).to.be.equal(accountAlice.publicKey); expect(signedTransaction.payload.indexOf(accountBob.publicKey) > -1).to.be.true; expect(signedTransaction.payload.indexOf(accountCarol.publicKey) > -1).to.be.true; + + // To make sure that the new cosign method returns the same payload & hash as standard cosigning + const standardCosignedTransaction = aggregateTransaction + .signTransactionWithCosignatories(accountAlice, [accountBob, accountCarol], generationHash); + expect(standardCosignedTransaction.payload).to.be.equal(signedTransaction.payload); + expect(standardCosignedTransaction.hash).to.be.equal(signedTransaction.hash); }); describe('size', () => { From e11205c9068f03841d892964328a268e9eac18a6 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 15:02:49 +0100 Subject: [PATCH 02/13] Added signSchema to signWithPayload --- src/infrastructure/builders/AggregateTransaction.ts | 2 +- src/model/transaction/CosignatureTransaction.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/builders/AggregateTransaction.ts b/src/infrastructure/builders/AggregateTransaction.ts index 96790b9a0f..8aae5a5e28 100644 --- a/src/infrastructure/builders/AggregateTransaction.ts +++ b/src/infrastructure/builders/AggregateTransaction.ts @@ -56,7 +56,7 @@ export class AggregateTransaction extends VerifiableTransaction { return signedTransaction; } - signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema) { + signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema = SignSchema.SHA3) { const signedTransaction = this.signTransaction(initializer, generationHash, signSchema); cosignedSignedTransactions.forEach((cosignedTransaction) => { signedTransaction.payload = signedTransaction.payload + cosignedTransaction.signer + cosignedTransaction.signature; diff --git a/src/model/transaction/CosignatureTransaction.ts b/src/model/transaction/CosignatureTransaction.ts index 2f37079c9f..d1b6ddc5b5 100644 --- a/src/model/transaction/CosignatureTransaction.ts +++ b/src/model/transaction/CosignatureTransaction.ts @@ -54,15 +54,19 @@ export class CosignatureTransaction { * @param account - The signing account * @param payload - off transaction payload (aggregated transaction is unannounced) * @param generationHash - Network generation hash + * @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3) * @returns {CosignatureSignedTransaction} */ - public static signTransactionPayload(account: Account, payload: string, generationHash: string): CosignatureSignedTransaction { + public static signTransactionPayload(account: Account, + payload: string, + generationHash: string, + signSchema: SignSchema = SignSchema.SHA3): CosignatureSignedTransaction { /** * For aggregated complete transaction, cosignatories are gathered off chain announced. */ const transactionHash = VerifiableTransaction.createTransactionHash(payload, Array.from(Convert.hexToUint8(generationHash))); const aggregateSignatureTransaction = new CosignaturetransactionLibrary(transactionHash); - const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account); + const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account, signSchema); return new CosignatureSignedTransaction(signedTransactionRaw.parentHash, signedTransactionRaw.signature, signedTransactionRaw.signer); From a21f98041903f2f15cc8596f5569a035af1cb9ab Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 15:42:55 +0100 Subject: [PATCH 03/13] Exposed signTransactionGivenSignatures method --- src/model/account/Account.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/model/account/Account.ts b/src/model/account/Account.ts index 7e26c2d4f9..7395b232fb 100644 --- a/src/model/account/Account.ts +++ b/src/model/account/Account.ts @@ -171,6 +171,21 @@ export class Account { return transaction.signTransactionWithCosignatories(this, cosignatories, generationHash, signSchema); } + /** + * Sign transaction with cosignatories collected from cosigned transactions and creating a new SignedTransaction + * For off chain Aggregated Complete Transaction co-signing. + * @param initiatorAccount - Initiator account + * @param {CosignatureSignedTransaction[]} cosignatureSignedTransactions - Array of cosigned transaction + * @param generationHash - Network generation hash hex + * @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3) + * @return {SignedTransaction} + */ + public signTransactionGivenSignatures(transaction: AggregateTransaction, + cosignatureSignedTransactions: CosignatureSignedTransaction[], + generationHash: string, + signSchema: SignSchema = SignSchema.SHA3): SignedTransaction { + return transaction.signTransactionGivenSignatures(this, cosignatureSignedTransactions, generationHash, signSchema); + } /** * Sign aggregate signature transaction * @param cosignatureTransaction - The aggregate signature transaction. From 2a5acb59d6dccbd4e05ce3dcdbd3cec80349bb56 Mon Sep 17 00:00:00 2001 From: Jonathan Tey Date: Tue, 23 Jul 2019 11:52:31 +0800 Subject: [PATCH 04/13] Fixed version --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d10ea6d2e..f09503ffb5 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ with the NEM2 (a.k.a Catapult) ## Important Notes -### _Elephant Network Compatibility (catapult-server@0.5.0.1) +### _Elephant_ Network Compatibility (catapult-server@0.5.0.1) -Due to a network upgrade with [catapult-server@elephant](https://github.com/nemtech/catapult-server/releases/tag/v0.5.0.1) version, **it is recommended to use this package's 0.13.0 version and upwards to use this package with Dragon versioned networks**. +Due to a network upgrade with [catapult-server@elephant](https://github.com/nemtech/catapult-server/releases/tag/v0.5.0.1) version, **it is recommended to use this package's 0.13.0 version and upwards to use this package with Elephant versioned networks**. -The upgrade to this package's [version v0.13.0](https://github.com/nemtech/nem2-sdk-typescript-javascript/releases/tag/v0.13.0) is mandatory for **dragon compatibility**. +The upgrade to this package's [version v0.13.0](https://github.com/nemtech/nem2-sdk-typescript-javascript/releases/tag/v0.13.0) is mandatory for **elephant compatibility**. ### _Dragon_ Network Compatibility (catapult-server@0.4.0.1) From 5899cce535fc6c9c0979cea09a1163fbb034122d Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 8 Jul 2019 22:45:10 +0100 Subject: [PATCH 05/13] Added #195 fixed compatibility issue on new rxjs version --- src/infrastructure/AccountHttp.ts | 220 +++++++++++------- src/infrastructure/BlockHttp.ts | 159 +++++++------ src/infrastructure/ChainHttp.ts | 31 ++- src/infrastructure/DiagnosticHttp.ts | 35 +-- src/infrastructure/Http.ts | 8 + src/infrastructure/MosaicHttp.ts | 152 ++++++------ src/infrastructure/NamespaceHttp.ts | 97 +++++--- src/infrastructure/NetworkHttp.ts | 23 +- src/infrastructure/NodeHttp.ts | 42 ++-- src/infrastructure/TransactionHttp.ts | 69 ++++-- src/infrastructure/api/accountRoutesApi.ts | 84 ++----- src/infrastructure/api/blockRoutesApi.ts | 42 +--- src/infrastructure/api/chainRoutesApi.ts | 14 +- src/infrastructure/api/diagnosticRoutesApi.ts | 14 +- src/infrastructure/api/mosaicRoutesApi.ts | 21 +- src/infrastructure/api/namespaceRoutesApi.ts | 28 +-- src/infrastructure/api/networkRoutesApi.ts | 7 +- src/infrastructure/api/nodeRoutesApi.ts | 14 +- .../api/transactionRoutesApi.ts | 49 ++-- .../templates/api-single.mustache | 7 +- 20 files changed, 580 insertions(+), 536 deletions(-) diff --git a/src/infrastructure/AccountHttp.ts b/src/infrastructure/AccountHttp.ts index 6ef6ba3fae..aed431fd19 100644 --- a/src/infrastructure/AccountHttp.ts +++ b/src/infrastructure/AccountHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import { DtoMapping } from '../core/utils/DtoMapping'; import {AccountInfo} from '../model/account/AccountInfo'; import { AccountNames } from '../model/account/AccountNames'; @@ -34,7 +35,6 @@ import {UInt64} from '../model/UInt64'; import {AccountRepository} from './AccountRepository'; import { AccountInfoDTO, AccountNamesDTO, - AccountRestrictionsDTO, AccountRestrictionsInfoDTO, AccountRoutesApi, MosaicDTO, @@ -75,21 +75,25 @@ export class AccountHttp extends Http implements AccountRepository { * @returns Observable */ public getAccountInfo(address: Address): Observable { - return observableFrom(this.accountRoutesApi.getAccountInfo(address.plain())).pipe(map((accountInfoDTO: AccountInfoDTO) => { - return new AccountInfo( - accountInfoDTO.meta, - Address.createFromEncoded(accountInfoDTO.account.address), - new UInt64(accountInfoDTO.account.addressHeight), - accountInfoDTO.account.publicKey, - new UInt64(accountInfoDTO.account.publicKeyHeight), - accountInfoDTO.account.mosaics.map((mosaicDTO) => new Mosaic( - new MosaicId(mosaicDTO.id), - new UInt64(mosaicDTO.amount), - )), - new UInt64(accountInfoDTO.account.importance), - new UInt64(accountInfoDTO.account.importanceHeight), - ); - })); + return observableFrom(this.accountRoutesApi.getAccountInfo(address.plain())).pipe( + map((response: { response: ClientResponse; body: AccountInfoDTO; }) => { + const accountInfoDTO = response.body; + return new AccountInfo( + accountInfoDTO.meta, + Address.createFromEncoded(accountInfoDTO.account.address), + new UInt64(accountInfoDTO.account.addressHeight), + accountInfoDTO.account.publicKey, + new UInt64(accountInfoDTO.account.publicKeyHeight), + accountInfoDTO.account.mosaics.map((mosaicDTO) => new Mosaic( + new MosaicId(mosaicDTO.id), + new UInt64(mosaicDTO.amount), + )), + new UInt64(accountInfoDTO.account.importance), + new UInt64(accountInfoDTO.account.importanceHeight), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -99,9 +103,12 @@ export class AccountHttp extends Http implements AccountRepository { */ public getAccountRestrictions(address: Address): Observable { return observableFrom(this.accountRoutesApi.getAccountRestrictions(address.plain())) - .pipe(map((accountRestrictions: AccountRestrictionsInfoDTO) => { - return DtoMapping.extractAccountRestrictionFromDto(accountRestrictions); - })); + .pipe(map((response: { response: ClientResponse; body: AccountRestrictionsInfoDTO; }) => { + const accountRestrictions = response.body; + return DtoMapping.extractAccountRestrictionFromDto(accountRestrictions); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -115,11 +122,14 @@ export class AccountHttp extends Http implements AccountRepository { }; return observableFrom( this.accountRoutesApi.getAccountRestrictionsFromAccounts(accountIds)) - .pipe(map((accountRestrictions: AccountRestrictionsDTO[]) => { - return accountRestrictions.map((restriction) => { - return DtoMapping.extractAccountRestrictionFromDto(restriction); - }); - })); + .pipe(map((response: { response: ClientResponse; body: AccountRestrictionsInfoDTO[]; }) => { + const accountRestrictions = response.body; + return accountRestrictions.map((restriction) => { + return DtoMapping.extractAccountRestrictionFromDto(restriction); + }); + }), + catchError((error) => throwError(error)), + ); } /** @@ -132,21 +142,25 @@ export class AccountHttp extends Http implements AccountRepository { addresses: addresses.map((address) => address.plain()), }; return observableFrom( - this.accountRoutesApi.getAccountsInfo(accountIdsBody)).pipe(map((accountsInfoMetaDataDTO: AccountInfoDTO[]) => { - return accountsInfoMetaDataDTO.map((accountInfoDTO: AccountInfoDTO) => { - return new AccountInfo( - accountInfoDTO.meta, - Address.createFromEncoded(accountInfoDTO.account.address), - new UInt64(accountInfoDTO.account.addressHeight), - accountInfoDTO.account.publicKey, - new UInt64(accountInfoDTO.account.publicKeyHeight), - accountInfoDTO.account.mosaics.map((mosaicDTO: MosaicDTO) => - new Mosaic(new MosaicId(mosaicDTO.id), new UInt64(mosaicDTO.amount))), - new UInt64(accountInfoDTO.account.importance), - new UInt64(accountInfoDTO.account.importanceHeight), - ); - }); - })); + this.accountRoutesApi.getAccountsInfo(accountIdsBody)).pipe( + map((response: { response: ClientResponse; body: AccountInfoDTO[]; }) => { + const accountsInfoMetaDataDTO = response.body; + return accountsInfoMetaDataDTO.map((accountInfoDTO: AccountInfoDTO) => { + return new AccountInfo( + accountInfoDTO.meta, + Address.createFromEncoded(accountInfoDTO.account.address), + new UInt64(accountInfoDTO.account.addressHeight), + accountInfoDTO.account.publicKey, + new UInt64(accountInfoDTO.account.publicKeyHeight), + accountInfoDTO.account.mosaics.map((mosaicDTO: MosaicDTO) => + new Mosaic(new MosaicId(mosaicDTO.id), new UInt64(mosaicDTO.amount))), + new UInt64(accountInfoDTO.account.importance), + new UInt64(accountInfoDTO.account.importanceHeight), + ); + }); + }), + catchError((error) => throwError(error)), + ); } public getAccountsNames(addresses: Address[]): Observable { @@ -154,16 +168,20 @@ export class AccountHttp extends Http implements AccountRepository { addresses: addresses.map((address) => address.plain()), }; return observableFrom( - this.accountRoutesApi.getAccountsNames(accountIdsBody)).pipe(map((accountNames: AccountNamesDTO[]) => { - return accountNames.map((accountName) => { - return new AccountNames( - Address.createFromEncoded(accountName.address), - accountName.names.map((name) => { - return new NamespaceName(new NamespaceId(name), name); - }), - ); - }); - })); + this.accountRoutesApi.getAccountsNames(accountIdsBody)).pipe( + map((response: { response: ClientResponse; body: AccountNamesDTO[]; }) => { + const accountNames = response.body; + return accountNames.map((accountName) => { + return new AccountNames( + Address.createFromEncoded(accountName.address), + accountName.names.map((name) => { + return new NamespaceName(new NamespaceId(name), name); + }), + ); + }); + }), + catchError((error) => throwError(error)), + ); } /** * Gets a MultisigAccountInfo for an account. @@ -174,17 +192,20 @@ export class AccountHttp extends Http implements AccountRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.accountRoutesApi.getAccountMultisig(address.plain())) - .pipe(map((multisigAccountInfoDTO: MultisigAccountInfoDTO) => { - return new MultisigAccountInfo( - PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), - multisigAccountInfoDTO.multisig.minApproval, - multisigAccountInfoDTO.multisig.minRemoval, - multisigAccountInfoDTO.multisig.cosignatories - .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), - multisigAccountInfoDTO.multisig.multisigAccounts - .map((multisigAccount) => PublicAccount.createFromPublicKey(multisigAccount, networkType)), - ); - })))); + .pipe(map((response: { response: ClientResponse; body: MultisigAccountInfoDTO; }) => { + const multisigAccountInfoDTO = response.body; + return new MultisigAccountInfo( + PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), + multisigAccountInfoDTO.multisig.minApproval, + multisigAccountInfoDTO.multisig.minRemoval, + multisigAccountInfoDTO.multisig.cosignatories + .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), + multisigAccountInfoDTO.multisig.multisigAccounts + .map((multisigAccount) => PublicAccount.createFromPublicKey(multisigAccount, networkType)), + ); + }), + catchError((error) => throwError(error)), + ))); } /** @@ -196,24 +217,28 @@ export class AccountHttp extends Http implements AccountRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.accountRoutesApi.getAccountMultisigGraph(address.plain())) - .pipe(map((multisigAccountGraphInfosDTO: MultisigAccountGraphInfoDTO[]) => { - const multisigAccounts = new Map(); - multisigAccountGraphInfosDTO.map((multisigAccountGraphInfoDTO) => { - multisigAccounts.set(multisigAccountGraphInfoDTO.level, - multisigAccountGraphInfoDTO.multisigEntries.map((multisigAccountInfoDTO) => { - return new MultisigAccountInfo( - PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), - multisigAccountInfoDTO.multisig.minApproval, - multisigAccountInfoDTO.multisig.minRemoval, - multisigAccountInfoDTO.multisig.cosignatories - .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), - multisigAccountInfoDTO.multisig.multisigAccounts - .map((multisigAccountDTO) => PublicAccount.createFromPublicKey(multisigAccountDTO, networkType))); - }), - ); - }); - return new MultisigAccountGraphInfo(multisigAccounts); - })))); + .pipe(map((response: { response: ClientResponse; body: MultisigAccountGraphInfoDTO[]; }) => { + const multisigAccountGraphInfosDTO = response.body; + const multisigAccounts = new Map(); + multisigAccountGraphInfosDTO.map((multisigAccountGraphInfoDTO) => { + multisigAccounts.set(multisigAccountGraphInfoDTO.level, + multisigAccountGraphInfoDTO.multisigEntries.map((multisigAccountInfoDTO) => { + return new MultisigAccountInfo( + PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), + multisigAccountInfoDTO.multisig.minApproval, + multisigAccountInfoDTO.multisig.minRemoval, + multisigAccountInfoDTO.multisig.cosignatories + .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), + multisigAccountInfoDTO.multisig.multisigAccounts + .map((multisigAccountDTO) => + PublicAccount.createFromPublicKey(multisigAccountDTO, networkType))); + }), + ); + }); + return new MultisigAccountGraphInfo(multisigAccounts); + }), + catchError((error) => throwError(error)), + ))); } /** @@ -228,11 +253,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -248,11 +276,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -268,11 +299,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -289,11 +323,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -309,10 +346,13 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO) as AggregateTransaction; }); - })); + }), + catchError((error) => throwError(error)), + ); } } diff --git a/src/infrastructure/BlockHttp.ts b/src/infrastructure/BlockHttp.ts index f04089fb52..a6f4ce9bb8 100644 --- a/src/infrastructure/BlockHttp.ts +++ b/src/infrastructure/BlockHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {BlockInfo} from '../model/blockchain/BlockInfo'; import { MerklePathItem } from '../model/blockchain/MerklePathItem'; @@ -79,29 +80,33 @@ export class BlockHttp extends Http implements BlockRepository { * @returns Observable */ public getBlockByHeight(height: number): Observable { - return observableFrom(this.blockRoutesApi.getBlockByHeight(height)).pipe(map((blockDTO: BlockInfoDTO) => { - const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); - return new BlockInfo( - blockDTO.meta.hash, - blockDTO.meta.generationHash, - new UInt64(blockDTO.meta.totalFee), - blockDTO.meta.numTransactions, - blockDTO.block.signature, - PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), - networkType, - parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version - blockDTO.block.type, - new UInt64(blockDTO.block.height), - new UInt64(blockDTO.block.timestamp), - new UInt64(blockDTO.block.difficulty), - blockDTO.block.feeMultiplier, - blockDTO.block.previousBlockHash, - blockDTO.block.blockTransactionsHash, - blockDTO.block.blockReceiptsHash, - blockDTO.block.stateHash, - extractBeneficiary(blockDTO, networkType), - ); - })); + return observableFrom(this.blockRoutesApi.getBlockByHeight(height)).pipe( + map((response: { response: ClientResponse; body: BlockInfoDTO; } ) => { + const blockDTO = response.body; + const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); + return new BlockInfo( + blockDTO.meta.hash, + blockDTO.meta.generationHash, + new UInt64(blockDTO.meta.totalFee), + blockDTO.meta.numTransactions, + blockDTO.block.signature, + PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), + networkType, + parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version + blockDTO.block.type, + new UInt64(blockDTO.block.height), + new UInt64(blockDTO.block.timestamp), + new UInt64(blockDTO.block.difficulty), + blockDTO.block.feeMultiplier, + blockDTO.block.previousBlockHash, + blockDTO.block.blockTransactionsHash, + blockDTO.block.blockReceiptsHash, + blockDTO.block.stateHash, + extractBeneficiary(blockDTO, networkType), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -117,11 +122,14 @@ export class BlockHttp extends Http implements BlockRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)) - .pipe(map((transactionsDTO: TransactionInfoDTO[]) => { + .pipe(map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -132,31 +140,35 @@ export class BlockHttp extends Http implements BlockRepository { */ public getBlocksByHeightWithLimit(height: number, limit: LimitType = LimitType.N_25): Observable { return observableFrom( - this.blockRoutesApi.getBlocksByHeightWithLimit(height, limit)).pipe(map((blocksDTO: BlockInfoDTO[]) => { - return blocksDTO.map((blockDTO) => { - const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); - return new BlockInfo( - blockDTO.meta.hash, - blockDTO.meta.generationHash, - new UInt64(blockDTO.meta.totalFee), - blockDTO.meta.numTransactions, - blockDTO.block.signature, - PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), - networkType, - parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version - blockDTO.block.type, - new UInt64(blockDTO.block.height), - new UInt64(blockDTO.block.timestamp), - new UInt64(blockDTO.block.difficulty), - blockDTO.block.feeMultiplier, - blockDTO.block.previousBlockHash, - blockDTO.block.blockTransactionsHash, - blockDTO.block.blockReceiptsHash, - blockDTO.block.stateHash, - extractBeneficiary(blockDTO, networkType), - ); - }); - })); + this.blockRoutesApi.getBlocksByHeightWithLimit(height, limit)).pipe( + map((response: { response: ClientResponse; body: BlockInfoDTO[]; }) => { + const blocksDTO = response.body; + return blocksDTO.map((blockDTO) => { + const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); + return new BlockInfo( + blockDTO.meta.hash, + blockDTO.meta.generationHash, + new UInt64(blockDTO.meta.totalFee), + blockDTO.meta.numTransactions, + blockDTO.block.signature, + PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), + networkType, + parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version + blockDTO.block.type, + new UInt64(blockDTO.block.height), + new UInt64(blockDTO.block.timestamp), + new UInt64(blockDTO.block.difficulty), + blockDTO.block.feeMultiplier, + blockDTO.block.previousBlockHash, + blockDTO.block.blockTransactionsHash, + blockDTO.block.blockReceiptsHash, + blockDTO.block.stateHash, + extractBeneficiary(blockDTO, networkType), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -171,14 +183,18 @@ export class BlockHttp extends Http implements BlockRepository { */ public getMerkleReceipts(height: number, hash: string): Observable { return observableFrom( - this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe(map((merkleProofReceipt: MerkleProofInfoDTO) => { - return new MerkleProofInfo( - new MerkleProofInfoPayload( - merkleProofReceipt.payload.merklePath!.map( - (payload) => new MerklePathItem(payload.position, payload.hash))), - merkleProofReceipt.type, - ); - })); + this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe( + map((response: { response: ClientResponse; body: MerkleProofInfoDTO; } ) => { + const merkleProofReceipt = response.body; + return new MerkleProofInfo( + new MerkleProofInfoPayload( + merkleProofReceipt.payload.merklePath!.map( + (payload) => new MerklePathItem(payload.position, payload.hash))), + merkleProofReceipt.type, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -193,13 +209,18 @@ export class BlockHttp extends Http implements BlockRepository { */ public getMerkleTransaction(height: number, hash: string): Observable { return observableFrom( - this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe(map((merkleProofTransaction: MerkleProofInfoDTO) => { - return new MerkleProofInfo( - new MerkleProofInfoPayload( - merkleProofTransaction.payload.merklePath!.map((payload) => new MerklePathItem(payload.position, payload.hash))), - merkleProofTransaction.type, - ); - })); + this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe( + map((response: { response: ClientResponse; body: MerkleProofInfoDTO; } ) => { + const merkleProofTransaction = response.body; + return new MerkleProofInfo( + new MerkleProofInfoPayload( + merkleProofTransaction.payload.merklePath!.map((payload) => + new MerklePathItem(payload.position, payload.hash))), + merkleProofTransaction.type, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -212,9 +233,11 @@ export class BlockHttp extends Http implements BlockRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.blockRoutesApi.getBlockReceipts(height)).pipe( - map((receiptDTO: StatementsDTO) => { + map((response: { response: ClientResponse; body: StatementsDTO; }) => { + const receiptDTO = response.body; return CreateStatementFromDTO(receiptDTO, networkType); }), + catchError((error) => throwError(this.errorHandling(error))), ), ), ); diff --git a/src/infrastructure/ChainHttp.ts b/src/infrastructure/ChainHttp.ts index c791b69297..5b32953b6f 100644 --- a/src/infrastructure/ChainHttp.ts +++ b/src/infrastructure/ChainHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {BlockchainScore} from '../model/blockchain/BlockchainScore'; import {UInt64} from '../model/UInt64'; import { BlockchainScoreDTO, @@ -50,9 +51,13 @@ export class ChainHttp extends Http implements ChainRepository { * @returns Observable */ public getBlockchainHeight(): Observable { - return observableFrom(this.chainRoutesApi.getBlockchainHeight()).pipe(map((heightDTO: HeightInfoDTO) => { - return new UInt64(heightDTO.height); - })); + return observableFrom(this.chainRoutesApi.getBlockchainHeight()).pipe( + map((response: { response: ClientResponse; body: HeightInfoDTO; } ) => { + const heightDTO = response.body; + return new UInt64(heightDTO.height); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -60,11 +65,15 @@ export class ChainHttp extends Http implements ChainRepository { * @returns Observable */ public getBlockchainScore(): Observable { - return observableFrom(this.chainRoutesApi.getBlockchainScore()).pipe(map((blockchainScoreDTO: BlockchainScoreDTO) => { - return new BlockchainScore( - new UInt64(blockchainScoreDTO.scoreLow), - new UInt64(blockchainScoreDTO.scoreHigh), - ); - })); + return observableFrom(this.chainRoutesApi.getBlockchainScore()).pipe( + map((response: { response: ClientResponse; body: BlockchainScoreDTO; } ) => { + const blockchainScoreDTO = response.body; + return new BlockchainScore( + new UInt64(blockchainScoreDTO.scoreLow), + new UInt64(blockchainScoreDTO.scoreHigh), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/DiagnosticHttp.ts b/src/infrastructure/DiagnosticHttp.ts index be17dbcf5e..0af049602a 100644 --- a/src/infrastructure/DiagnosticHttp.ts +++ b/src/infrastructure/DiagnosticHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {BlockchainStorageInfo} from '../model/blockchain/BlockchainStorageInfo'; import { ServerInfo } from '../model/diagnostic/ServerInfo'; import { DiagnosticRoutesApi, ServerDTO, StorageInfoDTO } from './api'; @@ -49,13 +50,17 @@ export class DiagnosticHttp extends Http implements DiagnosticRepository { */ public getDiagnosticStorage(): Observable { return observableFrom( - this.diagnosticRoutesApi.getDiagnosticStorage()).pipe(map((blockchainStorageInfoDTO: StorageInfoDTO) => { - return new BlockchainStorageInfo( - blockchainStorageInfoDTO.numBlocks, - blockchainStorageInfoDTO.numTransactions, - blockchainStorageInfoDTO.numAccounts, - ); - })); + this.diagnosticRoutesApi.getDiagnosticStorage()).pipe( + map((response: { response: ClientResponse; body: StorageInfoDTO; } ) => { + const blockchainStorageInfoDTO = response.body; + return new BlockchainStorageInfo( + blockchainStorageInfoDTO.numBlocks, + blockchainStorageInfoDTO.numTransactions, + blockchainStorageInfoDTO.numAccounts, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -64,9 +69,13 @@ export class DiagnosticHttp extends Http implements DiagnosticRepository { */ public getServerInfo(): Observable { return observableFrom( - this.diagnosticRoutesApi.getServerInfo()).pipe(map((serverDTO: ServerDTO) => { - return new ServerInfo(serverDTO.serverInfo.restVersion, - serverDTO.serverInfo.sdkVersion); - })); + this.diagnosticRoutesApi.getServerInfo()).pipe( + map((response: { response: ClientResponse; body: ServerDTO; } ) => { + const serverDTO = response.body; + return new ServerInfo(serverDTO.serverInfo.restVersion, + serverDTO.serverInfo.sdkVersion); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/Http.ts b/src/infrastructure/Http.ts index 7185797d17..2a94ac1a66 100644 --- a/src/infrastructure/Http.ts +++ b/src/infrastructure/Http.ts @@ -57,4 +57,12 @@ export abstract class Http { order: queryParams ? queryParams.order : undefined, }; } + + errorHandling(error: any): Error { + const formattedError = { + statusCode: error.response.statusCode, + errorDetails: error.response.body, + }; + return new Error(JSON.stringify(formattedError)); + } } diff --git a/src/infrastructure/MosaicHttp.ts b/src/infrastructure/MosaicHttp.ts index 1d56765c0b..104aee210b 100644 --- a/src/infrastructure/MosaicHttp.ts +++ b/src/infrastructure/MosaicHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {MosaicId} from '../model/mosaic/MosaicId'; import {MosaicInfo} from '../model/mosaic/MosaicInfo'; @@ -61,33 +62,38 @@ export class MosaicHttp extends Http implements MosaicRepository { public getMosaic(mosaicId: MosaicId): Observable { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.mosaicRoutesApi.getMosaic(mosaicId.toHex())).pipe(map((mosaicInfoDTO: MosaicInfoDTO) => { - let mosaicFlag; - let divisibility; - let duration; - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { - mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { - divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { - duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - return new MosaicInfo( - mosaicInfoDTO.meta.id, - new MosaicId(mosaicInfoDTO.mosaic.mosaicId), - new UInt64(mosaicInfoDTO.mosaic.supply), - new UInt64(mosaicInfoDTO.mosaic.height), - PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), - mosaicInfoDTO.mosaic.revision, - new MosaicProperties( - mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), - (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), - duration ? new UInt64(duration) : undefined, - ), - ); - })))); + this.mosaicRoutesApi.getMosaic(mosaicId.toHex())).pipe( + map((response: { response: ClientResponse; body: MosaicInfoDTO; } ) => { + const mosaicInfoDTO = response.body; + let mosaicFlag; + let divisibility; + let duration; + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { + mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { + divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { + duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + return new MosaicInfo( + mosaicInfoDTO.meta.id, + new MosaicId(mosaicInfoDTO.mosaic.mosaicId), + new UInt64(mosaicInfoDTO.mosaic.supply), + new UInt64(mosaicInfoDTO.mosaic.height), + PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), + mosaicInfoDTO.mosaic.revision, + new MosaicProperties( + mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), + (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), + duration ? new UInt64(duration) : undefined, + ), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + )), + ); } /** @@ -101,35 +107,41 @@ export class MosaicHttp extends Http implements MosaicRepository { }; return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.mosaicRoutesApi.getMosaics(mosaicIdsBody)).pipe(map((mosaicInfosDTO: MosaicInfoDTO[]) => { - return mosaicInfosDTO.map((mosaicInfoDTO) => { - let mosaicFlag; - let divisibility; - let duration; - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { - mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { - divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { - duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value; - } - return new MosaicInfo( - mosaicInfoDTO.meta.id, - new MosaicId(mosaicInfoDTO.mosaic.mosaicId), - new UInt64(mosaicInfoDTO.mosaic.supply), - new UInt64(mosaicInfoDTO.mosaic.height), - PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), - mosaicInfoDTO.mosaic.revision, - new MosaicProperties( - mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), - (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), - duration ? new UInt64(duration) : undefined, - ), - ); - }); - })))); + this.mosaicRoutesApi.getMosaics(mosaicIdsBody)).pipe( + map((response: { response: ClientResponse; body: MosaicInfoDTO[]; }) => { + const mosaicInfosDTO = response.body; + return mosaicInfosDTO.map((mosaicInfoDTO) => { + let mosaicFlag; + let divisibility; + let duration; + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { + mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { + divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { + duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value; + } + return new MosaicInfo( + mosaicInfoDTO.meta.id, + new MosaicId(mosaicInfoDTO.mosaic.mosaicId), + new UInt64(mosaicInfoDTO.mosaic.supply), + new UInt64(mosaicInfoDTO.mosaic.height), + PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), + mosaicInfoDTO.mosaic.revision, + new MosaicProperties( + mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), + (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), + duration ? new UInt64(duration) : undefined, + ), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + ), + ); } /** @@ -143,15 +155,19 @@ export class MosaicHttp extends Http implements MosaicRepository { mosaicIds: mosaicIds.map((id) => id.toHex()), }; return observableFrom( - this.mosaicRoutesApi.getMosaicsNames(mosaicIdsBody)).pipe(map((mosaics: MosaicNamesDTO[]) => { - return mosaics.map((mosaic) => { - return new MosaicNames( - new MosaicId(mosaic.mosaicId), - mosaic.names.map((name) => { - return new NamespaceName(new NamespaceId(name), name); - }), - ); - }); - })); + this.mosaicRoutesApi.getMosaicsNames(mosaicIdsBody)).pipe( + map((response: { response: ClientResponse; body: MosaicNamesDTO[]; }) => { + const mosaics = response.body; + return mosaics.map((mosaic) => { + return new MosaicNames( + new MosaicId(mosaic.mosaicId), + mosaic.names.map((name) => { + return new NamespaceName(new NamespaceId(name), name); + }), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/NamespaceHttp.ts b/src/infrastructure/NamespaceHttp.ts index 64ad0e94af..4d695f44bc 100644 --- a/src/infrastructure/NamespaceHttp.ts +++ b/src/infrastructure/NamespaceHttp.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {Convert as convert, RawAddress as AddressLibrary} from '../core/format'; import {Address} from '../model/account/Address'; import {PublicAccount} from '../model/account/PublicAccount'; @@ -65,21 +66,27 @@ export class NamespaceHttp extends Http implements NamespaceRepository { public getNamespace(namespaceId: NamespaceId): Observable { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe(map((namespaceInfoDTO: NamespaceInfoDTO) => { - return new NamespaceInfo( - namespaceInfoDTO.meta.active, - namespaceInfoDTO.meta.index, - namespaceInfoDTO.meta.id, - namespaceInfoDTO.namespace.type as number, - namespaceInfoDTO.namespace.depth, - this.extractLevels(namespaceInfoDTO.namespace), - new NamespaceId(namespaceInfoDTO.namespace.parentId), - PublicAccount.createFromPublicKey(namespaceInfoDTO.namespace.owner, networkType), - new UInt64(namespaceInfoDTO.namespace.startHeight), - new UInt64(namespaceInfoDTO.namespace.endHeight), - this.extractAlias(namespaceInfoDTO.namespace), - ); - })))); + this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; + return new NamespaceInfo( + namespaceInfoDTO.meta.active, + namespaceInfoDTO.meta.index, + namespaceInfoDTO.meta.id, + namespaceInfoDTO.namespace.type as number, + namespaceInfoDTO.namespace.depth, + this.extractLevels(namespaceInfoDTO.namespace), + new NamespaceId(namespaceInfoDTO.namespace.parentId), + PublicAccount.createFromPublicKey(namespaceInfoDTO.namespace.owner, networkType), + new UInt64(namespaceInfoDTO.namespace.startHeight), + new UInt64(namespaceInfoDTO.namespace.endHeight), + this.extractAlias(namespaceInfoDTO.namespace), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + ), + ); } /** @@ -96,7 +103,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((namespaceInfosDTO: NamespaceInfoDTO[]) => { + map((response: { response: ClientResponse; body: NamespaceInfoDTO[]; }) => { + const namespaceInfosDTO = response.body; return namespaceInfosDTO.map((namespaceInfoDTO) => { return new NamespaceInfo( namespaceInfoDTO.meta.active, @@ -112,7 +120,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.extractAlias(namespaceInfoDTO.namespace), ); }); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -132,7 +143,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((namespaceInfosDTO: NamespaceInfoDTO[]) => { + map((response: { response: ClientResponse; body: NamespaceInfoDTO[]; }) => { + const namespaceInfosDTO = response.body; return namespaceInfosDTO.map((namespaceInfoDTO) => { return new NamespaceInfo( namespaceInfoDTO.meta.active, @@ -148,7 +160,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.extractAlias(namespaceInfoDTO.namespace), ); }); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -161,15 +176,19 @@ export class NamespaceHttp extends Http implements NamespaceRepository { namespaceIds: namespaceIds.map((id) => id.toHex()), }; return observableFrom( - this.namespaceRoutesApi.getNamespacesNames(namespaceIdsBody)).pipe(map((namespaceNamesDTO: NamespaceNameDTO[]) => { - return namespaceNamesDTO.map((namespaceNameDTO) => { - return new NamespaceName( - new NamespaceId(namespaceNameDTO.namespaceId), - namespaceNameDTO.name, - namespaceNameDTO.parentId ? new NamespaceId(namespaceNameDTO.parentId) : undefined, - ); - }); - })); + this.namespaceRoutesApi.getNamespacesNames(namespaceIdsBody)).pipe( + map((response: { response: ClientResponse; body: NamespaceNameDTO[]; } ) => { + const namespaceNamesDTO = response.body; + return namespaceNamesDTO.map((namespaceNameDTO) => { + return new NamespaceName( + new NamespaceId(namespaceNameDTO.namespaceId), + namespaceNameDTO.name, + namespaceNameDTO.parentId ? new NamespaceId(namespaceNameDTO.parentId) : undefined, + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -181,8 +200,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( - map((namespaceInfoDTO: NamespaceInfoDTO) => { - + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; if (namespaceInfoDTO.namespace === undefined) { // forward catapult-rest error throw namespaceInfoDTO; @@ -194,7 +213,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { throw new Error('No mosaicId is linked to namespace \'' + namespaceInfoDTO.namespace.level0 + '\''); } return new MosaicId(namespaceInfoDTO.namespace.alias.mosaicId); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -206,8 +228,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( - map((namespaceInfoDTO: NamespaceInfoDTO) => { - + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; if (namespaceInfoDTO.namespace === undefined) { // forward catapult-rest error throw namespaceInfoDTO; @@ -222,7 +244,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { const addressDecoded = namespaceInfoDTO.namespace.alias.address; const address = AddressLibrary.addressToString(convert.hexToUint8(addressDecoded)); return Address.createFromRawAddress(address); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } private extractLevels(namespace: any): NamespaceId[] { diff --git a/src/infrastructure/NetworkHttp.ts b/src/infrastructure/NetworkHttp.ts index cbdc53ee9a..a635710304 100644 --- a/src/infrastructure/NetworkHttp.ts +++ b/src/infrastructure/NetworkHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {NetworkType} from '../model/blockchain/NetworkType'; import { NetworkRoutesApi, NetworkTypeDTO } from './api'; import {Http} from './Http'; @@ -49,12 +50,16 @@ export class NetworkHttp extends Http implements NetworkRepository { * @return network type enum. */ public getNetworkType(): Observable { - return observableFrom(this.networkRoutesApi.getNetworkType()).pipe(map((networkTypeDTO: NetworkTypeDTO) => { - if (networkTypeDTO.name === 'mijinTest') { - return NetworkType.MIJIN_TEST; - } else { - throw new Error('network ' + networkTypeDTO.name + ' is not supported yet by the sdk'); - } - })); + return observableFrom(this.networkRoutesApi.getNetworkType()).pipe( + map((response: { response: ClientResponse; body: NetworkTypeDTO; } ) => { + const networkTypeDTO = response.body; + if (networkTypeDTO.name === 'mijinTest') { + return NetworkType.MIJIN_TEST; + } else { + throw new Error('network ' + networkTypeDTO.name + ' is not supported yet by the sdk'); + } + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/NodeHttp.ts b/src/infrastructure/NodeHttp.ts index 7a29ea3388..81f81a8d25 100644 --- a/src/infrastructure/NodeHttp.ts +++ b/src/infrastructure/NodeHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import { NodeInfo } from '../model/node/NodeInfo'; import { NodeTime } from '../model/node/NodeTime'; import { NodeInfoDTO, NodeRoutesApi, NodeTimeDTO } from './api'; @@ -49,17 +50,21 @@ export class NodeHttp extends Http implements NodeRepository { * @summary Get the node information */ public getNodeInfo(): Observable { - return observableFrom(this.nodeRoutesApi.getNodeInfo()).pipe(map((nodeInfoDTO: NodeInfoDTO) => { - return new NodeInfo( - nodeInfoDTO.publicKey, - nodeInfoDTO.port, - nodeInfoDTO.networkIdentifier, - nodeInfoDTO.version, - nodeInfoDTO.roles as number, - nodeInfoDTO.host, - nodeInfoDTO.friendlyName, - ); - })); + return observableFrom(this.nodeRoutesApi.getNodeInfo()).pipe( + map((response: { response: ClientResponse; body: NodeInfoDTO; } ) => { + const nodeInfoDTO = response.body; + return new NodeInfo( + nodeInfoDTO.publicKey, + nodeInfoDTO.port, + nodeInfoDTO.networkIdentifier, + nodeInfoDTO.version, + nodeInfoDTO.roles as number, + nodeInfoDTO.host, + nodeInfoDTO.friendlyName, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -67,8 +72,13 @@ export class NodeHttp extends Http implements NodeRepository { * @summary Get the node time */ public getNodeTime(): Observable { - return observableFrom(this.nodeRoutesApi.getNodeTime()).pipe(map((nodeTimeDTO: NodeTimeDTO) => { - return new NodeTime(nodeTimeDTO.communicationTimestamps.sendTimestamp, nodeTimeDTO.communicationTimestamps.receiveTimestamp); - })); + return observableFrom(this.nodeRoutesApi.getNodeTime()).pipe( + map((response: { response: ClientResponse; body: NodeTimeDTO; } ) => { + const nodeTimeDTO = response.body; + return new NodeTime(nodeTimeDTO.communicationTimestamps.sendTimestamp, + nodeTimeDTO.communicationTimestamps.receiveTimestamp); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/TransactionHttp.ts b/src/infrastructure/TransactionHttp.ts index 332ada1e85..8c6455f6f9 100644 --- a/src/infrastructure/TransactionHttp.ts +++ b/src/infrastructure/TransactionHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { ClientResponse } from 'http'; import * as requestPromise from 'request-promise-native'; -import {from as observableFrom, Observable, throwError as observableThrowError} from 'rxjs'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {CosignatureSignedTransaction} from '../model/transaction/CosignatureSignedTransaction'; @@ -86,11 +87,15 @@ export class TransactionHttp extends Http implements TransactionRepository { transactionIds, }; return observableFrom( - this.transactionRoutesApi.getTransactions(transactionIdsBody)).pipe(map((transactionsDTO: TransactionInfoDTO[]) => { - return transactionsDTO.map((transactionDTO) => { - return CreateTransactionFromDTO(transactionDTO); - }); - })); + this.transactionRoutesApi.getTransactions(transactionIdsBody)).pipe( + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; } ) => { + const transactionsDTO = response.body; + return transactionsDTO.map((transactionDTO) => { + return CreateTransactionFromDTO(transactionDTO); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -100,14 +105,17 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public getTransactionStatus(transactionHash: string): Observable { return observableFrom(this.transactionRoutesApi.getTransactionStatus(transactionHash)).pipe( - map((transactionStatusDTO: TransactionStatusDTO) => { + map((response: { response: ClientResponse; body: TransactionStatusDTO; } ) => { + const transactionStatusDTO = response.body; return new TransactionStatus( transactionStatusDTO.status, transactionStatusDTO.group, transactionStatusDTO.hash, transactionStatusDTO.deadline ? Deadline.createFromDTO(transactionStatusDTO.deadline) : undefined, transactionStatusDTO.height ? new UInt64(transactionStatusDTO.height) : undefined); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -121,7 +129,8 @@ export class TransactionHttp extends Http implements TransactionRepository { }; return observableFrom( this.transactionRoutesApi.getTransactionsStatuses(transactionHashesBody)).pipe( - map((transactionStatusesDTO: TransactionStatusDTO[]) => { + map((response: { response: ClientResponse; body: TransactionStatusDTO[]; }) => { + const transactionStatusesDTO = response.body; return transactionStatusesDTO.map((transactionStatusDTO) => { return new TransactionStatus( transactionStatusDTO.status, @@ -130,7 +139,9 @@ export class TransactionHttp extends Http implements TransactionRepository { transactionStatusDTO.deadline ? Deadline.createFromDTO(transactionStatusDTO.deadline) : undefined, transactionStatusDTO.height ? new UInt64(transactionStatusDTO.height) : undefined); }); - })); + }), + catchError((error) => throwError(error.error.errorMessage)), + ); } /** @@ -140,9 +151,12 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announce(signedTransaction: SignedTransaction): Observable { return observableFrom(this.transactionRoutesApi.announceTransaction(signedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -152,14 +166,15 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announceAggregateBonded(signedTransaction: SignedTransaction): Observable { if (signedTransaction.type !== TransactionType.AGGREGATE_BONDED) { - return observableFrom(new Promise((resolve, reject) => { - reject('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); - })); + throwError('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); } return observableFrom(this.transactionRoutesApi.announcePartialTransaction(signedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -170,9 +185,12 @@ export class TransactionHttp extends Http implements TransactionRepository { public announceAggregateBondedCosignature( cosignatureSignedTransaction: CosignatureSignedTransaction): Observable { return observableFrom(this.transactionRoutesApi.announceCosignatureTransaction(cosignatureSignedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } public announceSync(signedTx: SignedTransaction): Observable { @@ -198,9 +216,9 @@ export class TransactionHttp extends Http implements TransactionRepository { } }), catchError((err) => { if (err.statusCode === 405) { - return observableThrowError('non sync server'); + return throwError('non sync server'); } - return observableThrowError(err); + return throwError(err); })); } @@ -218,14 +236,15 @@ export class TransactionHttp extends Http implements TransactionRepository { // now read block details return observableFrom(this.blockRoutesApi.getBlockByHeight(uintHeight.compact())).pipe( - map((blockDTO: BlockInfoDTO) => { - + map((response: { response: ClientResponse; body: BlockInfoDTO; } ) => { + const blockDTO = response.body; // @see https://nemtech.github.io/concepts/transaction.html#fees // effective_fee = feeMultiplier x transaction::size return blockDTO.block.feeMultiplier * transaction.size; - })); + }), + catchError((error) => throwError(this.errorHandling(error)))); }), catchError((err) => { - return observableThrowError(err); + return throwError(err); })); } } diff --git a/src/infrastructure/api/accountRoutesApi.ts b/src/infrastructure/api/accountRoutesApi.ts index 529245b7a5..a4c378b15f 100644 --- a/src/infrastructure/api/accountRoutesApi.ts +++ b/src/infrastructure/api/accountRoutesApi.ts @@ -136,12 +136,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AccountInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -193,12 +190,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MultisigAccountInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -250,12 +244,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -307,12 +298,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AccountRestrictionsInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -364,12 +352,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -421,12 +406,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -478,12 +460,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -550,12 +529,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -622,12 +598,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -694,12 +667,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -766,12 +736,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -838,12 +805,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/blockRoutesApi.ts b/src/infrastructure/api/blockRoutesApi.ts index 881fb16997..eafea7acf8 100644 --- a/src/infrastructure/api/blockRoutesApi.ts +++ b/src/infrastructure/api/blockRoutesApi.ts @@ -133,12 +133,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "BlockInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -190,12 +187,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "StatementsDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -257,12 +251,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -321,12 +312,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -385,12 +373,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MerkleProofInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -449,12 +434,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MerkleProofInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/chainRoutesApi.ts b/src/infrastructure/api/chainRoutesApi.ts index 4e0706620c..e2697992b4 100644 --- a/src/infrastructure/api/chainRoutesApi.ts +++ b/src/infrastructure/api/chainRoutesApi.ts @@ -124,12 +124,9 @@ export class ChainRoutesApi { } else { body = ObjectSerializer.deserialize(body, "HeightInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class ChainRoutesApi { } else { body = ObjectSerializer.deserialize(body, "BlockchainScoreDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/diagnosticRoutesApi.ts b/src/infrastructure/api/diagnosticRoutesApi.ts index e70a25623f..01daa002d8 100644 --- a/src/infrastructure/api/diagnosticRoutesApi.ts +++ b/src/infrastructure/api/diagnosticRoutesApi.ts @@ -124,12 +124,9 @@ export class DiagnosticRoutesApi { } else { body = ObjectSerializer.deserialize(body, "StorageInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class DiagnosticRoutesApi { } else { body = ObjectSerializer.deserialize(body, "ServerDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/mosaicRoutesApi.ts b/src/infrastructure/api/mosaicRoutesApi.ts index dfb0e36a8b..00e398b6b6 100644 --- a/src/infrastructure/api/mosaicRoutesApi.ts +++ b/src/infrastructure/api/mosaicRoutesApi.ts @@ -132,12 +132,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MosaicInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -189,12 +186,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -246,12 +240,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/namespaceRoutesApi.ts b/src/infrastructure/api/namespaceRoutesApi.ts index 7ce0824c7b..9559ef2f13 100644 --- a/src/infrastructure/api/namespaceRoutesApi.ts +++ b/src/infrastructure/api/namespaceRoutesApi.ts @@ -133,12 +133,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NamespaceInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -200,12 +197,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -267,12 +261,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -324,12 +315,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/networkRoutesApi.ts b/src/infrastructure/api/networkRoutesApi.ts index 1e9fa0422c..3c574d8c46 100644 --- a/src/infrastructure/api/networkRoutesApi.ts +++ b/src/infrastructure/api/networkRoutesApi.ts @@ -123,12 +123,9 @@ export class NetworkRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NetworkTypeDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/nodeRoutesApi.ts b/src/infrastructure/api/nodeRoutesApi.ts index cd2b0ca19b..456a05ad64 100644 --- a/src/infrastructure/api/nodeRoutesApi.ts +++ b/src/infrastructure/api/nodeRoutesApi.ts @@ -124,12 +124,9 @@ export class NodeRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NodeInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class NodeRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NodeTimeDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/transactionRoutesApi.ts b/src/infrastructure/api/transactionRoutesApi.ts index 39618d7377..0a3abdd119 100644 --- a/src/infrastructure/api/transactionRoutesApi.ts +++ b/src/infrastructure/api/transactionRoutesApi.ts @@ -136,12 +136,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -193,12 +190,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -250,12 +244,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -307,12 +298,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "TransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -364,12 +352,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "TransactionStatusDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -421,12 +406,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -478,12 +460,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/templates/api-single.mustache b/src/infrastructure/templates/api-single.mustache index c90274237c..9dd163676f 100755 --- a/src/infrastructure/templates/api-single.mustache +++ b/src/infrastructure/templates/api-single.mustache @@ -219,12 +219,9 @@ export class {{classname}} { body = ObjectSerializer.deserialize(body, "{{{returnType}}}"); {{/returnType}} if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); From 6ccd22477547a2d412005450f716d2cc17e4fd8e Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 9 Jul 2019 09:56:52 +0100 Subject: [PATCH 06/13] Fixed error handling --- src/infrastructure/Http.ts | 13 ++++++++----- test/infrastructure/TransactionHttp.spec.ts | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/infrastructure/Http.ts b/src/infrastructure/Http.ts index 2a94ac1a66..7df9e615ae 100644 --- a/src/infrastructure/Http.ts +++ b/src/infrastructure/Http.ts @@ -59,10 +59,13 @@ export abstract class Http { } errorHandling(error: any): Error { - const formattedError = { - statusCode: error.response.statusCode, - errorDetails: error.response.body, - }; - return new Error(JSON.stringify(formattedError)); + if (error.response && error.response.statusCode && error.response.body) { + const formattedError = { + statusCode: error.response.statusCode, + errorDetails: error.response.body, + }; + return new Error(JSON.stringify(formattedError)); + } + return new Error(error); } } diff --git a/test/infrastructure/TransactionHttp.spec.ts b/test/infrastructure/TransactionHttp.spec.ts index 5a45c7d440..d7ab93c3b3 100644 --- a/test/infrastructure/TransactionHttp.spec.ts +++ b/test/infrastructure/TransactionHttp.spec.ts @@ -49,7 +49,6 @@ describe('TransactionHttp', () => { return trnsHttp.announceAggregateBonded(signedTx) .toPromise() .then(() => { - throw new Error('Should be called'); }) .catch((reason) => { expect(reason.toString()).to.be.equal('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); From 2a67d4de8b82aa60635d910403933dfbb059ee23 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Wed, 10 Jul 2019 09:56:29 +0100 Subject: [PATCH 07/13] Fixed transactionHttp unit test --- src/infrastructure/TransactionHttp.ts | 2 +- test/infrastructure/TransactionHttp.spec.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/infrastructure/TransactionHttp.ts b/src/infrastructure/TransactionHttp.ts index 8c6455f6f9..c96c863910 100644 --- a/src/infrastructure/TransactionHttp.ts +++ b/src/infrastructure/TransactionHttp.ts @@ -166,7 +166,7 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announceAggregateBonded(signedTransaction: SignedTransaction): Observable { if (signedTransaction.type !== TransactionType.AGGREGATE_BONDED) { - throwError('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); + throw new Error('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); } return observableFrom(this.transactionRoutesApi.announcePartialTransaction(signedTransaction)).pipe( map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { diff --git a/test/infrastructure/TransactionHttp.spec.ts b/test/infrastructure/TransactionHttp.spec.ts index d7ab93c3b3..40107dae10 100644 --- a/test/infrastructure/TransactionHttp.spec.ts +++ b/test/infrastructure/TransactionHttp.spec.ts @@ -46,12 +46,10 @@ describe('TransactionHttp', () => { const signedTx = account.sign(aggTx, generationHash); const trnsHttp = new TransactionHttp(NIS2_URL); - return trnsHttp.announceAggregateBonded(signedTx) + expect(() => { + trnsHttp.announceAggregateBonded(signedTx) .toPromise() - .then(() => { - }) - .catch((reason) => { - expect(reason.toString()).to.be.equal('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); - }); + .then(); + }).to.throw(Error, 'Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); }); }); From b02cfea9dea32fe333564bc0757727288d88980b Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 14:58:42 +0100 Subject: [PATCH 08/13] Added #204 - Fixed signTransactionGivenSignatures bug - Added e2e test for signTransactionGivenSignatures - Improved unit test for signTransactionGivenSignatures - Fixed typo --- e2e/infrastructure/TransactionHttp.spec.ts | 63 +++++++++++++++++++ .../transaction/CosignatureTransaction.ts | 11 ++-- .../transaction/AggregateTransaction.spec.ts | 22 ++++--- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/e2e/infrastructure/TransactionHttp.spec.ts b/e2e/infrastructure/TransactionHttp.spec.ts index 51c85b0408..2f60993e0c 100644 --- a/e2e/infrastructure/TransactionHttp.spec.ts +++ b/e2e/infrastructure/TransactionHttp.spec.ts @@ -19,6 +19,7 @@ import {ChronoUnit} from 'js-joda'; import {keccak_256, sha3_256} from 'js-sha3'; import {Crypto} from '../../src/core/crypto'; import { Convert as convert } from '../../src/core/format'; +import { TransactionMapping } from '../../src/core/utils/TransactionMapping'; import {AccountHttp} from '../../src/infrastructure/AccountHttp'; import { NamespaceHttp } from '../../src/infrastructure/infrastructure'; import {Listener} from '../../src/infrastructure/Listener'; @@ -45,6 +46,7 @@ import { AccountRestrictionTransaction } from '../../src/model/transaction/Accou import { AddressAliasTransaction } from '../../src/model/transaction/AddressAliasTransaction'; import {AggregateTransaction} from '../../src/model/transaction/AggregateTransaction'; import {CosignatureSignedTransaction} from '../../src/model/transaction/CosignatureSignedTransaction'; +import { CosignatureTransaction } from '../../src/model/transaction/CosignatureTransaction'; import {Deadline} from '../../src/model/transaction/Deadline'; import { HashLockTransaction } from '../../src/model/transaction/HashLockTransaction'; import {HashType} from '../../src/model/transaction/HashType'; @@ -1761,6 +1763,67 @@ describe('TransactionHttp', () => { }); }); + describe('SignTransactionGivenSignatures', () => { + let listener: Listener; + before (() => { + listener = new Listener(config.apiUrl); + return listener.open(); + }); + after(() => { + return listener.close(); + }); + it('Announce cosign signatures given', (done) => { + + /** + * @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 + */ + // AliceAccount: account + // BobAccount: account + + const sendAmount = NetworkCurrencyMosaic.createRelative(1000); + const backAmount = NetworkCurrencyMosaic.createRelative(1); + + const aliceTransferTransaction = TransferTransaction.create(Deadline.create(), account2.address, [sendAmount], + PlainMessage.create('payout'), NetworkType.MIJIN_TEST); + const bobTransferTransaction = TransferTransaction.create(Deadline.create(), account.address, [backAmount], + PlainMessage.create('payout'), NetworkType.MIJIN_TEST); + + // 01. Alice creates the aggregated tx and sign it. Then payload send to Bob + const aggregateTransaction = AggregateTransaction.createComplete( + Deadline.create(), + [ + aliceTransferTransaction.toAggregate(account.publicAccount), + bobTransferTransaction.toAggregate(account2.publicAccount), + ], + NetworkType.MIJIN_TEST, + [], + ); + + const aliceSignedTransaction = aggregateTransaction.signWith(account, generationHash); + + // 02 Bob cosigns the tx and sends it back to Alice + const signedTxBob = CosignatureTransaction.signTransactionPayload(account2, aliceSignedTransaction.payload, generationHash); + + // 03. Alice collects the cosignatures, recreate, sign, and announces the transaction + const cosignatureSignedTransactions = [ + new CosignatureSignedTransaction(signedTxBob.parentHash, signedTxBob.signature, signedTxBob.signer), + ]; + const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction; + + const signedTransaction = recreatedTx.signTransactionGivenSignatures(account, cosignatureSignedTransactions, generationHash); + + listener.confirmed(account.address).subscribe(() => { + done(); + }); + listener.status(account.address).subscribe((error) => { + console.log('Error:', error); + assert(false); + done(); + }); + transactionHttp.announce(signedTransaction); + }); + }); + describe('transactions', () => { it('should call transactions successfully', (done) => { accountHttp.transactions(account.publicAccount).subscribe((transactions) => { diff --git a/src/model/transaction/CosignatureTransaction.ts b/src/model/transaction/CosignatureTransaction.ts index 1eb021e01a..2f37079c9f 100644 --- a/src/model/transaction/CosignatureTransaction.ts +++ b/src/model/transaction/CosignatureTransaction.ts @@ -15,11 +15,12 @@ */ import { SignSchema } from '../../core/crypto'; +import { Convert } from '../../core/format/Convert'; import {CosignatureTransaction as CosignaturetransactionLibrary} from '../../infrastructure/builders/CosignatureTransaction'; +import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction'; import {Account} from '../account/Account'; import {AggregateTransaction} from './AggregateTransaction'; import {CosignatureSignedTransaction} from './CosignatureSignedTransaction'; -import { VerifiableTransaction } from '../../infrastructure/builders/VerifiableTransaction'; /** * Cosignature transaction is used to sign an aggregate transactions with missing cosignatures. @@ -52,14 +53,14 @@ export class CosignatureTransaction { * Creating a new CosignatureSignedTransaction * @param account - The signing account * @param payload - off transaction payload (aggregated transaction is unannounced) - * @param gernationHash - Network generation hash + * @param generationHash - Network generation hash * @returns {CosignatureSignedTransaction} */ - public static signTransactionPayload(account: Account, payload: string, gernationHash: string): CosignatureSignedTransaction { + public static signTransactionPayload(account: Account, payload: string, generationHash: string): CosignatureSignedTransaction { /** * For aggregated complete transaction, cosignatories are gathered off chain announced. */ - const transactionHash = VerifiableTransaction.createTransactionHash(payload, gernationHash); + const transactionHash = VerifiableTransaction.createTransactionHash(payload, Array.from(Convert.hexToUint8(generationHash))); const aggregateSignatureTransaction = new CosignaturetransactionLibrary(transactionHash); const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account); return new CosignatureSignedTransaction(signedTransactionRaw.parentHash, @@ -81,4 +82,4 @@ export class CosignatureTransaction { signedTransactionRaw.signature, signedTransactionRaw.signer); } -} \ No newline at end of file +} diff --git a/test/model/transaction/AggregateTransaction.spec.ts b/test/model/transaction/AggregateTransaction.spec.ts index d32bdc1a1d..ab53059940 100644 --- a/test/model/transaction/AggregateTransaction.spec.ts +++ b/test/model/transaction/AggregateTransaction.spec.ts @@ -389,7 +389,7 @@ describe('AggregateTransaction', () => { it('Should create signed transaction with cosignatories - Aggregated Complete', () => { /** - * https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 + * @see https://github.com/nemtech/nem2-sdk-typescript-javascript/issues/112 */ const accountAlice = TestingAccount; const accountBob = CosignatoryAccount; @@ -411,8 +411,8 @@ describe('AggregateTransaction', () => { PlainMessage.create('c to a'), NetworkType.MIJIN_TEST); - // 01. Alice creates the aggregated tx and serialize it, Then payload send to Bob & Carol - const aggregateTransactionPayload = AggregateTransaction.createComplete( + // 01. Alice creates the aggregated tx and sign it, Then payload send to Bob & Carol + const aggregateTransaction = AggregateTransaction.createComplete( Deadline.create(), [ AtoBTx.toAggregate(accountAlice.publicAccount), @@ -420,13 +420,15 @@ describe('AggregateTransaction', () => { CtoATx.toAggregate(accountCarol.publicAccount)], NetworkType.MIJIN_TEST, [], - ).serialize(); + ); + + const aliceSignedTransaction = aggregateTransaction.signWith(accountAlice, generationHash); // 02.1 Bob cosigns the tx and sends it back to Alice - const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aggregateTransactionPayload, generationHash); + const signedTxBob = CosignatureTransaction.signTransactionPayload(accountBob, aliceSignedTransaction.payload, generationHash); // 02.2 Carol cosigns the tx and sends it back to Alice - const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aggregateTransactionPayload, generationHash); + const signedTxCarol = CosignatureTransaction.signTransactionPayload(accountCarol, aliceSignedTransaction.payload, generationHash); // 03. Alice collects the cosignatures, recreate, sign, and announces the transaction @@ -436,7 +438,7 @@ describe('AggregateTransaction', () => { new CosignatureSignedTransaction(signedTxCarol.parentHash, signedTxCarol.signature, signedTxCarol.signer), ]; - const recreatedTx = TransactionMapping.createFromPayload(aggregateTransactionPayload) as AggregateTransaction; + const recreatedTx = TransactionMapping.createFromPayload(aliceSignedTransaction.payload) as AggregateTransaction; const signedTransaction = recreatedTx.signTransactionGivenSignatures(accountAlice, cosignatureSignedTransactions, generationHash); @@ -444,6 +446,12 @@ describe('AggregateTransaction', () => { expect(signedTransaction.signer).to.be.equal(accountAlice.publicKey); expect(signedTransaction.payload.indexOf(accountBob.publicKey) > -1).to.be.true; expect(signedTransaction.payload.indexOf(accountCarol.publicKey) > -1).to.be.true; + + // To make sure that the new cosign method returns the same payload & hash as standard cosigning + const standardCosignedTransaction = aggregateTransaction + .signTransactionWithCosignatories(accountAlice, [accountBob, accountCarol], generationHash); + expect(standardCosignedTransaction.payload).to.be.equal(signedTransaction.payload); + expect(standardCosignedTransaction.hash).to.be.equal(signedTransaction.hash); }); describe('size', () => { From a5a6b259faad9410300bafb12ff9681845efa703 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 15:02:49 +0100 Subject: [PATCH 09/13] Added signSchema to signWithPayload --- src/infrastructure/builders/AggregateTransaction.ts | 2 +- src/model/transaction/CosignatureTransaction.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/builders/AggregateTransaction.ts b/src/infrastructure/builders/AggregateTransaction.ts index 96790b9a0f..8aae5a5e28 100644 --- a/src/infrastructure/builders/AggregateTransaction.ts +++ b/src/infrastructure/builders/AggregateTransaction.ts @@ -56,7 +56,7 @@ export class AggregateTransaction extends VerifiableTransaction { return signedTransaction; } - signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema) { + signTransactionGivenSignatures(initializer, cosignedSignedTransactions, generationHash, signSchema = SignSchema.SHA3) { const signedTransaction = this.signTransaction(initializer, generationHash, signSchema); cosignedSignedTransactions.forEach((cosignedTransaction) => { signedTransaction.payload = signedTransaction.payload + cosignedTransaction.signer + cosignedTransaction.signature; diff --git a/src/model/transaction/CosignatureTransaction.ts b/src/model/transaction/CosignatureTransaction.ts index 2f37079c9f..d1b6ddc5b5 100644 --- a/src/model/transaction/CosignatureTransaction.ts +++ b/src/model/transaction/CosignatureTransaction.ts @@ -54,15 +54,19 @@ export class CosignatureTransaction { * @param account - The signing account * @param payload - off transaction payload (aggregated transaction is unannounced) * @param generationHash - Network generation hash + * @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3) * @returns {CosignatureSignedTransaction} */ - public static signTransactionPayload(account: Account, payload: string, generationHash: string): CosignatureSignedTransaction { + public static signTransactionPayload(account: Account, + payload: string, + generationHash: string, + signSchema: SignSchema = SignSchema.SHA3): CosignatureSignedTransaction { /** * For aggregated complete transaction, cosignatories are gathered off chain announced. */ const transactionHash = VerifiableTransaction.createTransactionHash(payload, Array.from(Convert.hexToUint8(generationHash))); const aggregateSignatureTransaction = new CosignaturetransactionLibrary(transactionHash); - const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account); + const signedTransactionRaw = aggregateSignatureTransaction.signCosignatoriesTransaction(account, signSchema); return new CosignatureSignedTransaction(signedTransactionRaw.parentHash, signedTransactionRaw.signature, signedTransactionRaw.signer); From 58745994ab35f7e5de378d7032e2a879c57239f2 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 16 Jul 2019 15:42:55 +0100 Subject: [PATCH 10/13] Exposed signTransactionGivenSignatures method --- src/model/account/Account.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/model/account/Account.ts b/src/model/account/Account.ts index 7e26c2d4f9..7395b232fb 100644 --- a/src/model/account/Account.ts +++ b/src/model/account/Account.ts @@ -171,6 +171,21 @@ export class Account { return transaction.signTransactionWithCosignatories(this, cosignatories, generationHash, signSchema); } + /** + * Sign transaction with cosignatories collected from cosigned transactions and creating a new SignedTransaction + * For off chain Aggregated Complete Transaction co-signing. + * @param initiatorAccount - Initiator account + * @param {CosignatureSignedTransaction[]} cosignatureSignedTransactions - Array of cosigned transaction + * @param generationHash - Network generation hash hex + * @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3) + * @return {SignedTransaction} + */ + public signTransactionGivenSignatures(transaction: AggregateTransaction, + cosignatureSignedTransactions: CosignatureSignedTransaction[], + generationHash: string, + signSchema: SignSchema = SignSchema.SHA3): SignedTransaction { + return transaction.signTransactionGivenSignatures(this, cosignatureSignedTransactions, generationHash, signSchema); + } /** * Sign aggregate signature transaction * @param cosignatureTransaction - The aggregate signature transaction. From 3279d939149979403978fdb410c9453226f4081a Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 8 Jul 2019 22:45:10 +0100 Subject: [PATCH 11/13] Added #195 fixed compatibility issue on new rxjs version --- src/infrastructure/AccountHttp.ts | 220 +++++++++++------- src/infrastructure/BlockHttp.ts | 159 +++++++------ src/infrastructure/ChainHttp.ts | 31 ++- src/infrastructure/DiagnosticHttp.ts | 35 +-- src/infrastructure/Http.ts | 8 + src/infrastructure/MosaicHttp.ts | 152 ++++++------ src/infrastructure/NamespaceHttp.ts | 97 +++++--- src/infrastructure/NetworkHttp.ts | 23 +- src/infrastructure/NodeHttp.ts | 42 ++-- src/infrastructure/TransactionHttp.ts | 69 ++++-- src/infrastructure/api/accountRoutesApi.ts | 84 ++----- src/infrastructure/api/blockRoutesApi.ts | 42 +--- src/infrastructure/api/chainRoutesApi.ts | 14 +- src/infrastructure/api/diagnosticRoutesApi.ts | 14 +- src/infrastructure/api/mosaicRoutesApi.ts | 21 +- src/infrastructure/api/namespaceRoutesApi.ts | 28 +-- src/infrastructure/api/networkRoutesApi.ts | 7 +- src/infrastructure/api/nodeRoutesApi.ts | 14 +- .../api/transactionRoutesApi.ts | 49 ++-- .../templates/api-single.mustache | 7 +- 20 files changed, 580 insertions(+), 536 deletions(-) diff --git a/src/infrastructure/AccountHttp.ts b/src/infrastructure/AccountHttp.ts index 6ef6ba3fae..aed431fd19 100644 --- a/src/infrastructure/AccountHttp.ts +++ b/src/infrastructure/AccountHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import { DtoMapping } from '../core/utils/DtoMapping'; import {AccountInfo} from '../model/account/AccountInfo'; import { AccountNames } from '../model/account/AccountNames'; @@ -34,7 +35,6 @@ import {UInt64} from '../model/UInt64'; import {AccountRepository} from './AccountRepository'; import { AccountInfoDTO, AccountNamesDTO, - AccountRestrictionsDTO, AccountRestrictionsInfoDTO, AccountRoutesApi, MosaicDTO, @@ -75,21 +75,25 @@ export class AccountHttp extends Http implements AccountRepository { * @returns Observable */ public getAccountInfo(address: Address): Observable { - return observableFrom(this.accountRoutesApi.getAccountInfo(address.plain())).pipe(map((accountInfoDTO: AccountInfoDTO) => { - return new AccountInfo( - accountInfoDTO.meta, - Address.createFromEncoded(accountInfoDTO.account.address), - new UInt64(accountInfoDTO.account.addressHeight), - accountInfoDTO.account.publicKey, - new UInt64(accountInfoDTO.account.publicKeyHeight), - accountInfoDTO.account.mosaics.map((mosaicDTO) => new Mosaic( - new MosaicId(mosaicDTO.id), - new UInt64(mosaicDTO.amount), - )), - new UInt64(accountInfoDTO.account.importance), - new UInt64(accountInfoDTO.account.importanceHeight), - ); - })); + return observableFrom(this.accountRoutesApi.getAccountInfo(address.plain())).pipe( + map((response: { response: ClientResponse; body: AccountInfoDTO; }) => { + const accountInfoDTO = response.body; + return new AccountInfo( + accountInfoDTO.meta, + Address.createFromEncoded(accountInfoDTO.account.address), + new UInt64(accountInfoDTO.account.addressHeight), + accountInfoDTO.account.publicKey, + new UInt64(accountInfoDTO.account.publicKeyHeight), + accountInfoDTO.account.mosaics.map((mosaicDTO) => new Mosaic( + new MosaicId(mosaicDTO.id), + new UInt64(mosaicDTO.amount), + )), + new UInt64(accountInfoDTO.account.importance), + new UInt64(accountInfoDTO.account.importanceHeight), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -99,9 +103,12 @@ export class AccountHttp extends Http implements AccountRepository { */ public getAccountRestrictions(address: Address): Observable { return observableFrom(this.accountRoutesApi.getAccountRestrictions(address.plain())) - .pipe(map((accountRestrictions: AccountRestrictionsInfoDTO) => { - return DtoMapping.extractAccountRestrictionFromDto(accountRestrictions); - })); + .pipe(map((response: { response: ClientResponse; body: AccountRestrictionsInfoDTO; }) => { + const accountRestrictions = response.body; + return DtoMapping.extractAccountRestrictionFromDto(accountRestrictions); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -115,11 +122,14 @@ export class AccountHttp extends Http implements AccountRepository { }; return observableFrom( this.accountRoutesApi.getAccountRestrictionsFromAccounts(accountIds)) - .pipe(map((accountRestrictions: AccountRestrictionsDTO[]) => { - return accountRestrictions.map((restriction) => { - return DtoMapping.extractAccountRestrictionFromDto(restriction); - }); - })); + .pipe(map((response: { response: ClientResponse; body: AccountRestrictionsInfoDTO[]; }) => { + const accountRestrictions = response.body; + return accountRestrictions.map((restriction) => { + return DtoMapping.extractAccountRestrictionFromDto(restriction); + }); + }), + catchError((error) => throwError(error)), + ); } /** @@ -132,21 +142,25 @@ export class AccountHttp extends Http implements AccountRepository { addresses: addresses.map((address) => address.plain()), }; return observableFrom( - this.accountRoutesApi.getAccountsInfo(accountIdsBody)).pipe(map((accountsInfoMetaDataDTO: AccountInfoDTO[]) => { - return accountsInfoMetaDataDTO.map((accountInfoDTO: AccountInfoDTO) => { - return new AccountInfo( - accountInfoDTO.meta, - Address.createFromEncoded(accountInfoDTO.account.address), - new UInt64(accountInfoDTO.account.addressHeight), - accountInfoDTO.account.publicKey, - new UInt64(accountInfoDTO.account.publicKeyHeight), - accountInfoDTO.account.mosaics.map((mosaicDTO: MosaicDTO) => - new Mosaic(new MosaicId(mosaicDTO.id), new UInt64(mosaicDTO.amount))), - new UInt64(accountInfoDTO.account.importance), - new UInt64(accountInfoDTO.account.importanceHeight), - ); - }); - })); + this.accountRoutesApi.getAccountsInfo(accountIdsBody)).pipe( + map((response: { response: ClientResponse; body: AccountInfoDTO[]; }) => { + const accountsInfoMetaDataDTO = response.body; + return accountsInfoMetaDataDTO.map((accountInfoDTO: AccountInfoDTO) => { + return new AccountInfo( + accountInfoDTO.meta, + Address.createFromEncoded(accountInfoDTO.account.address), + new UInt64(accountInfoDTO.account.addressHeight), + accountInfoDTO.account.publicKey, + new UInt64(accountInfoDTO.account.publicKeyHeight), + accountInfoDTO.account.mosaics.map((mosaicDTO: MosaicDTO) => + new Mosaic(new MosaicId(mosaicDTO.id), new UInt64(mosaicDTO.amount))), + new UInt64(accountInfoDTO.account.importance), + new UInt64(accountInfoDTO.account.importanceHeight), + ); + }); + }), + catchError((error) => throwError(error)), + ); } public getAccountsNames(addresses: Address[]): Observable { @@ -154,16 +168,20 @@ export class AccountHttp extends Http implements AccountRepository { addresses: addresses.map((address) => address.plain()), }; return observableFrom( - this.accountRoutesApi.getAccountsNames(accountIdsBody)).pipe(map((accountNames: AccountNamesDTO[]) => { - return accountNames.map((accountName) => { - return new AccountNames( - Address.createFromEncoded(accountName.address), - accountName.names.map((name) => { - return new NamespaceName(new NamespaceId(name), name); - }), - ); - }); - })); + this.accountRoutesApi.getAccountsNames(accountIdsBody)).pipe( + map((response: { response: ClientResponse; body: AccountNamesDTO[]; }) => { + const accountNames = response.body; + return accountNames.map((accountName) => { + return new AccountNames( + Address.createFromEncoded(accountName.address), + accountName.names.map((name) => { + return new NamespaceName(new NamespaceId(name), name); + }), + ); + }); + }), + catchError((error) => throwError(error)), + ); } /** * Gets a MultisigAccountInfo for an account. @@ -174,17 +192,20 @@ export class AccountHttp extends Http implements AccountRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.accountRoutesApi.getAccountMultisig(address.plain())) - .pipe(map((multisigAccountInfoDTO: MultisigAccountInfoDTO) => { - return new MultisigAccountInfo( - PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), - multisigAccountInfoDTO.multisig.minApproval, - multisigAccountInfoDTO.multisig.minRemoval, - multisigAccountInfoDTO.multisig.cosignatories - .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), - multisigAccountInfoDTO.multisig.multisigAccounts - .map((multisigAccount) => PublicAccount.createFromPublicKey(multisigAccount, networkType)), - ); - })))); + .pipe(map((response: { response: ClientResponse; body: MultisigAccountInfoDTO; }) => { + const multisigAccountInfoDTO = response.body; + return new MultisigAccountInfo( + PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), + multisigAccountInfoDTO.multisig.minApproval, + multisigAccountInfoDTO.multisig.minRemoval, + multisigAccountInfoDTO.multisig.cosignatories + .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), + multisigAccountInfoDTO.multisig.multisigAccounts + .map((multisigAccount) => PublicAccount.createFromPublicKey(multisigAccount, networkType)), + ); + }), + catchError((error) => throwError(error)), + ))); } /** @@ -196,24 +217,28 @@ export class AccountHttp extends Http implements AccountRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.accountRoutesApi.getAccountMultisigGraph(address.plain())) - .pipe(map((multisigAccountGraphInfosDTO: MultisigAccountGraphInfoDTO[]) => { - const multisigAccounts = new Map(); - multisigAccountGraphInfosDTO.map((multisigAccountGraphInfoDTO) => { - multisigAccounts.set(multisigAccountGraphInfoDTO.level, - multisigAccountGraphInfoDTO.multisigEntries.map((multisigAccountInfoDTO) => { - return new MultisigAccountInfo( - PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), - multisigAccountInfoDTO.multisig.minApproval, - multisigAccountInfoDTO.multisig.minRemoval, - multisigAccountInfoDTO.multisig.cosignatories - .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), - multisigAccountInfoDTO.multisig.multisigAccounts - .map((multisigAccountDTO) => PublicAccount.createFromPublicKey(multisigAccountDTO, networkType))); - }), - ); - }); - return new MultisigAccountGraphInfo(multisigAccounts); - })))); + .pipe(map((response: { response: ClientResponse; body: MultisigAccountGraphInfoDTO[]; }) => { + const multisigAccountGraphInfosDTO = response.body; + const multisigAccounts = new Map(); + multisigAccountGraphInfosDTO.map((multisigAccountGraphInfoDTO) => { + multisigAccounts.set(multisigAccountGraphInfoDTO.level, + multisigAccountGraphInfoDTO.multisigEntries.map((multisigAccountInfoDTO) => { + return new MultisigAccountInfo( + PublicAccount.createFromPublicKey(multisigAccountInfoDTO.multisig.account, networkType), + multisigAccountInfoDTO.multisig.minApproval, + multisigAccountInfoDTO.multisig.minRemoval, + multisigAccountInfoDTO.multisig.cosignatories + .map((cosigner) => PublicAccount.createFromPublicKey(cosigner, networkType)), + multisigAccountInfoDTO.multisig.multisigAccounts + .map((multisigAccountDTO) => + PublicAccount.createFromPublicKey(multisigAccountDTO, networkType))); + }), + ); + }); + return new MultisigAccountGraphInfo(multisigAccounts); + }), + catchError((error) => throwError(error)), + ))); } /** @@ -228,11 +253,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -248,11 +276,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -268,11 +299,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -289,11 +323,14 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(error)), + ); } /** @@ -309,10 +346,13 @@ export class AccountHttp extends Http implements AccountRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((transactionsDTO: TransactionInfoDTO[]) => { + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO) as AggregateTransaction; }); - })); + }), + catchError((error) => throwError(error)), + ); } } diff --git a/src/infrastructure/BlockHttp.ts b/src/infrastructure/BlockHttp.ts index f04089fb52..a6f4ce9bb8 100644 --- a/src/infrastructure/BlockHttp.ts +++ b/src/infrastructure/BlockHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {BlockInfo} from '../model/blockchain/BlockInfo'; import { MerklePathItem } from '../model/blockchain/MerklePathItem'; @@ -79,29 +80,33 @@ export class BlockHttp extends Http implements BlockRepository { * @returns Observable */ public getBlockByHeight(height: number): Observable { - return observableFrom(this.blockRoutesApi.getBlockByHeight(height)).pipe(map((blockDTO: BlockInfoDTO) => { - const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); - return new BlockInfo( - blockDTO.meta.hash, - blockDTO.meta.generationHash, - new UInt64(blockDTO.meta.totalFee), - blockDTO.meta.numTransactions, - blockDTO.block.signature, - PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), - networkType, - parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version - blockDTO.block.type, - new UInt64(blockDTO.block.height), - new UInt64(blockDTO.block.timestamp), - new UInt64(blockDTO.block.difficulty), - blockDTO.block.feeMultiplier, - blockDTO.block.previousBlockHash, - blockDTO.block.blockTransactionsHash, - blockDTO.block.blockReceiptsHash, - blockDTO.block.stateHash, - extractBeneficiary(blockDTO, networkType), - ); - })); + return observableFrom(this.blockRoutesApi.getBlockByHeight(height)).pipe( + map((response: { response: ClientResponse; body: BlockInfoDTO; } ) => { + const blockDTO = response.body; + const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); + return new BlockInfo( + blockDTO.meta.hash, + blockDTO.meta.generationHash, + new UInt64(blockDTO.meta.totalFee), + blockDTO.meta.numTransactions, + blockDTO.block.signature, + PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), + networkType, + parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version + blockDTO.block.type, + new UInt64(blockDTO.block.height), + new UInt64(blockDTO.block.timestamp), + new UInt64(blockDTO.block.difficulty), + blockDTO.block.feeMultiplier, + blockDTO.block.previousBlockHash, + blockDTO.block.blockTransactionsHash, + blockDTO.block.blockReceiptsHash, + blockDTO.block.stateHash, + extractBeneficiary(blockDTO, networkType), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -117,11 +122,14 @@ export class BlockHttp extends Http implements BlockRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)) - .pipe(map((transactionsDTO: TransactionInfoDTO[]) => { + .pipe(map((response: { response: ClientResponse; body: TransactionInfoDTO[]; }) => { + const transactionsDTO = response.body; return transactionsDTO.map((transactionDTO) => { return CreateTransactionFromDTO(transactionDTO); }); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -132,31 +140,35 @@ export class BlockHttp extends Http implements BlockRepository { */ public getBlocksByHeightWithLimit(height: number, limit: LimitType = LimitType.N_25): Observable { return observableFrom( - this.blockRoutesApi.getBlocksByHeightWithLimit(height, limit)).pipe(map((blocksDTO: BlockInfoDTO[]) => { - return blocksDTO.map((blockDTO) => { - const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); - return new BlockInfo( - blockDTO.meta.hash, - blockDTO.meta.generationHash, - new UInt64(blockDTO.meta.totalFee), - blockDTO.meta.numTransactions, - blockDTO.block.signature, - PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), - networkType, - parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version - blockDTO.block.type, - new UInt64(blockDTO.block.height), - new UInt64(blockDTO.block.timestamp), - new UInt64(blockDTO.block.difficulty), - blockDTO.block.feeMultiplier, - blockDTO.block.previousBlockHash, - blockDTO.block.blockTransactionsHash, - blockDTO.block.blockReceiptsHash, - blockDTO.block.stateHash, - extractBeneficiary(blockDTO, networkType), - ); - }); - })); + this.blockRoutesApi.getBlocksByHeightWithLimit(height, limit)).pipe( + map((response: { response: ClientResponse; body: BlockInfoDTO[]; }) => { + const blocksDTO = response.body; + return blocksDTO.map((blockDTO) => { + const networkType = parseInt((blockDTO.block.version as number).toString(16).substr(0, 2), 16); + return new BlockInfo( + blockDTO.meta.hash, + blockDTO.meta.generationHash, + new UInt64(blockDTO.meta.totalFee), + blockDTO.meta.numTransactions, + blockDTO.block.signature, + PublicAccount.createFromPublicKey(blockDTO.block.signer, networkType), + networkType, + parseInt((blockDTO.block.version as number).toString(16).substr(2, 2), 16), // Tx version + blockDTO.block.type, + new UInt64(blockDTO.block.height), + new UInt64(blockDTO.block.timestamp), + new UInt64(blockDTO.block.difficulty), + blockDTO.block.feeMultiplier, + blockDTO.block.previousBlockHash, + blockDTO.block.blockTransactionsHash, + blockDTO.block.blockReceiptsHash, + blockDTO.block.stateHash, + extractBeneficiary(blockDTO, networkType), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -171,14 +183,18 @@ export class BlockHttp extends Http implements BlockRepository { */ public getMerkleReceipts(height: number, hash: string): Observable { return observableFrom( - this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe(map((merkleProofReceipt: MerkleProofInfoDTO) => { - return new MerkleProofInfo( - new MerkleProofInfoPayload( - merkleProofReceipt.payload.merklePath!.map( - (payload) => new MerklePathItem(payload.position, payload.hash))), - merkleProofReceipt.type, - ); - })); + this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe( + map((response: { response: ClientResponse; body: MerkleProofInfoDTO; } ) => { + const merkleProofReceipt = response.body; + return new MerkleProofInfo( + new MerkleProofInfoPayload( + merkleProofReceipt.payload.merklePath!.map( + (payload) => new MerklePathItem(payload.position, payload.hash))), + merkleProofReceipt.type, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -193,13 +209,18 @@ export class BlockHttp extends Http implements BlockRepository { */ public getMerkleTransaction(height: number, hash: string): Observable { return observableFrom( - this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe(map((merkleProofTransaction: MerkleProofInfoDTO) => { - return new MerkleProofInfo( - new MerkleProofInfoPayload( - merkleProofTransaction.payload.merklePath!.map((payload) => new MerklePathItem(payload.position, payload.hash))), - merkleProofTransaction.type, - ); - })); + this.blockRoutesApi.getMerkleReceipts(height, hash)).pipe( + map((response: { response: ClientResponse; body: MerkleProofInfoDTO; } ) => { + const merkleProofTransaction = response.body; + return new MerkleProofInfo( + new MerkleProofInfoPayload( + merkleProofTransaction.payload.merklePath!.map((payload) => + new MerklePathItem(payload.position, payload.hash))), + merkleProofTransaction.type, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -212,9 +233,11 @@ export class BlockHttp extends Http implements BlockRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.blockRoutesApi.getBlockReceipts(height)).pipe( - map((receiptDTO: StatementsDTO) => { + map((response: { response: ClientResponse; body: StatementsDTO; }) => { + const receiptDTO = response.body; return CreateStatementFromDTO(receiptDTO, networkType); }), + catchError((error) => throwError(this.errorHandling(error))), ), ), ); diff --git a/src/infrastructure/ChainHttp.ts b/src/infrastructure/ChainHttp.ts index c791b69297..5b32953b6f 100644 --- a/src/infrastructure/ChainHttp.ts +++ b/src/infrastructure/ChainHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {BlockchainScore} from '../model/blockchain/BlockchainScore'; import {UInt64} from '../model/UInt64'; import { BlockchainScoreDTO, @@ -50,9 +51,13 @@ export class ChainHttp extends Http implements ChainRepository { * @returns Observable */ public getBlockchainHeight(): Observable { - return observableFrom(this.chainRoutesApi.getBlockchainHeight()).pipe(map((heightDTO: HeightInfoDTO) => { - return new UInt64(heightDTO.height); - })); + return observableFrom(this.chainRoutesApi.getBlockchainHeight()).pipe( + map((response: { response: ClientResponse; body: HeightInfoDTO; } ) => { + const heightDTO = response.body; + return new UInt64(heightDTO.height); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -60,11 +65,15 @@ export class ChainHttp extends Http implements ChainRepository { * @returns Observable */ public getBlockchainScore(): Observable { - return observableFrom(this.chainRoutesApi.getBlockchainScore()).pipe(map((blockchainScoreDTO: BlockchainScoreDTO) => { - return new BlockchainScore( - new UInt64(blockchainScoreDTO.scoreLow), - new UInt64(blockchainScoreDTO.scoreHigh), - ); - })); + return observableFrom(this.chainRoutesApi.getBlockchainScore()).pipe( + map((response: { response: ClientResponse; body: BlockchainScoreDTO; } ) => { + const blockchainScoreDTO = response.body; + return new BlockchainScore( + new UInt64(blockchainScoreDTO.scoreLow), + new UInt64(blockchainScoreDTO.scoreHigh), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/DiagnosticHttp.ts b/src/infrastructure/DiagnosticHttp.ts index be17dbcf5e..0af049602a 100644 --- a/src/infrastructure/DiagnosticHttp.ts +++ b/src/infrastructure/DiagnosticHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {BlockchainStorageInfo} from '../model/blockchain/BlockchainStorageInfo'; import { ServerInfo } from '../model/diagnostic/ServerInfo'; import { DiagnosticRoutesApi, ServerDTO, StorageInfoDTO } from './api'; @@ -49,13 +50,17 @@ export class DiagnosticHttp extends Http implements DiagnosticRepository { */ public getDiagnosticStorage(): Observable { return observableFrom( - this.diagnosticRoutesApi.getDiagnosticStorage()).pipe(map((blockchainStorageInfoDTO: StorageInfoDTO) => { - return new BlockchainStorageInfo( - blockchainStorageInfoDTO.numBlocks, - blockchainStorageInfoDTO.numTransactions, - blockchainStorageInfoDTO.numAccounts, - ); - })); + this.diagnosticRoutesApi.getDiagnosticStorage()).pipe( + map((response: { response: ClientResponse; body: StorageInfoDTO; } ) => { + const blockchainStorageInfoDTO = response.body; + return new BlockchainStorageInfo( + blockchainStorageInfoDTO.numBlocks, + blockchainStorageInfoDTO.numTransactions, + blockchainStorageInfoDTO.numAccounts, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -64,9 +69,13 @@ export class DiagnosticHttp extends Http implements DiagnosticRepository { */ public getServerInfo(): Observable { return observableFrom( - this.diagnosticRoutesApi.getServerInfo()).pipe(map((serverDTO: ServerDTO) => { - return new ServerInfo(serverDTO.serverInfo.restVersion, - serverDTO.serverInfo.sdkVersion); - })); + this.diagnosticRoutesApi.getServerInfo()).pipe( + map((response: { response: ClientResponse; body: ServerDTO; } ) => { + const serverDTO = response.body; + return new ServerInfo(serverDTO.serverInfo.restVersion, + serverDTO.serverInfo.sdkVersion); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/Http.ts b/src/infrastructure/Http.ts index 7185797d17..2a94ac1a66 100644 --- a/src/infrastructure/Http.ts +++ b/src/infrastructure/Http.ts @@ -57,4 +57,12 @@ export abstract class Http { order: queryParams ? queryParams.order : undefined, }; } + + errorHandling(error: any): Error { + const formattedError = { + statusCode: error.response.statusCode, + errorDetails: error.response.body, + }; + return new Error(JSON.stringify(formattedError)); + } } diff --git a/src/infrastructure/MosaicHttp.ts b/src/infrastructure/MosaicHttp.ts index 1d56765c0b..104aee210b 100644 --- a/src/infrastructure/MosaicHttp.ts +++ b/src/infrastructure/MosaicHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {MosaicId} from '../model/mosaic/MosaicId'; import {MosaicInfo} from '../model/mosaic/MosaicInfo'; @@ -61,33 +62,38 @@ export class MosaicHttp extends Http implements MosaicRepository { public getMosaic(mosaicId: MosaicId): Observable { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.mosaicRoutesApi.getMosaic(mosaicId.toHex())).pipe(map((mosaicInfoDTO: MosaicInfoDTO) => { - let mosaicFlag; - let divisibility; - let duration; - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { - mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { - divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { - duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - return new MosaicInfo( - mosaicInfoDTO.meta.id, - new MosaicId(mosaicInfoDTO.mosaic.mosaicId), - new UInt64(mosaicInfoDTO.mosaic.supply), - new UInt64(mosaicInfoDTO.mosaic.height), - PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), - mosaicInfoDTO.mosaic.revision, - new MosaicProperties( - mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), - (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), - duration ? new UInt64(duration) : undefined, - ), - ); - })))); + this.mosaicRoutesApi.getMosaic(mosaicId.toHex())).pipe( + map((response: { response: ClientResponse; body: MosaicInfoDTO; } ) => { + const mosaicInfoDTO = response.body; + let mosaicFlag; + let divisibility; + let duration; + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { + mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { + divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { + duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + return new MosaicInfo( + mosaicInfoDTO.meta.id, + new MosaicId(mosaicInfoDTO.mosaic.mosaicId), + new UInt64(mosaicInfoDTO.mosaic.supply), + new UInt64(mosaicInfoDTO.mosaic.height), + PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), + mosaicInfoDTO.mosaic.revision, + new MosaicProperties( + mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), + (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), + duration ? new UInt64(duration) : undefined, + ), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + )), + ); } /** @@ -101,35 +107,41 @@ export class MosaicHttp extends Http implements MosaicRepository { }; return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.mosaicRoutesApi.getMosaics(mosaicIdsBody)).pipe(map((mosaicInfosDTO: MosaicInfoDTO[]) => { - return mosaicInfosDTO.map((mosaicInfoDTO) => { - let mosaicFlag; - let divisibility; - let duration; - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { - mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { - divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; - } - if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { - duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value; - } - return new MosaicInfo( - mosaicInfoDTO.meta.id, - new MosaicId(mosaicInfoDTO.mosaic.mosaicId), - new UInt64(mosaicInfoDTO.mosaic.supply), - new UInt64(mosaicInfoDTO.mosaic.height), - PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), - mosaicInfoDTO.mosaic.revision, - new MosaicProperties( - mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), - (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), - duration ? new UInt64(duration) : undefined, - ), - ); - }); - })))); + this.mosaicRoutesApi.getMosaics(mosaicIdsBody)).pipe( + map((response: { response: ClientResponse; body: MosaicInfoDTO[]; }) => { + const mosaicInfosDTO = response.body; + return mosaicInfosDTO.map((mosaicInfoDTO) => { + let mosaicFlag; + let divisibility; + let duration; + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value) { + mosaicFlag = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.MosaicFlags].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value) { + divisibility = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Divisibility].value; + } + if (mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value) { + duration = mosaicInfoDTO.mosaic.properties[MosaicPropertyType.Duration].value; + } + return new MosaicInfo( + mosaicInfoDTO.meta.id, + new MosaicId(mosaicInfoDTO.mosaic.mosaicId), + new UInt64(mosaicInfoDTO.mosaic.supply), + new UInt64(mosaicInfoDTO.mosaic.height), + PublicAccount.createFromPublicKey(mosaicInfoDTO.mosaic.owner, networkType), + mosaicInfoDTO.mosaic.revision, + new MosaicProperties( + mosaicFlag ? new UInt64(mosaicFlag) : UInt64.fromUint(0), + (divisibility ? new UInt64(divisibility) : UInt64.fromUint(0)).compact(), + duration ? new UInt64(duration) : undefined, + ), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + ), + ); } /** @@ -143,15 +155,19 @@ export class MosaicHttp extends Http implements MosaicRepository { mosaicIds: mosaicIds.map((id) => id.toHex()), }; return observableFrom( - this.mosaicRoutesApi.getMosaicsNames(mosaicIdsBody)).pipe(map((mosaics: MosaicNamesDTO[]) => { - return mosaics.map((mosaic) => { - return new MosaicNames( - new MosaicId(mosaic.mosaicId), - mosaic.names.map((name) => { - return new NamespaceName(new NamespaceId(name), name); - }), - ); - }); - })); + this.mosaicRoutesApi.getMosaicsNames(mosaicIdsBody)).pipe( + map((response: { response: ClientResponse; body: MosaicNamesDTO[]; }) => { + const mosaics = response.body; + return mosaics.map((mosaic) => { + return new MosaicNames( + new MosaicId(mosaic.mosaicId), + mosaic.names.map((name) => { + return new NamespaceName(new NamespaceId(name), name); + }), + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/NamespaceHttp.ts b/src/infrastructure/NamespaceHttp.ts index 64ad0e94af..4d695f44bc 100644 --- a/src/infrastructure/NamespaceHttp.ts +++ b/src/infrastructure/NamespaceHttp.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map, mergeMap} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map, mergeMap} from 'rxjs/operators'; import {Convert as convert, RawAddress as AddressLibrary} from '../core/format'; import {Address} from '../model/account/Address'; import {PublicAccount} from '../model/account/PublicAccount'; @@ -65,21 +66,27 @@ export class NamespaceHttp extends Http implements NamespaceRepository { public getNamespace(namespaceId: NamespaceId): Observable { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( - this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe(map((namespaceInfoDTO: NamespaceInfoDTO) => { - return new NamespaceInfo( - namespaceInfoDTO.meta.active, - namespaceInfoDTO.meta.index, - namespaceInfoDTO.meta.id, - namespaceInfoDTO.namespace.type as number, - namespaceInfoDTO.namespace.depth, - this.extractLevels(namespaceInfoDTO.namespace), - new NamespaceId(namespaceInfoDTO.namespace.parentId), - PublicAccount.createFromPublicKey(namespaceInfoDTO.namespace.owner, networkType), - new UInt64(namespaceInfoDTO.namespace.startHeight), - new UInt64(namespaceInfoDTO.namespace.endHeight), - this.extractAlias(namespaceInfoDTO.namespace), - ); - })))); + this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; + return new NamespaceInfo( + namespaceInfoDTO.meta.active, + namespaceInfoDTO.meta.index, + namespaceInfoDTO.meta.id, + namespaceInfoDTO.namespace.type as number, + namespaceInfoDTO.namespace.depth, + this.extractLevels(namespaceInfoDTO.namespace), + new NamespaceId(namespaceInfoDTO.namespace.parentId), + PublicAccount.createFromPublicKey(namespaceInfoDTO.namespace.owner, networkType), + new UInt64(namespaceInfoDTO.namespace.startHeight), + new UInt64(namespaceInfoDTO.namespace.endHeight), + this.extractAlias(namespaceInfoDTO.namespace), + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + ), + ); } /** @@ -96,7 +103,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((namespaceInfosDTO: NamespaceInfoDTO[]) => { + map((response: { response: ClientResponse; body: NamespaceInfoDTO[]; }) => { + const namespaceInfosDTO = response.body; return namespaceInfosDTO.map((namespaceInfoDTO) => { return new NamespaceInfo( namespaceInfoDTO.meta.active, @@ -112,7 +120,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.extractAlias(namespaceInfoDTO.namespace), ); }); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -132,7 +143,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.queryParams(queryParams).pageSize, this.queryParams(queryParams).id, this.queryParams(queryParams).order)).pipe( - map((namespaceInfosDTO: NamespaceInfoDTO[]) => { + map((response: { response: ClientResponse; body: NamespaceInfoDTO[]; }) => { + const namespaceInfosDTO = response.body; return namespaceInfosDTO.map((namespaceInfoDTO) => { return new NamespaceInfo( namespaceInfoDTO.meta.active, @@ -148,7 +160,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { this.extractAlias(namespaceInfoDTO.namespace), ); }); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -161,15 +176,19 @@ export class NamespaceHttp extends Http implements NamespaceRepository { namespaceIds: namespaceIds.map((id) => id.toHex()), }; return observableFrom( - this.namespaceRoutesApi.getNamespacesNames(namespaceIdsBody)).pipe(map((namespaceNamesDTO: NamespaceNameDTO[]) => { - return namespaceNamesDTO.map((namespaceNameDTO) => { - return new NamespaceName( - new NamespaceId(namespaceNameDTO.namespaceId), - namespaceNameDTO.name, - namespaceNameDTO.parentId ? new NamespaceId(namespaceNameDTO.parentId) : undefined, - ); - }); - })); + this.namespaceRoutesApi.getNamespacesNames(namespaceIdsBody)).pipe( + map((response: { response: ClientResponse; body: NamespaceNameDTO[]; } ) => { + const namespaceNamesDTO = response.body; + return namespaceNamesDTO.map((namespaceNameDTO) => { + return new NamespaceName( + new NamespaceId(namespaceNameDTO.namespaceId), + namespaceNameDTO.name, + namespaceNameDTO.parentId ? new NamespaceId(namespaceNameDTO.parentId) : undefined, + ); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -181,8 +200,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( - map((namespaceInfoDTO: NamespaceInfoDTO) => { - + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; if (namespaceInfoDTO.namespace === undefined) { // forward catapult-rest error throw namespaceInfoDTO; @@ -194,7 +213,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { throw new Error('No mosaicId is linked to namespace \'' + namespaceInfoDTO.namespace.level0 + '\''); } return new MosaicId(namespaceInfoDTO.namespace.alias.mosaicId); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } /** @@ -206,8 +228,8 @@ export class NamespaceHttp extends Http implements NamespaceRepository { return this.getNetworkTypeObservable().pipe( mergeMap((networkType) => observableFrom( this.namespaceRoutesApi.getNamespace(namespaceId.toHex())).pipe( - map((namespaceInfoDTO: NamespaceInfoDTO) => { - + map((response: { response: ClientResponse; body: NamespaceInfoDTO; } ) => { + const namespaceInfoDTO = response.body; if (namespaceInfoDTO.namespace === undefined) { // forward catapult-rest error throw namespaceInfoDTO; @@ -222,7 +244,10 @@ export class NamespaceHttp extends Http implements NamespaceRepository { const addressDecoded = namespaceInfoDTO.namespace.alias.address; const address = AddressLibrary.addressToString(convert.hexToUint8(addressDecoded)); return Address.createFromRawAddress(address); - })))); + }), + catchError((error) => throwError(this.errorHandling(error))), + ), + )); } private extractLevels(namespace: any): NamespaceId[] { diff --git a/src/infrastructure/NetworkHttp.ts b/src/infrastructure/NetworkHttp.ts index cbdc53ee9a..a635710304 100644 --- a/src/infrastructure/NetworkHttp.ts +++ b/src/infrastructure/NetworkHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import {NetworkType} from '../model/blockchain/NetworkType'; import { NetworkRoutesApi, NetworkTypeDTO } from './api'; import {Http} from './Http'; @@ -49,12 +50,16 @@ export class NetworkHttp extends Http implements NetworkRepository { * @return network type enum. */ public getNetworkType(): Observable { - return observableFrom(this.networkRoutesApi.getNetworkType()).pipe(map((networkTypeDTO: NetworkTypeDTO) => { - if (networkTypeDTO.name === 'mijinTest') { - return NetworkType.MIJIN_TEST; - } else { - throw new Error('network ' + networkTypeDTO.name + ' is not supported yet by the sdk'); - } - })); + return observableFrom(this.networkRoutesApi.getNetworkType()).pipe( + map((response: { response: ClientResponse; body: NetworkTypeDTO; } ) => { + const networkTypeDTO = response.body; + if (networkTypeDTO.name === 'mijinTest') { + return NetworkType.MIJIN_TEST; + } else { + throw new Error('network ' + networkTypeDTO.name + ' is not supported yet by the sdk'); + } + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/NodeHttp.ts b/src/infrastructure/NodeHttp.ts index 7a29ea3388..81f81a8d25 100644 --- a/src/infrastructure/NodeHttp.ts +++ b/src/infrastructure/NodeHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -import {from as observableFrom, Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; +import { ClientResponse } from 'http'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; +import {catchError, map} from 'rxjs/operators'; import { NodeInfo } from '../model/node/NodeInfo'; import { NodeTime } from '../model/node/NodeTime'; import { NodeInfoDTO, NodeRoutesApi, NodeTimeDTO } from './api'; @@ -49,17 +50,21 @@ export class NodeHttp extends Http implements NodeRepository { * @summary Get the node information */ public getNodeInfo(): Observable { - return observableFrom(this.nodeRoutesApi.getNodeInfo()).pipe(map((nodeInfoDTO: NodeInfoDTO) => { - return new NodeInfo( - nodeInfoDTO.publicKey, - nodeInfoDTO.port, - nodeInfoDTO.networkIdentifier, - nodeInfoDTO.version, - nodeInfoDTO.roles as number, - nodeInfoDTO.host, - nodeInfoDTO.friendlyName, - ); - })); + return observableFrom(this.nodeRoutesApi.getNodeInfo()).pipe( + map((response: { response: ClientResponse; body: NodeInfoDTO; } ) => { + const nodeInfoDTO = response.body; + return new NodeInfo( + nodeInfoDTO.publicKey, + nodeInfoDTO.port, + nodeInfoDTO.networkIdentifier, + nodeInfoDTO.version, + nodeInfoDTO.roles as number, + nodeInfoDTO.host, + nodeInfoDTO.friendlyName, + ); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -67,8 +72,13 @@ export class NodeHttp extends Http implements NodeRepository { * @summary Get the node time */ public getNodeTime(): Observable { - return observableFrom(this.nodeRoutesApi.getNodeTime()).pipe(map((nodeTimeDTO: NodeTimeDTO) => { - return new NodeTime(nodeTimeDTO.communicationTimestamps.sendTimestamp, nodeTimeDTO.communicationTimestamps.receiveTimestamp); - })); + return observableFrom(this.nodeRoutesApi.getNodeTime()).pipe( + map((response: { response: ClientResponse; body: NodeTimeDTO; } ) => { + const nodeTimeDTO = response.body; + return new NodeTime(nodeTimeDTO.communicationTimestamps.sendTimestamp, + nodeTimeDTO.communicationTimestamps.receiveTimestamp); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } } diff --git a/src/infrastructure/TransactionHttp.ts b/src/infrastructure/TransactionHttp.ts index 332ada1e85..8c6455f6f9 100644 --- a/src/infrastructure/TransactionHttp.ts +++ b/src/infrastructure/TransactionHttp.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { ClientResponse } from 'http'; import * as requestPromise from 'request-promise-native'; -import {from as observableFrom, Observable, throwError as observableThrowError} from 'rxjs'; +import {from as observableFrom, Observable, throwError} from 'rxjs'; import {catchError, map, mergeMap} from 'rxjs/operators'; import {PublicAccount} from '../model/account/PublicAccount'; import {CosignatureSignedTransaction} from '../model/transaction/CosignatureSignedTransaction'; @@ -86,11 +87,15 @@ export class TransactionHttp extends Http implements TransactionRepository { transactionIds, }; return observableFrom( - this.transactionRoutesApi.getTransactions(transactionIdsBody)).pipe(map((transactionsDTO: TransactionInfoDTO[]) => { - return transactionsDTO.map((transactionDTO) => { - return CreateTransactionFromDTO(transactionDTO); - }); - })); + this.transactionRoutesApi.getTransactions(transactionIdsBody)).pipe( + map((response: { response: ClientResponse; body: TransactionInfoDTO[]; } ) => { + const transactionsDTO = response.body; + return transactionsDTO.map((transactionDTO) => { + return CreateTransactionFromDTO(transactionDTO); + }); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -100,14 +105,17 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public getTransactionStatus(transactionHash: string): Observable { return observableFrom(this.transactionRoutesApi.getTransactionStatus(transactionHash)).pipe( - map((transactionStatusDTO: TransactionStatusDTO) => { + map((response: { response: ClientResponse; body: TransactionStatusDTO; } ) => { + const transactionStatusDTO = response.body; return new TransactionStatus( transactionStatusDTO.status, transactionStatusDTO.group, transactionStatusDTO.hash, transactionStatusDTO.deadline ? Deadline.createFromDTO(transactionStatusDTO.deadline) : undefined, transactionStatusDTO.height ? new UInt64(transactionStatusDTO.height) : undefined); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -121,7 +129,8 @@ export class TransactionHttp extends Http implements TransactionRepository { }; return observableFrom( this.transactionRoutesApi.getTransactionsStatuses(transactionHashesBody)).pipe( - map((transactionStatusesDTO: TransactionStatusDTO[]) => { + map((response: { response: ClientResponse; body: TransactionStatusDTO[]; }) => { + const transactionStatusesDTO = response.body; return transactionStatusesDTO.map((transactionStatusDTO) => { return new TransactionStatus( transactionStatusDTO.status, @@ -130,7 +139,9 @@ export class TransactionHttp extends Http implements TransactionRepository { transactionStatusDTO.deadline ? Deadline.createFromDTO(transactionStatusDTO.deadline) : undefined, transactionStatusDTO.height ? new UInt64(transactionStatusDTO.height) : undefined); }); - })); + }), + catchError((error) => throwError(error.error.errorMessage)), + ); } /** @@ -140,9 +151,12 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announce(signedTransaction: SignedTransaction): Observable { return observableFrom(this.transactionRoutesApi.announceTransaction(signedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -152,14 +166,15 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announceAggregateBonded(signedTransaction: SignedTransaction): Observable { if (signedTransaction.type !== TransactionType.AGGREGATE_BONDED) { - return observableFrom(new Promise((resolve, reject) => { - reject('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); - })); + throwError('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); } return observableFrom(this.transactionRoutesApi.announcePartialTransaction(signedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } /** @@ -170,9 +185,12 @@ export class TransactionHttp extends Http implements TransactionRepository { public announceAggregateBondedCosignature( cosignatureSignedTransaction: CosignatureSignedTransaction): Observable { return observableFrom(this.transactionRoutesApi.announceCosignatureTransaction(cosignatureSignedTransaction)).pipe( - map((transactionAnnounceResponseDTO: AnnounceTransactionInfoDTO) => { + map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { + const transactionAnnounceResponseDTO = response.body; return new TransactionAnnounceResponse(transactionAnnounceResponseDTO.message); - })); + }), + catchError((error) => throwError(this.errorHandling(error))), + ); } public announceSync(signedTx: SignedTransaction): Observable { @@ -198,9 +216,9 @@ export class TransactionHttp extends Http implements TransactionRepository { } }), catchError((err) => { if (err.statusCode === 405) { - return observableThrowError('non sync server'); + return throwError('non sync server'); } - return observableThrowError(err); + return throwError(err); })); } @@ -218,14 +236,15 @@ export class TransactionHttp extends Http implements TransactionRepository { // now read block details return observableFrom(this.blockRoutesApi.getBlockByHeight(uintHeight.compact())).pipe( - map((blockDTO: BlockInfoDTO) => { - + map((response: { response: ClientResponse; body: BlockInfoDTO; } ) => { + const blockDTO = response.body; // @see https://nemtech.github.io/concepts/transaction.html#fees // effective_fee = feeMultiplier x transaction::size return blockDTO.block.feeMultiplier * transaction.size; - })); + }), + catchError((error) => throwError(this.errorHandling(error)))); }), catchError((err) => { - return observableThrowError(err); + return throwError(err); })); } } diff --git a/src/infrastructure/api/accountRoutesApi.ts b/src/infrastructure/api/accountRoutesApi.ts index 529245b7a5..a4c378b15f 100644 --- a/src/infrastructure/api/accountRoutesApi.ts +++ b/src/infrastructure/api/accountRoutesApi.ts @@ -136,12 +136,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AccountInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -193,12 +190,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MultisigAccountInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -250,12 +244,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -307,12 +298,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AccountRestrictionsInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -364,12 +352,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -421,12 +406,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -478,12 +460,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -550,12 +529,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -622,12 +598,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -694,12 +667,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -766,12 +736,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -838,12 +805,9 @@ export class AccountRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/blockRoutesApi.ts b/src/infrastructure/api/blockRoutesApi.ts index 881fb16997..eafea7acf8 100644 --- a/src/infrastructure/api/blockRoutesApi.ts +++ b/src/infrastructure/api/blockRoutesApi.ts @@ -133,12 +133,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "BlockInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -190,12 +187,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "StatementsDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -257,12 +251,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -321,12 +312,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -385,12 +373,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MerkleProofInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -449,12 +434,9 @@ export class BlockRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MerkleProofInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/chainRoutesApi.ts b/src/infrastructure/api/chainRoutesApi.ts index 4e0706620c..e2697992b4 100644 --- a/src/infrastructure/api/chainRoutesApi.ts +++ b/src/infrastructure/api/chainRoutesApi.ts @@ -124,12 +124,9 @@ export class ChainRoutesApi { } else { body = ObjectSerializer.deserialize(body, "HeightInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class ChainRoutesApi { } else { body = ObjectSerializer.deserialize(body, "BlockchainScoreDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/diagnosticRoutesApi.ts b/src/infrastructure/api/diagnosticRoutesApi.ts index e70a25623f..01daa002d8 100644 --- a/src/infrastructure/api/diagnosticRoutesApi.ts +++ b/src/infrastructure/api/diagnosticRoutesApi.ts @@ -124,12 +124,9 @@ export class DiagnosticRoutesApi { } else { body = ObjectSerializer.deserialize(body, "StorageInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class DiagnosticRoutesApi { } else { body = ObjectSerializer.deserialize(body, "ServerDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/mosaicRoutesApi.ts b/src/infrastructure/api/mosaicRoutesApi.ts index dfb0e36a8b..00e398b6b6 100644 --- a/src/infrastructure/api/mosaicRoutesApi.ts +++ b/src/infrastructure/api/mosaicRoutesApi.ts @@ -132,12 +132,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "MosaicInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -189,12 +186,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -246,12 +240,9 @@ export class MosaicRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/namespaceRoutesApi.ts b/src/infrastructure/api/namespaceRoutesApi.ts index 7ce0824c7b..9559ef2f13 100644 --- a/src/infrastructure/api/namespaceRoutesApi.ts +++ b/src/infrastructure/api/namespaceRoutesApi.ts @@ -133,12 +133,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NamespaceInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -200,12 +197,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -267,12 +261,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -324,12 +315,9 @@ export class NamespaceRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/networkRoutesApi.ts b/src/infrastructure/api/networkRoutesApi.ts index 1e9fa0422c..3c574d8c46 100644 --- a/src/infrastructure/api/networkRoutesApi.ts +++ b/src/infrastructure/api/networkRoutesApi.ts @@ -123,12 +123,9 @@ export class NetworkRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NetworkTypeDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/nodeRoutesApi.ts b/src/infrastructure/api/nodeRoutesApi.ts index cd2b0ca19b..456a05ad64 100644 --- a/src/infrastructure/api/nodeRoutesApi.ts +++ b/src/infrastructure/api/nodeRoutesApi.ts @@ -124,12 +124,9 @@ export class NodeRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NodeInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -174,12 +171,9 @@ export class NodeRoutesApi { } else { body = ObjectSerializer.deserialize(body, "NodeTimeDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/api/transactionRoutesApi.ts b/src/infrastructure/api/transactionRoutesApi.ts index 39618d7377..0a3abdd119 100644 --- a/src/infrastructure/api/transactionRoutesApi.ts +++ b/src/infrastructure/api/transactionRoutesApi.ts @@ -136,12 +136,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -193,12 +190,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -250,12 +244,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "AnnounceTransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -307,12 +298,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "TransactionInfoDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -364,12 +352,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "TransactionStatusDTO"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -421,12 +406,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); @@ -478,12 +460,9 @@ export class TransactionRoutesApi { } else { body = ObjectSerializer.deserialize(body, "Array"); if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); diff --git a/src/infrastructure/templates/api-single.mustache b/src/infrastructure/templates/api-single.mustache index c90274237c..9dd163676f 100755 --- a/src/infrastructure/templates/api-single.mustache +++ b/src/infrastructure/templates/api-single.mustache @@ -219,12 +219,9 @@ export class {{classname}} { body = ObjectSerializer.deserialize(body, "{{{returnType}}}"); {{/returnType}} if (response.statusCode && response.statusCode >= 200 && response.statusCode <= 299) { - resolve(body); + resolve({ response, body }); } else { - reject({ - statusCode: response.statusCode, - statusMessage: response.statusMessage - }); + reject({ response, body }); } } }); From 46141f9d3efebc41f7dbee7482bbd82c20aac2f4 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 9 Jul 2019 09:56:52 +0100 Subject: [PATCH 12/13] Fixed error handling --- src/infrastructure/Http.ts | 13 ++++++++----- test/infrastructure/TransactionHttp.spec.ts | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/infrastructure/Http.ts b/src/infrastructure/Http.ts index 2a94ac1a66..7df9e615ae 100644 --- a/src/infrastructure/Http.ts +++ b/src/infrastructure/Http.ts @@ -59,10 +59,13 @@ export abstract class Http { } errorHandling(error: any): Error { - const formattedError = { - statusCode: error.response.statusCode, - errorDetails: error.response.body, - }; - return new Error(JSON.stringify(formattedError)); + if (error.response && error.response.statusCode && error.response.body) { + const formattedError = { + statusCode: error.response.statusCode, + errorDetails: error.response.body, + }; + return new Error(JSON.stringify(formattedError)); + } + return new Error(error); } } diff --git a/test/infrastructure/TransactionHttp.spec.ts b/test/infrastructure/TransactionHttp.spec.ts index 5a45c7d440..d7ab93c3b3 100644 --- a/test/infrastructure/TransactionHttp.spec.ts +++ b/test/infrastructure/TransactionHttp.spec.ts @@ -49,7 +49,6 @@ describe('TransactionHttp', () => { return trnsHttp.announceAggregateBonded(signedTx) .toPromise() .then(() => { - throw new Error('Should be called'); }) .catch((reason) => { expect(reason.toString()).to.be.equal('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); From 3f67948ac21eb8bf97ee3a19ed42a1b849dfd565 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Wed, 10 Jul 2019 09:56:29 +0100 Subject: [PATCH 13/13] Fixed transactionHttp unit test --- src/infrastructure/TransactionHttp.ts | 2 +- test/infrastructure/TransactionHttp.spec.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/infrastructure/TransactionHttp.ts b/src/infrastructure/TransactionHttp.ts index 8c6455f6f9..c96c863910 100644 --- a/src/infrastructure/TransactionHttp.ts +++ b/src/infrastructure/TransactionHttp.ts @@ -166,7 +166,7 @@ export class TransactionHttp extends Http implements TransactionRepository { */ public announceAggregateBonded(signedTransaction: SignedTransaction): Observable { if (signedTransaction.type !== TransactionType.AGGREGATE_BONDED) { - throwError('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); + throw new Error('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); } return observableFrom(this.transactionRoutesApi.announcePartialTransaction(signedTransaction)).pipe( map((response: { response: ClientResponse; body: AnnounceTransactionInfoDTO; } ) => { diff --git a/test/infrastructure/TransactionHttp.spec.ts b/test/infrastructure/TransactionHttp.spec.ts index d7ab93c3b3..40107dae10 100644 --- a/test/infrastructure/TransactionHttp.spec.ts +++ b/test/infrastructure/TransactionHttp.spec.ts @@ -46,12 +46,10 @@ describe('TransactionHttp', () => { const signedTx = account.sign(aggTx, generationHash); const trnsHttp = new TransactionHttp(NIS2_URL); - return trnsHttp.announceAggregateBonded(signedTx) + expect(() => { + trnsHttp.announceAggregateBonded(signedTx) .toPromise() - .then(() => { - }) - .catch((reason) => { - expect(reason.toString()).to.be.equal('Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); - }); + .then(); + }).to.throw(Error, 'Only Transaction Type 0x4241 is allowed for announce aggregate bonded'); }); });