Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions modules/sdk-coin-apt/src/apt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
BaseCoin,
BaseTransaction,
BitGoBase,
InvalidAddressError,
KeyPair,
MPCAlgorithm,
MultisigType,
Expand All @@ -14,7 +13,9 @@ import {
PrebuildTransactionWithIntentOptions,
SignedTransaction,
SignTransactionOptions,
VerifyAddressOptions,
TssVerifyAddressOptions,
UnexpectedAddressError,
verifyEddsaTssWalletAddress,
VerifyTransactionOptions,
} from '@bitgo/sdk-core';
import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
Expand Down Expand Up @@ -120,12 +121,22 @@ export class Apt extends BaseCoin {
return true;
}

async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
const { address: newAddress } = params;
/**
* Verify that an address belongs to this wallet.
*
* @param params - Verification parameters including address, keychains, and index
* @returns True if address belongs to wallet
* @throws UnexpectedAddressError if address doesn't match derived address
*/
async isWalletAddress(params: TssVerifyAddressOptions): Promise<boolean> {
const isValid = await verifyEddsaTssWalletAddress(params, this.isValidAddress.bind(this), (pubKey) =>
utils.getAddressFromPublicKey(pubKey)
);

if (!this.isValidAddress(newAddress)) {
throw new InvalidAddressError(`invalid address: ${newAddress}`);
if (!isValid) {
throw new UnexpectedAddressError();
}

return true;
}

Expand Down
67 changes: 24 additions & 43 deletions modules/sdk-coin-apt/test/unit/apt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,42 +280,19 @@ describe('APT:', function () {
});

describe('Address Validation', () => {
let keychains;
let commonKeychain;

before(function () {
commonKeychain =
'19bdfe2a4b498a05511381235a8892d54267807c4a3f654e310b938b8b424ff4adedbe92f4c146de641c67508a961324c8504cdf8e0c0acbb68d6104ccccd781';
keychains = [
{
id: '6424c353eaf78d000766e95949868468',
source: 'user',
type: 'tss',
commonKeychain:
'19bdfe2a4b498a05511381235a8892d54267807c4a3f654e310b938b8b424ff4adedbe92f4c146de641c67508a961324c8504cdf8e0c0acbb68d6104ccccd781',
encryptedPrv:
'{"iv":"cZd5i7L4RxtwrALW2rK7UA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"5zgoH1Bd3Fw=","ct":"9vVlnXFRtrM9FVEo+d2chbGHlM9lFZemueBuAs3BIkPo33Fo7jzwwNK/kIWkEyg+NmEBd5IaqAS157nvvvwzzsmMWlQdUz9qbmXNv3pg987cXFR08exS+4uhwP1YNOjJTRvRNcO9ZqHb46d4fmyJ/yC9/susCge7r/EsbaN5C3afv1dzybuq912FwaQElZLYYp5BICudFOMZ9k0UDMfKM/PMDkH7WexoGHr9GKq/bgCH2B39TZZyHKU6Uy47lXep2s6h0DrMwHOrnmiL3DZjOj88Ynvphlzxuo4eOlD2UHia2+nvIaISYs29Pr0DAvREutchvcBpExj1kWWPv7hQYrv8F0NAdatsbWl3w+xKyfiMKo1USlrwyJviypGtQtXOJyw0XPN0rv2+L5lW8BbjpzHfYYN13fJTedlGTFhhkzVtbbPAKE02kx7zCJcjYaiexdSTsrDLScYNT9/Jhdt27KpsooehwVohLfSKz4vbFfRu2MPZw3/+c/hfiJNgtz6esWbnxGrcE8U2IwPYCaK+Ghk4DcqWNIni59RI5B5kAsQOToII40qPN510uTgxBSPO7q7MHgkxdd4CqBq+ojr9j0P7oao8E5Y+CBDJrojDoCh1oCCDW9vo2dXlVcD8SIbw7U/9AfvEbA4xyE/5md1M7CIwLnWs2Ynv0YtaKoqhdS9x6FmHlMDhN/DKHinrwmowtrTT82fOkpO5g9saSmgU7Qy3gLt8t+VwdEyeFeQUKRSyci8qgqXQaZIg4+aXgaSOnlCFMtmB8ekYxEhTY5uzRfrNgS4s1QeqFBpNtUF+Ydi297pbVXnJoXAN+SVWd80GCx+yI2dpVC89k3rOWK9WeyqlnzuLJWp2RIOB9cdW8GFv/fN+QAJpYeVxOE4+nZDsKnsj8nKcg9t4Dlx1G6gLM1/Vq9YxNLbuzuRC0asUYvdMnoMvszmpm++TxndYisgNYscpZSoz7wvcazJNEPfhPVjEkd6tUUuN4GM35H0DmKCUQNT+a6B6hmHlTZvjxiyGAg5bY59hdjvJ+22QduazlEEC6LI3HrA7uK0TpplWzS1tCIFvTMUhj65DEZmNJ2+ZY9bQ4vsMf+DRR3OOG4t+DMlNfjOd3zNv3QoY95BjfWpryFwPzDq7bCP67JDsoj7j2TY5FRSrRkD77H0Ewlux2cWfjRTwcMHcdQxxuV0OP0aNjGDjybFN"}',
},
{
id: '6424c353eaf78d000766e96137d4404b',
source: 'backup',
type: 'tss',
commonKeychain:
'19bdfe2a4b498a05511381235a8892d54267807c4a3f654e310b938b8b424ff4adedbe92f4c146de641c67508a961324c8504cdf8e0c0acbb68d6104ccccd781',
encryptedPrv:
'{"iv":"vi0dPef/Rx7kG/pRySQi6Q==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"9efhQsiEvVs=","ct":"Gw6atvf6gxKzsjtl3xseipO3rAxp1mAz7Yu1ihFsi5/lf2vMZegApgZx+pyILFS9KKLHbNF3U6WgSYdrr2t4vzdLsXkH1WIxfHS+cd2C5N59yADZDnPJBT6pv/IRvaYelP0Ck3nIYQ2hSMm8op+VOWC/SzHeh7slYDqwEHTGan0Wigfvk1yRd7CCJTaEAomnc/4eFi2NY3X3gt/3opy9IAgknnwUFohn96EWpEQ0F6pbzH/Z8VF6gF+DUcrrByAxExUPnHQZiFk3YHU/vVV4FxBU/mVAE8xBsBn5ul5e5SUMPfc7TBuJWv4BByTNg9xDShF/91Yx2nbfUm5d9QmM8lpKgzzQvcK8POAPk87gRCuKnsGh5vNS0UppkHc+ocfzRQlGA6jze7QyyQO0rMj5Ly8kWjwk2vISvKYHYS1NR7VU549UIXo7NXjatunKSc3+IreoRUHIshiaLg6hl+pxCCuc0qQ43V0mdIfCjTN8gkGWLNk8R7tAGPz9jyapQPcPEGHgEz0ATIi6yMNWCsibS2eLiE1uVEJONoM4lk6FPl3Q2CHbW2MeEbqjY8hbaw18mNb2xSBH/Fwpiial+Tvi2imqgnCO4ZpO9bllKftZPcQy0stN+eGBlb5ufyflKkDSiChHYroGjEpmiFicdde48cJszF52uKNnf1q67fA9/S2FAHQab3EXojxH2Gbk+kkV2h/TYKFFZSWC3vi4e8mO+vjMUcR0AdsgPFyEIz0SCGuba3CnTLNdEuZwsauAeHkx2vUTnRgJPVgNeeuXmsVG76Sy2ggJHuals0Hj8U2Xda0qO1RuFfoCWfss9wn6HGRwPPkhSB/8oNguAqmRVGKkd8Zwt3IvrTd9fk0/rFFDJKGz7WyNHkYgUmNiGcItD12v0jx7FZ52EJzl3Av1RyJUQK18+8EYPh3SGiU9dt7VX0aF0uo6JouKhOeldUvMP+AugQz8fUclwTQsbboVg27Yxo0DyATVwThW5a56R6Qf5ZiQJluFuzs5y98rq0S5q046lE6o3vVmJpEdwjeSCJoET5CL4nTgkXyWvhm4eB8u/e66l3o0qbaSx8q9YYmT9EpRcl5TP4ThLBKETYdzVvg4exjQfektMatk5EyUpEIhZPXh5vXpJZesdfO9LJ8zTaHBsBjDPU7cdNgQMbebpataRi8A0el2/IJXl+E+olgAz5zC4i2O1Q=="}',
},
{
id: '6424c353eaf78d000766e9510b125fba',
source: 'bitgo',
type: 'tss',
commonKeychain:
'19bdfe2a4b498a05511381235a8892d54267807c4a3f654e310b938b8b424ff4adedbe92f4c146de641c67508a961324c8504cdf8e0c0acbb68d6104ccccd781',
verifiedVssProof: true,
isBitGo: true,
},
];
});
const testData = {
commonKeychain:
'6a724c11eafea4209704c35e6ee3e1fba80d2a40860d873bbe5981de636c9cf6ade77e6fdd4388889ee93d7eaa737ab584edb57cc0cc15b2899380348d6e482c',
rootAddress: '0x0598b31aa77176dbaba25306404aa8131218068df58bf0b7eec13f57053fd5a7',
receiveAddress: '0xdc169725dd6d9a07ee255b17087b4079e8a80850c895c65b62c0ef6de740d37a',
receiveAddressIndex: 1,
};

const keychains = [
{ commonKeychain: testData.commonKeychain },
{ commonKeychain: testData.commonKeychain },
{ commonKeychain: testData.commonKeychain },
];

it('should return true when validating a well formatted address prefixed with 0x', async function () {
const address = '0xf941ae3cbe5645dccc15da8346b533f7f91f202089a5521653c062b2ff10b304';
Expand All @@ -332,27 +309,31 @@ describe('APT:', function () {
basecoin.isValidAddress(address).should.equal(false);
});

it('should return true for isWalletAddress with valid address for index 4', async function () {
const newAddress = '0x8b3c7807730d75792dd6c49732cf9f014d6984a9c77d386bdb1072a9e537d8d8';
const index = 4;
it('should verify a valid receive address', async function () {
const params = {
address: testData.receiveAddress,
rootAddress: testData.rootAddress,
keychains,
index: testData.receiveAddressIndex,
};

const params = { commonKeychain, address: newAddress, index, keychains };
(await basecoin.isWalletAddress(params)).should.equal(true);
const result = await basecoin.isWalletAddress(params);
result.should.equal(true);
});

it('should throw error for isWalletAddress when keychains is missing', async function () {
const address = '0x2959bfc3fdb7dc23fed8deba2fafb70f3e606a59';
const index = 0;

const params = { commonKeychain, address, index };
const params = { commonKeychain: testData.commonKeychain, address, index };
await assert.rejects(async () => basecoin.isWalletAddress(params));
});

it('should throw error for isWalletAddress when new address is invalid', async function () {
const wrongAddress = 'badAddress';
const index = 0;

const params = { commonKeychain, address: wrongAddress, index };
const params = { commonKeychain: testData.commonKeychain, address: wrongAddress, index };
await assert.rejects(async () => basecoin.isWalletAddress(params), {
message: `invalid address: ${wrongAddress}`,
});
Expand Down