@metamask-previews/user-operation-controller 41.2.8-preview-c2ef75d18 → 41.2.8-preview-e81fe8853
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BlockTrackerPollingController.cjs +68 -0
- package/dist/BlockTrackerPollingController.cjs.map +1 -0
- package/dist/BlockTrackerPollingController.d.cts +41 -0
- package/dist/BlockTrackerPollingController.d.cts.map +1 -0
- package/dist/BlockTrackerPollingController.d.mts +41 -0
- package/dist/BlockTrackerPollingController.d.mts.map +1 -0
- package/dist/BlockTrackerPollingController.mjs +63 -0
- package/dist/BlockTrackerPollingController.mjs.map +1 -0
- package/dist/helpers/PendingUserOperationTracker.cjs +2 -2
- package/dist/helpers/PendingUserOperationTracker.cjs.map +1 -1
- package/dist/helpers/PendingUserOperationTracker.d.cts +1 -1
- package/dist/helpers/PendingUserOperationTracker.d.cts.map +1 -1
- package/dist/helpers/PendingUserOperationTracker.d.mts +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 +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.BlockTrackerPollingController = exports.BlockTrackerPollingControllerOnly = void 0;
|
|
9
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
10
|
+
const polling_controller_1 = require("@metamask/polling-controller");
|
|
11
|
+
/**
|
|
12
|
+
* BlockTrackerPollingControllerMixin
|
|
13
|
+
* A polling controller that polls using a block tracker.
|
|
14
|
+
*
|
|
15
|
+
* @param Base - The base class to mix onto.
|
|
16
|
+
* @returns The composed class.
|
|
17
|
+
*/
|
|
18
|
+
// This is a function that's used as class, and the return type is inferred from
|
|
19
|
+
// the class defined inside the function scope, so this can't be easily typed.
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/naming-convention
|
|
21
|
+
function BlockTrackerPollingControllerMixin(Base) {
|
|
22
|
+
var _BlockTrackerPollingController_activeListeners;
|
|
23
|
+
class BlockTrackerPollingController extends (0, polling_controller_1.AbstractPollingControllerBaseMixin)(Base) {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
_BlockTrackerPollingController_activeListeners.set(this, {});
|
|
27
|
+
}
|
|
28
|
+
_startPolling(input) {
|
|
29
|
+
const key = (0, polling_controller_1.getKey)(input);
|
|
30
|
+
if (__classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key]) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const networkClient = this._getNetworkClientById(input.networkClientId);
|
|
34
|
+
if (networkClient) {
|
|
35
|
+
const updateOnNewBlock = this._executePoll.bind(this, input);
|
|
36
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
38
|
+
networkClient.blockTracker.addListener('latest', updateOnNewBlock);
|
|
39
|
+
__classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key] = updateOnNewBlock;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw new Error(`Unable to retrieve blockTracker for networkClientId ${input.networkClientId}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
_stopPollingByPollingTokenSetId(key) {
|
|
46
|
+
const { networkClientId } = JSON.parse(key);
|
|
47
|
+
const networkClient = this._getNetworkClientById(networkClientId);
|
|
48
|
+
if (networkClient && __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key]) {
|
|
49
|
+
const listener = __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key];
|
|
50
|
+
if (listener) {
|
|
51
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
53
|
+
networkClient.blockTracker.removeListener('latest', listener);
|
|
54
|
+
delete __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
_BlockTrackerPollingController_activeListeners = new WeakMap();
|
|
60
|
+
return BlockTrackerPollingController;
|
|
61
|
+
}
|
|
62
|
+
class Empty {
|
|
63
|
+
}
|
|
64
|
+
const BlockTrackerPollingControllerOnly = () => BlockTrackerPollingControllerMixin(Empty);
|
|
65
|
+
exports.BlockTrackerPollingControllerOnly = BlockTrackerPollingControllerOnly;
|
|
66
|
+
const BlockTrackerPollingController = () => BlockTrackerPollingControllerMixin(base_controller_1.BaseController);
|
|
67
|
+
exports.BlockTrackerPollingController = BlockTrackerPollingController;
|
|
68
|
+
//# sourceMappingURL=BlockTrackerPollingController.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockTrackerPollingController.cjs","sourceRoot":"","sources":["../src/BlockTrackerPollingController.ts"],"names":[],"mappings":";;;;;;;;AAAA,+DAA2D;AAK3D,qEAKsC;AAWtC;;;;;;GAMG;AACH,gFAAgF;AAChF,8EAA8E;AAC9E,kHAAkH;AAClH,SAAS,kCAAkC,CAGzC,IAAW;;IACX,MAAe,6BAA8B,SAAQ,IAAA,uDAAkC,EAGrF,IAAI,CAAC;QAHP;;YAIE,yDAAqE,EAAE,EAAC;QA2C1E,CAAC;QArCC,aAAa,CAAC,KAAmB;YAC/B,MAAM,GAAG,GAAG,IAAA,2BAAM,EAAC,KAAK,CAAC,CAAC;YAE1B,IAAI,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YACxE,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7D,gFAAgF;gBAChF,kEAAkE;gBAClE,aAAa,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;gBACnE,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,uDAAuD,KAAK,CAAC,eAAe,EAAE,CAC/E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,+BAA+B,CAAC,GAAsB;YACpD,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAC9C,eAAkC,CACnC,CAAC;YAEF,IAAI,aAAa,IAAI,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChD,MAAM,QAAQ,GAAG,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,CAAC;gBAC5C,IAAI,QAAQ,EAAE,CAAC;oBACb,gFAAgF;oBAChF,kEAAkE;oBAClE,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBAC9D,OAAO,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;KACF;;IAED,OAAO,6BAA6B,CAAC;AACvC,CAAC;AAED,MAAM,KAAK;CAAG;AAEP,MAAM,iCAAiC,GAAG,GAK7C,EAAE,CAAC,kCAAkC,CAA6B,KAAK,CAAC,CAAC;AALhE,QAAA,iCAAiC,qCAK+B;AAEtE,MAAM,6BAA6B,GAAG,GAKzC,EAAE,CACJ,kCAAkC,CAChC,gCAAc,CACf,CAAC;AARS,QAAA,6BAA6B,iCAQtC","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n NetworkClientId,\n NetworkClient,\n} from '@metamask/network-controller';\nimport {\n AbstractPollingControllerBaseMixin,\n getKey,\n Constructor,\n PollingTokenSetId,\n} from '@metamask/polling-controller';\nimport type { Json } from '@metamask/utils';\n\n/**\n * The minimum input required to start polling for a {@link BlockTrackerPollingController}.\n * Implementing classes may provide additional properties.\n */\nexport type BlockTrackerPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * BlockTrackerPollingControllerMixin\n * A polling controller that polls using a block tracker.\n *\n * @param Base - The base class to mix onto.\n * @returns The composed class.\n */\n// This is a function that's used as class, and the return type is inferred from\n// the class defined inside the function scope, so this can't be easily typed.\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/naming-convention\nfunction BlockTrackerPollingControllerMixin<\n TBase extends Constructor,\n PollingInput extends BlockTrackerPollingInput,\n>(Base: TBase) {\n abstract class BlockTrackerPollingController extends AbstractPollingControllerBaseMixin<\n TBase,\n PollingInput\n >(Base) {\n #activeListeners: Record<string, (options: Json) => Promise<void>> = {};\n\n abstract _getNetworkClientById(\n networkClientId: NetworkClientId,\n ): NetworkClient | undefined;\n\n _startPolling(input: PollingInput): void {\n const key = getKey(input);\n\n if (this.#activeListeners[key]) {\n return;\n }\n\n const networkClient = this._getNetworkClientById(input.networkClientId);\n if (networkClient) {\n const updateOnNewBlock = this._executePoll.bind(this, input);\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n networkClient.blockTracker.addListener('latest', updateOnNewBlock);\n this.#activeListeners[key] = updateOnNewBlock;\n } else {\n throw new Error(\n `Unable to retrieve blockTracker for networkClientId ${input.networkClientId}`,\n );\n }\n }\n\n _stopPollingByPollingTokenSetId(key: PollingTokenSetId): void {\n const { networkClientId } = JSON.parse(key);\n const networkClient = this._getNetworkClientById(\n networkClientId as NetworkClientId,\n );\n\n if (networkClient && this.#activeListeners[key]) {\n const listener = this.#activeListeners[key];\n if (listener) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n networkClient.blockTracker.removeListener('latest', listener);\n delete this.#activeListeners[key];\n }\n }\n }\n }\n\n return BlockTrackerPollingController;\n}\n\nclass Empty {}\n\nexport const BlockTrackerPollingControllerOnly = <\n PollingInput extends BlockTrackerPollingInput,\n // The return type is inferred from the class defined inside the function\n // scope, so this can't be easily typed.\n // eslint-disable-next-line @typescript-eslint/explicit-function-return-type\n>() => BlockTrackerPollingControllerMixin<typeof Empty, PollingInput>(Empty);\n\nexport const BlockTrackerPollingController = <\n PollingInput extends BlockTrackerPollingInput,\n // The return type is inferred from the class defined inside the function\n // scope, so this can't be easily typed.\n // eslint-disable-next-line @typescript-eslint/explicit-function-return-type\n>() =>\n BlockTrackerPollingControllerMixin<typeof BaseController, PollingInput>(\n BaseController,\n );\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseController } from "@metamask/base-controller";
|
|
2
|
+
import type { NetworkClientId, NetworkClient } from "@metamask/network-controller";
|
|
3
|
+
import { PollingTokenSetId } from "@metamask/polling-controller";
|
|
4
|
+
import type { Json } from "@metamask/utils";
|
|
5
|
+
/**
|
|
6
|
+
* The minimum input required to start polling for a {@link BlockTrackerPollingController}.
|
|
7
|
+
* Implementing classes may provide additional properties.
|
|
8
|
+
*/
|
|
9
|
+
export type BlockTrackerPollingInput = {
|
|
10
|
+
networkClientId: NetworkClientId;
|
|
11
|
+
};
|
|
12
|
+
declare class Empty {
|
|
13
|
+
}
|
|
14
|
+
export declare const BlockTrackerPollingControllerOnly: <PollingInput extends BlockTrackerPollingInput>() => (abstract new (...args: any[]) => {
|
|
15
|
+
"__#18@#activeListeners": Record<string, (options: Json) => Promise<void>>;
|
|
16
|
+
_getNetworkClientById(networkClientId: NetworkClientId): NetworkClient | undefined;
|
|
17
|
+
_startPolling(input: PollingInput): void;
|
|
18
|
+
_stopPollingByPollingTokenSetId(key: PollingTokenSetId): void;
|
|
19
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
20
|
+
readonly "__#3@#callbacks": Map<string, Set<(input: PollingInput) => void>>;
|
|
21
|
+
_executePoll(input: PollingInput): Promise<void>;
|
|
22
|
+
startPolling(input: PollingInput): string;
|
|
23
|
+
stopAllPolling(): void;
|
|
24
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
25
|
+
onPollingComplete(input: PollingInput, callback: (input: PollingInput) => void): void;
|
|
26
|
+
}) & typeof Empty;
|
|
27
|
+
export declare const BlockTrackerPollingController: <PollingInput extends BlockTrackerPollingInput>() => (abstract new (...args: any[]) => {
|
|
28
|
+
"__#18@#activeListeners": Record<string, (options: Json) => Promise<void>>;
|
|
29
|
+
_getNetworkClientById(networkClientId: NetworkClientId): NetworkClient | undefined;
|
|
30
|
+
_startPolling(input: PollingInput): void;
|
|
31
|
+
_stopPollingByPollingTokenSetId(key: PollingTokenSetId): void;
|
|
32
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
33
|
+
readonly "__#3@#callbacks": Map<string, Set<(input: PollingInput) => void>>;
|
|
34
|
+
_executePoll(input: PollingInput): Promise<void>;
|
|
35
|
+
startPolling(input: PollingInput): string;
|
|
36
|
+
stopAllPolling(): void;
|
|
37
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
38
|
+
onPollingComplete(input: PollingInput, callback: (input: PollingInput) => void): void;
|
|
39
|
+
}) & typeof BaseController;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=BlockTrackerPollingController.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockTrackerPollingController.d.cts","sourceRoot":"","sources":["../src/BlockTrackerPollingController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACd,qCAAqC;AACtC,OAAO,EAIL,iBAAiB,EAClB,qCAAqC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAoEF,cAAM,KAAK;CAAG;AAEd,eAAO,MAAM,iCAAiC;uDAlDC,IAAI,KAAK,QAAQ,IAAI,CAAC;2CAG9C,eAAe,GAC/B,aAAa,GAAG,SAAS;wCAEQ,IAAI;yCAqBH,iBAAiB,GAAG,IAAI;;;;;;;;iBA4BW,CAAC;AAE7E,eAAO,MAAM,6BAA6B;uDAzDK,IAAI,KAAK,QAAQ,IAAI,CAAC;2CAG9C,eAAe,GAC/B,aAAa,GAAG,SAAS;wCAEQ,IAAI;yCAqBH,iBAAiB,GAAG,IAAI;;;;;;;;0BAsC9D,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseController } from "@metamask/base-controller";
|
|
2
|
+
import type { NetworkClientId, NetworkClient } from "@metamask/network-controller";
|
|
3
|
+
import { PollingTokenSetId } from "@metamask/polling-controller";
|
|
4
|
+
import type { Json } from "@metamask/utils";
|
|
5
|
+
/**
|
|
6
|
+
* The minimum input required to start polling for a {@link BlockTrackerPollingController}.
|
|
7
|
+
* Implementing classes may provide additional properties.
|
|
8
|
+
*/
|
|
9
|
+
export type BlockTrackerPollingInput = {
|
|
10
|
+
networkClientId: NetworkClientId;
|
|
11
|
+
};
|
|
12
|
+
declare class Empty {
|
|
13
|
+
}
|
|
14
|
+
export declare const BlockTrackerPollingControllerOnly: <PollingInput extends BlockTrackerPollingInput>() => (abstract new (...args: any[]) => {
|
|
15
|
+
"__#18@#activeListeners": Record<string, (options: Json) => Promise<void>>;
|
|
16
|
+
_getNetworkClientById(networkClientId: NetworkClientId): NetworkClient | undefined;
|
|
17
|
+
_startPolling(input: PollingInput): void;
|
|
18
|
+
_stopPollingByPollingTokenSetId(key: PollingTokenSetId): void;
|
|
19
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
20
|
+
readonly "__#3@#callbacks": Map<string, Set<(input: PollingInput) => void>>;
|
|
21
|
+
_executePoll(input: PollingInput): Promise<void>;
|
|
22
|
+
startPolling(input: PollingInput): string;
|
|
23
|
+
stopAllPolling(): void;
|
|
24
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
25
|
+
onPollingComplete(input: PollingInput, callback: (input: PollingInput) => void): void;
|
|
26
|
+
}) & typeof Empty;
|
|
27
|
+
export declare const BlockTrackerPollingController: <PollingInput extends BlockTrackerPollingInput>() => (abstract new (...args: any[]) => {
|
|
28
|
+
"__#18@#activeListeners": Record<string, (options: Json) => Promise<void>>;
|
|
29
|
+
_getNetworkClientById(networkClientId: NetworkClientId): NetworkClient | undefined;
|
|
30
|
+
_startPolling(input: PollingInput): void;
|
|
31
|
+
_stopPollingByPollingTokenSetId(key: PollingTokenSetId): void;
|
|
32
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
33
|
+
readonly "__#3@#callbacks": Map<string, Set<(input: PollingInput) => void>>;
|
|
34
|
+
_executePoll(input: PollingInput): Promise<void>;
|
|
35
|
+
startPolling(input: PollingInput): string;
|
|
36
|
+
stopAllPolling(): void;
|
|
37
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
38
|
+
onPollingComplete(input: PollingInput, callback: (input: PollingInput) => void): void;
|
|
39
|
+
}) & typeof BaseController;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=BlockTrackerPollingController.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockTrackerPollingController.d.mts","sourceRoot":"","sources":["../src/BlockTrackerPollingController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACd,qCAAqC;AACtC,OAAO,EAIL,iBAAiB,EAClB,qCAAqC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAE5C;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAoEF,cAAM,KAAK;CAAG;AAEd,eAAO,MAAM,iCAAiC;uDAlDC,IAAI,KAAK,QAAQ,IAAI,CAAC;2CAG9C,eAAe,GAC/B,aAAa,GAAG,SAAS;wCAEQ,IAAI;yCAqBH,iBAAiB,GAAG,IAAI;;;;;;;;iBA4BW,CAAC;AAE7E,eAAO,MAAM,6BAA6B;uDAzDK,IAAI,KAAK,QAAQ,IAAI,CAAC;2CAG9C,eAAe,GAC/B,aAAa,GAAG,SAAS;wCAEQ,IAAI;yCAqBH,iBAAiB,GAAG,IAAI;;;;;;;;0BAsC9D,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
import { BaseController } from "@metamask/base-controller";
|
|
7
|
+
import { AbstractPollingControllerBaseMixin, getKey } from "@metamask/polling-controller";
|
|
8
|
+
/**
|
|
9
|
+
* BlockTrackerPollingControllerMixin
|
|
10
|
+
* A polling controller that polls using a block tracker.
|
|
11
|
+
*
|
|
12
|
+
* @param Base - The base class to mix onto.
|
|
13
|
+
* @returns The composed class.
|
|
14
|
+
*/
|
|
15
|
+
// This is a function that's used as class, and the return type is inferred from
|
|
16
|
+
// the class defined inside the function scope, so this can't be easily typed.
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/naming-convention
|
|
18
|
+
function BlockTrackerPollingControllerMixin(Base) {
|
|
19
|
+
var _BlockTrackerPollingController_activeListeners;
|
|
20
|
+
class BlockTrackerPollingController extends AbstractPollingControllerBaseMixin(Base) {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(...arguments);
|
|
23
|
+
_BlockTrackerPollingController_activeListeners.set(this, {});
|
|
24
|
+
}
|
|
25
|
+
_startPolling(input) {
|
|
26
|
+
const key = getKey(input);
|
|
27
|
+
if (__classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key]) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const networkClient = this._getNetworkClientById(input.networkClientId);
|
|
31
|
+
if (networkClient) {
|
|
32
|
+
const updateOnNewBlock = this._executePoll.bind(this, input);
|
|
33
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
35
|
+
networkClient.blockTracker.addListener('latest', updateOnNewBlock);
|
|
36
|
+
__classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key] = updateOnNewBlock;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(`Unable to retrieve blockTracker for networkClientId ${input.networkClientId}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
_stopPollingByPollingTokenSetId(key) {
|
|
43
|
+
const { networkClientId } = JSON.parse(key);
|
|
44
|
+
const networkClient = this._getNetworkClientById(networkClientId);
|
|
45
|
+
if (networkClient && __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key]) {
|
|
46
|
+
const listener = __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key];
|
|
47
|
+
if (listener) {
|
|
48
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
50
|
+
networkClient.blockTracker.removeListener('latest', listener);
|
|
51
|
+
delete __classPrivateFieldGet(this, _BlockTrackerPollingController_activeListeners, "f")[key];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
_BlockTrackerPollingController_activeListeners = new WeakMap();
|
|
57
|
+
return BlockTrackerPollingController;
|
|
58
|
+
}
|
|
59
|
+
class Empty {
|
|
60
|
+
}
|
|
61
|
+
export const BlockTrackerPollingControllerOnly = () => BlockTrackerPollingControllerMixin(Empty);
|
|
62
|
+
export const BlockTrackerPollingController = () => BlockTrackerPollingControllerMixin(BaseController);
|
|
63
|
+
//# sourceMappingURL=BlockTrackerPollingController.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockTrackerPollingController.mjs","sourceRoot":"","sources":["../src/BlockTrackerPollingController.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAK3D,OAAO,EACL,kCAAkC,EAClC,MAAM,EAGP,qCAAqC;AAWtC;;;;;;GAMG;AACH,gFAAgF;AAChF,8EAA8E;AAC9E,kHAAkH;AAClH,SAAS,kCAAkC,CAGzC,IAAW;;IACX,MAAe,6BAA8B,SAAQ,kCAAkC,CAGrF,IAAI,CAAC;QAHP;;YAIE,yDAAqE,EAAE,EAAC;QA2C1E,CAAC;QArCC,aAAa,CAAC,KAAmB;YAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAE1B,IAAI,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YACxE,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7D,gFAAgF;gBAChF,kEAAkE;gBAClE,aAAa,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;gBACnE,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,uDAAuD,KAAK,CAAC,eAAe,EAAE,CAC/E,CAAC;YACJ,CAAC;QACH,CAAC;QAED,+BAA+B,CAAC,GAAsB;YACpD,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAC9C,eAAkC,CACnC,CAAC;YAEF,IAAI,aAAa,IAAI,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChD,MAAM,QAAQ,GAAG,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,CAAC;gBAC5C,IAAI,QAAQ,EAAE,CAAC;oBACb,gFAAgF;oBAChF,kEAAkE;oBAClE,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBAC9D,OAAO,uBAAA,IAAI,sDAAiB,CAAC,GAAG,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;KACF;;IAED,OAAO,6BAA6B,CAAC;AACvC,CAAC;AAED,MAAM,KAAK;CAAG;AAEd,MAAM,CAAC,MAAM,iCAAiC,GAAG,GAK7C,EAAE,CAAC,kCAAkC,CAA6B,KAAK,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAKzC,EAAE,CACJ,kCAAkC,CAChC,cAAc,CACf,CAAC","sourcesContent":["import { BaseController } from '@metamask/base-controller';\nimport type {\n NetworkClientId,\n NetworkClient,\n} from '@metamask/network-controller';\nimport {\n AbstractPollingControllerBaseMixin,\n getKey,\n Constructor,\n PollingTokenSetId,\n} from '@metamask/polling-controller';\nimport type { Json } from '@metamask/utils';\n\n/**\n * The minimum input required to start polling for a {@link BlockTrackerPollingController}.\n * Implementing classes may provide additional properties.\n */\nexport type BlockTrackerPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * BlockTrackerPollingControllerMixin\n * A polling controller that polls using a block tracker.\n *\n * @param Base - The base class to mix onto.\n * @returns The composed class.\n */\n// This is a function that's used as class, and the return type is inferred from\n// the class defined inside the function scope, so this can't be easily typed.\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/naming-convention\nfunction BlockTrackerPollingControllerMixin<\n TBase extends Constructor,\n PollingInput extends BlockTrackerPollingInput,\n>(Base: TBase) {\n abstract class BlockTrackerPollingController extends AbstractPollingControllerBaseMixin<\n TBase,\n PollingInput\n >(Base) {\n #activeListeners: Record<string, (options: Json) => Promise<void>> = {};\n\n abstract _getNetworkClientById(\n networkClientId: NetworkClientId,\n ): NetworkClient | undefined;\n\n _startPolling(input: PollingInput): void {\n const key = getKey(input);\n\n if (this.#activeListeners[key]) {\n return;\n }\n\n const networkClient = this._getNetworkClientById(input.networkClientId);\n if (networkClient) {\n const updateOnNewBlock = this._executePoll.bind(this, input);\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n networkClient.blockTracker.addListener('latest', updateOnNewBlock);\n this.#activeListeners[key] = updateOnNewBlock;\n } else {\n throw new Error(\n `Unable to retrieve blockTracker for networkClientId ${input.networkClientId}`,\n );\n }\n }\n\n _stopPollingByPollingTokenSetId(key: PollingTokenSetId): void {\n const { networkClientId } = JSON.parse(key);\n const networkClient = this._getNetworkClientById(\n networkClientId as NetworkClientId,\n );\n\n if (networkClient && this.#activeListeners[key]) {\n const listener = this.#activeListeners[key];\n if (listener) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n networkClient.blockTracker.removeListener('latest', listener);\n delete this.#activeListeners[key];\n }\n }\n }\n }\n\n return BlockTrackerPollingController;\n}\n\nclass Empty {}\n\nexport const BlockTrackerPollingControllerOnly = <\n PollingInput extends BlockTrackerPollingInput,\n // The return type is inferred from the class defined inside the function\n // scope, so this can't be easily typed.\n // eslint-disable-next-line @typescript-eslint/explicit-function-return-type\n>() => BlockTrackerPollingControllerMixin<typeof Empty, PollingInput>(Empty);\n\nexport const BlockTrackerPollingController = <\n PollingInput extends BlockTrackerPollingInput,\n // The return type is inferred from the class defined inside the function\n // scope, so this can't be easily typed.\n // eslint-disable-next-line @typescript-eslint/explicit-function-return-type\n>() =>\n BlockTrackerPollingControllerMixin<typeof BaseController, PollingInput>(\n BaseController,\n );\n"]}
|
|
@@ -18,11 +18,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.PendingUserOperationTracker = void 0;
|
|
19
19
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
20
20
|
const eth_query_1 = __importDefault(require("@metamask/eth-query"));
|
|
21
|
-
const polling_controller_1 = require("@metamask/polling-controller");
|
|
22
21
|
const utils_1 = require("@metamask/utils");
|
|
23
22
|
// This package purposefully relies on Node's EventEmitter module.
|
|
24
23
|
// eslint-disable-next-line import-x/no-nodejs-modules
|
|
25
24
|
const events_1 = __importDefault(require("events"));
|
|
25
|
+
const BlockTrackerPollingController_js_1 = require("../BlockTrackerPollingController.cjs");
|
|
26
26
|
const logger_js_1 = require("../logger.cjs");
|
|
27
27
|
const types_js_1 = require("../types.cjs");
|
|
28
28
|
const Bundler_js_1 = require("./Bundler.cjs");
|
|
@@ -31,7 +31,7 @@ const log = (0, utils_1.createModuleLogger)(logger_js_1.projectLogger, 'pending-
|
|
|
31
31
|
* A helper class to periodically query the bundlers
|
|
32
32
|
* and update the status of any submitted user operations.
|
|
33
33
|
*/
|
|
34
|
-
class PendingUserOperationTracker extends (0,
|
|
34
|
+
class PendingUserOperationTracker extends (0, BlockTrackerPollingController_js_1.BlockTrackerPollingControllerOnly)() {
|
|
35
35
|
constructor({ getUserOperations, messenger, }) {
|
|
36
36
|
super();
|
|
37
37
|
_PendingUserOperationTracker_instances.add(this);
|
|
@@ -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 { projectLogger } from '../logger.js';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types.js';\nimport { UserOperationStatus } from '../types.js';\nimport type { UserOperationControllerMessenger } from '../UserOperationController.js';\nimport { Bundler } from './Bundler.js';\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 { 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 { BlockTrackerPollingControllerOnly } from '../BlockTrackerPollingController.js';\nimport { projectLogger } from '../logger.js';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types.js';\nimport { UserOperationStatus } from '../types.js';\nimport type { UserOperationControllerMessenger } from '../UserOperationController.js';\nimport { Bundler } from './Bundler.js';\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"]}
|
|
@@ -19,7 +19,7 @@ type PendingUserOperationPollingInput = {
|
|
|
19
19
|
networkClientId: NetworkClientId;
|
|
20
20
|
};
|
|
21
21
|
declare const PendingUserOperationTracker_base: (abstract new (...args: any[]) => {
|
|
22
|
-
"__#
|
|
22
|
+
"__#18@#activeListeners": Record<string, (options: import("@metamask/utils").Json) => Promise<void>>;
|
|
23
23
|
_getNetworkClientById(networkClientId: string): NetworkClient | undefined;
|
|
24
24
|
_startPolling(input: PendingUserOperationPollingInput): void;
|
|
25
25
|
_stopPollingByPollingTokenSetId(key: string): void;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.d.cts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";;AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAKtC,OAAO,YAAY,eAAe;AAIlC,OAAO,KAAK,EAAE,qBAAqB,EAAwB,qBAAoB;AAE/E,OAAO,KAAK,EAAE,gCAAgC,EAAE,uCAAsC;AAKtF,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"}
|
|
@@ -19,7 +19,7 @@ type PendingUserOperationPollingInput = {
|
|
|
19
19
|
networkClientId: NetworkClientId;
|
|
20
20
|
};
|
|
21
21
|
declare const PendingUserOperationTracker_base: (abstract new (...args: any[]) => {
|
|
22
|
-
"__#
|
|
22
|
+
"__#18@#activeListeners": Record<string, (options: import("@metamask/utils").Json) => Promise<void>>;
|
|
23
23
|
_getNetworkClientById(networkClientId: string): NetworkClient | undefined;
|
|
24
24
|
_startPolling(input: PendingUserOperationPollingInput): void;
|
|
25
25
|
_stopPollingByPollingTokenSetId(key: string): void;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"PendingUserOperationTracker.d.mts","sourceRoot":"","sources":["../../src/helpers/PendingUserOperationTracker.ts"],"names":[],"mappings":";;AAEA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,qCAAqC;AAKtC,OAAO,YAAY,eAAe;AAIlC,OAAO,KAAK,EAAE,qBAAqB,EAAwB,qBAAoB;AAE/E,OAAO,KAAK,EAAE,gCAAgC,EAAE,uCAAsC;AAKtF,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"}
|
|
@@ -19,11 +19,11 @@ function $importDefault(module) {
|
|
|
19
19
|
import { query, toHex } from "@metamask/controller-utils";
|
|
20
20
|
import $EthQuery from "@metamask/eth-query";
|
|
21
21
|
const EthQuery = $importDefault($EthQuery);
|
|
22
|
-
import { BlockTrackerPollingControllerOnly } from "@metamask/polling-controller";
|
|
23
22
|
import { createModuleLogger } from "@metamask/utils";
|
|
24
23
|
// This package purposefully relies on Node's EventEmitter module.
|
|
25
24
|
// eslint-disable-next-line import-x/no-nodejs-modules
|
|
26
25
|
import EventEmitter from "events";
|
|
26
|
+
import { BlockTrackerPollingControllerOnly } from "../BlockTrackerPollingController.mjs";
|
|
27
27
|
import { projectLogger } from "../logger.mjs";
|
|
28
28
|
import { UserOperationStatus } from "../types.mjs";
|
|
29
29
|
import { Bundler } from "./Bundler.mjs";
|
|
@@ -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 { projectLogger } from '../logger.js';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types.js';\nimport { UserOperationStatus } from '../types.js';\nimport type { UserOperationControllerMessenger } from '../UserOperationController.js';\nimport { Bundler } from './Bundler.js';\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 { 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 { BlockTrackerPollingControllerOnly } from '../BlockTrackerPollingController.js';\nimport { projectLogger } from '../logger.js';\nimport type { UserOperationMetadata, UserOperationReceipt } from '../types.js';\nimport { UserOperationStatus } from '../types.js';\nimport type { UserOperationControllerMessenger } from '../UserOperationController.js';\nimport { Bundler } from './Bundler.js';\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