Skip to content

Commit 18900e3

Browse files
test: add coverage for resolveAccountAddress
1 parent 1d8c08f commit 18900e3

File tree

2 files changed

+238
-2
lines changed

2 files changed

+238
-2
lines changed

packages/snap/src/handlers/KeyringHandler.test.ts

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import type {
1414
KeyringResponse,
1515
Transaction as KeyringTransaction,
1616
KeyringRequest,
17+
KeyringAccount,
1718
} from '@metamask/keyring-api';
18-
import { BtcAccountType, BtcScope } from '@metamask/keyring-api';
19+
import { BtcAccountType, BtcMethod, BtcScope } from '@metamask/keyring-api';
1920
import { mock } from 'jest-mock-extended';
2021
import { assert } from 'superstruct';
2122

@@ -844,4 +845,112 @@ describe('KeyringHandler', () => {
844845
expect(result).toStrictEqual(expectedResponse);
845846
});
846847
});
848+
849+
describe('resolveAccountAddress', () => {
850+
const mockKeyringAccount1 = mock<KeyringAccount>({
851+
id: 'account-1',
852+
address: 'test123',
853+
scopes: [BtcScope.Regtest],
854+
});
855+
const mockKeyringAccount2 = mock<KeyringAccount>({
856+
id: 'account-2',
857+
address: 'test456',
858+
scopes: [BtcScope.Regtest],
859+
});
860+
861+
beforeEach(() => {
862+
mockAccounts.list.mockResolvedValue([mockAccount]);
863+
});
864+
865+
it('resolves account address successfully', async () => {
866+
const request = {
867+
id: '1',
868+
jsonrpc: '2.0' as const,
869+
method: BtcMethod.SignPsbt,
870+
params: {
871+
account: { address: 'test123' },
872+
psbt: 'psbt',
873+
},
874+
};
875+
const requestWithoutCommonHeader = {
876+
method: request.method,
877+
params: request.params,
878+
};
879+
880+
// mockAccounts.list.mockResolvedValue([mockAccount]);
881+
jest
882+
.spyOn(handler, 'listAccounts')
883+
.mockResolvedValueOnce([mockKeyringAccount1, mockKeyringAccount2]);
884+
mockKeyringRequest.resolveAccountAddress.mockReturnValue(
885+
'bip122:000000000019d6689c085ae165831e93:test123',
886+
);
887+
888+
const result = await handler.resolveAccountAddress(
889+
BtcScope.Regtest,
890+
request,
891+
);
892+
893+
expect(handler.listAccounts).toHaveBeenCalled();
894+
expect(mockKeyringRequest.resolveAccountAddress).toHaveBeenCalledWith(
895+
[mockKeyringAccount1, mockKeyringAccount2],
896+
BtcScope.Regtest,
897+
requestWithoutCommonHeader,
898+
);
899+
expect(result).toStrictEqual({
900+
address: 'bip122:000000000019d6689c085ae165831e93:test123',
901+
});
902+
});
903+
904+
it('returns null on error', async () => {
905+
const request = {
906+
id: '1',
907+
jsonrpc: '2.0' as const,
908+
method: BtcMethod.SignPsbt,
909+
params: {
910+
account: { address: 'notfound' },
911+
psbt: 'psbt',
912+
},
913+
};
914+
915+
jest
916+
.spyOn(handler, 'listAccounts')
917+
.mockImplementation()
918+
.mockResolvedValue([mockKeyringAccount1, mockKeyringAccount2]);
919+
mockKeyringRequest.resolveAccountAddress.mockImplementation(() => {
920+
throw new Error('Account not found');
921+
});
922+
923+
const result = await handler.resolveAccountAddress(
924+
BtcScope.Regtest,
925+
request,
926+
);
927+
928+
expect(result).toBeNull();
929+
});
930+
931+
it('returns null when request validation fails', async () => {
932+
const invalidRequest = {
933+
id: '1',
934+
jsonrpc: '2.0' as const,
935+
method: 'invalid',
936+
params: {},
937+
};
938+
939+
jest
940+
.spyOn(handler, 'listAccounts')
941+
.mockImplementation()
942+
.mockResolvedValue([mockKeyringAccount1, mockKeyringAccount2]);
943+
944+
jest.mocked(assert).mockImplementationOnce(() => {
945+
throw new Error('Invalid request');
946+
});
947+
948+
const result = await handler.resolveAccountAddress(
949+
BtcScope.Regtest,
950+
invalidRequest,
951+
);
952+
953+
expect(result).toBeNull();
954+
});
955+
});
847956
});

packages/snap/src/handlers/KeyringRequestHandler.test.ts

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Txid, Psbt, Amount, LocalOutput } from '@metamask/bitcoindevkit';
2-
import type { KeyringRequest } from '@metamask/keyring-api';
2+
import type { KeyringRequest, KeyringAccount } from '@metamask/keyring-api';
3+
import { BtcMethod, BtcScope } from '@metamask/keyring-api';
34
import { mock } from 'jest-mock-extended';
45
import { assert } from 'superstruct';
56

@@ -491,4 +492,130 @@ describe('KeyringRequestHandler', () => {
491492
});
492493
});
493494
});
495+
496+
describe('resolveAccountAddress', () => {
497+
const mockAccount1 = mock<KeyringAccount>({
498+
id: 'account-1',
499+
address: 'test123',
500+
scopes: [BtcScope.Regtest],
501+
});
502+
const mockAccount2 = mock<KeyringAccount>({
503+
id: 'account-2',
504+
address: 'test456',
505+
scopes: [BtcScope.Regtest, BtcScope.Testnet],
506+
});
507+
const mockAccount3 = mock<KeyringAccount>({
508+
id: 'account-3',
509+
address: 'test789',
510+
scopes: [BtcScope.Testnet],
511+
});
512+
513+
it('resolves account address for SignPsbt', () => {
514+
const request = {
515+
method: BtcMethod.SignPsbt as const,
516+
params: {
517+
account: { address: 'test123' },
518+
psbt: 'psbt',
519+
options: { fill: false, broadcast: false },
520+
},
521+
};
522+
523+
const result = handler.resolveAccountAddress(
524+
[mockAccount1, mockAccount2, mockAccount3],
525+
BtcScope.Regtest,
526+
request,
527+
);
528+
529+
expect(result).toBe('bip122:regtest:test123');
530+
});
531+
532+
it('resolves account address for SendTransfer', () => {
533+
const request = {
534+
method: BtcMethod.SendTransfer as const,
535+
params: {
536+
account: { address: 'test456' },
537+
recipients: [{ address: 'recipient', amount: '1000' }],
538+
},
539+
};
540+
541+
const result = handler.resolveAccountAddress(
542+
[mockAccount1, mockAccount2, mockAccount3],
543+
BtcScope.Regtest,
544+
request,
545+
);
546+
547+
expect(result).toBe('bip122:regtest:test456');
548+
});
549+
550+
it('resolves account address for SignMessage', () => {
551+
const request = {
552+
method: BtcMethod.SignMessage as const,
553+
params: {
554+
account: { address: 'test123' },
555+
message: 'hello',
556+
},
557+
};
558+
559+
const result = handler.resolveAccountAddress(
560+
[mockAccount1, mockAccount2, mockAccount3],
561+
BtcScope.Regtest,
562+
request,
563+
);
564+
565+
expect(result).toBe('bip122:regtest:test123');
566+
});
567+
568+
it('throws error if no accounts with scope', () => {
569+
const request = {
570+
method: BtcMethod.SignPsbt as const,
571+
params: {
572+
account: { address: 'test123' },
573+
psbt: 'psbt',
574+
options: { fill: false, broadcast: false },
575+
},
576+
};
577+
578+
expect(() =>
579+
handler.resolveAccountAddress(
580+
[mockAccount3],
581+
BtcScope.Regtest,
582+
request,
583+
),
584+
).toThrow('No accounts with this scope');
585+
});
586+
587+
it('throws error if account address not found', () => {
588+
const request = {
589+
method: BtcMethod.SignPsbt as const,
590+
params: {
591+
account: { address: 'notfound' },
592+
psbt: 'psbt',
593+
options: { fill: false, broadcast: false },
594+
},
595+
};
596+
597+
expect(() =>
598+
handler.resolveAccountAddress(
599+
[mockAccount1, mockAccount2, mockAccount3],
600+
BtcScope.Regtest,
601+
request,
602+
),
603+
).toThrow('Account not found');
604+
});
605+
606+
it('throws error for unsupported method', () => {
607+
const request = {
608+
method: 'unsupported' as BtcMethod,
609+
params: {},
610+
};
611+
612+
expect(() =>
613+
handler.resolveAccountAddress(
614+
[mockAccount1, mockAccount2, mockAccount3],
615+
BtcScope.Regtest,
616+
request as any,
617+
),
618+
).toThrow('Unsupported method');
619+
});
620+
});
494621
});

0 commit comments

Comments
 (0)