Skip to content

Commit e111914

Browse files
Merge pull request #7674 from BitGo/WP-7050-address-verification-vet
feat: address verification for vet
2 parents ea150f3 + 3638dd5 commit e111914

File tree

2 files changed

+141
-5
lines changed

2 files changed

+141
-5
lines changed

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

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ import {
2020
SignedTransaction,
2121
SignTransactionOptions,
2222
TokenTransferRecipientParams,
23-
VerifyAddressOptions,
23+
TssVerifyAddressOptions,
2424
VerifyTransactionOptions,
2525
TokenType,
2626
Ecdsa,
2727
ECDSAUtils,
2828
Environments,
2929
BaseBroadcastTransactionOptions,
3030
BaseBroadcastTransactionResult,
31+
verifyMPCWalletAddress,
3132
} from '@bitgo/sdk-core';
3233
import * as mpc from '@bitgo/sdk-lib-mpc';
3334
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
@@ -53,6 +54,12 @@ interface FeeEstimateData {
5354
coefDivisor: string;
5455
}
5556

57+
export interface TssVerifyVetAddressOptions extends TssVerifyAddressOptions {
58+
address: string;
59+
baseAddress?: string;
60+
walletVersion?: number;
61+
}
62+
5663
/**
5764
* Full Name: Vechain
5865
* Docs: https://docs.vechain.org/
@@ -153,12 +160,46 @@ export class Vet extends BaseCoin {
153160
return true;
154161
}
155162

156-
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
157-
const { address: newAddress } = params;
163+
/**
164+
* Verify that an address belongs to this wallet.
165+
*
166+
* @param {TssVerifyVetAddressOptions} params - Verification parameters
167+
* @returns {Promise<boolean>} True if address belongs to wallet
168+
* @throws {InvalidAddressError} If address format is invalid
169+
* @throws {Error} If invalid wallet version or missing parameters
170+
*/
171+
async isWalletAddress(params: TssVerifyVetAddressOptions): Promise<boolean> {
172+
const { address, baseAddress, walletVersion } = params;
173+
174+
if (address && !this.isValidAddress(address)) {
175+
throw new InvalidAddressError(`invalid address: ${address}`);
176+
}
177+
178+
if (walletVersion !== 6) {
179+
throw new Error(`VET only supports wallet version 6, but got version ${walletVersion}`);
180+
}
181+
182+
const isVerifyingBaseAddress = baseAddress && address.toLowerCase() === baseAddress.toLowerCase();
183+
if (isVerifyingBaseAddress) {
184+
const index = typeof params.index === 'string' ? parseInt(params.index, 10) : params.index;
185+
if (index !== 0) {
186+
throw new Error(`Base address verification requires index 0, but got index ${params.index}.`);
187+
}
188+
}
158189

159-
if (!this.isValidAddress(newAddress)) {
160-
throw new InvalidAddressError(`invalid address: ${newAddress}`);
190+
const result = await verifyMPCWalletAddress(
191+
{ ...params, keyCurve: 'secp256k1' },
192+
this.isValidAddress.bind(this),
193+
(pubKey) => {
194+
const keyPair = new EthKeyPair({ pub: pubKey });
195+
return keyPair.getAddress();
196+
}
197+
);
198+
199+
if (!result) {
200+
throw new InvalidAddressError(`invalid address: ${address}`);
161201
}
202+
162203
return true;
163204
}
164205

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

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,99 @@ describe('Vechain', function () {
238238
basecoin.isValidAddress(address).should.equal(false);
239239
});
240240
});
241+
242+
describe('address verification', () => {
243+
const testData = {
244+
walletVersion: 6,
245+
commonKeychain:
246+
'02fad451e7d1a536897ded5f803a73cc7309a403cf43bb25bda494b9800efe32999b6b71b6159eccf1244492556b733f68733a23c184bf40bc37c52da5ad29e575',
247+
baseAddress: '0x8420429aa50b7f6ab196c4ce0dcf629fdbb821a1',
248+
feeAddress: '0x33f9d3172de8a88e47b399562e51fa9cde0f2511',
249+
depositAddress: '0x26b88c0a103d185792a9597580c2c5170d93f410',
250+
depositIndex: 3,
251+
forwarderVersion: 5,
252+
};
253+
254+
it('should verify a valid TSS base address (wallet version 6)', async function () {
255+
const params = {
256+
address: testData.baseAddress,
257+
baseAddress: testData.baseAddress,
258+
keychains: [
259+
{ commonKeychain: testData.commonKeychain },
260+
{ commonKeychain: testData.commonKeychain },
261+
{ commonKeychain: testData.commonKeychain },
262+
],
263+
index: 0,
264+
walletVersion: testData.walletVersion,
265+
coinSpecific: {
266+
feeAddress: testData.feeAddress,
267+
forwarderVersion: testData.forwarderVersion,
268+
},
269+
};
270+
271+
const result = await basecoin.isWalletAddress(params);
272+
result.should.equal(true);
273+
});
274+
275+
it('should fail to verify a invalid TSS base address (wallet version 6)', async function () {
276+
const params = {
277+
address: '0x8420429aa50b7f6ab196c4ce0dcf629fdbb821a0',
278+
baseAddress: testData.baseAddress,
279+
keychains: [
280+
{ commonKeychain: testData.commonKeychain },
281+
{ commonKeychain: testData.commonKeychain },
282+
{ commonKeychain: testData.commonKeychain },
283+
],
284+
index: 0,
285+
walletVersion: testData.walletVersion,
286+
coinSpecific: {
287+
feeAddress: testData.feeAddress,
288+
forwarderVersion: testData.forwarderVersion,
289+
},
290+
};
291+
292+
await basecoin.isWalletAddress(params).should.be.rejected();
293+
});
294+
295+
it('should verify a valid TSS deposit address (wallet version 6)', async function () {
296+
const params = {
297+
address: testData.depositAddress,
298+
baseAddress: testData.baseAddress,
299+
keychains: [
300+
{ commonKeychain: testData.commonKeychain },
301+
{ commonKeychain: testData.commonKeychain },
302+
{ commonKeychain: testData.commonKeychain },
303+
],
304+
index: testData.depositIndex,
305+
walletVersion: testData.walletVersion,
306+
coinSpecific: {
307+
feeAddress: testData.feeAddress,
308+
forwarderVersion: testData.forwarderVersion,
309+
},
310+
};
311+
312+
const result = await basecoin.isWalletAddress(params);
313+
result.should.equal(true);
314+
});
315+
316+
it('should fail to verify a invalid TSS deposit address (wallet version 6)', async function () {
317+
const params = {
318+
address: '0x26b88c0a103d185792a9597580c2c5170d93f411',
319+
baseAddress: testData.baseAddress,
320+
keychains: [
321+
{ commonKeychain: testData.commonKeychain },
322+
{ commonKeychain: testData.commonKeychain },
323+
{ commonKeychain: testData.commonKeychain },
324+
],
325+
index: testData.depositIndex,
326+
walletVersion: testData.walletVersion,
327+
coinSpecific: {
328+
feeAddress: testData.feeAddress,
329+
forwarderVersion: testData.forwarderVersion,
330+
},
331+
};
332+
333+
await basecoin.isWalletAddress(params).should.be.rejected();
334+
});
335+
});
241336
});

0 commit comments

Comments
 (0)