Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 35 additions & 63 deletions src/infrastructure/MetadataHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
* limitations under the License.
*/

import { from as observableFrom, Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { MetadataDTO, MetadataRoutesApi } from 'symbol-openapi-typescript-node-client';
import { Convert } from '../core/format/Convert';
import { Address } from '../model/account/Address';
Expand Down Expand Up @@ -43,8 +42,7 @@ export class MetadataHttp extends Http implements MetadataRepository {

/**
* Constructor
* @param url
* @param networkType
* @param url the url.
*/
constructor(url: string) {
super(url);
Expand All @@ -59,15 +57,12 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
public getAccountMetadata(address: Address, queryParams?: QueryParams): Observable<Metadata[]> {
return observableFrom(
return this.call(
this.metadataRoutesApi.getAccountMetadata(address.plain(),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering),
(body) => body.metadataEntries.map((metadataEntry) => this.buildMetadata(metadataEntry))
);
}

Expand All @@ -78,12 +73,9 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
getAccountMetadataByKey(address: Address, key: string): Observable<Metadata[]> {
return observableFrom(
this.metadataRoutesApi.getAccountMetadataByKey(address.plain(), key)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
return this.call(
this.metadataRoutesApi.getAccountMetadataByKey(address.plain(), key),
(body) => body.metadataEntries.map((metadataEntry) => this.buildMetadata(metadataEntry))
);
}

Expand All @@ -95,10 +87,9 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata>
*/
getAccountMetadataByKeyAndSender(address: Address, key: string, publicKey: string): Observable<Metadata> {
return observableFrom(
this.metadataRoutesApi.getAccountMetadataByKeyAndSender(address.plain(), key, publicKey)).pipe(
map(({body}) => this.buildMetadata(body)),
catchError((error) => throwError(this.errorHandling(error))),
return this.call(
this.metadataRoutesApi.getAccountMetadataByKeyAndSender(address.plain(), key, publicKey),
(body) => this.buildMetadata(body)
);
}

Expand All @@ -109,15 +100,12 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
getMosaicMetadata(mosaicId: MosaicId, queryParams?: QueryParams): Observable<Metadata[]> {
return observableFrom(
return this.call(
this.metadataRoutesApi.getMosaicMetadata(mosaicId.toHex(),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering),
(body) => body.metadataEntries.map((metadataEntry) => this.buildMetadata(metadataEntry))
);
}

Expand All @@ -128,12 +116,9 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
getMosaicMetadataByKey(mosaicId: MosaicId, key: string): Observable<Metadata[]> {
return observableFrom(
this.metadataRoutesApi.getMosaicMetadataByKey(mosaicId.toHex(), key)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
return this.call(
this.metadataRoutesApi.getMosaicMetadataByKey(mosaicId.toHex(), key),
(body) => body.metadataEntries.map((metadataEntry) => this.buildMetadata(metadataEntry))
);
}

Expand All @@ -145,10 +130,8 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata>
*/
getMosaicMetadataByKeyAndSender(mosaicId: MosaicId, key: string, publicKey: string): Observable<Metadata> {
return observableFrom(
this.metadataRoutesApi.getMosaicMetadataByKeyAndSender(mosaicId.toHex(), key, publicKey)).pipe(
map(({body}) => this.buildMetadata(body)),
catchError((error) => throwError(this.errorHandling(error))),
return this.call(
this.metadataRoutesApi.getMosaicMetadataByKeyAndSender(mosaicId.toHex(), key, publicKey), this.buildMetadata
);
}

Expand All @@ -159,15 +142,11 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
public getNamespaceMetadata(namespaceId: NamespaceId, queryParams?: QueryParams): Observable<Metadata[]> {
return observableFrom(
return this.call(
this.metadataRoutesApi.getNamespaceMetadata(namespaceId.toHex(),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).ordering), body => body.metadataEntries.map(this.buildMetadata)
);
}

Expand All @@ -178,12 +157,9 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata[]>
*/
public getNamespaceMetadataByKey(namespaceId: NamespaceId, key: string): Observable<Metadata[]> {
return observableFrom(
this.metadataRoutesApi.getNamespaceMetadataByKey(namespaceId.toHex(), key)).pipe(
map(({body}) => body.metadataEntries.map((metadataEntry) => {
return this.buildMetadata(metadataEntry);
})),
catchError((error) => throwError(this.errorHandling(error))),
return this.call(
this.metadataRoutesApi.getNamespaceMetadataByKey(namespaceId.toHex(), key),
(body) => body.metadataEntries.map(this.buildMetadata)
);
}

Expand All @@ -195,18 +171,14 @@ export class MetadataHttp extends Http implements MetadataRepository {
* @returns Observable<Metadata>
*/
public getNamespaceMetadataByKeyAndSender(namespaceId: NamespaceId, key: string, publicKey: string): Observable<Metadata> {
return observableFrom(
this.metadataRoutesApi.getNamespaceMetadataByKeyAndSender(namespaceId.toHex(), key, publicKey)).pipe(
map(({body}) => this.buildMetadata(body)),
catchError((error) => throwError(this.errorHandling(error))),
);
return this.call(
this.metadataRoutesApi.getNamespaceMetadataByKeyAndSender(namespaceId.toHex(), key, publicKey), this.buildMetadata);
}

/**
* Returns the mosaic metadata given a mosaic id.
* @param namespaceId - Namespace identifier.
* @param queryParams - Optional query parameters
* @returns Observable<Metadata[]>
* It maps MetadataDTO into a Metadata
* @param metadata - the dto
* @returns the model Metadata.
*/
private buildMetadata(metadata: MetadataDTO): Metadata {
const metadataEntry = metadata.metadataEntry;
Expand Down
216 changes: 216 additions & 0 deletions test/infrastructure/MetadataHttp.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* Copyright 2020 NEM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { expect } from 'chai';
import * as http from 'http';
import {
MetadataDTO,
MetadataEntriesDTO,
MetadataEntryDTO,
MetadataRoutesApi,
MetadataTypeEnum,
} from 'symbol-openapi-typescript-node-client';
import { instance, mock, reset, when } from 'ts-mockito';
import { DtoMapping } from '../../src/core/utils/DtoMapping';
import { MetadataHttp } from '../../src/infrastructure/MetadataHttp';
import { MetadataRepository } from '../../src/infrastructure/MetadataRepository';
import { QueryParams } from '../../src/infrastructure/QueryParams';
import { Address } from '../../src/model/account/Address';
import { Metadata } from '../../src/model/metadata/Metadata';
import { MetadataType } from '../../src/model/metadata/MetadataType';
import { MosaicId } from '../../src/model/mosaic/MosaicId';
import { NamespaceId } from '../../src/model/namespace/NamespaceId';

describe('MetadataHttp', () => {

const address = Address.createFromRawAddress('MCTVW23D2MN5VE4AQ4TZIDZENGNOZXPRPR72DYSX');
const mosaicId = new MosaicId('941299B2B7E1291C');
const namespaceId = new NamespaceId('some.address');

const metadataDTOMosaic = new MetadataDTO();
metadataDTOMosaic.id = 'aaa';

const metadataEntryDtoMosaic = new MetadataEntryDTO();
metadataEntryDtoMosaic.compositeHash = '1';
metadataEntryDtoMosaic.metadataType = MetadataTypeEnum.NUMBER_1;
metadataEntryDtoMosaic.scopedMetadataKey = '123451234512345A';
metadataEntryDtoMosaic.senderPublicKey = 'aSenderPublicKey1';
metadataEntryDtoMosaic.targetPublicKey = 'aTargetPublicKey1';
metadataEntryDtoMosaic.value = 'value1';
metadataEntryDtoMosaic.targetId = '941299B2B7E1291C' as any;
metadataDTOMosaic.metadataEntry = metadataEntryDtoMosaic;

const metadataDTOAddress = new MetadataDTO();
metadataDTOAddress.id = 'bbb';

const metadataEntryDtoAddress = new MetadataEntryDTO();
metadataEntryDtoAddress.compositeHash = '2';
metadataEntryDtoAddress.metadataType = MetadataTypeEnum.NUMBER_0;
metadataEntryDtoAddress.scopedMetadataKey = '123451234512345B';
metadataEntryDtoAddress.senderPublicKey = 'aSenderPublicKey2';
metadataEntryDtoAddress.targetPublicKey = 'aTargetPublicKey2';
metadataEntryDtoAddress.value = 'value1';
metadataEntryDtoAddress.targetId = '941299B2B7E1291D' as any;
metadataDTOAddress.metadataEntry = metadataEntryDtoAddress;

const metadataDTONamespace = new MetadataDTO();
metadataDTONamespace.id = 'ccc';

const metadataEntryDtoNamespace = new MetadataEntryDTO();
metadataEntryDtoNamespace.compositeHash = '3';
metadataEntryDtoNamespace.metadataType = MetadataTypeEnum.NUMBER_2;
metadataEntryDtoNamespace.scopedMetadataKey = '123451234512345C';
metadataEntryDtoNamespace.senderPublicKey = 'aSenderPublicKey3';
metadataEntryDtoNamespace.targetPublicKey = 'aTargetPublicKey3';
metadataEntryDtoNamespace.value = 'value1';
metadataEntryDtoNamespace.targetId = '941299B2B7E1291E' as any;
metadataDTONamespace.metadataEntry = metadataEntryDtoNamespace;

const metadataEntriesDTO = new MetadataEntriesDTO();
metadataEntriesDTO.metadataEntries = [metadataDTOMosaic, metadataDTOAddress, metadataDTONamespace];

const url = 'http://someHost';
const response: http.IncomingMessage = mock();
const metadataRoutesApi: MetadataRoutesApi = mock();
const metadataRepository: MetadataRepository = DtoMapping.assign(
new MetadataHttp(url), {metadataRoutesApi: instance(metadataRoutesApi)});
before(() => {
reset(response);
reset(metadataRoutesApi);
});

function assertMetadataInfo(metadataInfo: Metadata, dto: MetadataDTO) {
expect(metadataInfo).to.be.not.null;
expect(metadataInfo.id).to.be.equals(dto.id);
if (metadataInfo.metadataEntry.metadataType === MetadataType.Mosaic) {
expect(metadataInfo.metadataEntry.targetId!.toHex()).to.be.equals(dto.metadataEntry.targetId);
}
if (metadataInfo.metadataEntry.metadataType === MetadataType.Account) {
expect(metadataInfo.metadataEntry.targetId).to.be.undefined;
}
if (metadataInfo.metadataEntry.metadataType === MetadataType.Namespace) {
expect(metadataInfo.metadataEntry.targetId!.toHex()).to.be.equals(dto.metadataEntry.targetId);
}
expect(metadataInfo.metadataEntry.targetPublicKey).to.be.equals(dto.metadataEntry.targetPublicKey);
expect(metadataInfo.metadataEntry.scopedMetadataKey.toHex()).to.be.equals(dto.metadataEntry.scopedMetadataKey);
expect(metadataInfo.metadataEntry.compositeHash).to.be.equals(dto.metadataEntry.compositeHash);
}

it('getAccountMetadata', async () => {
when(metadataRoutesApi.getAccountMetadata(address.plain(), 1, 'a', '-id')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getAccountMetadata(address, new QueryParams({
pageSize: 1,
id: 'a',
})).toPromise();
expect(metadatas.length).to.be.equals(3);
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getAccountMetadataByKey', async () => {
when(metadataRoutesApi.getAccountMetadataByKey(address.plain(), 'aaa')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getAccountMetadataByKey(address, 'aaa').toPromise();
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getAccountMetadataByKeyAndSender', async () => {
when(metadataRoutesApi.getAccountMetadataByKeyAndSender(address.plain(), 'aaa', 'sender')).thenReturn(Promise.resolve({
response,
body: metadataDTOMosaic,
}));
const metadata = await metadataRepository.getAccountMetadataByKeyAndSender(address, 'aaa', 'sender').toPromise();
assertMetadataInfo(metadata, metadataDTOMosaic);
});

it('getMosaicMetadata', async () => {
when(metadataRoutesApi.getMosaicMetadata(mosaicId.toHex(), 1, 'a', '-id')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getMosaicMetadata(mosaicId, new QueryParams({
pageSize: 1,
id: 'a',
})).toPromise();
expect(metadatas.length).to.be.equals(3);
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getMosaicMetadataByKey', async () => {
when(metadataRoutesApi.getMosaicMetadataByKey(mosaicId.toHex(), 'aaa')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getMosaicMetadataByKey(mosaicId, 'aaa').toPromise();
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getMosaicMetadataByKeyAndSender', async () => {
when(metadataRoutesApi.getMosaicMetadataByKeyAndSender(mosaicId.toHex(), 'aaa', 'sender')).thenReturn(Promise.resolve({
response,
body: metadataDTOMosaic,
}));
const metadata = await metadataRepository.getMosaicMetadataByKeyAndSender(mosaicId, 'aaa', 'sender').toPromise();
assertMetadataInfo(metadata, metadataDTOMosaic);
});

it('getNamespaceMetadata', async () => {
when(metadataRoutesApi.getNamespaceMetadata(namespaceId.toHex(), 2, 'a', '-id')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getNamespaceMetadata(namespaceId, new QueryParams({
pageSize: 2,
id: 'a',
})).toPromise();
expect(metadatas.length).to.be.equals(3);
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getNamespaceMetadataByKey', async () => {
when(metadataRoutesApi.getNamespaceMetadataByKey(namespaceId.toHex(), 'bbb')).thenReturn(Promise.resolve({
response,
body: metadataEntriesDTO,
}));
const metadatas = await metadataRepository.getNamespaceMetadataByKey(namespaceId, 'bbb').toPromise();
assertMetadataInfo(metadatas[0], metadataDTOMosaic);
assertMetadataInfo(metadatas[1], metadataDTOAddress);
assertMetadataInfo(metadatas[2], metadataDTONamespace);
});

it('getNamespaceMetadataByKeyAndSender', async () => {
when(metadataRoutesApi.getNamespaceMetadataByKeyAndSender(namespaceId.toHex(), 'cccc', 'sender1')).thenReturn(Promise.resolve({
response,
body: metadataDTOMosaic,
}));
const metadata = await metadataRepository.getNamespaceMetadataByKeyAndSender(namespaceId, 'cccc', 'sender1').toPromise();
assertMetadataInfo(metadata, metadataDTOMosaic);
});

});