@metamask-previews/multichain-transactions-controller 0.8.0-preview-7f6d1f4 → 0.8.0-preview-d987e9b2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MultichainTransactionsController.cjs +1 -14
- package/dist/MultichainTransactionsController.cjs.map +1 -1
- package/dist/MultichainTransactionsController.d.cts +1 -15
- package/dist/MultichainTransactionsController.d.cts.map +1 -1
- package/dist/MultichainTransactionsController.d.mts +1 -15
- package/dist/MultichainTransactionsController.d.mts.map +1 -1
- package/dist/MultichainTransactionsController.mjs +2 -15
- package/dist/MultichainTransactionsController.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
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");
|
|
5
5
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
6
|
};
|
|
7
|
-
var _MultichainTransactionsController_instances, _MultichainTransactionsController_listMultichainAccounts, _MultichainTransactionsController_listAccounts, _MultichainTransactionsController_getTransactions, _MultichainTransactionsController_filterTransactions, _MultichainTransactionsController_isNonEvmAccount, _MultichainTransactionsController_handleOnAccountAdded, _MultichainTransactionsController_handleOnAccountRemoved,
|
|
7
|
+
var _MultichainTransactionsController_instances, _MultichainTransactionsController_listMultichainAccounts, _MultichainTransactionsController_listAccounts, _MultichainTransactionsController_getTransactions, _MultichainTransactionsController_filterTransactions, _MultichainTransactionsController_isNonEvmAccount, _MultichainTransactionsController_handleOnAccountAdded, _MultichainTransactionsController_handleOnAccountRemoved, _MultichainTransactionsController_handleOnAccountTransactionsUpdated, _MultichainTransactionsController_getClient;
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.MultichainTransactionsController = exports.getDefaultMultichainTransactionsControllerState = void 0;
|
|
10
10
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -150,16 +150,8 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
150
150
|
delete state.nonEvmTransactions[accountId];
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
|
-
}, _MultichainTransactionsController_publishTransactionUpdateEvent = function _MultichainTransactionsController_publishTransactionUpdateEvent(updatedTransaction) {
|
|
154
|
-
if (updatedTransaction.status === keyring_api_1.TransactionStatus.Confirmed) {
|
|
155
|
-
this.messagingSystem.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
|
|
156
|
-
}
|
|
157
|
-
if (updatedTransaction.status === keyring_api_1.TransactionStatus.Submitted) {
|
|
158
|
-
this.messagingSystem.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
|
|
159
|
-
}
|
|
160
153
|
}, _MultichainTransactionsController_handleOnAccountTransactionsUpdated = function _MultichainTransactionsController_handleOnAccountTransactionsUpdated(transactionsUpdate) {
|
|
161
154
|
const updatedTransactions = {};
|
|
162
|
-
const transactionsToPublish = [];
|
|
163
155
|
if (!transactionsUpdate?.transactions) {
|
|
164
156
|
return;
|
|
165
157
|
}
|
|
@@ -176,7 +168,6 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
176
168
|
});
|
|
177
169
|
filteredNewTransactions.forEach((tx) => {
|
|
178
170
|
transactions.set(tx.id, tx);
|
|
179
|
-
transactionsToPublish.push(tx);
|
|
180
171
|
});
|
|
181
172
|
// Sorted by timestamp (newest first). If the timestamp is not provided, those
|
|
182
173
|
// transactions will be put in the end of this list.
|
|
@@ -191,10 +182,6 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
191
182
|
};
|
|
192
183
|
});
|
|
193
184
|
});
|
|
194
|
-
// After we update the state, publish the events for new/updated transactions
|
|
195
|
-
transactionsToPublish.forEach((tx) => {
|
|
196
|
-
__classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_publishTransactionUpdateEvent).call(this, tx);
|
|
197
|
-
});
|
|
198
185
|
}, _MultichainTransactionsController_getClient = function _MultichainTransactionsController_getClient(snapId) {
|
|
199
186
|
return new keyring_snap_client_1.KeyringClient({
|
|
200
187
|
send: async (request) => (await this.messagingSystem.call('SnapController:handleRequest', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainTransactionsController.cjs","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountTransactionsUpdatedEvent,\n} from '@metamask/accounts-controller';\nimport {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n type RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n isEvmAccountType,\n type Transaction,\n type AccountTransactionsUpdatedEventPayload,\n TransactionStatus,\n} from '@metamask/keyring-api';\nimport type { KeyringControllerGetStateAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n KnownCaipNamespace,\n parseCaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\n\nimport { MultichainNetwork } from './constants';\n\nconst controllerName = 'MultichainTransactionsController';\n\n/**\n * PaginationOptions\n *\n * Represents options for paginating transaction results\n * limit - The maximum number of transactions to return\n * next - The cursor for the next page of transactions, or null if there is no next page\n */\nexport type PaginationOptions = {\n limit: number;\n next?: string | null;\n};\n\n/**\n * State used by the {@link MultichainTransactionsController} to cache account transactions.\n */\nexport type MultichainTransactionsControllerState = {\n nonEvmTransactions: {\n [accountId: string]: TransactionStateEntry;\n };\n};\n\n/**\n * Constructs the default {@link MultichainTransactionsController} state.\n *\n * @returns The default {@link MultichainTransactionsController} state.\n */\nexport function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState {\n return {\n nonEvmTransactions: {},\n };\n}\n\n/**\n * Event emitted when a transaction is finalized.\n */\nexport type MultichainTransactionsControllerTransactionConfirmedEvent = {\n type: `${typeof controllerName}:transactionConfirmed`;\n payload: [Transaction];\n};\n\n/**\n * Event emitted when a transaction is submitted.\n */\nexport type MultichainTransactionsControllerTransactionSubmittedEvent = {\n type: `${typeof controllerName}:transactionSubmitted`;\n payload: [Transaction];\n};\n\n/**\n * Returns the state of the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Event emitted when the state of the {@link MultichainTransactionsController} changes.\n */\nexport type MultichainTransactionsControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Actions exposed by the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerActions =\n MultichainTransactionsControllerGetStateAction;\n\n/**\n * Events emitted by {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerEvents =\n | MultichainTransactionsControllerStateChange\n | MultichainTransactionsControllerTransactionConfirmedEvent\n | MultichainTransactionsControllerTransactionSubmittedEvent;\n\n/**\n * Messenger type for the MultichainTransactionsController.\n */\nexport type MultichainTransactionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\nexport type AllowedEvents =\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | AccountsControllerAccountTransactionsUpdatedEvent;\n\n/**\n * {@link MultichainTransactionsController}'s metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst multichainTransactionsControllerMetadata = {\n nonEvmTransactions: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The state of transactions for a specific account.\n */\nexport type TransactionStateEntry = {\n transactions: Transaction[];\n next: string | null;\n lastUpdated: number;\n};\n\n/**\n * The MultichainTransactionsController is responsible for fetching and caching account\n * transactions for non-EVM accounts.\n */\nexport class MultichainTransactionsController extends BaseController<\n typeof controllerName,\n MultichainTransactionsControllerState,\n MultichainTransactionsControllerMessenger\n> {\n constructor({\n messenger,\n state,\n }: {\n messenger: MultichainTransactionsControllerMessenger;\n state?: Partial<MultichainTransactionsControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: multichainTransactionsControllerMetadata,\n state: {\n ...getDefaultMultichainTransactionsControllerState(),\n ...state,\n },\n });\n\n // Fetch initial transactions for all non-EVM accounts\n for (const account of this.#listAccounts()) {\n this.updateTransactionsForAccount(account.id).catch((error) => {\n console.error(\n `Failed to fetch initial transactions for account ${account.id}:`,\n error,\n );\n });\n }\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountTransactionsUpdated',\n (transactionsUpdate: AccountTransactionsUpdatedEventPayload) =>\n this.#handleOnAccountTransactionsUpdated(transactionsUpdate),\n );\n }\n\n /**\n * Lists the multichain accounts coming from the `AccountsController`.\n *\n * @returns A list of multichain accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Lists the accounts that we should get transactions for.\n *\n * @returns A list of accounts that we should get transactions for.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Gets transactions for an account.\n *\n * @param accountId - The ID of the account to get transactions for.\n * @param snapId - The ID of the snap that manages the account.\n * @param pagination - Options for paginating transaction results.\n * @returns A promise that resolves to the transaction data and pagination info.\n */\n async #getTransactions(\n accountId: string,\n snapId: string,\n pagination: PaginationOptions,\n ): Promise<{\n data: Transaction[];\n next: string | null;\n }> {\n return await this.#getClient(snapId).listAccountTransactions(\n accountId,\n pagination,\n );\n }\n\n /**\n * Updates transactions for a specific account. This is used for the initial fetch\n * when an account is first added.\n *\n * @param accountId - The ID of the account to get transactions for.\n */\n async updateTransactionsForAccount(accountId: string) {\n const { isUnlocked } = this.messagingSystem.call(\n 'KeyringController:getState',\n );\n\n if (!isUnlocked) {\n return;\n }\n\n try {\n const account = this.#listAccounts().find(\n (accountItem) => accountItem.id === accountId,\n );\n\n if (account?.metadata.snap) {\n const response = await this.#getTransactions(\n account.id,\n account.metadata.snap.id,\n { limit: 10 },\n );\n\n const transactions = this.#filterTransactions(response.data);\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n const entry: TransactionStateEntry = {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n };\n\n Object.assign(state.nonEvmTransactions, { [account.id]: entry });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\n }\n }\n\n /**\n * Filters transactions to only include mainnet Solana transactions for Solana chains.\n * Non-Solana chain transactions are kept as is.\n *\n * @param transactions - Array of transactions to filter\n * @returns Filtered transactions array\n */\n #filterTransactions(transactions: Transaction[]): Transaction[] {\n return transactions.filter((tx) => {\n const chain = tx.chain as MultichainNetwork;\n const { namespace } = parseCaipChainId(chain);\n\n // Enum comparison is safe here as we control both enum values\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n if (namespace === KnownCaipNamespace.Solana) {\n return chain === MultichainNetwork.Solana;\n }\n return true;\n });\n }\n\n /**\n * Checks for non-EVM accounts.\n *\n * @param account - The new account to be checked.\n * @returns True if the account is a non-EVM account, false otherwise.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) &&\n // Non-EVM accounts are backed by a Snap for now\n account.metadata.snap !== undefined\n );\n }\n\n /**\n * Handles changes when a new account has been added.\n *\n * @param account - The new account being added.\n */\n async #handleOnAccountAdded(account: InternalAccount) {\n if (!this.#isNonEvmAccount(account)) {\n return;\n }\n\n await this.updateTransactionsForAccount(account.id);\n }\n\n /**\n * Handles changes when a new account has been removed.\n *\n * @param accountId - The account ID being removed.\n */\n async #handleOnAccountRemoved(accountId: string) {\n if (accountId in this.state.nonEvmTransactions) {\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n delete state.nonEvmTransactions[accountId];\n });\n }\n }\n\n /**\n * Publishes transaction update events.\n *\n * @param updatedTransaction - The updated transaction.\n */\n #publishTransactionUpdateEvent(updatedTransaction: Transaction) {\n if (updatedTransaction.status === TransactionStatus.Confirmed) {\n this.messagingSystem.publish(\n 'MultichainTransactionsController:transactionConfirmed',\n updatedTransaction,\n );\n }\n\n if (updatedTransaction.status === TransactionStatus.Submitted) {\n this.messagingSystem.publish(\n 'MultichainTransactionsController:transactionSubmitted',\n updatedTransaction,\n );\n }\n }\n\n /**\n * Handles transaction updates received from the AccountsController.\n *\n * @param transactionsUpdate - The transaction update event containing new transactions.\n */\n #handleOnAccountTransactionsUpdated(\n transactionsUpdate: AccountTransactionsUpdatedEventPayload,\n ): void {\n const updatedTransactions: Record<string, Transaction[]> = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.transactions ?? [];\n\n const filteredNewTransactions =\n this.#filterTransactions(newTransactions);\n\n // Uses a `Map` to deduplicate transactions by ID, ensuring we keep the latest version\n // of each transaction while preserving older transactions and transactions from other accounts.\n // Transactions are sorted by timestamp (newest first).\n const transactions = new Map();\n\n oldTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n filteredNewTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n transactionsToPublish.push(tx);\n });\n\n // Sorted by timestamp (newest first). If the timestamp is not provided, those\n // transactions will be put in the end of this list.\n updatedTransactions[accountId] = Array.from(transactions.values()).sort(\n (a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0),\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(\n ([accountId, transactions]) => {\n state.nonEvmTransactions[accountId] = {\n ...state.nonEvmTransactions[accountId],\n transactions,\n lastUpdated: Date.now(),\n };\n },\n );\n });\n\n // After we update the state, publish the events for new/updated transactions\n transactionsToPublish.forEach((tx) => {\n this.#publishTransactionUpdateEvent(tx);\n });\n }\n\n /**\n * Gets a `KeyringClient` for a Snap.\n *\n * @param snapId - ID of the Snap to get the client for.\n * @returns A `KeyringClient` for the Snap.\n */\n #getClient(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest) =>\n (await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n })) as Promise<Json>,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MultichainTransactionsController.cjs","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountTransactionsUpdatedEvent,\n} from '@metamask/accounts-controller';\nimport {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n type RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n isEvmAccountType,\n type Transaction,\n type AccountTransactionsUpdatedEventPayload,\n} from '@metamask/keyring-api';\nimport type { KeyringControllerGetStateAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n KnownCaipNamespace,\n parseCaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\n\nimport { MultichainNetwork } from './constants';\n\nconst controllerName = 'MultichainTransactionsController';\n\n/**\n * PaginationOptions\n *\n * Represents options for paginating transaction results\n * limit - The maximum number of transactions to return\n * next - The cursor for the next page of transactions, or null if there is no next page\n */\nexport type PaginationOptions = {\n limit: number;\n next?: string | null;\n};\n\n/**\n * State used by the {@link MultichainTransactionsController} to cache account transactions.\n */\nexport type MultichainTransactionsControllerState = {\n nonEvmTransactions: {\n [accountId: string]: TransactionStateEntry;\n };\n};\n\n/**\n * Constructs the default {@link MultichainTransactionsController} state.\n *\n * @returns The default {@link MultichainTransactionsController} state.\n */\nexport function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState {\n return {\n nonEvmTransactions: {},\n };\n}\n\n/**\n * Returns the state of the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Event emitted when the state of the {@link MultichainTransactionsController} changes.\n */\nexport type MultichainTransactionsControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Actions exposed by the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerActions =\n MultichainTransactionsControllerGetStateAction;\n\n/**\n * Events emitted by {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerEvents =\n MultichainTransactionsControllerStateChange;\n\n/**\n * Messenger type for the MultichainTransactionsController.\n */\nexport type MultichainTransactionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\nexport type AllowedEvents =\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | AccountsControllerAccountTransactionsUpdatedEvent;\n\n/**\n * {@link MultichainTransactionsController}'s metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst multichainTransactionsControllerMetadata = {\n nonEvmTransactions: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The state of transactions for a specific account.\n */\nexport type TransactionStateEntry = {\n transactions: Transaction[];\n next: string | null;\n lastUpdated: number;\n};\n\n/**\n * The MultichainTransactionsController is responsible for fetching and caching account\n * transactions for non-EVM accounts.\n */\nexport class MultichainTransactionsController extends BaseController<\n typeof controllerName,\n MultichainTransactionsControllerState,\n MultichainTransactionsControllerMessenger\n> {\n constructor({\n messenger,\n state,\n }: {\n messenger: MultichainTransactionsControllerMessenger;\n state?: Partial<MultichainTransactionsControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: multichainTransactionsControllerMetadata,\n state: {\n ...getDefaultMultichainTransactionsControllerState(),\n ...state,\n },\n });\n\n // Fetch initial transactions for all non-EVM accounts\n for (const account of this.#listAccounts()) {\n this.updateTransactionsForAccount(account.id).catch((error) => {\n console.error(\n `Failed to fetch initial transactions for account ${account.id}:`,\n error,\n );\n });\n }\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountTransactionsUpdated',\n (transactionsUpdate: AccountTransactionsUpdatedEventPayload) =>\n this.#handleOnAccountTransactionsUpdated(transactionsUpdate),\n );\n }\n\n /**\n * Lists the multichain accounts coming from the `AccountsController`.\n *\n * @returns A list of multichain accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Lists the accounts that we should get transactions for.\n *\n * @returns A list of accounts that we should get transactions for.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Gets transactions for an account.\n *\n * @param accountId - The ID of the account to get transactions for.\n * @param snapId - The ID of the snap that manages the account.\n * @param pagination - Options for paginating transaction results.\n * @returns A promise that resolves to the transaction data and pagination info.\n */\n async #getTransactions(\n accountId: string,\n snapId: string,\n pagination: PaginationOptions,\n ): Promise<{\n data: Transaction[];\n next: string | null;\n }> {\n return await this.#getClient(snapId).listAccountTransactions(\n accountId,\n pagination,\n );\n }\n\n /**\n * Updates transactions for a specific account. This is used for the initial fetch\n * when an account is first added.\n *\n * @param accountId - The ID of the account to get transactions for.\n */\n async updateTransactionsForAccount(accountId: string) {\n const { isUnlocked } = this.messagingSystem.call(\n 'KeyringController:getState',\n );\n\n if (!isUnlocked) {\n return;\n }\n\n try {\n const account = this.#listAccounts().find(\n (accountItem) => accountItem.id === accountId,\n );\n\n if (account?.metadata.snap) {\n const response = await this.#getTransactions(\n account.id,\n account.metadata.snap.id,\n { limit: 10 },\n );\n\n const transactions = this.#filterTransactions(response.data);\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n const entry: TransactionStateEntry = {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n };\n\n Object.assign(state.nonEvmTransactions, { [account.id]: entry });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\n }\n }\n\n /**\n * Filters transactions to only include mainnet Solana transactions for Solana chains.\n * Non-Solana chain transactions are kept as is.\n *\n * @param transactions - Array of transactions to filter\n * @returns Filtered transactions array\n */\n #filterTransactions(transactions: Transaction[]): Transaction[] {\n return transactions.filter((tx) => {\n const chain = tx.chain as MultichainNetwork;\n const { namespace } = parseCaipChainId(chain);\n\n // Enum comparison is safe here as we control both enum values\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n if (namespace === KnownCaipNamespace.Solana) {\n return chain === MultichainNetwork.Solana;\n }\n return true;\n });\n }\n\n /**\n * Checks for non-EVM accounts.\n *\n * @param account - The new account to be checked.\n * @returns True if the account is a non-EVM account, false otherwise.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) &&\n // Non-EVM accounts are backed by a Snap for now\n account.metadata.snap !== undefined\n );\n }\n\n /**\n * Handles changes when a new account has been added.\n *\n * @param account - The new account being added.\n */\n async #handleOnAccountAdded(account: InternalAccount) {\n if (!this.#isNonEvmAccount(account)) {\n return;\n }\n\n await this.updateTransactionsForAccount(account.id);\n }\n\n /**\n * Handles changes when a new account has been removed.\n *\n * @param accountId - The account ID being removed.\n */\n async #handleOnAccountRemoved(accountId: string) {\n if (accountId in this.state.nonEvmTransactions) {\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n delete state.nonEvmTransactions[accountId];\n });\n }\n }\n\n /**\n * Handles transaction updates received from the AccountsController.\n *\n * @param transactionsUpdate - The transaction update event containing new transactions.\n */\n #handleOnAccountTransactionsUpdated(\n transactionsUpdate: AccountTransactionsUpdatedEventPayload,\n ): void {\n const updatedTransactions: Record<string, Transaction[]> = {};\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.transactions ?? [];\n\n const filteredNewTransactions =\n this.#filterTransactions(newTransactions);\n\n // Uses a `Map` to deduplicate transactions by ID, ensuring we keep the latest version\n // of each transaction while preserving older transactions and transactions from other accounts.\n // Transactions are sorted by timestamp (newest first).\n const transactions = new Map();\n\n oldTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n filteredNewTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n // Sorted by timestamp (newest first). If the timestamp is not provided, those\n // transactions will be put in the end of this list.\n updatedTransactions[accountId] = Array.from(transactions.values()).sort(\n (a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0),\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(\n ([accountId, transactions]) => {\n state.nonEvmTransactions[accountId] = {\n ...state.nonEvmTransactions[accountId],\n transactions,\n lastUpdated: Date.now(),\n };\n },\n );\n });\n }\n\n /**\n * Gets a `KeyringClient` for a Snap.\n *\n * @param snapId - ID of the Snap to get the client for.\n * @returns A `KeyringClient` for the Snap.\n */\n #getClient(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest) =>\n (await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n })) as Promise<Json>,\n });\n }\n}\n"]}
|
|
@@ -29,20 +29,6 @@ export type MultichainTransactionsControllerState = {
|
|
|
29
29
|
* @returns The default {@link MultichainTransactionsController} state.
|
|
30
30
|
*/
|
|
31
31
|
export declare function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState;
|
|
32
|
-
/**
|
|
33
|
-
* Event emitted when a transaction is finalized.
|
|
34
|
-
*/
|
|
35
|
-
export type MultichainTransactionsControllerTransactionConfirmedEvent = {
|
|
36
|
-
type: `${typeof controllerName}:transactionConfirmed`;
|
|
37
|
-
payload: [Transaction];
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Event emitted when a transaction is submitted.
|
|
41
|
-
*/
|
|
42
|
-
export type MultichainTransactionsControllerTransactionSubmittedEvent = {
|
|
43
|
-
type: `${typeof controllerName}:transactionSubmitted`;
|
|
44
|
-
payload: [Transaction];
|
|
45
|
-
};
|
|
46
32
|
/**
|
|
47
33
|
* Returns the state of the {@link MultichainTransactionsController}.
|
|
48
34
|
*/
|
|
@@ -58,7 +44,7 @@ export type MultichainTransactionsControllerActions = MultichainTransactionsCont
|
|
|
58
44
|
/**
|
|
59
45
|
* Events emitted by {@link MultichainTransactionsController}.
|
|
60
46
|
*/
|
|
61
|
-
export type MultichainTransactionsControllerEvents = MultichainTransactionsControllerStateChange
|
|
47
|
+
export type MultichainTransactionsControllerEvents = MultichainTransactionsControllerStateChange;
|
|
62
48
|
/**
|
|
63
49
|
* Messenger type for the MultichainTransactionsController.
|
|
64
50
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainTransactionsController.d.cts","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,8CAA8C,EAC9C,iDAAiD,EAClD,sCAAsC;AACvC,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACzB,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"MultichainTransactionsController.d.cts","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,8CAA8C,EAC9C,iDAAiD,EAClD,sCAAsC;AACvC,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACzB,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,EAEjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAarE,QAAA,MAAM,cAAc,qCAAqC,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAAG;IAClD,kBAAkB,EAAE;QAClB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,CAAC;KAC5C,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,8CAA8C,GACxD,wBAAwB,CACtB,OAAO,cAAc,EACrB,qCAAqC,CACtC,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,2CAA2C,GACrD,0BAA0B,CACxB,OAAO,cAAc,EACrB,qCAAqC,CACtC,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,uCAAuC,GACjD,8CAA8C,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAChD,2CAA2C,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,yCAAyC,GAAG,mBAAmB,CACzE,OAAO,cAAc,EACrB,uCAAuC,GAAG,cAAc,EACxD,sCAAsC,GAAG,aAAa,EACtD,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,iBAAiB,GACjB,+BAA+B,GAC/B,8CAA8C,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,mCAAmC,GACnC,qCAAqC,GACrC,iDAAiD,CAAC;AAgBtD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,qBAAa,gCAAiC,SAAQ,cAAc,CAClE,OAAO,cAAc,EACrB,qCAAqC,EACrC,yCAAyC,CAC1C;;gBACa,EACV,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,yCAAyC,CAAC;QACrD,KAAK,CAAC,EAAE,OAAO,CAAC,qCAAqC,CAAC,CAAC;KACxD;IA+ED;;;;;OAKG;IACG,4BAA4B,CAAC,SAAS,EAAE,MAAM;CAgLrD"}
|
|
@@ -29,20 +29,6 @@ export type MultichainTransactionsControllerState = {
|
|
|
29
29
|
* @returns The default {@link MultichainTransactionsController} state.
|
|
30
30
|
*/
|
|
31
31
|
export declare function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState;
|
|
32
|
-
/**
|
|
33
|
-
* Event emitted when a transaction is finalized.
|
|
34
|
-
*/
|
|
35
|
-
export type MultichainTransactionsControllerTransactionConfirmedEvent = {
|
|
36
|
-
type: `${typeof controllerName}:transactionConfirmed`;
|
|
37
|
-
payload: [Transaction];
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Event emitted when a transaction is submitted.
|
|
41
|
-
*/
|
|
42
|
-
export type MultichainTransactionsControllerTransactionSubmittedEvent = {
|
|
43
|
-
type: `${typeof controllerName}:transactionSubmitted`;
|
|
44
|
-
payload: [Transaction];
|
|
45
|
-
};
|
|
46
32
|
/**
|
|
47
33
|
* Returns the state of the {@link MultichainTransactionsController}.
|
|
48
34
|
*/
|
|
@@ -58,7 +44,7 @@ export type MultichainTransactionsControllerActions = MultichainTransactionsCont
|
|
|
58
44
|
/**
|
|
59
45
|
* Events emitted by {@link MultichainTransactionsController}.
|
|
60
46
|
*/
|
|
61
|
-
export type MultichainTransactionsControllerEvents = MultichainTransactionsControllerStateChange
|
|
47
|
+
export type MultichainTransactionsControllerEvents = MultichainTransactionsControllerStateChange;
|
|
62
48
|
/**
|
|
63
49
|
* Messenger type for the MultichainTransactionsController.
|
|
64
50
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainTransactionsController.d.mts","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,8CAA8C,EAC9C,iDAAiD,EAClD,sCAAsC;AACvC,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACzB,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"MultichainTransactionsController.d.mts","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,8CAA8C,EAC9C,iDAAiD,EAClD,sCAAsC;AACvC,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACzB,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,EAEjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAarE,QAAA,MAAM,cAAc,qCAAqC,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAAG;IAClD,kBAAkB,EAAE;QAClB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,CAAC;KAC5C,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,8CAA8C,GACxD,wBAAwB,CACtB,OAAO,cAAc,EACrB,qCAAqC,CACtC,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,2CAA2C,GACrD,0BAA0B,CACxB,OAAO,cAAc,EACrB,qCAAqC,CACtC,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,uCAAuC,GACjD,8CAA8C,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAChD,2CAA2C,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,yCAAyC,GAAG,mBAAmB,CACzE,OAAO,cAAc,EACrB,uCAAuC,GAAG,cAAc,EACxD,sCAAsC,GAAG,aAAa,EACtD,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,iBAAiB,GACjB,+BAA+B,GAC/B,8CAA8C,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,mCAAmC,GACnC,qCAAqC,GACrC,iDAAiD,CAAC;AAgBtD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,qBAAa,gCAAiC,SAAQ,cAAc,CAClE,OAAO,cAAc,EACrB,qCAAqC,EACrC,yCAAyC,CAC1C;;gBACa,EACV,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,yCAAyC,CAAC;QACrD,KAAK,CAAC,EAAE,OAAO,CAAC,qCAAqC,CAAC,CAAC;KACxD;IA+ED;;;;;OAKG;IACG,4BAA4B,CAAC,SAAS,EAAE,MAAM;CAgLrD"}
|
|
@@ -3,9 +3,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
3
|
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");
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _MultichainTransactionsController_instances, _MultichainTransactionsController_listMultichainAccounts, _MultichainTransactionsController_listAccounts, _MultichainTransactionsController_getTransactions, _MultichainTransactionsController_filterTransactions, _MultichainTransactionsController_isNonEvmAccount, _MultichainTransactionsController_handleOnAccountAdded, _MultichainTransactionsController_handleOnAccountRemoved,
|
|
6
|
+
var _MultichainTransactionsController_instances, _MultichainTransactionsController_listMultichainAccounts, _MultichainTransactionsController_listAccounts, _MultichainTransactionsController_getTransactions, _MultichainTransactionsController_filterTransactions, _MultichainTransactionsController_isNonEvmAccount, _MultichainTransactionsController_handleOnAccountAdded, _MultichainTransactionsController_handleOnAccountRemoved, _MultichainTransactionsController_handleOnAccountTransactionsUpdated, _MultichainTransactionsController_getClient;
|
|
7
7
|
import { BaseController } from "@metamask/base-controller";
|
|
8
|
-
import { isEvmAccountType
|
|
8
|
+
import { isEvmAccountType } from "@metamask/keyring-api";
|
|
9
9
|
import { KeyringClient } from "@metamask/keyring-snap-client";
|
|
10
10
|
import { HandlerType } from "@metamask/snaps-utils";
|
|
11
11
|
import { KnownCaipNamespace, parseCaipChainId } from "@metamask/utils";
|
|
@@ -145,16 +145,8 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
145
145
|
delete state.nonEvmTransactions[accountId];
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
|
-
}, _MultichainTransactionsController_publishTransactionUpdateEvent = function _MultichainTransactionsController_publishTransactionUpdateEvent(updatedTransaction) {
|
|
149
|
-
if (updatedTransaction.status === TransactionStatus.Confirmed) {
|
|
150
|
-
this.messagingSystem.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
|
|
151
|
-
}
|
|
152
|
-
if (updatedTransaction.status === TransactionStatus.Submitted) {
|
|
153
|
-
this.messagingSystem.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
|
|
154
|
-
}
|
|
155
148
|
}, _MultichainTransactionsController_handleOnAccountTransactionsUpdated = function _MultichainTransactionsController_handleOnAccountTransactionsUpdated(transactionsUpdate) {
|
|
156
149
|
const updatedTransactions = {};
|
|
157
|
-
const transactionsToPublish = [];
|
|
158
150
|
if (!transactionsUpdate?.transactions) {
|
|
159
151
|
return;
|
|
160
152
|
}
|
|
@@ -171,7 +163,6 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
171
163
|
});
|
|
172
164
|
filteredNewTransactions.forEach((tx) => {
|
|
173
165
|
transactions.set(tx.id, tx);
|
|
174
|
-
transactionsToPublish.push(tx);
|
|
175
166
|
});
|
|
176
167
|
// Sorted by timestamp (newest first). If the timestamp is not provided, those
|
|
177
168
|
// transactions will be put in the end of this list.
|
|
@@ -186,10 +177,6 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
|
|
|
186
177
|
};
|
|
187
178
|
});
|
|
188
179
|
});
|
|
189
|
-
// After we update the state, publish the events for new/updated transactions
|
|
190
|
-
transactionsToPublish.forEach((tx) => {
|
|
191
|
-
__classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_publishTransactionUpdateEvent).call(this, tx);
|
|
192
|
-
});
|
|
193
180
|
}, _MultichainTransactionsController_getClient = function _MultichainTransactionsController_getClient(snapId) {
|
|
194
181
|
return new KeyringClient({
|
|
195
182
|
send: async (request) => (await this.messagingSystem.call('SnapController:handleRequest', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainTransactionsController.mjs","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":";;;;;;AAMA,OAAO,EACL,cAAc,EAIf,kCAAkC;AACnC,OAAO,EACL,gBAAgB,EAGhB,iBAAiB,EAClB,8BAA8B;AAG/B,OAAO,EAAE,aAAa,EAAE,sCAAsC;AAG9D,OAAO,EAAE,WAAW,EAAE,8BAA8B;AACpD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAGjB,wBAAwB;AAGzB,OAAO,EAAE,iBAAiB,EAAE,wBAAoB;AAEhD,MAAM,cAAc,GAAG,kCAAkC,CAAC;AAuB1D;;;;GAIG;AACH,MAAM,UAAU,+CAA+C;IAC7D,OAAO;QACL,kBAAkB,EAAE,EAAE;KACvB,CAAC;AACJ,CAAC;AA6ED;;;;;;GAMG;AACH,MAAM,wCAAwC,GAAG;IAC/C,kBAAkB,EAAE;QAClB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAWF;;;GAGG;AACH,MAAM,OAAO,gCAAiC,SAAQ,cAIrD;IACC,YAAY,EACV,SAAS,EACT,KAAK,GAIN;QACC,KAAK,CAAC;YACJ,SAAS;YACT,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,wCAAwC;YAClD,KAAK,EAAE;gBACL,GAAG,+CAA+C,EAAE;gBACpD,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QAEH,sDAAsD;QACtD,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,mGAAc,MAAlB,IAAI,CAAgB,EAAE;YAC1C,IAAI,CAAC,4BAA4B,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC5D,OAAO,CAAC,KAAK,CACX,oDAAoD,OAAO,CAAC,EAAE,GAAG,EACjE,KAAK,CACN,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;QAED,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,iCAAiC,EACjC,CAAC,OAAwB,EAAE,EAAE,CAAC,uBAAA,IAAI,2GAAsB,MAA1B,IAAI,EAAuB,OAAO,CAAC,CAClE,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,mCAAmC,EACnC,CAAC,SAAiB,EAAE,EAAE,CAAC,uBAAA,IAAI,6GAAwB,MAA5B,IAAI,EAAyB,SAAS,CAAC,CAC/D,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,+CAA+C,EAC/C,CAAC,kBAA0D,EAAE,EAAE,CAC7D,uBAAA,IAAI,yHAAoC,MAAxC,IAAI,EAAqC,kBAAkB,CAAC,CAC/D,CAAC;IACJ,CAAC;IA6CD;;;;;OAKG;IACH,KAAK,CAAC,4BAA4B,CAAC,SAAiB;QAClD,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9C,4BAA4B,CAC7B,CAAC;QAEF,IAAI,CAAC,UAAU,EAAE;YACf,OAAO;SACR;QAED,IAAI;YACF,MAAM,OAAO,GAAG,uBAAA,IAAI,mGAAc,MAAlB,IAAI,CAAgB,CAAC,IAAI,CACvC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,SAAS,CAC9C,CAAC;YAEF,IAAI,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;gBAC1B,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,sGAAiB,MAArB,IAAI,EACzB,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EACxB,EAAE,KAAK,EAAE,EAAE,EAAE,CACd,CAAC;gBAEF,MAAM,YAAY,GAAG,uBAAA,IAAI,yGAAoB,MAAxB,IAAI,EAAqB,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAE7D,IAAI,CAAC,MAAM,CAAC,CAAC,KAAmD,EAAE,EAAE;oBAClE,MAAM,KAAK,GAA0B;wBACnC,YAAY;wBACZ,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;qBACxB,CAAC;oBAEF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACnE,CAAC,CAAC,CAAC;aACJ;SACF;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CACX,4CAA4C,SAAS,GAAG,EACxD,KAAK,CACN,CAAC;SACH;IACH,CAAC;CAqKF;;IAvPG,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9B,2CAA2C,CAC5C,CAAC;AACJ,CAAC;IAQC,MAAM,QAAQ,GAAG,uBAAA,IAAI,6GAAwB,MAA5B,IAAI,CAA0B,CAAC;IAChD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,uBAAA,IAAI,sGAAiB,MAArB,IAAI,EAAkB,OAAO,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,4DACH,SAAiB,EACjB,MAAc,EACd,UAA6B;IAK7B,OAAO,MAAM,uBAAA,IAAI,gGAAW,MAAf,IAAI,EAAY,MAAM,CAAC,CAAC,uBAAuB,CAC1D,SAAS,EACT,UAAU,CACX,CAAC;AACJ,CAAC,uHAwDmB,YAA2B;IAC7C,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QAChC,MAAM,KAAK,GAAG,EAAE,CAAC,KAA0B,CAAC;QAC5C,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE9C,8DAA8D;QAC9D,wEAAwE;QACxE,IAAI,SAAS,KAAK,kBAAkB,CAAC,MAAM,EAAE;YAC3C,OAAO,KAAK,KAAK,iBAAiB,CAAC,MAAM,CAAC;SAC3C;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC,iHAQgB,OAAwB;IACvC,OAAO,CACL,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/B,gDAAgD;QAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CACpC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,iEAAuB,OAAwB;IAClD,IAAI,CAAC,uBAAA,IAAI,sGAAiB,MAArB,IAAI,EAAkB,OAAO,CAAC,EAAE;QACnC,OAAO;KACR;IAED,MAAM,IAAI,CAAC,4BAA4B,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,KAAK,mEAAyB,SAAiB;IAC7C,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAmD,EAAE,EAAE;YAClE,OAAO,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;KACJ;AACH,CAAC,6IAO8B,kBAA+B;IAC5D,IAAI,kBAAkB,CAAC,MAAM,KAAK,iBAAiB,CAAC,SAAS,EAAE;QAC7D,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,uDAAuD,EACvD,kBAAkB,CACnB,CAAC;KACH;IAED,IAAI,kBAAkB,CAAC,MAAM,KAAK,iBAAiB,CAAC,SAAS,EAAE;QAC7D,IAAI,CAAC,eAAe,CAAC,OAAO,CAC1B,uDAAuD,EACvD,kBAAkB,CACnB,CAAC;KACH;AACH,CAAC,uJAQC,kBAA0D;IAE1D,MAAM,mBAAmB,GAAkC,EAAE,CAAC;IAC9D,MAAM,qBAAqB,GAAkB,EAAE,CAAC;IAEhD,IAAI,CAAC,kBAAkB,EAAE,YAAY,EAAE;QACrC,OAAO;KACR;IAED,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,OAAO,CACrD,CAAC,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,EAAE;QAC/B,yEAAyE;QACzE,MAAM,eAAe,GACnB,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,EAAE,YAAY,IAAI,EAAE,CAAC;QAE/D,MAAM,uBAAuB,GAC3B,uBAAA,IAAI,yGAAoB,MAAxB,IAAI,EAAqB,eAAe,CAAC,CAAC;QAE5C,sFAAsF;QACtF,gGAAgG;QAChG,uDAAuD;QACvD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;QAE/B,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YAC7B,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,uBAAuB,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YACrC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC5B,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,8EAA8E;QAC9E,oDAAoD;QACpD,mBAAmB,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACrE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAClD,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,OAAO,CACzC,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,EAAE;YAC5B,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,GAAG;gBACpC,GAAG,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC;gBACtC,YAAY;gBACZ,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACxB,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,qBAAqB,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QACnC,uBAAA,IAAI,oHAA+B,MAAnC,IAAI,EAAgC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,qGAQU,MAAc;IACvB,OAAO,IAAI,aAAa,CAAC;QACvB,IAAI,EAAE,KAAK,EAAE,OAAuB,EAAE,EAAE,CACtC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,8BAA8B,EAAE;YAC/D,MAAM,EAAE,MAAgB;YACxB,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,WAAW,CAAC,gBAAgB;YACrC,OAAO;SACR,CAAC,CAAkB;KACvB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountTransactionsUpdatedEvent,\n} from '@metamask/accounts-controller';\nimport {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n type RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n isEvmAccountType,\n type Transaction,\n type AccountTransactionsUpdatedEventPayload,\n TransactionStatus,\n} from '@metamask/keyring-api';\nimport type { KeyringControllerGetStateAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n KnownCaipNamespace,\n parseCaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\n\nimport { MultichainNetwork } from './constants';\n\nconst controllerName = 'MultichainTransactionsController';\n\n/**\n * PaginationOptions\n *\n * Represents options for paginating transaction results\n * limit - The maximum number of transactions to return\n * next - The cursor for the next page of transactions, or null if there is no next page\n */\nexport type PaginationOptions = {\n limit: number;\n next?: string | null;\n};\n\n/**\n * State used by the {@link MultichainTransactionsController} to cache account transactions.\n */\nexport type MultichainTransactionsControllerState = {\n nonEvmTransactions: {\n [accountId: string]: TransactionStateEntry;\n };\n};\n\n/**\n * Constructs the default {@link MultichainTransactionsController} state.\n *\n * @returns The default {@link MultichainTransactionsController} state.\n */\nexport function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState {\n return {\n nonEvmTransactions: {},\n };\n}\n\n/**\n * Event emitted when a transaction is finalized.\n */\nexport type MultichainTransactionsControllerTransactionConfirmedEvent = {\n type: `${typeof controllerName}:transactionConfirmed`;\n payload: [Transaction];\n};\n\n/**\n * Event emitted when a transaction is submitted.\n */\nexport type MultichainTransactionsControllerTransactionSubmittedEvent = {\n type: `${typeof controllerName}:transactionSubmitted`;\n payload: [Transaction];\n};\n\n/**\n * Returns the state of the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Event emitted when the state of the {@link MultichainTransactionsController} changes.\n */\nexport type MultichainTransactionsControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Actions exposed by the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerActions =\n MultichainTransactionsControllerGetStateAction;\n\n/**\n * Events emitted by {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerEvents =\n | MultichainTransactionsControllerStateChange\n | MultichainTransactionsControllerTransactionConfirmedEvent\n | MultichainTransactionsControllerTransactionSubmittedEvent;\n\n/**\n * Messenger type for the MultichainTransactionsController.\n */\nexport type MultichainTransactionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\nexport type AllowedEvents =\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | AccountsControllerAccountTransactionsUpdatedEvent;\n\n/**\n * {@link MultichainTransactionsController}'s metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst multichainTransactionsControllerMetadata = {\n nonEvmTransactions: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The state of transactions for a specific account.\n */\nexport type TransactionStateEntry = {\n transactions: Transaction[];\n next: string | null;\n lastUpdated: number;\n};\n\n/**\n * The MultichainTransactionsController is responsible for fetching and caching account\n * transactions for non-EVM accounts.\n */\nexport class MultichainTransactionsController extends BaseController<\n typeof controllerName,\n MultichainTransactionsControllerState,\n MultichainTransactionsControllerMessenger\n> {\n constructor({\n messenger,\n state,\n }: {\n messenger: MultichainTransactionsControllerMessenger;\n state?: Partial<MultichainTransactionsControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: multichainTransactionsControllerMetadata,\n state: {\n ...getDefaultMultichainTransactionsControllerState(),\n ...state,\n },\n });\n\n // Fetch initial transactions for all non-EVM accounts\n for (const account of this.#listAccounts()) {\n this.updateTransactionsForAccount(account.id).catch((error) => {\n console.error(\n `Failed to fetch initial transactions for account ${account.id}:`,\n error,\n );\n });\n }\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountTransactionsUpdated',\n (transactionsUpdate: AccountTransactionsUpdatedEventPayload) =>\n this.#handleOnAccountTransactionsUpdated(transactionsUpdate),\n );\n }\n\n /**\n * Lists the multichain accounts coming from the `AccountsController`.\n *\n * @returns A list of multichain accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Lists the accounts that we should get transactions for.\n *\n * @returns A list of accounts that we should get transactions for.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Gets transactions for an account.\n *\n * @param accountId - The ID of the account to get transactions for.\n * @param snapId - The ID of the snap that manages the account.\n * @param pagination - Options for paginating transaction results.\n * @returns A promise that resolves to the transaction data and pagination info.\n */\n async #getTransactions(\n accountId: string,\n snapId: string,\n pagination: PaginationOptions,\n ): Promise<{\n data: Transaction[];\n next: string | null;\n }> {\n return await this.#getClient(snapId).listAccountTransactions(\n accountId,\n pagination,\n );\n }\n\n /**\n * Updates transactions for a specific account. This is used for the initial fetch\n * when an account is first added.\n *\n * @param accountId - The ID of the account to get transactions for.\n */\n async updateTransactionsForAccount(accountId: string) {\n const { isUnlocked } = this.messagingSystem.call(\n 'KeyringController:getState',\n );\n\n if (!isUnlocked) {\n return;\n }\n\n try {\n const account = this.#listAccounts().find(\n (accountItem) => accountItem.id === accountId,\n );\n\n if (account?.metadata.snap) {\n const response = await this.#getTransactions(\n account.id,\n account.metadata.snap.id,\n { limit: 10 },\n );\n\n const transactions = this.#filterTransactions(response.data);\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n const entry: TransactionStateEntry = {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n };\n\n Object.assign(state.nonEvmTransactions, { [account.id]: entry });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\n }\n }\n\n /**\n * Filters transactions to only include mainnet Solana transactions for Solana chains.\n * Non-Solana chain transactions are kept as is.\n *\n * @param transactions - Array of transactions to filter\n * @returns Filtered transactions array\n */\n #filterTransactions(transactions: Transaction[]): Transaction[] {\n return transactions.filter((tx) => {\n const chain = tx.chain as MultichainNetwork;\n const { namespace } = parseCaipChainId(chain);\n\n // Enum comparison is safe here as we control both enum values\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n if (namespace === KnownCaipNamespace.Solana) {\n return chain === MultichainNetwork.Solana;\n }\n return true;\n });\n }\n\n /**\n * Checks for non-EVM accounts.\n *\n * @param account - The new account to be checked.\n * @returns True if the account is a non-EVM account, false otherwise.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) &&\n // Non-EVM accounts are backed by a Snap for now\n account.metadata.snap !== undefined\n );\n }\n\n /**\n * Handles changes when a new account has been added.\n *\n * @param account - The new account being added.\n */\n async #handleOnAccountAdded(account: InternalAccount) {\n if (!this.#isNonEvmAccount(account)) {\n return;\n }\n\n await this.updateTransactionsForAccount(account.id);\n }\n\n /**\n * Handles changes when a new account has been removed.\n *\n * @param accountId - The account ID being removed.\n */\n async #handleOnAccountRemoved(accountId: string) {\n if (accountId in this.state.nonEvmTransactions) {\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n delete state.nonEvmTransactions[accountId];\n });\n }\n }\n\n /**\n * Publishes transaction update events.\n *\n * @param updatedTransaction - The updated transaction.\n */\n #publishTransactionUpdateEvent(updatedTransaction: Transaction) {\n if (updatedTransaction.status === TransactionStatus.Confirmed) {\n this.messagingSystem.publish(\n 'MultichainTransactionsController:transactionConfirmed',\n updatedTransaction,\n );\n }\n\n if (updatedTransaction.status === TransactionStatus.Submitted) {\n this.messagingSystem.publish(\n 'MultichainTransactionsController:transactionSubmitted',\n updatedTransaction,\n );\n }\n }\n\n /**\n * Handles transaction updates received from the AccountsController.\n *\n * @param transactionsUpdate - The transaction update event containing new transactions.\n */\n #handleOnAccountTransactionsUpdated(\n transactionsUpdate: AccountTransactionsUpdatedEventPayload,\n ): void {\n const updatedTransactions: Record<string, Transaction[]> = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.transactions ?? [];\n\n const filteredNewTransactions =\n this.#filterTransactions(newTransactions);\n\n // Uses a `Map` to deduplicate transactions by ID, ensuring we keep the latest version\n // of each transaction while preserving older transactions and transactions from other accounts.\n // Transactions are sorted by timestamp (newest first).\n const transactions = new Map();\n\n oldTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n filteredNewTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n transactionsToPublish.push(tx);\n });\n\n // Sorted by timestamp (newest first). If the timestamp is not provided, those\n // transactions will be put in the end of this list.\n updatedTransactions[accountId] = Array.from(transactions.values()).sort(\n (a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0),\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(\n ([accountId, transactions]) => {\n state.nonEvmTransactions[accountId] = {\n ...state.nonEvmTransactions[accountId],\n transactions,\n lastUpdated: Date.now(),\n };\n },\n );\n });\n\n // After we update the state, publish the events for new/updated transactions\n transactionsToPublish.forEach((tx) => {\n this.#publishTransactionUpdateEvent(tx);\n });\n }\n\n /**\n * Gets a `KeyringClient` for a Snap.\n *\n * @param snapId - ID of the Snap to get the client for.\n * @returns A `KeyringClient` for the Snap.\n */\n #getClient(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest) =>\n (await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n })) as Promise<Json>,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MultichainTransactionsController.mjs","sourceRoot":"","sources":["../src/MultichainTransactionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountTransactionsUpdatedEvent,\n} from '@metamask/accounts-controller';\nimport {\n BaseController,\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n type RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n isEvmAccountType,\n type Transaction,\n type AccountTransactionsUpdatedEventPayload,\n} from '@metamask/keyring-api';\nimport type { KeyringControllerGetStateAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n KnownCaipNamespace,\n parseCaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\n\nimport { MultichainNetwork } from './constants';\n\nconst controllerName = 'MultichainTransactionsController';\n\n/**\n * PaginationOptions\n *\n * Represents options for paginating transaction results\n * limit - The maximum number of transactions to return\n * next - The cursor for the next page of transactions, or null if there is no next page\n */\nexport type PaginationOptions = {\n limit: number;\n next?: string | null;\n};\n\n/**\n * State used by the {@link MultichainTransactionsController} to cache account transactions.\n */\nexport type MultichainTransactionsControllerState = {\n nonEvmTransactions: {\n [accountId: string]: TransactionStateEntry;\n };\n};\n\n/**\n * Constructs the default {@link MultichainTransactionsController} state.\n *\n * @returns The default {@link MultichainTransactionsController} state.\n */\nexport function getDefaultMultichainTransactionsControllerState(): MultichainTransactionsControllerState {\n return {\n nonEvmTransactions: {},\n };\n}\n\n/**\n * Returns the state of the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Event emitted when the state of the {@link MultichainTransactionsController} changes.\n */\nexport type MultichainTransactionsControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainTransactionsControllerState\n >;\n\n/**\n * Actions exposed by the {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerActions =\n MultichainTransactionsControllerGetStateAction;\n\n/**\n * Events emitted by {@link MultichainTransactionsController}.\n */\nexport type MultichainTransactionsControllerEvents =\n MultichainTransactionsControllerStateChange;\n\n/**\n * Messenger type for the MultichainTransactionsController.\n */\nexport type MultichainTransactionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\nexport type AllowedEvents =\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | AccountsControllerAccountTransactionsUpdatedEvent;\n\n/**\n * {@link MultichainTransactionsController}'s metadata.\n *\n * This allows us to choose if fields of the state should be persisted or not\n * using the `persist` flag; and if they can be sent to Sentry or not, using\n * the `anonymous` flag.\n */\nconst multichainTransactionsControllerMetadata = {\n nonEvmTransactions: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The state of transactions for a specific account.\n */\nexport type TransactionStateEntry = {\n transactions: Transaction[];\n next: string | null;\n lastUpdated: number;\n};\n\n/**\n * The MultichainTransactionsController is responsible for fetching and caching account\n * transactions for non-EVM accounts.\n */\nexport class MultichainTransactionsController extends BaseController<\n typeof controllerName,\n MultichainTransactionsControllerState,\n MultichainTransactionsControllerMessenger\n> {\n constructor({\n messenger,\n state,\n }: {\n messenger: MultichainTransactionsControllerMessenger;\n state?: Partial<MultichainTransactionsControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: multichainTransactionsControllerMetadata,\n state: {\n ...getDefaultMultichainTransactionsControllerState(),\n ...state,\n },\n });\n\n // Fetch initial transactions for all non-EVM accounts\n for (const account of this.#listAccounts()) {\n this.updateTransactionsForAccount(account.id).catch((error) => {\n console.error(\n `Failed to fetch initial transactions for account ${account.id}:`,\n error,\n );\n });\n }\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messagingSystem.subscribe(\n 'AccountsController:accountTransactionsUpdated',\n (transactionsUpdate: AccountTransactionsUpdatedEventPayload) =>\n this.#handleOnAccountTransactionsUpdated(transactionsUpdate),\n );\n }\n\n /**\n * Lists the multichain accounts coming from the `AccountsController`.\n *\n * @returns A list of multichain accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Lists the accounts that we should get transactions for.\n *\n * @returns A list of accounts that we should get transactions for.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Gets transactions for an account.\n *\n * @param accountId - The ID of the account to get transactions for.\n * @param snapId - The ID of the snap that manages the account.\n * @param pagination - Options for paginating transaction results.\n * @returns A promise that resolves to the transaction data and pagination info.\n */\n async #getTransactions(\n accountId: string,\n snapId: string,\n pagination: PaginationOptions,\n ): Promise<{\n data: Transaction[];\n next: string | null;\n }> {\n return await this.#getClient(snapId).listAccountTransactions(\n accountId,\n pagination,\n );\n }\n\n /**\n * Updates transactions for a specific account. This is used for the initial fetch\n * when an account is first added.\n *\n * @param accountId - The ID of the account to get transactions for.\n */\n async updateTransactionsForAccount(accountId: string) {\n const { isUnlocked } = this.messagingSystem.call(\n 'KeyringController:getState',\n );\n\n if (!isUnlocked) {\n return;\n }\n\n try {\n const account = this.#listAccounts().find(\n (accountItem) => accountItem.id === accountId,\n );\n\n if (account?.metadata.snap) {\n const response = await this.#getTransactions(\n account.id,\n account.metadata.snap.id,\n { limit: 10 },\n );\n\n const transactions = this.#filterTransactions(response.data);\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n const entry: TransactionStateEntry = {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n };\n\n Object.assign(state.nonEvmTransactions, { [account.id]: entry });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\n }\n }\n\n /**\n * Filters transactions to only include mainnet Solana transactions for Solana chains.\n * Non-Solana chain transactions are kept as is.\n *\n * @param transactions - Array of transactions to filter\n * @returns Filtered transactions array\n */\n #filterTransactions(transactions: Transaction[]): Transaction[] {\n return transactions.filter((tx) => {\n const chain = tx.chain as MultichainNetwork;\n const { namespace } = parseCaipChainId(chain);\n\n // Enum comparison is safe here as we control both enum values\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n if (namespace === KnownCaipNamespace.Solana) {\n return chain === MultichainNetwork.Solana;\n }\n return true;\n });\n }\n\n /**\n * Checks for non-EVM accounts.\n *\n * @param account - The new account to be checked.\n * @returns True if the account is a non-EVM account, false otherwise.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) &&\n // Non-EVM accounts are backed by a Snap for now\n account.metadata.snap !== undefined\n );\n }\n\n /**\n * Handles changes when a new account has been added.\n *\n * @param account - The new account being added.\n */\n async #handleOnAccountAdded(account: InternalAccount) {\n if (!this.#isNonEvmAccount(account)) {\n return;\n }\n\n await this.updateTransactionsForAccount(account.id);\n }\n\n /**\n * Handles changes when a new account has been removed.\n *\n * @param accountId - The account ID being removed.\n */\n async #handleOnAccountRemoved(accountId: string) {\n if (accountId in this.state.nonEvmTransactions) {\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n delete state.nonEvmTransactions[accountId];\n });\n }\n }\n\n /**\n * Handles transaction updates received from the AccountsController.\n *\n * @param transactionsUpdate - The transaction update event containing new transactions.\n */\n #handleOnAccountTransactionsUpdated(\n transactionsUpdate: AccountTransactionsUpdatedEventPayload,\n ): void {\n const updatedTransactions: Record<string, Transaction[]> = {};\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.transactions ?? [];\n\n const filteredNewTransactions =\n this.#filterTransactions(newTransactions);\n\n // Uses a `Map` to deduplicate transactions by ID, ensuring we keep the latest version\n // of each transaction while preserving older transactions and transactions from other accounts.\n // Transactions are sorted by timestamp (newest first).\n const transactions = new Map();\n\n oldTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n filteredNewTransactions.forEach((tx) => {\n transactions.set(tx.id, tx);\n });\n\n // Sorted by timestamp (newest first). If the timestamp is not provided, those\n // transactions will be put in the end of this list.\n updatedTransactions[accountId] = Array.from(transactions.values()).sort(\n (a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0),\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(\n ([accountId, transactions]) => {\n state.nonEvmTransactions[accountId] = {\n ...state.nonEvmTransactions[accountId],\n transactions,\n lastUpdated: Date.now(),\n };\n },\n );\n });\n }\n\n /**\n * Gets a `KeyringClient` for a Snap.\n *\n * @param snapId - ID of the Snap to get the client for.\n * @returns A `KeyringClient` for the Snap.\n */\n #getClient(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest) =>\n (await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n })) as Promise<Json>,\n });\n }\n}\n"]}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2FAAsF;AAA7E,oJAAA,gCAAgC,OAAA;
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2FAAsF;AAA7E,oJAAA,gCAAgC,OAAA;AAMzC,6CAAuE;AAA9D,8GAAA,iBAAiB,OAAA;AAAE,kHAAA,qBAAqB,OAAA","sourcesContent":["export { MultichainTransactionsController } from './MultichainTransactionsController';\nexport type {\n MultichainTransactionsControllerState,\n PaginationOptions,\n TransactionStateEntry,\n} from './MultichainTransactionsController';\nexport { MultichainNetwork, MultichainNativeAsset } from './constants';\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { MultichainTransactionsController } from "./MultichainTransactionsController.cjs";
|
|
2
|
-
export type { MultichainTransactionsControllerState, PaginationOptions, TransactionStateEntry,
|
|
2
|
+
export type { MultichainTransactionsControllerState, PaginationOptions, TransactionStateEntry, } from "./MultichainTransactionsController.cjs";
|
|
3
3
|
export { MultichainNetwork, MultichainNativeAsset } from "./constants.cjs";
|
|
4
4
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;AACtF,YAAY,EACV,qCAAqC,EACrC,iBAAiB,EACjB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;AACtF,YAAY,EACV,qCAAqC,EACrC,iBAAiB,EACjB,qBAAqB,GACtB,+CAA2C;AAC5C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,wBAAoB"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { MultichainTransactionsController } from "./MultichainTransactionsController.mjs";
|
|
2
|
-
export type { MultichainTransactionsControllerState, PaginationOptions, TransactionStateEntry,
|
|
2
|
+
export type { MultichainTransactionsControllerState, PaginationOptions, TransactionStateEntry, } from "./MultichainTransactionsController.mjs";
|
|
3
3
|
export { MultichainNetwork, MultichainNativeAsset } from "./constants.mjs";
|
|
4
4
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;AACtF,YAAY,EACV,qCAAqC,EACrC,iBAAiB,EACjB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;AACtF,YAAY,EACV,qCAAqC,EACrC,iBAAiB,EACjB,qBAAqB,GACtB,+CAA2C;AAC5C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,wBAAoB"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,+CAA2C;AAMtF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,wBAAoB","sourcesContent":["export { MultichainTransactionsController } from './MultichainTransactionsController';\nexport type {\n MultichainTransactionsControllerState,\n PaginationOptions,\n TransactionStateEntry,\n} from './MultichainTransactionsController';\nexport { MultichainNetwork, MultichainNativeAsset } from './constants';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/multichain-transactions-controller",
|
|
3
|
-
"version": "0.8.0-preview-
|
|
3
|
+
"version": "0.8.0-preview-d987e9b2",
|
|
4
4
|
"description": "This package is responsible for getting transactions from our Bitcoin and Solana snaps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|