@metamask-previews/user-operation-controller 41.2.0-preview-d5ac72227 → 41.2.0-preview-2e231093e
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 +1 -1
- package/dist/helpers/PendingUserOperationTracker.cjs +1 -1
- package/dist/helpers/PendingUserOperationTracker.cjs.map +1 -1
- package/dist/helpers/PendingUserOperationTracker.d.cts.map +1 -1
- package/dist/helpers/PendingUserOperationTracker.d.mts.map +1 -1
- package/dist/helpers/PendingUserOperationTracker.mjs +1 -1
- package/dist/helpers/PendingUserOperationTracker.mjs.map +1 -1
- package/package.json +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
- Bump `@metamask/keyring-controller` from `^25.1.1` to `^25.2.0` ([#8363](https://github.com/MetaMask/core/pull/8363))
|
|
13
13
|
- Bump `@metamask/messenger` from `^1.0.0` to `^1.1.1` ([#8364](https://github.com/MetaMask/core/pull/8364), [#8373](https://github.com/MetaMask/core/pull/8373))
|
|
14
|
-
- Bump `@metamask/transaction-controller` from `^64.0.0` to `^64.
|
|
14
|
+
- Bump `@metamask/transaction-controller` from `^64.0.0` to `^64.2.0` ([#8432](https://github.com/MetaMask/core/pull/8432), [#8447](https://github.com/MetaMask/core/pull/8447))
|
|
15
15
|
|
|
16
16
|
## [41.2.0]
|
|
17
17
|
|
|
@@ -23,9 +23,9 @@ const utils_1 = require("@metamask/utils");
|
|
|
23
23
|
// This package purposefully relies on Node's EventEmitter module.
|
|
24
24
|
// eslint-disable-next-line import-x/no-nodejs-modules
|
|
25
25
|
const events_1 = __importDefault(require("events"));
|
|
26
|
-
const Bundler_1 = require("./Bundler.cjs");
|
|
27
26
|
const logger_1 = require("../logger.cjs");
|
|
28
27
|
const types_1 = require("../types.cjs");
|
|
28
|
+
const Bundler_1 = require("./Bundler.cjs");
|
|
29
29
|
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'pending-user-operations');
|
|
30
30
|
/**
|
|
31
31
|
* A helper class to periodically query the bundlers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingUserOperationTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query, toHex } from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClient,\n NetworkClientId,\n Provider,\n} from '@metamask/network-controller';\nimport { BlockTrackerPollingControllerOnly } from '@metamask/polling-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { Bundler } from './Bundler';\nimport { projectLogger } from '../logger';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types';\nimport { UserOperationStatus } from '../types';\nimport type { UserOperationControllerMessenger } from '../UserOperationController';\n\nconst log = createModuleLogger(projectLogger, 'pending-user-operations');\n\ntype Events = {\n 'user-operation-confirmed': [metadata: UserOperationMetadata];\n 'user-operation-failed': [txMeta: UserOperationMetadata, error: Error];\n 'user-operation-updated': [txMeta: UserOperationMetadata];\n};\n\nexport type PendingUserOperationTrackerEventEmitter = EventEmitter & {\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n once<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n};\n\n/** The input to start polling for the {@link PendingUserOperationTracker} */\ntype PendingUserOperationPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * A helper class to periodically query the bundlers\n * and update the status of any submitted user operations.\n */\nexport class PendingUserOperationTracker extends BlockTrackerPollingControllerOnly<PendingUserOperationPollingInput>() {\n hub: PendingUserOperationTrackerEventEmitter;\n\n readonly #getUserOperations: () => UserOperationMetadata[];\n\n readonly #messenger: UserOperationControllerMessenger;\n\n constructor({\n getUserOperations,\n messenger,\n }: {\n getUserOperations: () => UserOperationMetadata[];\n messenger: UserOperationControllerMessenger;\n }) {\n super();\n\n this.hub = new EventEmitter() as PendingUserOperationTrackerEventEmitter;\n\n this.#getUserOperations = getUserOperations;\n this.#messenger = messenger;\n }\n\n async _executePoll({ networkClientId }: PendingUserOperationPollingInput) {\n try {\n const { blockTracker, configuration, provider } =\n this._getNetworkClientById(networkClientId) as NetworkClient;\n\n log('Polling', {\n blockNumber: blockTracker.getCurrentBlock(),\n chainId: configuration.chainId,\n });\n\n await this.#checkUserOperations(configuration.chainId, provider);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check user operations', error);\n }\n }\n\n _getNetworkClientById(networkClientId: string): NetworkClient | undefined {\n return this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n\n async #checkUserOperations(chainId: string, provider: Provider) {\n const pendingUserOperations = this.#getPendingUserOperations().filter(\n (metadata) => metadata.chainId === chainId,\n );\n\n if (!pendingUserOperations.length) {\n log('No pending user operations to check');\n return;\n }\n\n log('Found pending user operations to check', {\n count: pendingUserOperations.length,\n ids: pendingUserOperations.map((userOperation) => userOperation.id),\n });\n\n await Promise.all(\n pendingUserOperations.map((userOperation) =>\n this.#checkUserOperation(userOperation, provider),\n ),\n );\n }\n\n async #checkUserOperation(\n metadata: UserOperationMetadata,\n provider: Provider,\n ) {\n const { bundlerUrl, hash, id } = metadata;\n\n if (!hash || !bundlerUrl) {\n log('Skipping user operation as missing hash or bundler', id);\n return;\n }\n\n try {\n const receipt = await this.#getUserOperationReceipt(hash, bundlerUrl);\n const isSuccess = receipt?.success;\n\n if (receipt && !isSuccess) {\n this.#onUserOperationFailed(metadata, receipt);\n return;\n }\n\n if (isSuccess) {\n await this.#onUserOperationConfirmed(metadata, receipt, provider);\n return;\n }\n\n log('No receipt found for user operation', { id, hash });\n } catch (error) {\n log('Failed to check user operation', id, error);\n }\n }\n\n async #onUserOperationConfirmed(\n metadata: UserOperationMetadata,\n receipt: UserOperationReceipt,\n provider: Provider,\n ) {\n const { id } = metadata;\n\n const {\n actualGasCost,\n actualGasUsed,\n receipt: { blockHash, transactionHash },\n } = receipt;\n\n log('User operation confirmed', id, transactionHash);\n\n const { baseFeePerGas } = await query(\n new EthQuery(provider),\n 'getBlockByHash',\n [blockHash, false],\n );\n\n metadata.actualGasCost = this.#normalizeGasValue(actualGasCost);\n metadata.actualGasUsed = this.#normalizeGasValue(actualGasUsed);\n metadata.baseFeePerGas = baseFeePerGas;\n metadata.status = UserOperationStatus.Confirmed;\n metadata.transactionHash = transactionHash;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit('user-operation-confirmed', metadata);\n }\n\n #onUserOperationFailed(\n metadata: UserOperationMetadata,\n _receipt: UserOperationReceipt,\n ) {\n const { id } = metadata;\n\n log('User operation failed', id);\n\n metadata.status = UserOperationStatus.Failed;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit(\n 'user-operation-failed',\n metadata,\n new Error('User operation receipt has failed status'),\n );\n }\n\n #getPendingUserOperations(): UserOperationMetadata[] {\n return this.#getUserOperations().filter(\n (userOperation) => userOperation.status === UserOperationStatus.Submitted,\n );\n }\n\n #updateUserOperation(metadata: UserOperationMetadata) {\n this.hub.emit('user-operation-updated', metadata);\n }\n\n async #getUserOperationReceipt(\n hash: string,\n bundlerUrl: string,\n ): Promise<UserOperationReceipt | undefined> {\n const bundler = new Bundler(bundlerUrl);\n return bundler.getUserOperationReceipt(hash);\n }\n\n #normalizeGasValue(gasValue: Hex | number): string {\n if (typeof gasValue === 'number') {\n return toHex(gasValue);\n }\n return gasValue;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query, toHex } from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClient,\n NetworkClientId,\n Provider,\n} from '@metamask/network-controller';\nimport { BlockTrackerPollingControllerOnly } from '@metamask/polling-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types';\nimport { UserOperationStatus } from '../types';\nimport type { UserOperationControllerMessenger } from '../UserOperationController';\nimport { Bundler } from './Bundler';\n\nconst log = createModuleLogger(projectLogger, 'pending-user-operations');\n\ntype Events = {\n 'user-operation-confirmed': [metadata: UserOperationMetadata];\n 'user-operation-failed': [txMeta: UserOperationMetadata, error: Error];\n 'user-operation-updated': [txMeta: UserOperationMetadata];\n};\n\nexport type PendingUserOperationTrackerEventEmitter = EventEmitter & {\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n once<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n};\n\n/** The input to start polling for the {@link PendingUserOperationTracker} */\ntype PendingUserOperationPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * A helper class to periodically query the bundlers\n * and update the status of any submitted user operations.\n */\nexport class PendingUserOperationTracker extends BlockTrackerPollingControllerOnly<PendingUserOperationPollingInput>() {\n hub: PendingUserOperationTrackerEventEmitter;\n\n readonly #getUserOperations: () => UserOperationMetadata[];\n\n readonly #messenger: UserOperationControllerMessenger;\n\n constructor({\n getUserOperations,\n messenger,\n }: {\n getUserOperations: () => UserOperationMetadata[];\n messenger: UserOperationControllerMessenger;\n }) {\n super();\n\n this.hub = new EventEmitter() as PendingUserOperationTrackerEventEmitter;\n\n this.#getUserOperations = getUserOperations;\n this.#messenger = messenger;\n }\n\n async _executePoll({ networkClientId }: PendingUserOperationPollingInput) {\n try {\n const { blockTracker, configuration, provider } =\n this._getNetworkClientById(networkClientId) as NetworkClient;\n\n log('Polling', {\n blockNumber: blockTracker.getCurrentBlock(),\n chainId: configuration.chainId,\n });\n\n await this.#checkUserOperations(configuration.chainId, provider);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check user operations', error);\n }\n }\n\n _getNetworkClientById(networkClientId: string): NetworkClient | undefined {\n return this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n\n async #checkUserOperations(chainId: string, provider: Provider) {\n const pendingUserOperations = this.#getPendingUserOperations().filter(\n (metadata) => metadata.chainId === chainId,\n );\n\n if (!pendingUserOperations.length) {\n log('No pending user operations to check');\n return;\n }\n\n log('Found pending user operations to check', {\n count: pendingUserOperations.length,\n ids: pendingUserOperations.map((userOperation) => userOperation.id),\n });\n\n await Promise.all(\n pendingUserOperations.map((userOperation) =>\n this.#checkUserOperation(userOperation, provider),\n ),\n );\n }\n\n async #checkUserOperation(\n metadata: UserOperationMetadata,\n provider: Provider,\n ) {\n const { bundlerUrl, hash, id } = metadata;\n\n if (!hash || !bundlerUrl) {\n log('Skipping user operation as missing hash or bundler', id);\n return;\n }\n\n try {\n const receipt = await this.#getUserOperationReceipt(hash, bundlerUrl);\n const isSuccess = receipt?.success;\n\n if (receipt && !isSuccess) {\n this.#onUserOperationFailed(metadata, receipt);\n return;\n }\n\n if (isSuccess) {\n await this.#onUserOperationConfirmed(metadata, receipt, provider);\n return;\n }\n\n log('No receipt found for user operation', { id, hash });\n } catch (error) {\n log('Failed to check user operation', id, error);\n }\n }\n\n async #onUserOperationConfirmed(\n metadata: UserOperationMetadata,\n receipt: UserOperationReceipt,\n provider: Provider,\n ) {\n const { id } = metadata;\n\n const {\n actualGasCost,\n actualGasUsed,\n receipt: { blockHash, transactionHash },\n } = receipt;\n\n log('User operation confirmed', id, transactionHash);\n\n const { baseFeePerGas } = await query(\n new EthQuery(provider),\n 'getBlockByHash',\n [blockHash, false],\n );\n\n metadata.actualGasCost = this.#normalizeGasValue(actualGasCost);\n metadata.actualGasUsed = this.#normalizeGasValue(actualGasUsed);\n metadata.baseFeePerGas = baseFeePerGas;\n metadata.status = UserOperationStatus.Confirmed;\n metadata.transactionHash = transactionHash;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit('user-operation-confirmed', metadata);\n }\n\n #onUserOperationFailed(\n metadata: UserOperationMetadata,\n _receipt: UserOperationReceipt,\n ) {\n const { id } = metadata;\n\n log('User operation failed', id);\n\n metadata.status = UserOperationStatus.Failed;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit(\n 'user-operation-failed',\n metadata,\n new Error('User operation receipt has failed status'),\n );\n }\n\n #getPendingUserOperations(): UserOperationMetadata[] {\n return this.#getUserOperations().filter(\n (userOperation) => userOperation.status === UserOperationStatus.Submitted,\n );\n }\n\n #updateUserOperation(metadata: UserOperationMetadata) {\n this.hub.emit('user-operation-updated', metadata);\n }\n\n async #getUserOperationReceipt(\n hash: string,\n bundlerUrl: string,\n ): Promise<UserOperationReceipt | undefined> {\n const bundler = new Bundler(bundlerUrl);\n return bundler.getUserOperationReceipt(hash);\n }\n\n #normalizeGasValue(gasValue: Hex | number): string {\n if (typeof gasValue === 'number') {\n return toHex(gasValue);\n }\n return gasValue;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingUserOperationTracker.d.cts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAMtC,OAAO,YAAY,eAAe;
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.d.cts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAMtC,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAwB,qBAAiB;AAE5E,OAAO,KAAK,EAAE,gCAAgC,EAAE,uCAAmC;AAKnF,KAAK,MAAM,GAAG;IACZ,0BAA0B,EAAE,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAC9D,uBAAuB,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvE,wBAAwB,EAAE,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,uCAAuC,GAAG,YAAY,GAAG;IACnE,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EACvB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,uCAAuC,CAAC;IAE3C,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EACzB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,uCAAuC,CAAC;IAE3C,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACzE,CAAC;AAEF,6EAA6E;AAC7E,KAAK,gCAAgC,GAAG;IACtC,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,2BAA4B,SAAQ,gCAAqE;;IACpH,GAAG,EAAE,uCAAuC,CAAC;gBAMjC,EACV,iBAAiB,EACjB,SAAS,GACV,EAAE;QACD,iBAAiB,EAAE,MAAM,qBAAqB,EAAE,CAAC;QACjD,SAAS,EAAE,gCAAgC,CAAC;KAC7C;IASK,YAAY,CAAC,EAAE,eAAe,EAAE,EAAE,gCAAgC;IAiBxE,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAuI1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingUserOperationTracker.d.mts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAMtC,OAAO,YAAY,eAAe;
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.d.mts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAMtC,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAwB,qBAAiB;AAE5E,OAAO,KAAK,EAAE,gCAAgC,EAAE,uCAAmC;AAKnF,KAAK,MAAM,GAAG;IACZ,0BAA0B,EAAE,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAC9D,uBAAuB,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvE,wBAAwB,EAAE,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,uCAAuC,GAAG,YAAY,GAAG;IACnE,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EACvB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,uCAAuC,CAAC;IAE3C,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EACzB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,uCAAuC,CAAC;IAE3C,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACzE,CAAC;AAEF,6EAA6E;AAC7E,KAAK,gCAAgC,GAAG;IACtC,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,2BAA4B,SAAQ,gCAAqE;;IACpH,GAAG,EAAE,uCAAuC,CAAC;gBAMjC,EACV,iBAAiB,EACjB,SAAS,GACV,EAAE;QACD,iBAAiB,EAAE,MAAM,qBAAqB,EAAE,CAAC;QACjD,SAAS,EAAE,gCAAgC,CAAC;KAC7C;IASK,YAAY,CAAC,EAAE,eAAe,EAAE,EAAE,gCAAgC;IAiBxE,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAuI1E"}
|
|
@@ -24,9 +24,9 @@ import { createModuleLogger } from "@metamask/utils";
|
|
|
24
24
|
// This package purposefully relies on Node's EventEmitter module.
|
|
25
25
|
// eslint-disable-next-line import-x/no-nodejs-modules
|
|
26
26
|
import EventEmitter from "events";
|
|
27
|
-
import { Bundler } from "./Bundler.mjs";
|
|
28
27
|
import { projectLogger } from "../logger.mjs";
|
|
29
28
|
import { UserOperationStatus } from "../types.mjs";
|
|
29
|
+
import { Bundler } from "./Bundler.mjs";
|
|
30
30
|
const log = createModuleLogger(projectLogger, 'pending-user-operations');
|
|
31
31
|
/**
|
|
32
32
|
* A helper class to periodically query the bundlers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingUserOperationTracker.mjs","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query, toHex } from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClient,\n NetworkClientId,\n Provider,\n} from '@metamask/network-controller';\nimport { BlockTrackerPollingControllerOnly } from '@metamask/polling-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { Bundler } from './Bundler';\nimport { projectLogger } from '../logger';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types';\nimport { UserOperationStatus } from '../types';\nimport type { UserOperationControllerMessenger } from '../UserOperationController';\n\nconst log = createModuleLogger(projectLogger, 'pending-user-operations');\n\ntype Events = {\n 'user-operation-confirmed': [metadata: UserOperationMetadata];\n 'user-operation-failed': [txMeta: UserOperationMetadata, error: Error];\n 'user-operation-updated': [txMeta: UserOperationMetadata];\n};\n\nexport type PendingUserOperationTrackerEventEmitter = EventEmitter & {\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n once<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n};\n\n/** The input to start polling for the {@link PendingUserOperationTracker} */\ntype PendingUserOperationPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * A helper class to periodically query the bundlers\n * and update the status of any submitted user operations.\n */\nexport class PendingUserOperationTracker extends BlockTrackerPollingControllerOnly<PendingUserOperationPollingInput>() {\n hub: PendingUserOperationTrackerEventEmitter;\n\n readonly #getUserOperations: () => UserOperationMetadata[];\n\n readonly #messenger: UserOperationControllerMessenger;\n\n constructor({\n getUserOperations,\n messenger,\n }: {\n getUserOperations: () => UserOperationMetadata[];\n messenger: UserOperationControllerMessenger;\n }) {\n super();\n\n this.hub = new EventEmitter() as PendingUserOperationTrackerEventEmitter;\n\n this.#getUserOperations = getUserOperations;\n this.#messenger = messenger;\n }\n\n async _executePoll({ networkClientId }: PendingUserOperationPollingInput) {\n try {\n const { blockTracker, configuration, provider } =\n this._getNetworkClientById(networkClientId) as NetworkClient;\n\n log('Polling', {\n blockNumber: blockTracker.getCurrentBlock(),\n chainId: configuration.chainId,\n });\n\n await this.#checkUserOperations(configuration.chainId, provider);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check user operations', error);\n }\n }\n\n _getNetworkClientById(networkClientId: string): NetworkClient | undefined {\n return this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n\n async #checkUserOperations(chainId: string, provider: Provider) {\n const pendingUserOperations = this.#getPendingUserOperations().filter(\n (metadata) => metadata.chainId === chainId,\n );\n\n if (!pendingUserOperations.length) {\n log('No pending user operations to check');\n return;\n }\n\n log('Found pending user operations to check', {\n count: pendingUserOperations.length,\n ids: pendingUserOperations.map((userOperation) => userOperation.id),\n });\n\n await Promise.all(\n pendingUserOperations.map((userOperation) =>\n this.#checkUserOperation(userOperation, provider),\n ),\n );\n }\n\n async #checkUserOperation(\n metadata: UserOperationMetadata,\n provider: Provider,\n ) {\n const { bundlerUrl, hash, id } = metadata;\n\n if (!hash || !bundlerUrl) {\n log('Skipping user operation as missing hash or bundler', id);\n return;\n }\n\n try {\n const receipt = await this.#getUserOperationReceipt(hash, bundlerUrl);\n const isSuccess = receipt?.success;\n\n if (receipt && !isSuccess) {\n this.#onUserOperationFailed(metadata, receipt);\n return;\n }\n\n if (isSuccess) {\n await this.#onUserOperationConfirmed(metadata, receipt, provider);\n return;\n }\n\n log('No receipt found for user operation', { id, hash });\n } catch (error) {\n log('Failed to check user operation', id, error);\n }\n }\n\n async #onUserOperationConfirmed(\n metadata: UserOperationMetadata,\n receipt: UserOperationReceipt,\n provider: Provider,\n ) {\n const { id } = metadata;\n\n const {\n actualGasCost,\n actualGasUsed,\n receipt: { blockHash, transactionHash },\n } = receipt;\n\n log('User operation confirmed', id, transactionHash);\n\n const { baseFeePerGas } = await query(\n new EthQuery(provider),\n 'getBlockByHash',\n [blockHash, false],\n );\n\n metadata.actualGasCost = this.#normalizeGasValue(actualGasCost);\n metadata.actualGasUsed = this.#normalizeGasValue(actualGasUsed);\n metadata.baseFeePerGas = baseFeePerGas;\n metadata.status = UserOperationStatus.Confirmed;\n metadata.transactionHash = transactionHash;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit('user-operation-confirmed', metadata);\n }\n\n #onUserOperationFailed(\n metadata: UserOperationMetadata,\n _receipt: UserOperationReceipt,\n ) {\n const { id } = metadata;\n\n log('User operation failed', id);\n\n metadata.status = UserOperationStatus.Failed;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit(\n 'user-operation-failed',\n metadata,\n new Error('User operation receipt has failed status'),\n );\n }\n\n #getPendingUserOperations(): UserOperationMetadata[] {\n return this.#getUserOperations().filter(\n (userOperation) => userOperation.status === UserOperationStatus.Submitted,\n );\n }\n\n #updateUserOperation(metadata: UserOperationMetadata) {\n this.hub.emit('user-operation-updated', metadata);\n }\n\n async #getUserOperationReceipt(\n hash: string,\n bundlerUrl: string,\n ): Promise<UserOperationReceipt | undefined> {\n const bundler = new Bundler(bundlerUrl);\n return bundler.getUserOperationReceipt(hash);\n }\n\n #normalizeGasValue(gasValue: Hex | number): string {\n if (typeof gasValue === 'number') {\n return toHex(gasValue);\n }\n return gasValue;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.mjs","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query, toHex } from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClient,\n NetworkClientId,\n Provider,\n} from '@metamask/network-controller';\nimport { BlockTrackerPollingControllerOnly } from '@metamask/polling-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types';\nimport { UserOperationStatus } from '../types';\nimport type { UserOperationControllerMessenger } from '../UserOperationController';\nimport { Bundler } from './Bundler';\n\nconst log = createModuleLogger(projectLogger, 'pending-user-operations');\n\ntype Events = {\n 'user-operation-confirmed': [metadata: UserOperationMetadata];\n 'user-operation-failed': [txMeta: UserOperationMetadata, error: Error];\n 'user-operation-updated': [txMeta: UserOperationMetadata];\n};\n\nexport type PendingUserOperationTrackerEventEmitter = EventEmitter & {\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n once<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): PendingUserOperationTrackerEventEmitter;\n\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n};\n\n/** The input to start polling for the {@link PendingUserOperationTracker} */\ntype PendingUserOperationPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * A helper class to periodically query the bundlers\n * and update the status of any submitted user operations.\n */\nexport class PendingUserOperationTracker extends BlockTrackerPollingControllerOnly<PendingUserOperationPollingInput>() {\n hub: PendingUserOperationTrackerEventEmitter;\n\n readonly #getUserOperations: () => UserOperationMetadata[];\n\n readonly #messenger: UserOperationControllerMessenger;\n\n constructor({\n getUserOperations,\n messenger,\n }: {\n getUserOperations: () => UserOperationMetadata[];\n messenger: UserOperationControllerMessenger;\n }) {\n super();\n\n this.hub = new EventEmitter() as PendingUserOperationTrackerEventEmitter;\n\n this.#getUserOperations = getUserOperations;\n this.#messenger = messenger;\n }\n\n async _executePoll({ networkClientId }: PendingUserOperationPollingInput) {\n try {\n const { blockTracker, configuration, provider } =\n this._getNetworkClientById(networkClientId) as NetworkClient;\n\n log('Polling', {\n blockNumber: blockTracker.getCurrentBlock(),\n chainId: configuration.chainId,\n });\n\n await this.#checkUserOperations(configuration.chainId, provider);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check user operations', error);\n }\n }\n\n _getNetworkClientById(networkClientId: string): NetworkClient | undefined {\n return this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n }\n\n async #checkUserOperations(chainId: string, provider: Provider) {\n const pendingUserOperations = this.#getPendingUserOperations().filter(\n (metadata) => metadata.chainId === chainId,\n );\n\n if (!pendingUserOperations.length) {\n log('No pending user operations to check');\n return;\n }\n\n log('Found pending user operations to check', {\n count: pendingUserOperations.length,\n ids: pendingUserOperations.map((userOperation) => userOperation.id),\n });\n\n await Promise.all(\n pendingUserOperations.map((userOperation) =>\n this.#checkUserOperation(userOperation, provider),\n ),\n );\n }\n\n async #checkUserOperation(\n metadata: UserOperationMetadata,\n provider: Provider,\n ) {\n const { bundlerUrl, hash, id } = metadata;\n\n if (!hash || !bundlerUrl) {\n log('Skipping user operation as missing hash or bundler', id);\n return;\n }\n\n try {\n const receipt = await this.#getUserOperationReceipt(hash, bundlerUrl);\n const isSuccess = receipt?.success;\n\n if (receipt && !isSuccess) {\n this.#onUserOperationFailed(metadata, receipt);\n return;\n }\n\n if (isSuccess) {\n await this.#onUserOperationConfirmed(metadata, receipt, provider);\n return;\n }\n\n log('No receipt found for user operation', { id, hash });\n } catch (error) {\n log('Failed to check user operation', id, error);\n }\n }\n\n async #onUserOperationConfirmed(\n metadata: UserOperationMetadata,\n receipt: UserOperationReceipt,\n provider: Provider,\n ) {\n const { id } = metadata;\n\n const {\n actualGasCost,\n actualGasUsed,\n receipt: { blockHash, transactionHash },\n } = receipt;\n\n log('User operation confirmed', id, transactionHash);\n\n const { baseFeePerGas } = await query(\n new EthQuery(provider),\n 'getBlockByHash',\n [blockHash, false],\n );\n\n metadata.actualGasCost = this.#normalizeGasValue(actualGasCost);\n metadata.actualGasUsed = this.#normalizeGasValue(actualGasUsed);\n metadata.baseFeePerGas = baseFeePerGas;\n metadata.status = UserOperationStatus.Confirmed;\n metadata.transactionHash = transactionHash;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit('user-operation-confirmed', metadata);\n }\n\n #onUserOperationFailed(\n metadata: UserOperationMetadata,\n _receipt: UserOperationReceipt,\n ) {\n const { id } = metadata;\n\n log('User operation failed', id);\n\n metadata.status = UserOperationStatus.Failed;\n\n this.#updateUserOperation(metadata);\n\n this.hub.emit(\n 'user-operation-failed',\n metadata,\n new Error('User operation receipt has failed status'),\n );\n }\n\n #getPendingUserOperations(): UserOperationMetadata[] {\n return this.#getUserOperations().filter(\n (userOperation) => userOperation.status === UserOperationStatus.Submitted,\n );\n }\n\n #updateUserOperation(metadata: UserOperationMetadata) {\n this.hub.emit('user-operation-updated', metadata);\n }\n\n async #getUserOperationReceipt(\n hash: string,\n bundlerUrl: string,\n ): Promise<UserOperationReceipt | undefined> {\n const bundler = new Bundler(bundlerUrl);\n return bundler.getUserOperationReceipt(hash);\n }\n\n #normalizeGasValue(gasValue: Hex | number): string {\n if (typeof gasValue === 'number') {\n return toHex(gasValue);\n }\n return gasValue;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/user-operation-controller",
|
|
3
|
-
"version": "41.2.0-preview-
|
|
3
|
+
"version": "41.2.0-preview-2e231093e",
|
|
4
4
|
"description": "Creates user operations and manages their life cycle",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"Ethereum",
|
|
7
|
+
"MetaMask"
|
|
8
8
|
],
|
|
9
9
|
"homepage": "https://github.com/MetaMask/core/tree/main/packages/user-operation-controller#readme",
|
|
10
10
|
"bugs": {
|
|
11
11
|
"url": "https://github.com/MetaMask/core/issues"
|
|
12
12
|
},
|
|
13
|
+
"license": "MIT",
|
|
13
14
|
"repository": {
|
|
14
15
|
"type": "git",
|
|
15
16
|
"url": "https://github.com/MetaMask/core.git"
|
|
16
17
|
},
|
|
17
|
-
"
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/"
|
|
20
|
+
],
|
|
18
21
|
"sideEffects": false,
|
|
22
|
+
"main": "./dist/index.cjs",
|
|
23
|
+
"types": "./dist/index.d.cts",
|
|
19
24
|
"exports": {
|
|
20
25
|
".": {
|
|
21
26
|
"import": {
|
|
@@ -29,11 +34,10 @@
|
|
|
29
34
|
},
|
|
30
35
|
"./package.json": "./package.json"
|
|
31
36
|
},
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public",
|
|
39
|
+
"registry": "https://registry.npmjs.org/"
|
|
40
|
+
},
|
|
37
41
|
"scripts": {
|
|
38
42
|
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
|
|
39
43
|
"build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
|
|
@@ -61,7 +65,7 @@
|
|
|
61
65
|
"@metamask/polling-controller": "^16.0.4",
|
|
62
66
|
"@metamask/rpc-errors": "^7.0.2",
|
|
63
67
|
"@metamask/superstruct": "^3.1.0",
|
|
64
|
-
"@metamask/transaction-controller": "^64.
|
|
68
|
+
"@metamask/transaction-controller": "^64.2.0",
|
|
65
69
|
"@metamask/utils": "^11.9.0",
|
|
66
70
|
"bn.js": "^5.2.1",
|
|
67
71
|
"immer": "^9.0.6",
|
|
@@ -69,7 +73,7 @@
|
|
|
69
73
|
"uuid": "^8.3.2"
|
|
70
74
|
},
|
|
71
75
|
"devDependencies": {
|
|
72
|
-
"@metamask/auto-changelog": "^
|
|
76
|
+
"@metamask/auto-changelog": "^6.0.0",
|
|
73
77
|
"@metamask/eth-block-tracker": "^15.0.0",
|
|
74
78
|
"@ts-bridge/cli": "^0.6.4",
|
|
75
79
|
"@types/jest": "^29.5.14",
|
|
@@ -86,9 +90,5 @@
|
|
|
86
90
|
},
|
|
87
91
|
"engines": {
|
|
88
92
|
"node": "^18.18 || >=20"
|
|
89
|
-
},
|
|
90
|
-
"publishConfig": {
|
|
91
|
-
"access": "public",
|
|
92
|
-
"registry": "https://registry.npmjs.org/"
|
|
93
93
|
}
|
|
94
94
|
}
|