Skip to content

Commit ccaf664

Browse files
authored
Merge pull request #7712 from BitGo/WP-7082-address-verification-near
feat(sdk-coin-near): address verification for near
2 parents 79ece72 + 49c7e20 commit ccaf664

File tree

2 files changed

+125
-4
lines changed

2 files changed

+125
-4
lines changed

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

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
EDDSAMethodTypes,
2020
Environments,
2121
KeyPair,
22-
MethodNotImplementedError,
2322
MPCAlgorithm,
2423
MPCRecoveryOptions,
2524
MPCSweepRecoveryOptions,
@@ -38,7 +37,9 @@ import {
3837
TokenEnablementConfig,
3938
TransactionParams,
4039
TransactionType,
41-
VerifyAddressOptions,
40+
TssVerifyAddressOptions,
41+
UnexpectedAddressError,
42+
verifyEddsaTssWalletAddress,
4243
VerifyTransactionOptions,
4344
} from '@bitgo/sdk-core';
4445
import { BaseCoin as StaticsBaseCoin, CoinFamily, coins, Nep141Token, Networks } from '@bitgo/statics';
@@ -82,6 +83,15 @@ export interface NearParseTransactionOptions extends BaseParseTransactionOptions
8283
};
8384
}
8485

86+
/**
87+
* Options for verifying NEAR TSS/MPC wallet addresses.
88+
* Extends base TssVerifyAddressOptions with NEAR-specific fields.
89+
*/
90+
export interface TssVerifyNearAddressOptions extends TssVerifyAddressOptions {
91+
/** The root address of the wallet (for root address verification) */
92+
rootAddress?: string;
93+
}
94+
8595
interface TransactionOutput {
8696
address: string;
8797
amount: string;
@@ -984,8 +994,27 @@ export class Near extends BaseCoin {
984994
};
985995
}
986996

987-
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
988-
throw new MethodNotImplementedError();
997+
/**
998+
* Verifies if the given address belongs to a TSS wallet for NEAR.
999+
* For NEAR, the address is the public key directly (implicit accounts).
1000+
*
1001+
* @param {TssVerifyNearAddressOptions} params - Verification parameters
1002+
* @returns {Promise<boolean>} True if address belongs to wallet
1003+
* @throws {UnexpectedAddressError} If address doesn't match derived address
1004+
* @throws {Error} If invalid parameters or root address verification with wrong index
1005+
*/
1006+
async isWalletAddress(params: TssVerifyNearAddressOptions): Promise<boolean> {
1007+
const result = await verifyEddsaTssWalletAddress(
1008+
params,
1009+
(address) => this.isValidAddress(address),
1010+
(publicKey) => publicKey
1011+
);
1012+
1013+
if (!result) {
1014+
throw new UnexpectedAddressError(`address validation failure`);
1015+
}
1016+
1017+
return true;
9891018
}
9901019

9911020
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {

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

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,98 @@ describe('NEAR:', function () {
151151
});
152152
});
153153

154+
describe('Address verification', () => {
155+
const addressVerificationData = {
156+
commonKeychain:
157+
'43d3f6a94d7e3faf4dd390a7e26f554eaa98c8f0813e3f0ae959d61d8acd012e0504e552a5c311260f2fbaef3a817dfa5b85b984cd43b161bebad9ded25764cc',
158+
rootAddress: '98908af363d3e99d87b1d6dce4f80a28bbfe64fee22dbb8a36dada25ba30d027',
159+
receiveAddress: '6aa21569736f6ebaf925fef8ece219c2b703098cc358ce34a97f2c2a2e099659',
160+
receiveAddressIndex: 2,
161+
};
162+
163+
let keychains;
164+
165+
before(function () {
166+
keychains = [
167+
{ commonKeychain: addressVerificationData.commonKeychain },
168+
{ commonKeychain: addressVerificationData.commonKeychain },
169+
{ commonKeychain: addressVerificationData.commonKeychain },
170+
];
171+
});
172+
173+
it('should verify a valid TSS root address (index 0)', async function () {
174+
const params = {
175+
address: addressVerificationData.rootAddress,
176+
rootAddress: addressVerificationData.rootAddress,
177+
keychains: keychains,
178+
index: 0,
179+
};
180+
const result = await basecoin.isWalletAddress(params);
181+
result.should.equal(true);
182+
});
183+
184+
it('should verify a valid TSS receive address (index > 0)', async function () {
185+
const params = {
186+
address: addressVerificationData.receiveAddress,
187+
rootAddress: addressVerificationData.rootAddress,
188+
keychains: keychains,
189+
index: addressVerificationData.receiveAddressIndex,
190+
};
191+
const result = await basecoin.isWalletAddress(params);
192+
result.should.equal(true);
193+
});
194+
195+
it('should throw error for invalid address format', async function () {
196+
const invalidAddress = 'invalid-address';
197+
const params = {
198+
address: invalidAddress,
199+
keychains: keychains,
200+
index: 0,
201+
};
202+
await basecoin.isWalletAddress(params).should.be.rejectedWith('address validation failure');
203+
});
204+
205+
it('should throw error when verifying root address with wrong index', async function () {
206+
const params = {
207+
address: addressVerificationData.rootAddress,
208+
rootAddress: addressVerificationData.rootAddress,
209+
keychains: keychains,
210+
index: 1,
211+
};
212+
await basecoin.isWalletAddress(params).should.be.rejectedWith('address validation failure');
213+
});
214+
215+
it('should throw error when keychains is missing', async function () {
216+
const params = {
217+
address: addressVerificationData.rootAddress,
218+
keychains: [],
219+
index: 0,
220+
};
221+
await basecoin.isWalletAddress(params).should.be.rejectedWith('missing required param keychains');
222+
});
223+
224+
it('should throw error for address that does not match derivation', async function () {
225+
const wrongAddress = '0000000000000000000000000000000000000000000000000000000000000000';
226+
const params = {
227+
address: wrongAddress,
228+
keychains: keychains,
229+
index: 0,
230+
};
231+
await basecoin.isWalletAddress(params).should.be.rejectedWith('address validation failure');
232+
});
233+
234+
it('should handle string index', async function () {
235+
const params = {
236+
address: addressVerificationData.rootAddress,
237+
rootAddress: addressVerificationData.rootAddress,
238+
keychains: keychains,
239+
index: '0',
240+
};
241+
const result = await basecoin.isWalletAddress(params);
242+
result.should.equal(true);
243+
});
244+
});
245+
154246
describe('Verify transaction: ', () => {
155247
const amount = '1000000';
156248
const gas = '125000000000000';

0 commit comments

Comments
 (0)