Skip to content

Commit ccc7850

Browse files
feat: address verification for substrate coins (tao, polyx)
2 parents 442eb0a + 0fce509 commit ccc7850

File tree

2 files changed

+102
-4
lines changed

2 files changed

+102
-4
lines changed

modules/abstract-substrate/src/abstractSubstrateCoin.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
EDDSAMethods,
66
EDDSAMethodTypes,
77
KeyPair,
8-
MethodNotImplementedError,
98
MPCAlgorithm,
109
MPCConsolidationRecoveryOptions,
1110
MPCRecoveryOptions,
@@ -20,7 +19,9 @@ import {
2019
ParseTransactionOptions,
2120
RecoveryTxRequest,
2221
SignedTransaction,
23-
VerifyAddressOptions,
22+
TssVerifyAddressOptions,
23+
UnexpectedAddressError,
24+
verifyEddsaTssWalletAddress,
2425
VerifyTransactionOptions,
2526
} from '@bitgo/sdk-core';
2627
import { CoinFamily, BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
@@ -110,8 +111,18 @@ export class SubstrateCoin extends BaseCoin {
110111
}
111112

112113
/** @inheritDoc **/
113-
isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
114-
throw new MethodNotImplementedError();
114+
async isWalletAddress(params: TssVerifyAddressOptions): Promise<boolean> {
115+
const isValid = await verifyEddsaTssWalletAddress(
116+
params,
117+
(addr) => this.isValidAddress(addr),
118+
(pubKey) => this.getAddressFromPublicKey(pubKey)
119+
);
120+
121+
if (!isValid) {
122+
throw new UnexpectedAddressError(`address validation failure: ${params.address} is not a wallet address`);
123+
}
124+
125+
return true;
115126
}
116127

117128
/** @inheritDoc **/

modules/sdk-coin-tao/test/unit/tao.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ describe('Tao:', function () {
1111
let bitgo: TestBitGoAPI;
1212
let baseCoin;
1313

14+
// Test data from wallet 694042b5efbee757e47ec2771cf58a45
15+
const isWalletAddressTestData = {
16+
commonKeychain:
17+
'6e2235aee215f3909b42bf67c360f5bc6ba7087cbf0ed5ba841dd044ae7c3051722f9be974e8e79fa6c4c93d109dbc618672e36571925df0b5a7c5b015bcd382',
18+
rootAddress: '5GU55E8X2YVSpd4LApeJR5RsXwQ8AnPdjM37Qz1drLTKh7as',
19+
receiveAddress: '5EN6LFnhFRtWiwZfFncqBxaNUabTASKnSxoDt2zQvpVX4qVy',
20+
receiveAddressIndex: 1,
21+
};
22+
1423
before(function () {
1524
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
1625
bitgo.safeRegister('tao', Tao.createInstance);
@@ -19,6 +28,84 @@ describe('Tao:', function () {
1928
baseCoin = bitgo.coin('ttao') as Ttao;
2029
});
2130

31+
describe('isWalletAddress', function () {
32+
it('should verify root address (index 0)', async function () {
33+
const keychains = [
34+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
35+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
36+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
37+
];
38+
39+
const result = await baseCoin.isWalletAddress({
40+
address: isWalletAddressTestData.rootAddress,
41+
keychains,
42+
index: 0,
43+
});
44+
45+
result.should.be.true();
46+
});
47+
48+
it('should verify receive address (index > 0)', async function () {
49+
const keychains = [
50+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
51+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
52+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
53+
];
54+
55+
const result = await baseCoin.isWalletAddress({
56+
address: isWalletAddressTestData.receiveAddress,
57+
keychains,
58+
index: isWalletAddressTestData.receiveAddressIndex,
59+
});
60+
61+
result.should.be.true();
62+
});
63+
64+
it('should throw for address mismatch', async function () {
65+
const keychains = [
66+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
67+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
68+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
69+
];
70+
71+
await baseCoin
72+
.isWalletAddress({
73+
address: isWalletAddressTestData.receiveAddress,
74+
keychains,
75+
index: 0, // Wrong index for this address
76+
})
77+
.should.be.rejectedWith(
78+
`address validation failure: ${isWalletAddressTestData.receiveAddress} is not a wallet address`
79+
);
80+
});
81+
82+
it('should throw for invalid address', async function () {
83+
const keychains = [
84+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
85+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
86+
{ commonKeychain: isWalletAddressTestData.commonKeychain },
87+
];
88+
89+
await baseCoin
90+
.isWalletAddress({
91+
address: 'invalidaddress',
92+
keychains,
93+
index: 0,
94+
})
95+
.should.be.rejectedWith('invalid address: invalidaddress');
96+
});
97+
98+
it('should throw for missing keychains', async function () {
99+
await baseCoin
100+
.isWalletAddress({
101+
address: isWalletAddressTestData.rootAddress,
102+
keychains: [],
103+
index: 0,
104+
})
105+
.should.be.rejectedWith('missing required param keychains');
106+
});
107+
});
108+
22109
describe.skip('Recover Transactions:', function () {
23110
const sandBox = sinon.createSandbox();
24111
const recoveryDestination = '5FJ18ywfrWuRifNyc8aPwQ5ium19Fefwmx18H4XYkDc36F2A';

0 commit comments

Comments
 (0)