@metamask-previews/multichain-transactions-controller 5.1.1-preview-9fa15fd0 → 6.0.0-preview-46d2c977

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/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [6.0.0]
11
+
12
+ ### Changed
13
+
14
+ - **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6542](https://github.com/MetaMask/core/pull/6542))
15
+ - Previously, `MultichainTransactionsController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
16
+ - **BREAKING:** Metadata property `anonymous` renamed to `includeInDebugSnapshot` ([#6542](https://github.com/MetaMask/core/pull/6542))
17
+ - **BREAKING:** Bump `@metamask/accounts-controller` from `^33.0.0` to `^34.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
18
+ - Bump `@metamask/base-controller` from `^8.4.2` to `^9.0.0` ([#6962](https://github.com/MetaMask/core/pull/6962))
19
+
10
20
  ## [5.1.1]
11
21
 
12
22
  ### Changed
@@ -203,7 +213,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
203
213
 
204
214
  - Initial release ([#5133](https://github.com/MetaMask/core/pull/5133)), ([#5177](https://github.com/MetaMask/core/pull/5177))
205
215
 
206
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@5.1.1...HEAD
216
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@6.0.0...HEAD
217
+ [6.0.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@5.1.1...@metamask/multichain-transactions-controller@6.0.0
207
218
  [5.1.1]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@5.1.0...@metamask/multichain-transactions-controller@5.1.1
208
219
  [5.1.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@5.0.0...@metamask/multichain-transactions-controller@5.1.0
209
220
  [5.0.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-transactions-controller@4.0.1...@metamask/multichain-transactions-controller@5.0.0
@@ -34,7 +34,7 @@ const multichainTransactionsControllerMetadata = {
34
34
  nonEvmTransactions: {
35
35
  includeInStateLogs: true,
36
36
  persist: true,
37
- anonymous: false,
37
+ includeInDebugSnapshot: false,
38
38
  usedInUi: true,
39
39
  },
40
40
  };
@@ -60,9 +60,9 @@ class MultichainTransactionsController extends base_controller_1.BaseController
60
60
  console.error(`Failed to fetch initial transactions for account ${account.id}:`, error);
61
61
  });
62
62
  }
63
- this.messagingSystem.subscribe('AccountsController:accountAdded', (account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountAdded).call(this, account));
64
- this.messagingSystem.subscribe('AccountsController:accountRemoved', (accountId) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountRemoved).call(this, accountId));
65
- this.messagingSystem.subscribe('AccountsController:accountTransactionsUpdated', (transactionsUpdate) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountTransactionsUpdated).call(this, transactionsUpdate));
63
+ this.messenger.subscribe('AccountsController:accountAdded', (account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountAdded).call(this, account));
64
+ this.messenger.subscribe('AccountsController:accountRemoved', (accountId) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountRemoved).call(this, accountId));
65
+ this.messenger.subscribe('AccountsController:accountTransactionsUpdated', (transactionsUpdate) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountTransactionsUpdated).call(this, transactionsUpdate));
66
66
  }
67
67
  /**
68
68
  * Updates transactions for a specific account. This is used for the initial fetch
@@ -71,7 +71,7 @@ class MultichainTransactionsController extends base_controller_1.BaseController
71
71
  * @param accountId - The ID of the account to get transactions for.
72
72
  */
73
73
  async updateTransactionsForAccount(accountId) {
74
- const { isUnlocked } = this.messagingSystem.call('KeyringController:getState');
74
+ const { isUnlocked } = this.messenger.call('KeyringController:getState');
75
75
  if (!isUnlocked) {
76
76
  return;
77
77
  }
@@ -112,7 +112,7 @@ class MultichainTransactionsController extends base_controller_1.BaseController
112
112
  }
113
113
  exports.MultichainTransactionsController = MultichainTransactionsController;
114
114
  _MultichainTransactionsController_instances = new WeakSet(), _MultichainTransactionsController_listMultichainAccounts = function _MultichainTransactionsController_listMultichainAccounts() {
115
- return this.messagingSystem.call('AccountsController:listMultichainAccounts');
115
+ return this.messenger.call('AccountsController:listMultichainAccounts');
116
116
  }, _MultichainTransactionsController_listAccounts = function _MultichainTransactionsController_listAccounts() {
117
117
  const accounts = __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_listMultichainAccounts).call(this);
118
118
  return accounts.filter((account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_isNonEvmAccount).call(this, account));
@@ -156,10 +156,10 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
156
156
  }
157
157
  }, _MultichainTransactionsController_publishTransactionUpdateEvent = function _MultichainTransactionsController_publishTransactionUpdateEvent(updatedTransaction) {
158
158
  if (updatedTransaction.status === keyring_api_1.TransactionStatus.Confirmed) {
159
- this.messagingSystem.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
159
+ this.messenger.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
160
160
  }
161
161
  if (updatedTransaction.status === keyring_api_1.TransactionStatus.Submitted) {
162
- this.messagingSystem.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
162
+ this.messenger.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
163
163
  }
164
164
  }, _MultichainTransactionsController_handleOnAccountTransactionsUpdated = function _MultichainTransactionsController_handleOnAccountTransactionsUpdated(transactionsUpdate) {
165
165
  const updatedTransactions = {};
@@ -216,7 +216,7 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
216
216
  });
217
217
  }, _MultichainTransactionsController_getClient = function _MultichainTransactionsController_getClient(snapId) {
218
218
  return new keyring_snap_client_1.KeyringClient({
219
- send: async (request) => (await this.messagingSystem.call('SnapController:handleRequest', {
219
+ send: async (request) => (await this.messenger.call('SnapController:handleRequest', {
220
220
  snapId: snapId,
221
221
  origin: 'metamask',
222
222
  handler: snaps_utils_1.HandlerType.OnKeyringRequest,
@@ -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 type CaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\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]: {\n [chain: CaipChainId]: TransactionStateEntry;\n };\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 includeInStateLogs: true,\n persist: true,\n anonymous: false,\n usedInUi: true,\n },\n};\n\n/**\n * The state of transactions for a specific chain.\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 transactionsByChain: Record<CaipChainId, Transaction[]> = {};\n\n response.data.forEach((transaction) => {\n const { chain } = transaction;\n\n if (!transactionsByChain[chain]) {\n transactionsByChain[chain] = [];\n }\n transactionsByChain[chain].push(transaction);\n });\n\n const chainUpdates = Object.entries(transactionsByChain).map(\n ([chain, transactions]) => ({\n chain,\n entry: {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n },\n }),\n );\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n if (!state.nonEvmTransactions[account.id]) {\n state.nonEvmTransactions[account.id] = {};\n }\n\n chainUpdates.forEach(({ chain, entry }) => {\n state.nonEvmTransactions[account.id][chain as CaipChainId] = entry;\n });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\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<\n string,\n Record<CaipChainId, Transaction[]>\n > = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n updatedTransactions[accountId] = {};\n\n newTransactions.forEach((tx) => {\n const { chain } = tx;\n\n if (!updatedTransactions[accountId][chain]) {\n updatedTransactions[accountId][chain] = [];\n }\n\n updatedTransactions[accountId][chain].push(tx);\n transactionsToPublish.push(tx);\n });\n\n Object.entries(updatedTransactions[accountId]).forEach(\n ([chain, chainTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.[chain as CaipChainId]\n ?.transactions ?? [];\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 chainTransactions.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][chain as CaipChainId] = Array.from(\n transactions.values(),\n ).sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));\n },\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(([accountId, chainsData]) => {\n if (!state.nonEvmTransactions[accountId]) {\n state.nonEvmTransactions[accountId] = {};\n }\n\n Object.entries(chainsData).forEach(([chain, transactions]) => {\n state.nonEvmTransactions[accountId][chain as CaipChainId] = {\n transactions,\n next: null,\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} 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 { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n type CaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\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]: {\n [chain: CaipChainId]: TransactionStateEntry;\n };\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 = Messenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\ntype AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\ntype 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 includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n/**\n * The state of transactions for a specific chain.\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.messenger.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messenger.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messenger.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.messenger.call('AccountsController:listMultichainAccounts');\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.messenger.call('KeyringController:getState');\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 transactionsByChain: Record<CaipChainId, Transaction[]> = {};\n\n response.data.forEach((transaction) => {\n const { chain } = transaction;\n\n if (!transactionsByChain[chain]) {\n transactionsByChain[chain] = [];\n }\n transactionsByChain[chain].push(transaction);\n });\n\n const chainUpdates = Object.entries(transactionsByChain).map(\n ([chain, transactions]) => ({\n chain,\n entry: {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n },\n }),\n );\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n if (!state.nonEvmTransactions[account.id]) {\n state.nonEvmTransactions[account.id] = {};\n }\n\n chainUpdates.forEach(({ chain, entry }) => {\n state.nonEvmTransactions[account.id][chain as CaipChainId] = entry;\n });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\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.messenger.publish(\n 'MultichainTransactionsController:transactionConfirmed',\n updatedTransaction,\n );\n }\n\n if (updatedTransaction.status === TransactionStatus.Submitted) {\n this.messenger.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<\n string,\n Record<CaipChainId, Transaction[]>\n > = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n updatedTransactions[accountId] = {};\n\n newTransactions.forEach((tx) => {\n const { chain } = tx;\n\n if (!updatedTransactions[accountId][chain]) {\n updatedTransactions[accountId][chain] = [];\n }\n\n updatedTransactions[accountId][chain].push(tx);\n transactionsToPublish.push(tx);\n });\n\n Object.entries(updatedTransactions[accountId]).forEach(\n ([chain, chainTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.[chain as CaipChainId]\n ?.transactions ?? [];\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 chainTransactions.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][chain as CaipChainId] = Array.from(\n transactions.values(),\n ).sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));\n },\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(([accountId, chainsData]) => {\n if (!state.nonEvmTransactions[accountId]) {\n state.nonEvmTransactions[accountId] = {};\n }\n\n Object.entries(chainsData).forEach(([chain, transactions]) => {\n state.nonEvmTransactions[accountId][chain as CaipChainId] = {\n transactions,\n next: null,\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.messenger.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,7 +1,8 @@
1
1
  import type { AccountsControllerAccountAddedEvent, AccountsControllerAccountRemovedEvent, AccountsControllerListMultichainAccountsAction, AccountsControllerAccountTransactionsUpdatedEvent } from "@metamask/accounts-controller";
2
- import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent, type RestrictedMessenger } from "@metamask/base-controller";
2
+ import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
3
3
  import { type Transaction } from "@metamask/keyring-api";
4
4
  import type { KeyringControllerGetStateAction } from "@metamask/keyring-controller";
5
+ import type { Messenger } from "@metamask/messenger";
5
6
  import type { HandleSnapRequest } from "@metamask/snaps-controllers";
6
7
  import { type CaipChainId } from "@metamask/utils";
7
8
  declare const controllerName = "MultichainTransactionsController";
@@ -65,15 +66,15 @@ export type MultichainTransactionsControllerEvents = MultichainTransactionsContr
65
66
  /**
66
67
  * Messenger type for the MultichainTransactionsController.
67
68
  */
68
- export type MultichainTransactionsControllerMessenger = RestrictedMessenger<typeof controllerName, MultichainTransactionsControllerActions | AllowedActions, MultichainTransactionsControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
69
+ export type MultichainTransactionsControllerMessenger = Messenger<typeof controllerName, MultichainTransactionsControllerActions | AllowedActions, MultichainTransactionsControllerEvents | AllowedEvents>;
69
70
  /**
70
71
  * Actions that this controller is allowed to call.
71
72
  */
72
- export type AllowedActions = HandleSnapRequest | KeyringControllerGetStateAction | AccountsControllerListMultichainAccountsAction;
73
+ type AllowedActions = HandleSnapRequest | KeyringControllerGetStateAction | AccountsControllerListMultichainAccountsAction;
73
74
  /**
74
75
  * Events that this controller is allowed to subscribe.
75
76
  */
76
- export type AllowedEvents = AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent | AccountsControllerAccountTransactionsUpdatedEvent;
77
+ type AllowedEvents = AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent | AccountsControllerAccountTransactionsUpdatedEvent;
77
78
  /**
78
79
  * The state of transactions for a specific chain.
79
80
  */
@@ -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,EAGjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAGrE,OAAO,EACL,KAAK,WAAW,EAGjB,wBAAwB;AAGzB,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;YACnB,CAAC,KAAK,EAAE,WAAW,GAAG,qBAAqB,CAAC;SAC7C,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;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,GAC9C,2CAA2C,GAC3C,yDAAyD,GACzD,yDAAyD,CAAC;AAE9D;;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;AAkBtD;;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;CAgOrD"}
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,EAChC,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,EAGjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAGrE,OAAO,EACL,KAAK,WAAW,EAGjB,wBAAwB;AAGzB,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;YACnB,CAAC,KAAK,EAAE,WAAW,GAAG,qBAAqB,CAAC;SAC7C,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;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,GAC9C,2CAA2C,GAC3C,yDAAyD,GACzD,yDAAyD,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,yCAAyC,GAAG,SAAS,CAC/D,OAAO,cAAc,EACrB,uCAAuC,GAAG,cAAc,EACxD,sCAAsC,GAAG,aAAa,CACvD,CAAC;AAEF;;GAEG;AACH,KAAK,cAAc,GACf,iBAAiB,GACjB,+BAA+B,GAC/B,8CAA8C,CAAC;AAEnD;;GAEG;AACH,KAAK,aAAa,GACd,mCAAmC,GACnC,qCAAqC,GACrC,iDAAiD,CAAC;AAkBtD;;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;IA6ED;;;;;OAKG;IACG,4BAA4B,CAAC,SAAS,EAAE,MAAM;CA8NrD"}
@@ -1,7 +1,8 @@
1
1
  import type { AccountsControllerAccountAddedEvent, AccountsControllerAccountRemovedEvent, AccountsControllerListMultichainAccountsAction, AccountsControllerAccountTransactionsUpdatedEvent } from "@metamask/accounts-controller";
2
- import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent, type RestrictedMessenger } from "@metamask/base-controller";
2
+ import { BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent } from "@metamask/base-controller";
3
3
  import { type Transaction } from "@metamask/keyring-api";
4
4
  import type { KeyringControllerGetStateAction } from "@metamask/keyring-controller";
5
+ import type { Messenger } from "@metamask/messenger";
5
6
  import type { HandleSnapRequest } from "@metamask/snaps-controllers";
6
7
  import { type CaipChainId } from "@metamask/utils";
7
8
  declare const controllerName = "MultichainTransactionsController";
@@ -65,15 +66,15 @@ export type MultichainTransactionsControllerEvents = MultichainTransactionsContr
65
66
  /**
66
67
  * Messenger type for the MultichainTransactionsController.
67
68
  */
68
- export type MultichainTransactionsControllerMessenger = RestrictedMessenger<typeof controllerName, MultichainTransactionsControllerActions | AllowedActions, MultichainTransactionsControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
69
+ export type MultichainTransactionsControllerMessenger = Messenger<typeof controllerName, MultichainTransactionsControllerActions | AllowedActions, MultichainTransactionsControllerEvents | AllowedEvents>;
69
70
  /**
70
71
  * Actions that this controller is allowed to call.
71
72
  */
72
- export type AllowedActions = HandleSnapRequest | KeyringControllerGetStateAction | AccountsControllerListMultichainAccountsAction;
73
+ type AllowedActions = HandleSnapRequest | KeyringControllerGetStateAction | AccountsControllerListMultichainAccountsAction;
73
74
  /**
74
75
  * Events that this controller is allowed to subscribe.
75
76
  */
76
- export type AllowedEvents = AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent | AccountsControllerAccountTransactionsUpdatedEvent;
77
+ type AllowedEvents = AccountsControllerAccountAddedEvent | AccountsControllerAccountRemovedEvent | AccountsControllerAccountTransactionsUpdatedEvent;
77
78
  /**
78
79
  * The state of transactions for a specific chain.
79
80
  */
@@ -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,EAGjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAGrE,OAAO,EACL,KAAK,WAAW,EAGjB,wBAAwB;AAGzB,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;YACnB,CAAC,KAAK,EAAE,WAAW,GAAG,qBAAqB,CAAC;SAC7C,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;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,GAC9C,2CAA2C,GAC3C,yDAAyD,GACzD,yDAAyD,CAAC;AAE9D;;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;AAkBtD;;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;CAgOrD"}
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,EAChC,kCAAkC;AACnC,OAAO,EAEL,KAAK,WAAW,EAGjB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,qCAAqC;AAGpF,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AAGrE,OAAO,EACL,KAAK,WAAW,EAGjB,wBAAwB;AAGzB,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;YACnB,CAAC,KAAK,EAAE,WAAW,GAAG,qBAAqB,CAAC;SAC7C,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,+CAA+C,IAAI,qCAAqC,CAIvG;AAED;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yDAAyD,GAAG;IACtE,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;CACxB,CAAC;AAEF;;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,GAC9C,2CAA2C,GAC3C,yDAAyD,GACzD,yDAAyD,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,yCAAyC,GAAG,SAAS,CAC/D,OAAO,cAAc,EACrB,uCAAuC,GAAG,cAAc,EACxD,sCAAsC,GAAG,aAAa,CACvD,CAAC;AAEF;;GAEG;AACH,KAAK,cAAc,GACf,iBAAiB,GACjB,+BAA+B,GAC/B,8CAA8C,CAAC;AAEnD;;GAEG;AACH,KAAK,aAAa,GACd,mCAAmC,GACnC,qCAAqC,GACrC,iDAAiD,CAAC;AAkBtD;;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;IA6ED;;;;;OAKG;IACG,4BAA4B,CAAC,SAAS,EAAE,MAAM;CA8NrD"}
@@ -30,7 +30,7 @@ const multichainTransactionsControllerMetadata = {
30
30
  nonEvmTransactions: {
31
31
  includeInStateLogs: true,
32
32
  persist: true,
33
- anonymous: false,
33
+ includeInDebugSnapshot: false,
34
34
  usedInUi: true,
35
35
  },
36
36
  };
@@ -56,9 +56,9 @@ export class MultichainTransactionsController extends BaseController {
56
56
  console.error(`Failed to fetch initial transactions for account ${account.id}:`, error);
57
57
  });
58
58
  }
59
- this.messagingSystem.subscribe('AccountsController:accountAdded', (account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountAdded).call(this, account));
60
- this.messagingSystem.subscribe('AccountsController:accountRemoved', (accountId) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountRemoved).call(this, accountId));
61
- this.messagingSystem.subscribe('AccountsController:accountTransactionsUpdated', (transactionsUpdate) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountTransactionsUpdated).call(this, transactionsUpdate));
59
+ this.messenger.subscribe('AccountsController:accountAdded', (account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountAdded).call(this, account));
60
+ this.messenger.subscribe('AccountsController:accountRemoved', (accountId) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountRemoved).call(this, accountId));
61
+ this.messenger.subscribe('AccountsController:accountTransactionsUpdated', (transactionsUpdate) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_handleOnAccountTransactionsUpdated).call(this, transactionsUpdate));
62
62
  }
63
63
  /**
64
64
  * Updates transactions for a specific account. This is used for the initial fetch
@@ -67,7 +67,7 @@ export class MultichainTransactionsController extends BaseController {
67
67
  * @param accountId - The ID of the account to get transactions for.
68
68
  */
69
69
  async updateTransactionsForAccount(accountId) {
70
- const { isUnlocked } = this.messagingSystem.call('KeyringController:getState');
70
+ const { isUnlocked } = this.messenger.call('KeyringController:getState');
71
71
  if (!isUnlocked) {
72
72
  return;
73
73
  }
@@ -107,7 +107,7 @@ export class MultichainTransactionsController extends BaseController {
107
107
  }
108
108
  }
109
109
  _MultichainTransactionsController_instances = new WeakSet(), _MultichainTransactionsController_listMultichainAccounts = function _MultichainTransactionsController_listMultichainAccounts() {
110
- return this.messagingSystem.call('AccountsController:listMultichainAccounts');
110
+ return this.messenger.call('AccountsController:listMultichainAccounts');
111
111
  }, _MultichainTransactionsController_listAccounts = function _MultichainTransactionsController_listAccounts() {
112
112
  const accounts = __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_listMultichainAccounts).call(this);
113
113
  return accounts.filter((account) => __classPrivateFieldGet(this, _MultichainTransactionsController_instances, "m", _MultichainTransactionsController_isNonEvmAccount).call(this, account));
@@ -151,10 +151,10 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
151
151
  }
152
152
  }, _MultichainTransactionsController_publishTransactionUpdateEvent = function _MultichainTransactionsController_publishTransactionUpdateEvent(updatedTransaction) {
153
153
  if (updatedTransaction.status === TransactionStatus.Confirmed) {
154
- this.messagingSystem.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
154
+ this.messenger.publish('MultichainTransactionsController:transactionConfirmed', updatedTransaction);
155
155
  }
156
156
  if (updatedTransaction.status === TransactionStatus.Submitted) {
157
- this.messagingSystem.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
157
+ this.messenger.publish('MultichainTransactionsController:transactionSubmitted', updatedTransaction);
158
158
  }
159
159
  }, _MultichainTransactionsController_handleOnAccountTransactionsUpdated = function _MultichainTransactionsController_handleOnAccountTransactionsUpdated(transactionsUpdate) {
160
160
  const updatedTransactions = {};
@@ -211,7 +211,7 @@ async function _MultichainTransactionsController_handleOnAccountRemoved(accountI
211
211
  });
212
212
  }, _MultichainTransactionsController_getClient = function _MultichainTransactionsController_getClient(snapId) {
213
213
  return new KeyringClient({
214
- send: async (request) => (await this.messagingSystem.call('SnapController:handleRequest', {
214
+ send: async (request) => (await this.messenger.call('SnapController:handleRequest', {
215
215
  snapId: snapId,
216
216
  origin: 'metamask',
217
217
  handler: HandlerType.OnKeyringRequest,
@@ -1 +1 @@
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 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 type CaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\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]: {\n [chain: CaipChainId]: TransactionStateEntry;\n };\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 includeInStateLogs: true,\n persist: true,\n anonymous: false,\n usedInUi: true,\n },\n};\n\n/**\n * The state of transactions for a specific chain.\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 transactionsByChain: Record<CaipChainId, Transaction[]> = {};\n\n response.data.forEach((transaction) => {\n const { chain } = transaction;\n\n if (!transactionsByChain[chain]) {\n transactionsByChain[chain] = [];\n }\n transactionsByChain[chain].push(transaction);\n });\n\n const chainUpdates = Object.entries(transactionsByChain).map(\n ([chain, transactions]) => ({\n chain,\n entry: {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n },\n }),\n );\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n if (!state.nonEvmTransactions[account.id]) {\n state.nonEvmTransactions[account.id] = {};\n }\n\n chainUpdates.forEach(({ chain, entry }) => {\n state.nonEvmTransactions[account.id][chain as CaipChainId] = entry;\n });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\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<\n string,\n Record<CaipChainId, Transaction[]>\n > = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n updatedTransactions[accountId] = {};\n\n newTransactions.forEach((tx) => {\n const { chain } = tx;\n\n if (!updatedTransactions[accountId][chain]) {\n updatedTransactions[accountId][chain] = [];\n }\n\n updatedTransactions[accountId][chain].push(tx);\n transactionsToPublish.push(tx);\n });\n\n Object.entries(updatedTransactions[accountId]).forEach(\n ([chain, chainTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.[chain as CaipChainId]\n ?.transactions ?? [];\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 chainTransactions.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][chain as CaipChainId] = Array.from(\n transactions.values(),\n ).sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));\n },\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(([accountId, chainsData]) => {\n if (!state.nonEvmTransactions[accountId]) {\n state.nonEvmTransactions[accountId] = {};\n }\n\n Object.entries(chainsData).forEach(([chain, transactions]) => {\n state.nonEvmTransactions[accountId][chain as CaipChainId] = {\n transactions,\n next: null,\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} 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 { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport {\n type CaipChainId,\n type Json,\n type JsonRpcRequest,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\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]: {\n [chain: CaipChainId]: TransactionStateEntry;\n };\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 = Messenger<\n typeof controllerName,\n MultichainTransactionsControllerActions | AllowedActions,\n MultichainTransactionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Actions that this controller is allowed to call.\n */\ntype AllowedActions =\n | HandleSnapRequest\n | KeyringControllerGetStateAction\n | AccountsControllerListMultichainAccountsAction;\n\n/**\n * Events that this controller is allowed to subscribe.\n */\ntype 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 includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n/**\n * The state of transactions for a specific chain.\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.messenger.subscribe(\n 'AccountsController:accountAdded',\n (account: InternalAccount) => this.#handleOnAccountAdded(account),\n );\n this.messenger.subscribe(\n 'AccountsController:accountRemoved',\n (accountId: string) => this.#handleOnAccountRemoved(accountId),\n );\n this.messenger.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.messenger.call('AccountsController:listMultichainAccounts');\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.messenger.call('KeyringController:getState');\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 transactionsByChain: Record<CaipChainId, Transaction[]> = {};\n\n response.data.forEach((transaction) => {\n const { chain } = transaction;\n\n if (!transactionsByChain[chain]) {\n transactionsByChain[chain] = [];\n }\n transactionsByChain[chain].push(transaction);\n });\n\n const chainUpdates = Object.entries(transactionsByChain).map(\n ([chain, transactions]) => ({\n chain,\n entry: {\n transactions,\n next: response.next,\n lastUpdated: Date.now(),\n },\n }),\n );\n\n this.update((state: Draft<MultichainTransactionsControllerState>) => {\n if (!state.nonEvmTransactions[account.id]) {\n state.nonEvmTransactions[account.id] = {};\n }\n\n chainUpdates.forEach(({ chain, entry }) => {\n state.nonEvmTransactions[account.id][chain as CaipChainId] = entry;\n });\n });\n }\n } catch (error) {\n console.error(\n `Failed to fetch transactions for account ${accountId}:`,\n error,\n );\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.messenger.publish(\n 'MultichainTransactionsController:transactionConfirmed',\n updatedTransaction,\n );\n }\n\n if (updatedTransaction.status === TransactionStatus.Submitted) {\n this.messenger.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<\n string,\n Record<CaipChainId, Transaction[]>\n > = {};\n const transactionsToPublish: Transaction[] = [];\n\n if (!transactionsUpdate?.transactions) {\n return;\n }\n\n Object.entries(transactionsUpdate.transactions).forEach(\n ([accountId, newTransactions]) => {\n updatedTransactions[accountId] = {};\n\n newTransactions.forEach((tx) => {\n const { chain } = tx;\n\n if (!updatedTransactions[accountId][chain]) {\n updatedTransactions[accountId][chain] = [];\n }\n\n updatedTransactions[accountId][chain].push(tx);\n transactionsToPublish.push(tx);\n });\n\n Object.entries(updatedTransactions[accountId]).forEach(\n ([chain, chainTransactions]) => {\n // Account might not have any transactions yet, so use `[]` in that case.\n const oldTransactions =\n this.state.nonEvmTransactions[accountId]?.[chain as CaipChainId]\n ?.transactions ?? [];\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 chainTransactions.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][chain as CaipChainId] = Array.from(\n transactions.values(),\n ).sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));\n },\n );\n },\n );\n\n this.update((state) => {\n Object.entries(updatedTransactions).forEach(([accountId, chainsData]) => {\n if (!state.nonEvmTransactions[accountId]) {\n state.nonEvmTransactions[accountId] = {};\n }\n\n Object.entries(chainsData).forEach(([chain, transactions]) => {\n state.nonEvmTransactions[accountId][chain as CaipChainId] = {\n transactions,\n next: null,\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.messenger.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/multichain-transactions-controller",
3
- "version": "5.1.1-preview-9fa15fd0",
3
+ "version": "6.0.0-preview-46d2c977",
4
4
  "description": "This package is responsible for getting transactions from our Bitcoin and Solana snaps",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -47,11 +47,12 @@
47
47
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
48
48
  },
49
49
  "dependencies": {
50
- "@metamask/base-controller": "^8.4.2",
50
+ "@metamask/base-controller": "^9.0.0",
51
51
  "@metamask/keyring-api": "^21.0.0",
52
52
  "@metamask/keyring-internal-api": "^9.0.0",
53
53
  "@metamask/keyring-snap-client": "^8.0.0",
54
- "@metamask/polling-controller": "^14.0.2",
54
+ "@metamask/messenger": "^0.3.0",
55
+ "@metamask/polling-controller": "^15.0.0",
55
56
  "@metamask/snaps-sdk": "^9.0.0",
56
57
  "@metamask/snaps-utils": "^11.0.0",
57
58
  "@metamask/utils": "^11.8.1",
@@ -60,9 +61,9 @@
60
61
  "uuid": "^8.3.2"
61
62
  },
62
63
  "devDependencies": {
63
- "@metamask/accounts-controller": "^33.2.0",
64
+ "@metamask/accounts-controller": "^34.0.0",
64
65
  "@metamask/auto-changelog": "^3.4.4",
65
- "@metamask/keyring-controller": "^23.2.0",
66
+ "@metamask/keyring-controller": "^24.0.0",
66
67
  "@metamask/snaps-controllers": "^14.0.1",
67
68
  "@types/jest": "^27.4.1",
68
69
  "deepmerge": "^4.2.2",
@@ -73,7 +74,7 @@
73
74
  "typescript": "~5.2.2"
74
75
  },
75
76
  "peerDependencies": {
76
- "@metamask/accounts-controller": "^33.0.0",
77
+ "@metamask/accounts-controller": "^34.0.0",
77
78
  "@metamask/snaps-controllers": "^14.0.0"
78
79
  },
79
80
  "engines": {