Skip to content

Commit e42fb85

Browse files
committed
feat(sdk-coin-sol): implement isWalletAddress for address verfn
TICKET: WP-6459
1 parent 288d4d5 commit e42fb85

File tree

2 files changed

+98
-4
lines changed

2 files changed

+98
-4
lines changed

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
ITokenEnablement,
2424
KeyPair,
2525
Memo,
26-
MethodNotImplementedError,
2726
MPCAlgorithm,
2827
MPCConsolidationRecoveryOptions,
2928
MPCRecoveryOptions,
@@ -50,8 +49,9 @@ import {
5049
TransactionExplanation,
5150
TransactionParams,
5251
TransactionRecipient,
53-
VerifyAddressOptions,
5452
VerifyTransactionOptions,
53+
TssVerifyAddressOptions,
54+
verifyEddsaTssWalletAddress,
5555
} from '@bitgo/sdk-core';
5656
import { auditEddsaPrivateKey, getDerivationPath } from '@bitgo/sdk-lib-mpc';
5757
import { BaseNetwork, CoinFamily, coins, SolCoin, BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
@@ -560,8 +560,22 @@ export class Sol extends BaseCoin {
560560
return true;
561561
}
562562

563-
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
564-
throw new MethodNotImplementedError();
563+
async isWalletAddress(params: TssVerifyAddressOptions): Promise<boolean> {
564+
return verifyEddsaTssWalletAddress(
565+
params,
566+
(address) => this.isValidAddress(address),
567+
(publicKey) => this.getAddressFromPublicKey(publicKey)
568+
);
569+
}
570+
571+
/**
572+
* Converts a Solana public key to an address
573+
* @param publicKey Hex-encoded public key (64 hex characters = 32 bytes)
574+
* @returns Base58-encoded Solana address
575+
*/
576+
getAddressFromPublicKey(publicKey: string): string {
577+
const publicKeyBuffer = Buffer.from(publicKey, 'hex');
578+
return base58.encode(publicKeyBuffer);
565579
}
566580

567581
/**

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3353,4 +3353,84 @@ describe('SOL:', function () {
33533353
);
33543354
});
33553355
});
3356+
3357+
describe('isWalletAddress', () => {
3358+
it('should verify valid wallet address with correct keychain and index', async function () {
3359+
const address = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3360+
const commonKeychain =
3361+
'8ea32ecacfc83effbd2e2790ee44fa7c59b4d86c29a12f09fb613d8195f93f4e21875cad3b98adada40c040c54c3569467df41a020881a6184096378701862bd';
3362+
const index = '1';
3363+
const keychains = [{ commonKeychain }];
3364+
3365+
const result = await basecoin.isWalletAddress({ keychains, address, index });
3366+
result.should.equal(true);
3367+
});
3368+
3369+
it('should return false for address with incorrect keychain', async function () {
3370+
const address = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3371+
const wrongKeychain =
3372+
'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
3373+
const index = '1';
3374+
const keychains = [{ commonKeychain: wrongKeychain }];
3375+
3376+
const result = await basecoin.isWalletAddress({ keychains, address, index });
3377+
result.should.equal(false);
3378+
});
3379+
3380+
it('should return false for address with incorrect index', async function () {
3381+
const address = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3382+
const commonKeychain =
3383+
'8ea32ecacfc83effbd2e2790ee44fa7c59b4d86c29a12f09fb613d8195f93f4e21875cad3b98adada40c040c54c3569467df41a020881a6184096378701862bd';
3384+
const wrongIndex = '999';
3385+
const keychains = [{ commonKeychain }];
3386+
3387+
const result = await basecoin.isWalletAddress({ keychains, address, index: wrongIndex });
3388+
result.should.equal(false);
3389+
});
3390+
3391+
it('should throw error for invalid address', async function () {
3392+
const invalidAddress = 'invalidaddress';
3393+
const commonKeychain =
3394+
'8ea32ecacfc83effbd2e2790ee44fa7c59b4d86c29a12f09fb613d8195f93f4e21875cad3b98adada40c040c54c3569467df41a020881a6184096378701862bd';
3395+
const index = '1';
3396+
const keychains = [{ commonKeychain }];
3397+
3398+
await assert.rejects(async () => await basecoin.isWalletAddress({ keychains, address: invalidAddress, index }), {
3399+
message: `invalid address: ${invalidAddress}`,
3400+
});
3401+
});
3402+
3403+
it('should throw error when keychains are missing', async function () {
3404+
const address = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3405+
const index = '1';
3406+
3407+
await assert.rejects(async () => await basecoin.isWalletAddress({ address, index } as any), {
3408+
message: 'missing required param keychains',
3409+
});
3410+
});
3411+
3412+
it('should throw error when keychains have different commonKeychains', async function () {
3413+
const address = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3414+
const commonKeychain1 =
3415+
'8ea32ecacfc83effbd2e2790ee44fa7c59b4d86c29a12f09fb613d8195f93f4e21875cad3b98adada40c040c54c3569467df41a020881a6184096378701862bd';
3416+
const commonKeychain2 =
3417+
'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
3418+
const index = '1';
3419+
const keychains = [{ commonKeychain: commonKeychain1 }, { commonKeychain: commonKeychain2 }];
3420+
3421+
await assert.rejects(async () => await basecoin.isWalletAddress({ keychains, address, index }), {
3422+
message: 'all keychains must have the same commonKeychain for MPC coins',
3423+
});
3424+
});
3425+
});
3426+
3427+
describe('getAddressFromPublicKey', () => {
3428+
it('should convert public key to base58 address', function () {
3429+
const publicKey = '61220a9394802b1d1df37b35f7a3197970f48081092cee011fc98f7b71b2bd43';
3430+
const expectedAddress = '7YAesfwPk41VChUgr65bm8FEep7ymWqLSW5rpYB5zZPY';
3431+
3432+
const address = basecoin.getAddressFromPublicKey(publicKey);
3433+
address.should.equal(expectedAddress);
3434+
});
3435+
});
33563436
});

0 commit comments

Comments
 (0)