@metamask/multichain-account-service
Version:
Service to manage multichain accounts
182 lines • 8.65 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _MultichainAccountGroup_id, _MultichainAccountGroup_wallet, _MultichainAccountGroup_groupIndex, _MultichainAccountGroup_providers, _MultichainAccountGroup_providerToAccounts, _MultichainAccountGroup_accountToProvider;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MultichainAccountGroup = void 0;
const account_api_1 = require("@metamask/account-api");
const account_api_2 = require("@metamask/account-api");
/**
* A multichain account group that holds multiple accounts.
*/
class MultichainAccountGroup {
constructor({ groupIndex, wallet, providers, }) {
_MultichainAccountGroup_id.set(this, void 0);
_MultichainAccountGroup_wallet.set(this, void 0);
_MultichainAccountGroup_groupIndex.set(this, void 0);
_MultichainAccountGroup_providers.set(this, void 0);
_MultichainAccountGroup_providerToAccounts.set(this, void 0);
_MultichainAccountGroup_accountToProvider.set(this, void 0);
__classPrivateFieldSet(this, _MultichainAccountGroup_id, (0, account_api_2.toMultichainAccountGroupId)(wallet.id, groupIndex), "f");
__classPrivateFieldSet(this, _MultichainAccountGroup_groupIndex, groupIndex, "f");
__classPrivateFieldSet(this, _MultichainAccountGroup_wallet, wallet, "f");
__classPrivateFieldSet(this, _MultichainAccountGroup_providers, providers, "f");
__classPrivateFieldSet(this, _MultichainAccountGroup_providerToAccounts, new Map(), "f");
__classPrivateFieldSet(this, _MultichainAccountGroup_accountToProvider, new Map(), "f");
this.sync();
}
/**
* Force multichain account synchronization.
*
* This can be used if account providers got new accounts that the multichain
* account doesn't know about.
*/
sync() {
// Clear reverse mapping and re-construct it entirely based on the refreshed
// list of accounts from each providers.
__classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").clear();
for (const provider of __classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f")) {
// Filter account only for that index.
const accounts = [];
for (const account of provider.getAccounts()) {
if (account.options.entropy.id === this.wallet.entropySource &&
account.options.entropy.groupIndex === this.groupIndex) {
// We only use IDs to always fetch the latest version of accounts.
accounts.push(account.id);
}
}
__classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").set(provider, accounts);
// Reverse-mapping for fast indexing.
for (const id of accounts) {
__classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").set(id, provider);
}
}
}
/**
* Gets the multichain account group ID.
*
* @returns The multichain account group ID.
*/
get id() {
return __classPrivateFieldGet(this, _MultichainAccountGroup_id, "f");
}
/**
* Gets the multichain account group type.
*
* @returns The multichain account type.
*/
get type() {
return account_api_1.AccountGroupType.MultichainAccount;
}
/**
* Gets the multichain account's wallet reference (parent).
*
* @returns The multichain account's wallet.
*/
get wallet() {
return __classPrivateFieldGet(this, _MultichainAccountGroup_wallet, "f");
}
/**
* Gets the multichain account group index.
*
* @returns The multichain account group index.
*/
get groupIndex() {
return __classPrivateFieldGet(this, _MultichainAccountGroup_groupIndex, "f");
}
/**
* Checks if there's any underlying accounts for this multichain accounts.
*
* @returns True if there's any underlying accounts, false otherwise.
*/
hasAccounts() {
// If there's anything in the reverse-map, it means we have some accounts.
return __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").size > 0;
}
/**
* Gets the accounts for this multichain account.
*
* @returns The accounts.
*/
getAccounts() {
const allAccounts = [];
for (const [provider, accounts] of __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").entries()) {
for (const id of accounts) {
const account = provider.getAccount(id);
if (account) {
// If for some reason we cannot get this account from the provider, it
// might means it has been deleted or something, so we just filter it
// out.
allAccounts.push(account);
}
}
}
return allAccounts;
}
/**
* Gets the account for a given account ID.
*
* @param id - Account ID.
* @returns The account or undefined if not found.
*/
getAccount(id) {
const provider = __classPrivateFieldGet(this, _MultichainAccountGroup_accountToProvider, "f").get(id);
// If there's nothing in the map, it means we tried to get an account
// that does not belong to this multichain account.
if (!provider) {
return undefined;
}
return provider.getAccount(id);
}
/**
* Query an account matching the selector.
*
* @param selector - Query selector.
* @returns The account matching the selector or undefined if not matching.
* @throws If multiple accounts match the selector.
*/
get(selector) {
return (0, account_api_1.selectOne)(this.getAccounts(), selector);
}
/**
* Query accounts matching the selector.
*
* @param selector - Query selector.
* @returns The accounts matching the selector.
*/
select(selector) {
return (0, account_api_1.select)(this.getAccounts(), selector);
}
/**
* Align the multichain account group.
*
* This will create accounts for providers that don't have any accounts yet.
*/
async align() {
const results = await Promise.allSettled(__classPrivateFieldGet(this, _MultichainAccountGroup_providers, "f").map((provider) => {
const accounts = __classPrivateFieldGet(this, _MultichainAccountGroup_providerToAccounts, "f").get(provider);
if (!accounts || accounts.length === 0) {
return provider.createAccounts({
entropySource: this.wallet.entropySource,
groupIndex: this.groupIndex,
});
}
return Promise.resolve();
}));
if (results.some((result) => result.status === 'rejected')) {
console.warn(`Failed to fully align multichain account group for entropy ID: ${this.wallet.entropySource} and group index: ${this.groupIndex}, some accounts might be missing`);
}
}
}
exports.MultichainAccountGroup = MultichainAccountGroup;
_MultichainAccountGroup_id = new WeakMap(), _MultichainAccountGroup_wallet = new WeakMap(), _MultichainAccountGroup_groupIndex = new WeakMap(), _MultichainAccountGroup_providers = new WeakMap(), _MultichainAccountGroup_providerToAccounts = new WeakMap(), _MultichainAccountGroup_accountToProvider = new WeakMap();
//# sourceMappingURL=MultichainAccountGroup.cjs.map