Skip to content

Commit cc7f8e6

Browse files
committed
fix: allowing plain addresses in rest payloads
1 parent 81f5397 commit cc7f8e6

17 files changed

+82
-35
lines changed

src/core/utils/DtoMapping.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class DtoMapping {
4545
return new AccountRestrictions(
4646
accountRestrictions.accountRestrictions.version || 1,
4747
accountRestrictions['id'],
48-
Address.createFromEncoded(accountRestrictions.accountRestrictions.address),
48+
DtoMapping.toAddress(accountRestrictions.accountRestrictions.address),
4949
accountRestrictions.accountRestrictions.restrictions.map((prop) => {
5050
const restrictionFlags = prop.restrictionFlags as number;
5151
switch (restrictionFlags) {
@@ -55,7 +55,7 @@ export class DtoMapping {
5555
case AddressRestrictionFlag.BlockOutgoingAddress:
5656
return new AccountRestriction(
5757
restrictionFlags,
58-
prop.values.map((value) => Address.createFromEncoded(value as string)),
58+
prop.values.map((value) => DtoMapping.toAddress(value as string)),
5959
);
6060
case MosaicRestrictionFlag.AllowMosaic:
6161
case MosaicRestrictionFlag.BlockMosaic:
@@ -76,6 +76,22 @@ export class DtoMapping {
7676
);
7777
}
7878

79+
/**
80+
* This method knows how to convert an address payload sent by Rest to Address.
81+
*
82+
* Currently rest sends hex encoded addresses, it is desired to use decoded/plain addresses.
83+
*
84+
* This method handles both format, encoded (deprecated) and decoded/plain/raw addresses.
85+
*
86+
* Clients using this SDK will be able to process both payloads.
87+
*
88+
* @param value the address in encoded (6823BB7C3C089D996585466380EDBDC19D4959184893E38C) format or decoded/plain format (SB3KUBHATFCPV7UZQLWAQ2EUR6SIHBSBEOEDDDF3)
89+
* @return the Address object.
90+
*/
91+
public static toAddress(value: string): Address {
92+
return Address.isValidEncodedAddress(value) ? Address.createFromEncoded(value) : Address.createFromRawAddress(value);
93+
}
94+
7995
/**
8096
* Creates a copy of the first object adding the attributes of the second object.
8197
* @param object the object to be cloned

src/core/utils/UnresolvedMapping.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { NamespaceId } from '../../model/namespace/NamespaceId';
2121
import { NetworkType } from '../../model/network/NetworkType';
2222
import { Convert } from '../format/Convert';
2323
import { RawAddress } from '../format/RawAddress';
24+
import { DtoMapping } from './DtoMapping';
2425

2526
/**
2627
* @internal
@@ -67,7 +68,7 @@ export class UnresolvedMapping {
6768
}
6869

6970
// read address from encoded hexadecimal notation
70-
return Address.createFromEncoded(address);
71+
return DtoMapping.toAddress(address);
7172
}
7273

7374
/**

src/infrastructure/AccountHttp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class AccountHttp extends Http implements AccountRepository {
113113
return new AccountInfo(
114114
dto.account.version || 1,
115115
dto.id,
116-
Address.createFromEncoded(dto.account.address),
116+
DtoMapping.toAddress(dto.account.address),
117117
UInt64.fromNumericString(dto.account.addressHeight),
118118
dto.account.publicKey,
119119
UInt64.fromNumericString(dto.account.publicKeyHeight),

src/infrastructure/BlockHttp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export class BlockHttp extends Http implements BlockRepository {
121121
dto.block.proofGamma,
122122
dto.block.proofScalar,
123123
dto.block.proofVerificationHash,
124-
Address.createFromEncoded(dto.block.beneficiaryAddress),
124+
DtoMapping.toAddress(dto.block.beneficiaryAddress),
125125
dto.meta.transactionsCount,
126126
dto.meta.statementsCount,
127127
);

src/infrastructure/HashLockHttp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class HashLockHttp extends Http implements HashLockRepository {
100100
return new HashLockInfo(
101101
dto.lock.version || 1,
102102
dto.id,
103-
Address.createFromEncoded(dto.lock.ownerAddress),
103+
DtoMapping.toAddress(dto.lock.ownerAddress),
104104
new MosaicId(dto.lock.mosaicId),
105105
UInt64.fromNumericString(dto.lock.amount),
106106
UInt64.fromNumericString(dto.lock.endHeight),

src/infrastructure/Listener.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { Observable, of, Subject } from 'rxjs';
1818
import { catchError, distinctUntilChanged, filter, map, mergeMap, share, switchMap } from 'rxjs/operators';
1919
import { BlockInfoDTO } from 'symbol-openapi-typescript-fetch-client';
2020
import * as WebSocket from 'ws';
21+
import { DtoMapping } from '../core/utils';
2122
import { UnresolvedAddress } from '../model';
2223
import { Address } from '../model/account/Address';
2324
import { PublicAccount } from '../model/account/PublicAccount';
@@ -578,7 +579,7 @@ export class Listener implements IListener {
578579
dto.block.proofGamma,
579580
dto.block.proofScalar,
580581
dto.block.proofVerificationHash,
581-
dto.block.beneficiaryAddress ? Address.createFromEncoded(dto.block.beneficiaryAddress) : undefined,
582+
dto.block.beneficiaryAddress ? DtoMapping.toAddress(dto.block.beneficiaryAddress) : undefined,
582583
);
583584
}
584585

src/infrastructure/MetadataHttp.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ export class MetadataHttp extends Http implements MetadataRepository {
122122
new MetadataEntry(
123123
metadataEntry.version || 1,
124124
metadataEntry.compositeHash,
125-
Address.createFromEncoded(metadataEntry.sourceAddress),
126-
Address.createFromEncoded(metadataEntry.targetAddress),
125+
DtoMapping.toAddress(metadataEntry.sourceAddress),
126+
DtoMapping.toAddress(metadataEntry.targetAddress),
127127
UInt64.fromHex(metadataEntry.scopedMetadataKey),
128128
metadataEntry.metadataType.valueOf(),
129129
Convert.decodeHex(metadataEntry.value),

src/infrastructure/MosaicHttp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class MosaicHttp extends Http implements MosaicRepository {
133133
new MosaicId(mosaicInfo.mosaic.id),
134134
UInt64.fromNumericString(mosaicInfo.mosaic.supply),
135135
UInt64.fromNumericString(mosaicInfo.mosaic.startHeight),
136-
Address.createFromEncoded(mosaicInfo.mosaic.ownerAddress),
136+
DtoMapping.toAddress(mosaicInfo.mosaic.ownerAddress),
137137
mosaicInfo.mosaic.revision,
138138
new MosaicFlags(mosaicInfo.mosaic.flags),
139139
mosaicInfo.mosaic.divisibility,

src/infrastructure/MultisigHttp.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ export class MultisigHttp extends Http implements MultisigRepository {
9292
private toMultisigAccountInfo(dto: MultisigAccountInfoDTO): MultisigAccountInfo {
9393
return new MultisigAccountInfo(
9494
dto.multisig.version || 1,
95-
Address.createFromEncoded(dto.multisig.accountAddress),
95+
DtoMapping.toAddress(dto.multisig.accountAddress),
9696
dto.multisig.minApproval,
9797
dto.multisig.minRemoval,
98-
dto.multisig.cosignatoryAddresses.map((cosigner) => Address.createFromEncoded(cosigner)),
99-
dto.multisig.multisigAddresses.map((multisig) => Address.createFromEncoded(multisig)),
98+
dto.multisig.cosignatoryAddresses.map((cosigner) => DtoMapping.toAddress(cosigner)),
99+
dto.multisig.multisigAddresses.map((multisig) => DtoMapping.toAddress(multisig)),
100100
);
101101
}
102102
}

src/infrastructure/NamespaceHttp.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class NamespaceHttp extends Http implements NamespaceRepository {
8282
body.accountNames.map(
8383
(accountName) =>
8484
new AccountNames(
85-
Address.createFromEncoded(accountName.address),
85+
DtoMapping.toAddress(accountName.address),
8686
accountName.names.map((name) => {
8787
return new NamespaceName(new NamespaceId(name), name);
8888
}),
@@ -255,7 +255,7 @@ export class NamespaceHttp extends Http implements NamespaceRepository {
255255
dto.namespace.depth,
256256
NamespaceHttp.extractLevels(dto.namespace),
257257
NamespaceId.createFromEncoded(dto.namespace.parentId),
258-
Address.createFromEncoded(dto.namespace.ownerAddress),
258+
DtoMapping.toAddress(dto.namespace.ownerAddress),
259259
UInt64.fromNumericString(dto.namespace.startHeight),
260260
UInt64.fromNumericString(dto.namespace.endHeight),
261261
NamespaceHttp.extractAlias(dto.namespace),
@@ -292,7 +292,7 @@ export class NamespaceHttp extends Http implements NamespaceRepository {
292292
if (namespace.alias && namespace.alias.type.valueOf() === AliasType.Mosaic) {
293293
return new MosaicAlias(new MosaicId(namespace.alias.mosaicId!));
294294
} else if (namespace.alias && namespace.alias.type.valueOf() === AliasType.Address) {
295-
return new AddressAlias(Address.createFromEncoded(namespace.alias.address!));
295+
return new AddressAlias(DtoMapping.toAddress(namespace.alias.address!));
296296
}
297297
return new EmptyAlias();
298298
}

src/infrastructure/RestrictionMosaicHttp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class RestrictionMosaicHttp extends Http implements RestrictionMosaicRepo
100100
dto.mosaicRestrictionEntry.compositeHash,
101101
dto.mosaicRestrictionEntry.entryType.valueOf(),
102102
new MosaicId(dto.mosaicRestrictionEntry.mosaicId),
103-
Address.createFromEncoded(addressRestrictionDto.mosaicRestrictionEntry.targetAddress),
103+
DtoMapping.toAddress(addressRestrictionDto.mosaicRestrictionEntry.targetAddress),
104104
addressRestrictionDto.mosaicRestrictionEntry.restrictions.map(RestrictionMosaicHttp.toMosaicAddressRestrictionItem),
105105
);
106106
}

src/infrastructure/SecretLockHttp.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,14 @@ export class SecretLockHttp extends Http implements SecretLockRepository {
9292
return new SecretLockInfo(
9393
dto.lock.version || 1,
9494
dto.id,
95-
Address.createFromEncoded(dto.lock.ownerAddress),
95+
DtoMapping.toAddress(dto.lock.ownerAddress),
9696
new MosaicId(dto.lock.mosaicId),
9797
UInt64.fromNumericString(dto.lock.amount),
9898
UInt64.fromNumericString(dto.lock.endHeight),
9999
dto.lock.status.valueOf(),
100100
dto.lock.hashAlgorithm.valueOf(),
101101
dto.lock.secret,
102-
Address.createFromEncoded(dto.lock.recipientAddress),
102+
DtoMapping.toAddress(dto.lock.recipientAddress),
103103
dto.lock.compositeHash,
104104
);
105105
}

src/infrastructure/receipt/CreateReceiptFromDTO.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { ResolutionStatementInfoDTO, TransactionStatementInfoDTO } from 'symbol-openapi-typescript-fetch-client';
18+
import { DtoMapping } from '../../core/utils';
1819
import { UnresolvedMapping } from '../../core/utils/UnresolvedMapping';
1920
import { Address } from '../../model/account/Address';
2021
import { UnresolvedAddress } from '../../model/account/UnresolvedAddress';
@@ -85,7 +86,7 @@ export const createAddressResolutionStatement = (statementInfoDTO: ResolutionSta
8586
extractUnresolvedAddress(statementDTO.unresolved),
8687
statementDTO.resolutionEntries.map((entry) => {
8788
return new ResolutionEntry(
88-
Address.createFromEncoded(entry.resolved),
89+
DtoMapping.toAddress(entry.resolved),
8990
new ReceiptSource(entry.source.primaryId, entry.source.secondaryId),
9091
);
9192
}),
@@ -100,7 +101,7 @@ export const createAddressResolutionStatement = (statementInfoDTO: ResolutionSta
100101
*/
101102
const createBalanceChangeReceipt = (receiptDTO): Receipt => {
102103
return new BalanceChangeReceipt(
103-
Address.createFromEncoded(receiptDTO.targetAddress),
104+
DtoMapping.toAddress(receiptDTO.targetAddress),
104105
new MosaicId(receiptDTO.mosaicId),
105106
UInt64.fromNumericString(receiptDTO.amount),
106107
receiptDTO.version,
@@ -116,8 +117,8 @@ const createBalanceChangeReceipt = (receiptDTO): Receipt => {
116117
*/
117118
const createBalanceTransferReceipt = (receiptDTO): Receipt => {
118119
return new BalanceTransferReceipt(
119-
Address.createFromEncoded(receiptDTO.senderAddress),
120-
Address.createFromEncoded(receiptDTO.recipientAddress),
120+
DtoMapping.toAddress(receiptDTO.senderAddress),
121+
DtoMapping.toAddress(receiptDTO.recipientAddress),
121122
new MosaicId(receiptDTO.mosaicId),
122123
UInt64.fromNumericString(receiptDTO.amount),
123124
receiptDTO.version,

src/model/transaction/AddressAliasTransaction.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
TransactionBuilder,
2424
} from 'catbuffer-typescript';
2525
import { Convert } from '../../core/format';
26+
import { DtoMapping } from '../../core/utils';
2627
import { Address } from '../account/Address';
2728
import { PublicAccount } from '../account/PublicAccount';
2829
import { AliasAction } from '../namespace/AliasAction';
@@ -131,7 +132,7 @@ export class AddressAliasTransaction extends Transaction {
131132
: Deadline.createFromDTO((builder as AddressAliasTransactionBuilder).getDeadline().timestamp),
132133
builder.getAliasAction().valueOf(),
133134
new NamespaceId(builder.getNamespaceId().namespaceId),
134-
Address.createFromEncoded(Convert.uint8ToHex(builder.getAddress().address)),
135+
DtoMapping.toAddress(Convert.uint8ToHex(builder.getAddress().address)),
135136
networkType,
136137
isEmbedded ? new UInt64([0, 0]) : new UInt64((builder as AddressAliasTransactionBuilder).fee.amount),
137138
signature,

test/core/utils/DtoMapping.spec.ts

+30
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
MerkleTreeLeafDTO,
2424
} from 'symbol-openapi-typescript-fetch-client';
2525
import { DtoMapping } from '../../../src/core/utils/DtoMapping';
26+
import { Address } from '../../../src/model/account';
2627
import { PublicAccount } from '../../../src/model/account/PublicAccount';
2728
import { MosaicId } from '../../../src/model/mosaic/MosaicId';
2829
import { NetworkType } from '../../../src/model/network/NetworkType';
@@ -112,6 +113,35 @@ describe('DtoMapping', () => {
112113
expect(DtoMapping.toSimpleHex("0x29C6'42F2'F432'8612")).to.be.equal('29C642F2F4328612');
113114
});
114115

116+
it('toAddress', () => {
117+
expect(DtoMapping.toAddress('7826D27E1D0A26CA4E316F901E23E55C8711DB20DF5C49B5').plain()).to.be.equal(
118+
'PATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA35OETNI',
119+
);
120+
121+
expect(DtoMapping.toAddress('7826D27E1D0A26CA4E316F901E23E55C8711DB20DF5C49B5').encoded()).to.be.equal(
122+
'7826D27E1D0A26CA4E316F901E23E55C8711DB20DF5C49B5',
123+
);
124+
expect(DtoMapping.toAddress('TDR6EW2WBHJQDYMNGFX2UBZHMMZC5PGL2YBO3KA').plain()).to.be.equal(
125+
'TDR6EW2WBHJQDYMNGFX2UBZHMMZC5PGL2YBO3KA',
126+
);
127+
128+
expect(DtoMapping.toAddress('TDR6-EW2-WBHJQDYMNGFX-2UBZHMMZC5PG-L2YBO3KA').plain()).to.be.equal(
129+
'TDR6EW2WBHJQDYMNGFX2UBZHMMZC5PGL2YBO3KA',
130+
);
131+
// This method should raise! It does not validate the chechsum!
132+
expect(Address.createFromEncoded('917E7E29A01014C2F3000000000000000000000000000000').plain()).to.be.equal(
133+
'SF7H4KNACAKMF4YAAAAAAAAAAAAAAAAAAAAAAAA',
134+
);
135+
// This method should raise! It does not validate the chechsum!
136+
expect(Address.createFromRawAddress('SF7H4KNACAKMF4YAAAAAAAAAAAAAAAAAAAAAAAA').plain()).to.be.equal(
137+
'SF7H4KNACAKMF4YAAAAAAAAAAAAAAAAAAAAAAAA',
138+
);
139+
expect(Address.isValidEncodedAddress('917E7E29A01014C2F3000000000000000000000000000000')).to.be.equal(false);
140+
expect(() => DtoMapping.toAddress('917E7E29A01014C2F3000000000000000000000000000000')).to.throw;
141+
expect(() => DtoMapping.toAddress('XDR6-EW2-WBHJQDYMNGFX-2UBZHMMZC5PG-L2YBO3KA')).to.throw;
142+
expect(() => DtoMapping.toAddress('917E7E29A01014C2F3000000000000000000000000000')).to.throw;
143+
});
144+
115145
it('parse merkle tree', () => {
116146
const merkleStateInfoDTO = {} as MerkleStateInfoDTO;
117147
const merkleLeafDTO = {} as MerkleTreeLeafDTO;

test/infrastructure/receipt/CreateReceiptFromDTO.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ describe('Receipt - CreateStatementFromDTO', () => {
163163
primaryId: 4,
164164
secondaryId: 0,
165165
},
166-
resolved: '917E7E29A01014C2F3000000000000000000000000000000',
166+
resolved: '7826D27E1D0A26CA4E316F901E23E55C8711DB20DF5C49B5',
167167
},
168168
],
169169
},
@@ -179,7 +179,7 @@ describe('Receipt - CreateStatementFromDTO', () => {
179179
primaryId: 2,
180180
secondaryId: 0,
181181
},
182-
resolved: '9103B60AAF27626883000000000000000000000000000000',
182+
resolved: 'PATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA35OETNI',
183183
},
184184
],
185185
},
@@ -275,7 +275,7 @@ describe('Receipt - CreateStatementFromDTO', () => {
275275
deepEqual(unresolvedAddress.toHex(), '83686227AF0AB603');
276276
expect(statement.addressResolutionStatements[0].resolutionEntries.length).to.be.equal(1);
277277
expect((statement.addressResolutionStatements[0].resolutionEntries[0].resolved as Address).plain()).to.be.equal(
278-
Address.createFromEncoded('917E7E29A01014C2F3000000000000000000000000000000').plain(),
278+
'PATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA35OETNI',
279279
);
280280

281281
deepEqual(statement.mosaicResolutionStatements[0].height, UInt64.fromNumericString('1506'));
@@ -299,7 +299,7 @@ describe('Receipt - CreateStatementFromDTO', () => {
299299
primaryId: 4,
300300
secondaryId: 0,
301301
},
302-
resolved: '917E7E29A01014C2F3000000000000000000000000000000',
302+
resolved: account.address.encoded(),
303303
},
304304
],
305305
},
@@ -321,7 +321,7 @@ describe('Receipt - CreateStatementFromDTO', () => {
321321
primaryId: 4,
322322
secondaryId: 0,
323323
},
324-
resolved: '917E7E29A01014C2F3000000000000000000000000000000',
324+
resolved: account.address.encoded(),
325325
},
326326
],
327327
},

test/model/receipt/Receipt.spec.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('Receipt', () => {
8484
primaryId: 4,
8585
secondaryId: 0,
8686
},
87-
resolved: '917E7E29A01014C2F3000000000000000000000000000000',
87+
resolved: '7826D27E1D0A26CA4E316F901E23E55C8711DB20DF5C49B5',
8888
},
8989
],
9090
},
@@ -319,10 +319,7 @@ describe('Receipt', () => {
319319
(statement.unresolved as Address).plain(),
320320
Address.createFromEncoded('9103B60AAF27626883000000000000000000000000000000').plain(),
321321
);
322-
deepEqual(
323-
(statement.resolutionEntries[0].resolved as Address).plain(),
324-
Address.createFromEncoded('917E7E29A01014C2F3000000000000000000000000000000').plain(),
325-
);
322+
deepEqual((statement.resolutionEntries[0].resolved as Address).plain(), 'PATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA35OETNI');
326323
});
327324

328325
it('should createComplete a inflation receipt', () => {
@@ -355,7 +352,7 @@ describe('Receipt', () => {
355352
it('should generate hash for AddressResolutionStatement', () => {
356353
const receipt = createAddressResolutionStatement(statementDTO.addressResolutionStatements[0]);
357354
const hash = receipt.generateHash(NetworkType.MAIN_NET);
358-
expect(hash).to.be.equal('AA9B667C37C8A19902F3E1098FCEE681318455551CC2FBE9B81E8FA47007CA79');
355+
expect(hash).to.be.equal('EBCD71F16C70F7E34E8B9A98A174B759DB8457093CCF3ECAA3D05721E36AAA33');
359356
});
360357

361358
it('should generate hash for TransactionStatement', () => {

0 commit comments

Comments
 (0)