@metamask/multichain-account-service
Version:
Service to manage multichain accounts
102 lines • 4.14 kB
JavaScript
import { BtcScope, EthScope, SolScope, TrxScope, XlmScope } from "@metamask/keyring-api";
import { AccountProviderWrapper, EvmAccountProvider } from "../providers/index.mjs";
export function makeMockAccountProvider(accounts = []) {
return {
mockAccounts: accounts,
accounts: new Set(),
capabilities: {
scopes: [
SolScope.Devnet,
SolScope.Testnet,
BtcScope.Testnet,
TrxScope.Shasta,
XlmScope.Testnet,
EthScope.Eoa,
],
bip44: { deriveIndex: true },
},
constructor: jest.fn(),
alignAccounts: jest.fn(),
init: jest.fn(),
resyncAccounts: jest.fn(),
getAccount: jest.fn(),
getAccounts: jest.fn(),
createAccounts: jest.fn(),
deleteAccount: jest.fn(),
discoverAccounts: jest.fn(),
isAccountCompatible: jest.fn(),
isAligned: jest.fn().mockReturnValue(false),
getName: jest.fn(),
isDisabled: jest.fn(),
setEnabled: jest.fn(),
isEnabled: true,
};
}
export function setupBip44AccountProvider({ name = 'Mocked Provider', accounts, mocks = makeMockAccountProvider(), index, }) {
// You can mock this and all other mocks will re-use that list
// of accounts.
mocks.mockAccounts = accounts;
mocks.accounts = new Set(accounts.map((account) => account.id));
// Toggle enabled state only
mocks.setEnabled.mockImplementation((enabled) => {
mocks.isEnabled = enabled;
});
mocks.isDisabled.mockImplementation(() => !mocks.isEnabled);
const getAccounts = () => mocks.mockAccounts.filter((account) => [...mocks.accounts].includes(account.id));
mocks.getName.mockImplementation(() => name);
mocks.getAccounts.mockImplementation(getAccounts);
mocks.getAccount.mockImplementation((id) =>
// Assuming this never fails.
getAccounts().find((account) => account.id === id));
mocks.createAccounts.mockResolvedValue([]);
mocks.init.mockImplementation((accountIds) => {
accountIds.forEach((id) => mocks.accounts.add(id));
});
mocks.isAligned.mockImplementation((_context, accountIds) => accountIds.length >= 1 &&
accountIds.every((id) => mocks.accounts.has(id)));
if (index === 0) {
// Make the first provider to always be an `EvmAccountProvider`, since we
// check for this pre-condition in some methods.
Object.setPrototypeOf(mocks, EvmAccountProvider.prototype);
}
if (index !== 0) {
Object.setPrototypeOf(mocks, AccountProviderWrapper.prototype);
}
return mocks;
}
/**
* Helper to mock a single createAccounts call while updating the provider's
* internal state so subsequent getAccount/getAccounts can resolve the accounts.
*
* @param provider - The mock provider whose createAccounts call to mock.
* @param created - The accounts to be returned and persisted in the mock state.
*/
export function mockCreateAccountsOnce(provider, created) {
provider.createAccounts.mockImplementationOnce(async () => {
// Add newly created accounts to the provider's internal store
for (const acc of created) {
if (!provider.mockAccounts.some((a) => a.id === acc.id)) {
provider.mockAccounts.push(acc);
}
}
// Merge IDs into the visible list used by getAccounts/getAccount
const ids = created.map((a) => a.id);
for (const id of ids) {
provider.accounts.add(id);
}
return created;
});
}
/**
* Helper to convert a group index range to an array of group indices, inclusive of the
* start and end indices.
*
* @param range - The range.
* @param range.from - The starting index of the range (inclusive).
* @param range.to - The ending index of the range (inclusive).
* @returns An array of group indices from `from` to `to`, inclusive.
*/
export function toGroupIndexRangeArray({ from = 0, to, }) {
return Array.from({ length: to - from + 1 }, (_, i) => from + i);
}
//# sourceMappingURL=providers.mjs.map