Skip to content

Commit 29b9ca4

Browse files
committed
feat: added isWalletAddress implementation for canton
Ticket: COIN-6323
1 parent a9a5880 commit 29b9ca4

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

modules/sdk-coin-canton/src/canton.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import {
1111
SignedTransaction,
1212
SignTransactionOptions,
1313
TransactionType,
14-
TssVerifyAddressOptions,
1514
VerifyTransactionOptions,
1615
TransactionExplanation as BaseTransactionExplanation,
1716
BaseTransaction,
1817
PopulatedIntent,
1918
PrebuildTransactionWithIntentOptions,
19+
VerifyAddressOptions,
20+
InvalidAddressError,
21+
UnexpectedAddressError,
2022
} from '@bitgo/sdk-core';
2123
import { auditEddsaPrivateKey } from '@bitgo/sdk-lib-mpc';
2224
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
@@ -32,6 +34,15 @@ export interface ExplainTransactionOptions {
3234
txHex: string;
3335
}
3436

37+
interface AddressDetail {
38+
address: string;
39+
memoId?: string | null;
40+
}
41+
42+
interface CantonCoinSpecific {
43+
rootAddress: string;
44+
}
45+
3546
export class Canton extends BaseCoin {
3647
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
3748

@@ -115,8 +126,22 @@ export class Canton extends BaseCoin {
115126
}
116127

117128
/** @inheritDoc */
118-
isWalletAddress(params: TssVerifyAddressOptions): Promise<boolean> {
119-
throw new Error('Method not implemented.');
129+
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
130+
const [address, queryString] = params.address.split('?');
131+
const urlSearchParams = new URLSearchParams(queryString);
132+
const memoId = urlSearchParams.get('memoId');
133+
const addressDetail: AddressDetail = {
134+
address,
135+
memoId,
136+
};
137+
if (!this.isValidAddress(addressDetail.address)) {
138+
throw new InvalidAddressError(`invalid address: ${addressDetail.address}`);
139+
}
140+
const rootAddress = (params.coinSpecific as CantonCoinSpecific).rootAddress;
141+
if (addressDetail.address !== rootAddress) {
142+
throw new UnexpectedAddressError(`address validation failure: ${addressDetail.address} vs ${rootAddress}`);
143+
}
144+
return true;
120145
}
121146

122147
/** @inheritDoc */

modules/sdk-coin-canton/test/integration/canton.integration.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
import assert from 'assert';
22

3+
import { BitGoAPI } from '@bitgo/sdk-api';
34
import { TransactionType } from '@bitgo/sdk-core';
5+
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
46

57
import { getCantonBuilderFactory } from '../helper';
68
import {
9+
CANTON_ADDRESSES,
10+
CANTON_RECEIVE_ADDRESS,
711
GenerateTopologyResponse,
812
TransferAcceptRawTransaction,
913
TransferRejectRawTransaction,
1014
WalletInitRawTransaction,
1115
} from '../resources';
16+
import { Tcanton } from '../../src';
1217

1318
describe('Canton integration tests', function () {
19+
let bitgo: TestBitGoAPI;
20+
let basecoin: Tcanton;
21+
before(() => {
22+
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
23+
bitgo.safeRegister('tcanton', Tcanton.createInstance);
24+
basecoin = bitgo.coin('tcanton') as Tcanton;
25+
});
26+
1427
describe('Explain raw transaction', function () {
1528
const factory = getCantonBuilderFactory('tcanton');
1629
it('should explain raw wallet init transaction', function () {
@@ -41,4 +54,33 @@ describe('Canton integration tests', function () {
4154
assert.equal(explainTxData.inputAmount, '5.0000000000');
4255
});
4356
});
57+
58+
describe('isWalletAddress', function () {
59+
it('should return true when receive address is valid', async function () {
60+
const params = {
61+
address: CANTON_RECEIVE_ADDRESS.VALID_ADDRESS,
62+
coinSpecific: {
63+
rootAddress: CANTON_ADDRESSES.VALID_ADDRESS,
64+
memoId: '1',
65+
},
66+
};
67+
const isValid = await basecoin.isWalletAddress(params);
68+
isValid.should.equal(true);
69+
});
70+
71+
it('should return false when receive address is invalid', async function () {
72+
const params = {
73+
address: CANTON_RECEIVE_ADDRESS.INVALID_ADDRESS,
74+
coinSpecific: {
75+
rootAddress: CANTON_ADDRESSES.VALID_ADDRESS,
76+
memoId: '1',
77+
},
78+
};
79+
try {
80+
await basecoin.isWalletAddress(params);
81+
} catch (error) {
82+
assert.equal(error.message, 'invalid address: ' + CANTON_ADDRESSES.INVALID_FINGERPRINT);
83+
}
84+
});
85+
});
4486
});

modules/sdk-coin-canton/test/resources.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ export const CANTON_BLOCK_HEIGHT = {
7878
NEGATIVE_BLOCK_HASH: '-100',
7979
};
8080

81+
export const CANTON_RECEIVE_ADDRESS = {
82+
VALID_ADDRESS: `${CANTON_ADDRESSES.VALID_ADDRESS}?memoId=1`,
83+
INVALID_ADDRESS: `${CANTON_ADDRESSES.INVALID_FINGERPRINT}?memoId=1`,
84+
};
85+
8186
export const TransferAcceptance = {
8287
partyId: 'ravi-test-party-1::12205b4e3537a95126d90604592344d8ad3c3ddccda4f79901954280ee19c576714d',
8388
commandId: '3935a06d-3b03-41be-99a5-95b2ecaabf7d',

modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ export interface AddressCoinSpecific {
395395
baseAddress?: string;
396396
pendingChainInitialization?: boolean;
397397
forwarderVersion?: number;
398+
rootAddress?: string;
399+
memoId?: string | null;
398400
}
399401

400402
export interface FullySignedTransaction {

0 commit comments

Comments
 (0)