@metamask/multichain-api-middleware 0.1.0 → 0.2.0

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/handlers/types.cjs +12 -0
  3. package/dist/handlers/types.cjs.map +1 -0
  4. package/dist/handlers/types.d.cts +12 -0
  5. package/dist/handlers/types.d.cts.map +1 -0
  6. package/dist/handlers/types.d.mts +12 -0
  7. package/dist/handlers/types.d.mts.map +1 -0
  8. package/dist/handlers/types.mjs +9 -0
  9. package/dist/handlers/types.mjs.map +1 -0
  10. package/dist/handlers/wallet-createSession.cjs +150 -0
  11. package/dist/handlers/wallet-createSession.cjs.map +1 -0
  12. package/dist/handlers/wallet-createSession.d.cts +62 -0
  13. package/dist/handlers/wallet-createSession.d.cts.map +1 -0
  14. package/dist/handlers/wallet-createSession.d.mts +62 -0
  15. package/dist/handlers/wallet-createSession.d.mts.map +1 -0
  16. package/dist/handlers/wallet-createSession.mjs +147 -0
  17. package/dist/handlers/wallet-createSession.mjs.map +1 -0
  18. package/dist/index.cjs +5 -1
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +2 -0
  21. package/dist/index.d.cts.map +1 -1
  22. package/dist/index.d.mts +2 -0
  23. package/dist/index.d.mts.map +1 -1
  24. package/dist/index.mjs +2 -0
  25. package/dist/index.mjs.map +1 -1
  26. package/dist/middlewares/MultichainSubscriptionManager.cjs +2 -1
  27. package/dist/middlewares/MultichainSubscriptionManager.cjs.map +1 -1
  28. package/dist/middlewares/MultichainSubscriptionManager.d.cts.map +1 -1
  29. package/dist/middlewares/MultichainSubscriptionManager.d.mts.map +1 -1
  30. package/dist/middlewares/MultichainSubscriptionManager.mjs +2 -1
  31. package/dist/middlewares/MultichainSubscriptionManager.mjs.map +1 -1
  32. package/package.json +5 -3
package/CHANGELOG.md CHANGED
@@ -7,11 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0]
11
+
12
+ ### Added
13
+
14
+ - Add `wallet_createSession` handler ([#5647](https://github.com/MetaMask/core/pull/5647))
15
+ - Add `Caip25Errors` from `@metamask/chain-agnostic-permission` package ([#5566](https://github.com/MetaMask/core/pull/5566))
16
+
17
+ ### Changed
18
+
19
+ - Bump `@metamask/chain-agnostic-permission` to `^0.4.0` ([#5674](https://github.com/MetaMask/core/pull/5674))
20
+ - Bump `@metamask/network-controller` to `^23.2.0` ([#5583](https://github.com/MetaMask/core/pull/5583))
21
+
22
+ ## [0.1.1]
23
+
24
+ ### Added
25
+
26
+ - Add `MultichainApiNotifications` enum to standardize notification method names ([#5491](https://github.com/MetaMask/core/pull/5491))
27
+
28
+ ### Changed
29
+
30
+ - Bump `@metamask/network-controller` to `^23.1.0` ([#5507](https://github.com/MetaMask/core/pull/5507), [#5518](https://github.com/MetaMask/core/pull/5518))
31
+ - Bump `@metamask/chain-agnostic-permission` to `^0.2.0` ([#5518](https://github.com/MetaMask/core/pull/5518))
32
+
10
33
  ## [0.1.0]
11
34
 
12
35
  ### Added
13
36
 
14
37
  - Initial release
15
38
 
16
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-api-middleware@0.1.0...HEAD
39
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/multichain-api-middleware@0.2.0...HEAD
40
+ [0.2.0]: https://github.com/MetaMask/core/compare/@metamask/multichain-api-middleware@0.1.1...@metamask/multichain-api-middleware@0.2.0
41
+ [0.1.1]: https://github.com/MetaMask/core/compare/@metamask/multichain-api-middleware@0.1.0...@metamask/multichain-api-middleware@0.1.1
17
42
  [0.1.0]: https://github.com/MetaMask/core/releases/tag/@metamask/multichain-api-middleware@0.1.0
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MultichainApiNotifications = void 0;
4
+ /**
5
+ * Multichain API notifications currently supported by/known to the wallet.
6
+ */
7
+ var MultichainApiNotifications;
8
+ (function (MultichainApiNotifications) {
9
+ MultichainApiNotifications["sessionChanged"] = "wallet_sessionChanged";
10
+ MultichainApiNotifications["walletNotify"] = "wallet_notify";
11
+ })(MultichainApiNotifications || (exports.MultichainApiNotifications = MultichainApiNotifications = {}));
12
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.cjs","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":";;;AAMA;;GAEG;AACH,IAAY,0BAGX;AAHD,WAAY,0BAA0B;IACpC,sEAAwC,CAAA;IACxC,4DAA8B,CAAA;AAChC,CAAC,EAHW,0BAA0B,0CAA1B,0BAA0B,QAGrC","sourcesContent":["import type {\n CaveatSpecificationConstraint,\n PermissionController,\n PermissionSpecificationConstraint,\n} from '@metamask/permission-controller';\n\n/**\n * Multichain API notifications currently supported by/known to the wallet.\n */\nexport enum MultichainApiNotifications {\n sessionChanged = 'wallet_sessionChanged',\n walletNotify = 'wallet_notify',\n}\ntype AbstractPermissionController = PermissionController<\n PermissionSpecificationConstraint,\n CaveatSpecificationConstraint\n>;\n\nexport type GrantedPermissions = Awaited<\n ReturnType<AbstractPermissionController['requestPermissions']>\n>[0];\n"]}
@@ -0,0 +1,12 @@
1
+ import type { CaveatSpecificationConstraint, PermissionController, PermissionSpecificationConstraint } from "@metamask/permission-controller";
2
+ /**
3
+ * Multichain API notifications currently supported by/known to the wallet.
4
+ */
5
+ export declare enum MultichainApiNotifications {
6
+ sessionChanged = "wallet_sessionChanged",
7
+ walletNotify = "wallet_notify"
8
+ }
9
+ type AbstractPermissionController = PermissionController<PermissionSpecificationConstraint, CaveatSpecificationConstraint>;
10
+ export type GrantedPermissions = Awaited<ReturnType<AbstractPermissionController['requestPermissions']>>[0];
11
+ export {};
12
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,6BAA6B,EAC7B,oBAAoB,EACpB,iCAAiC,EAClC,wCAAwC;AAEzC;;GAEG;AACH,oBAAY,0BAA0B;IACpC,cAAc,0BAA0B;IACxC,YAAY,kBAAkB;CAC/B;AACD,KAAK,4BAA4B,GAAG,oBAAoB,CACtD,iCAAiC,EACjC,6BAA6B,CAC9B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,UAAU,CAAC,4BAA4B,CAAC,oBAAoB,CAAC,CAAC,CAC/D,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CaveatSpecificationConstraint, PermissionController, PermissionSpecificationConstraint } from "@metamask/permission-controller";
2
+ /**
3
+ * Multichain API notifications currently supported by/known to the wallet.
4
+ */
5
+ export declare enum MultichainApiNotifications {
6
+ sessionChanged = "wallet_sessionChanged",
7
+ walletNotify = "wallet_notify"
8
+ }
9
+ type AbstractPermissionController = PermissionController<PermissionSpecificationConstraint, CaveatSpecificationConstraint>;
10
+ export type GrantedPermissions = Awaited<ReturnType<AbstractPermissionController['requestPermissions']>>[0];
11
+ export {};
12
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,6BAA6B,EAC7B,oBAAoB,EACpB,iCAAiC,EAClC,wCAAwC;AAEzC;;GAEG;AACH,oBAAY,0BAA0B;IACpC,cAAc,0BAA0B;IACxC,YAAY,kBAAkB;CAC/B;AACD,KAAK,4BAA4B,GAAG,oBAAoB,CACtD,iCAAiC,EACjC,6BAA6B,CAC9B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,UAAU,CAAC,4BAA4B,CAAC,oBAAoB,CAAC,CAAC,CAC/D,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Multichain API notifications currently supported by/known to the wallet.
3
+ */
4
+ export var MultichainApiNotifications;
5
+ (function (MultichainApiNotifications) {
6
+ MultichainApiNotifications["sessionChanged"] = "wallet_sessionChanged";
7
+ MultichainApiNotifications["walletNotify"] = "wallet_notify";
8
+ })(MultichainApiNotifications || (MultichainApiNotifications = {}));
9
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.mjs","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,CAAN,IAAY,0BAGX;AAHD,WAAY,0BAA0B;IACpC,sEAAwC,CAAA;IACxC,4DAA8B,CAAA;AAChC,CAAC,EAHW,0BAA0B,KAA1B,0BAA0B,QAGrC","sourcesContent":["import type {\n CaveatSpecificationConstraint,\n PermissionController,\n PermissionSpecificationConstraint,\n} from '@metamask/permission-controller';\n\n/**\n * Multichain API notifications currently supported by/known to the wallet.\n */\nexport enum MultichainApiNotifications {\n sessionChanged = 'wallet_sessionChanged',\n walletNotify = 'wallet_notify',\n}\ntype AbstractPermissionController = PermissionController<\n PermissionSpecificationConstraint,\n CaveatSpecificationConstraint\n>;\n\nexport type GrantedPermissions = Awaited<\n ReturnType<AbstractPermissionController['requestPermissions']>\n>[0];\n"]}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.walletCreateSession = void 0;
4
+ const chain_agnostic_permission_1 = require("@metamask/chain-agnostic-permission");
5
+ const controller_utils_1 = require("@metamask/controller-utils");
6
+ const permission_controller_1 = require("@metamask/permission-controller");
7
+ const rpc_errors_1 = require("@metamask/rpc-errors");
8
+ const utils_1 = require("@metamask/utils");
9
+ /**
10
+ * Handler for the `wallet_createSession` RPC method which is responsible
11
+ * for prompting for approval and granting a CAIP-25 permission.
12
+ *
13
+ * This implementation primarily deviates from the CAIP-25 handler
14
+ * specification by treating all scopes as optional regardless of
15
+ * if they were specified in `requiredScopes` or `optionalScopes`.
16
+ * Additionally, provided scopes, methods, notifications, and
17
+ * account values that are invalid/malformed are ignored rather than
18
+ * causing an error to be returned.
19
+ *
20
+ * @param req - The request object.
21
+ * @param res - The response object.
22
+ * @param _next - The next middleware function.
23
+ * @param end - The end function.
24
+ * @param hooks - The hooks object.
25
+ * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.
26
+ * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.
27
+ * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.
28
+ * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.
29
+ * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.
30
+ * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.
31
+ * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.
32
+ * @returns A promise with wallet_createSession handler
33
+ */
34
+ async function walletCreateSessionHandler(req, res, _next, end, hooks) {
35
+ if (!(0, utils_1.isPlainObject)(req.params)) {
36
+ return end((0, permission_controller_1.invalidParams)({ data: { request: req } }));
37
+ }
38
+ const { requiredScopes, optionalScopes, sessionProperties } = req.params;
39
+ if (sessionProperties && Object.keys(sessionProperties).length === 0) {
40
+ return end(new rpc_errors_1.JsonRpcError(5302, 'Invalid sessionProperties requested'));
41
+ }
42
+ const filteredSessionProperties = Object.fromEntries(Object.entries(sessionProperties ?? {}).filter(([key]) => (0, chain_agnostic_permission_1.isKnownSessionPropertyValue)(key)));
43
+ try {
44
+ const { normalizedRequiredScopes, normalizedOptionalScopes } = (0, chain_agnostic_permission_1.validateAndNormalizeScopes)(requiredScopes || {}, optionalScopes || {});
45
+ const requiredScopesWithSupportedMethodsAndNotifications = (0, chain_agnostic_permission_1.getSupportedScopeObjects)(normalizedRequiredScopes, {
46
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
47
+ });
48
+ const optionalScopesWithSupportedMethodsAndNotifications = (0, chain_agnostic_permission_1.getSupportedScopeObjects)(normalizedOptionalScopes, {
49
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
50
+ });
51
+ const networkClientExistsForChainId = (chainId) => {
52
+ try {
53
+ hooks.findNetworkClientIdByChainId(chainId);
54
+ return true;
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ };
60
+ const { supportedScopes: supportedRequiredScopes } = (0, chain_agnostic_permission_1.bucketScopes)(requiredScopesWithSupportedMethodsAndNotifications, {
61
+ isEvmChainIdSupported: networkClientExistsForChainId,
62
+ isEvmChainIdSupportable: () => false,
63
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
64
+ isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,
65
+ });
66
+ const { supportedScopes: supportedOptionalScopes } = (0, chain_agnostic_permission_1.bucketScopes)(optionalScopesWithSupportedMethodsAndNotifications, {
67
+ isEvmChainIdSupported: networkClientExistsForChainId,
68
+ isEvmChainIdSupportable: () => false,
69
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
70
+ isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,
71
+ });
72
+ const allRequestedAccountAddresses = (0, chain_agnostic_permission_1.getCaipAccountIdsFromScopesObjects)([
73
+ supportedRequiredScopes,
74
+ supportedOptionalScopes,
75
+ ]);
76
+ const allSupportedRequestedCaipChainIds = (0, chain_agnostic_permission_1.getAllScopesFromScopesObjects)([
77
+ supportedRequiredScopes,
78
+ supportedOptionalScopes,
79
+ ]);
80
+ if (allSupportedRequestedCaipChainIds.length === 0) {
81
+ return end(new rpc_errors_1.JsonRpcError(5100, 'Requested scopes are not supported'));
82
+ }
83
+ const existingEvmAddresses = hooks
84
+ .listAccounts()
85
+ .map((account) => account.address);
86
+ const supportedRequestedAccountAddresses = allRequestedAccountAddresses.filter((requestedAccountAddress) => {
87
+ const { address, chain: { namespace }, chainId: caipChainId, } = (0, utils_1.parseCaipAccountId)(requestedAccountAddress);
88
+ if (namespace === utils_1.KnownCaipNamespace.Eip155.toString()) {
89
+ return existingEvmAddresses.some((existingEvmAddress) => {
90
+ return (0, controller_utils_1.isEqualCaseInsensitive)(address, existingEvmAddress);
91
+ });
92
+ }
93
+ // If the namespace is not eip155 (EVM) we do a case sensitive check
94
+ return hooks
95
+ .getNonEvmAccountAddresses(caipChainId)
96
+ .some((existingCaipAddress) => {
97
+ return requestedAccountAddress === existingCaipAddress;
98
+ });
99
+ });
100
+ const requestedCaip25CaveatValue = {
101
+ requiredScopes: (0, chain_agnostic_permission_1.getInternalScopesObject)(supportedRequiredScopes),
102
+ optionalScopes: (0, chain_agnostic_permission_1.getInternalScopesObject)(supportedOptionalScopes),
103
+ isMultichainOrigin: true,
104
+ sessionProperties: filteredSessionProperties,
105
+ };
106
+ const requestedCaip25CaveatValueWithSupportedAccounts = (0, chain_agnostic_permission_1.setPermittedAccounts)(requestedCaip25CaveatValue, supportedRequestedAccountAddresses);
107
+ const [grantedPermissions] = await hooks.requestPermissionsForOrigin({
108
+ [chain_agnostic_permission_1.Caip25EndowmentPermissionName]: {
109
+ caveats: [
110
+ {
111
+ type: chain_agnostic_permission_1.Caip25CaveatType,
112
+ value: requestedCaip25CaveatValueWithSupportedAccounts,
113
+ },
114
+ ],
115
+ },
116
+ });
117
+ const approvedCaip25Permission = grantedPermissions[chain_agnostic_permission_1.Caip25EndowmentPermissionName];
118
+ const approvedCaip25CaveatValue = approvedCaip25Permission?.caveats?.find((caveat) => caveat.type === chain_agnostic_permission_1.Caip25CaveatType)?.value;
119
+ if (!approvedCaip25CaveatValue) {
120
+ throw rpc_errors_1.rpcErrors.internal();
121
+ }
122
+ const sessionScopes = (0, chain_agnostic_permission_1.getSessionScopes)(approvedCaip25CaveatValue, {
123
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
124
+ });
125
+ const { sessionProperties: approvedSessionProperties = {} } = approvedCaip25CaveatValue;
126
+ hooks.trackSessionCreatedEvent?.(approvedCaip25CaveatValue);
127
+ res.result = {
128
+ sessionScopes,
129
+ sessionProperties: approvedSessionProperties,
130
+ };
131
+ return end();
132
+ }
133
+ catch (err) {
134
+ return end(err);
135
+ }
136
+ }
137
+ exports.walletCreateSession = {
138
+ methodNames: ['wallet_createSession'],
139
+ implementation: walletCreateSessionHandler,
140
+ hookNames: {
141
+ findNetworkClientIdByChainId: true,
142
+ listAccounts: true,
143
+ requestPermissionsForOrigin: true,
144
+ getNonEvmSupportedMethods: true,
145
+ isNonEvmScopeSupported: true,
146
+ getNonEvmAccountAddresses: true,
147
+ trackSessionCreatedEvent: true,
148
+ },
149
+ };
150
+ //# sourceMappingURL=wallet-createSession.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-createSession.cjs","sourceRoot":"","sources":["../../src/handlers/wallet-createSession.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Caip25CaveatType,\n Caip25EndowmentPermissionName,\n bucketScopes,\n validateAndNormalizeScopes,\n type Caip25Authorization,\n getInternalScopesObject,\n getSessionScopes,\n type NormalizedScopesObject,\n getSupportedScopeObjects,\n type Caip25CaveatValue,\n isKnownSessionPropertyValue,\n getCaipAccountIdsFromScopesObjects,\n getAllScopesFromScopesObjects,\n setPermittedAccounts,\n} from '@metamask/chain-agnostic-permission';\nimport { isEqualCaseInsensitive } from '@metamask/controller-utils';\nimport type {\n JsonRpcEngineEndCallback,\n JsonRpcEngineNextCallback,\n} from '@metamask/json-rpc-engine';\nimport type { NetworkController } from '@metamask/network-controller';\nimport {\n invalidParams,\n type RequestedPermissions,\n} from '@metamask/permission-controller';\nimport { JsonRpcError, rpcErrors } from '@metamask/rpc-errors';\nimport {\n type CaipAccountId,\n type CaipChainId,\n type Hex,\n isPlainObject,\n type Json,\n type JsonRpcRequest,\n type JsonRpcSuccess,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\n\nimport type { GrantedPermissions } from './types';\n\n/**\n * Handler for the `wallet_createSession` RPC method which is responsible\n * for prompting for approval and granting a CAIP-25 permission.\n *\n * This implementation primarily deviates from the CAIP-25 handler\n * specification by treating all scopes as optional regardless of\n * if they were specified in `requiredScopes` or `optionalScopes`.\n * Additionally, provided scopes, methods, notifications, and\n * account values that are invalid/malformed are ignored rather than\n * causing an error to be returned.\n *\n * @param req - The request object.\n * @param res - The response object.\n * @param _next - The next middleware function.\n * @param end - The end function.\n * @param hooks - The hooks object.\n * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.\n * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.\n * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.\n * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.\n * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.\n * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.\n * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.\n * @returns A promise with wallet_createSession handler\n */\nasync function walletCreateSessionHandler(\n req: JsonRpcRequest<Caip25Authorization> & { origin: string },\n res: JsonRpcSuccess<{\n sessionScopes: NormalizedScopesObject;\n sessionProperties?: Record<string, Json>;\n }>,\n _next: JsonRpcEngineNextCallback,\n end: JsonRpcEngineEndCallback,\n hooks: {\n listAccounts: () => { address: string }[];\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n requestPermissionsForOrigin: (\n requestedPermissions: RequestedPermissions,\n metadata?: Record<string, Json>,\n ) => Promise<[GrantedPermissions]>;\n getNonEvmSupportedMethods: (scope: CaipChainId) => string[];\n isNonEvmScopeSupported: (scope: CaipChainId) => boolean;\n getNonEvmAccountAddresses: (scope: CaipChainId) => CaipAccountId[];\n trackSessionCreatedEvent?: (\n approvedCaip25CaveatValue: Caip25CaveatValue,\n ) => void;\n },\n) {\n if (!isPlainObject(req.params)) {\n return end(invalidParams({ data: { request: req } }));\n }\n const { requiredScopes, optionalScopes, sessionProperties } = req.params;\n\n if (sessionProperties && Object.keys(sessionProperties).length === 0) {\n return end(new JsonRpcError(5302, 'Invalid sessionProperties requested'));\n }\n\n const filteredSessionProperties = Object.fromEntries(\n Object.entries(sessionProperties ?? {}).filter(([key]) =>\n isKnownSessionPropertyValue(key),\n ),\n );\n\n try {\n const { normalizedRequiredScopes, normalizedOptionalScopes } =\n validateAndNormalizeScopes(requiredScopes || {}, optionalScopes || {});\n\n const requiredScopesWithSupportedMethodsAndNotifications =\n getSupportedScopeObjects(normalizedRequiredScopes, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n const optionalScopesWithSupportedMethodsAndNotifications =\n getSupportedScopeObjects(normalizedOptionalScopes, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n\n const networkClientExistsForChainId = (chainId: Hex) => {\n try {\n hooks.findNetworkClientIdByChainId(chainId);\n return true;\n } catch {\n return false;\n }\n };\n\n const { supportedScopes: supportedRequiredScopes } = bucketScopes(\n requiredScopesWithSupportedMethodsAndNotifications,\n {\n isEvmChainIdSupported: networkClientExistsForChainId,\n isEvmChainIdSupportable: () => false, // intended for future usage with eip3085 scopedProperties\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,\n },\n );\n\n const { supportedScopes: supportedOptionalScopes } = bucketScopes(\n optionalScopesWithSupportedMethodsAndNotifications,\n {\n isEvmChainIdSupported: networkClientExistsForChainId,\n isEvmChainIdSupportable: () => false, // intended for future usage with eip3085 scopedProperties\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,\n },\n );\n\n const allRequestedAccountAddresses = getCaipAccountIdsFromScopesObjects([\n supportedRequiredScopes,\n supportedOptionalScopes,\n ]);\n\n const allSupportedRequestedCaipChainIds = getAllScopesFromScopesObjects([\n supportedRequiredScopes,\n supportedOptionalScopes,\n ]);\n\n if (allSupportedRequestedCaipChainIds.length === 0) {\n return end(new JsonRpcError(5100, 'Requested scopes are not supported'));\n }\n\n const existingEvmAddresses = hooks\n .listAccounts()\n .map((account) => account.address);\n\n const supportedRequestedAccountAddresses =\n allRequestedAccountAddresses.filter(\n (requestedAccountAddress: CaipAccountId) => {\n const {\n address,\n chain: { namespace },\n chainId: caipChainId,\n } = parseCaipAccountId(requestedAccountAddress);\n if (namespace === KnownCaipNamespace.Eip155.toString()) {\n return existingEvmAddresses.some((existingEvmAddress) => {\n return isEqualCaseInsensitive(address, existingEvmAddress);\n });\n }\n\n // If the namespace is not eip155 (EVM) we do a case sensitive check\n return hooks\n .getNonEvmAccountAddresses(caipChainId)\n .some((existingCaipAddress) => {\n return requestedAccountAddress === existingCaipAddress;\n });\n },\n );\n\n const requestedCaip25CaveatValue = {\n requiredScopes: getInternalScopesObject(supportedRequiredScopes),\n optionalScopes: getInternalScopesObject(supportedOptionalScopes),\n isMultichainOrigin: true,\n sessionProperties: filteredSessionProperties,\n };\n\n const requestedCaip25CaveatValueWithSupportedAccounts =\n setPermittedAccounts(\n requestedCaip25CaveatValue,\n supportedRequestedAccountAddresses,\n );\n\n const [grantedPermissions] = await hooks.requestPermissionsForOrigin({\n [Caip25EndowmentPermissionName]: {\n caveats: [\n {\n type: Caip25CaveatType,\n value: requestedCaip25CaveatValueWithSupportedAccounts,\n },\n ],\n },\n });\n\n const approvedCaip25Permission =\n grantedPermissions[Caip25EndowmentPermissionName];\n const approvedCaip25CaveatValue = approvedCaip25Permission?.caveats?.find(\n (caveat) => caveat.type === Caip25CaveatType,\n )?.value as Caip25CaveatValue;\n if (!approvedCaip25CaveatValue) {\n throw rpcErrors.internal();\n }\n\n const sessionScopes = getSessionScopes(approvedCaip25CaveatValue, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n\n const { sessionProperties: approvedSessionProperties = {} } =\n approvedCaip25CaveatValue;\n\n hooks.trackSessionCreatedEvent?.(approvedCaip25CaveatValue);\n\n res.result = {\n sessionScopes,\n sessionProperties: approvedSessionProperties,\n };\n return end();\n } catch (err) {\n return end(err);\n }\n}\n\nexport const walletCreateSession = {\n methodNames: ['wallet_createSession'],\n implementation: walletCreateSessionHandler,\n hookNames: {\n findNetworkClientIdByChainId: true,\n listAccounts: true,\n requestPermissionsForOrigin: true,\n getNonEvmSupportedMethods: true,\n isNonEvmScopeSupported: true,\n getNonEvmAccountAddresses: true,\n trackSessionCreatedEvent: true,\n },\n};\n"]}
@@ -0,0 +1,62 @@
1
+ import { type Caip25Authorization, type NormalizedScopesObject, type Caip25CaveatValue } from "@metamask/chain-agnostic-permission";
2
+ import type { JsonRpcEngineEndCallback, JsonRpcEngineNextCallback } from "@metamask/json-rpc-engine";
3
+ import type { NetworkController } from "@metamask/network-controller";
4
+ import { type RequestedPermissions } from "@metamask/permission-controller";
5
+ import { type CaipAccountId, type CaipChainId, type Json, type JsonRpcRequest, type JsonRpcSuccess } from "@metamask/utils";
6
+ import type { GrantedPermissions } from "./types.cjs";
7
+ /**
8
+ * Handler for the `wallet_createSession` RPC method which is responsible
9
+ * for prompting for approval and granting a CAIP-25 permission.
10
+ *
11
+ * This implementation primarily deviates from the CAIP-25 handler
12
+ * specification by treating all scopes as optional regardless of
13
+ * if they were specified in `requiredScopes` or `optionalScopes`.
14
+ * Additionally, provided scopes, methods, notifications, and
15
+ * account values that are invalid/malformed are ignored rather than
16
+ * causing an error to be returned.
17
+ *
18
+ * @param req - The request object.
19
+ * @param res - The response object.
20
+ * @param _next - The next middleware function.
21
+ * @param end - The end function.
22
+ * @param hooks - The hooks object.
23
+ * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.
24
+ * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.
25
+ * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.
26
+ * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.
27
+ * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.
28
+ * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.
29
+ * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.
30
+ * @returns A promise with wallet_createSession handler
31
+ */
32
+ declare function walletCreateSessionHandler(req: JsonRpcRequest<Caip25Authorization> & {
33
+ origin: string;
34
+ }, res: JsonRpcSuccess<{
35
+ sessionScopes: NormalizedScopesObject;
36
+ sessionProperties?: Record<string, Json>;
37
+ }>, _next: JsonRpcEngineNextCallback, end: JsonRpcEngineEndCallback, hooks: {
38
+ listAccounts: () => {
39
+ address: string;
40
+ }[];
41
+ findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];
42
+ requestPermissionsForOrigin: (requestedPermissions: RequestedPermissions, metadata?: Record<string, Json>) => Promise<[GrantedPermissions]>;
43
+ getNonEvmSupportedMethods: (scope: CaipChainId) => string[];
44
+ isNonEvmScopeSupported: (scope: CaipChainId) => boolean;
45
+ getNonEvmAccountAddresses: (scope: CaipChainId) => CaipAccountId[];
46
+ trackSessionCreatedEvent?: (approvedCaip25CaveatValue: Caip25CaveatValue) => void;
47
+ }): Promise<void>;
48
+ export declare const walletCreateSession: {
49
+ methodNames: string[];
50
+ implementation: typeof walletCreateSessionHandler;
51
+ hookNames: {
52
+ findNetworkClientIdByChainId: boolean;
53
+ listAccounts: boolean;
54
+ requestPermissionsForOrigin: boolean;
55
+ getNonEvmSupportedMethods: boolean;
56
+ isNonEvmScopeSupported: boolean;
57
+ getNonEvmAccountAddresses: boolean;
58
+ trackSessionCreatedEvent: boolean;
59
+ };
60
+ };
61
+ export {};
62
+ //# sourceMappingURL=wallet-createSession.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-createSession.d.cts","sourceRoot":"","sources":["../../src/handlers/wallet-createSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,mBAAmB,EAGxB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EAKvB,4CAA4C;AAE7C,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAC1B,kCAAkC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,wCAAwC;AAEzC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAGhB,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,cAAc,EAGpB,wBAAwB;AAEzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAgB;AAElD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,iBAAe,0BAA0B,CACvC,GAAG,EAAE,cAAc,CAAC,mBAAmB,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7D,GAAG,EAAE,cAAc,CAAC;IAClB,aAAa,EAAE,sBAAsB,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC1C,CAAC,EACF,KAAK,EAAE,yBAAyB,EAChC,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE;IACL,YAAY,EAAE,MAAM;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,2BAA2B,EAAE,CAC3B,oBAAoB,EAAE,oBAAoB,EAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAC5B,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACnC,yBAAyB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE,CAAC;IAC5D,sBAAsB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;IACxD,yBAAyB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,aAAa,EAAE,CAAC;IACnE,wBAAwB,CAAC,EAAE,CACzB,yBAAyB,EAAE,iBAAiB,KACzC,IAAI,CAAC;CACX,iBAsJF;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAY/B,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { type Caip25Authorization, type NormalizedScopesObject, type Caip25CaveatValue } from "@metamask/chain-agnostic-permission";
2
+ import type { JsonRpcEngineEndCallback, JsonRpcEngineNextCallback } from "@metamask/json-rpc-engine";
3
+ import type { NetworkController } from "@metamask/network-controller";
4
+ import { type RequestedPermissions } from "@metamask/permission-controller";
5
+ import { type CaipAccountId, type CaipChainId, type Json, type JsonRpcRequest, type JsonRpcSuccess } from "@metamask/utils";
6
+ import type { GrantedPermissions } from "./types.mjs";
7
+ /**
8
+ * Handler for the `wallet_createSession` RPC method which is responsible
9
+ * for prompting for approval and granting a CAIP-25 permission.
10
+ *
11
+ * This implementation primarily deviates from the CAIP-25 handler
12
+ * specification by treating all scopes as optional regardless of
13
+ * if they were specified in `requiredScopes` or `optionalScopes`.
14
+ * Additionally, provided scopes, methods, notifications, and
15
+ * account values that are invalid/malformed are ignored rather than
16
+ * causing an error to be returned.
17
+ *
18
+ * @param req - The request object.
19
+ * @param res - The response object.
20
+ * @param _next - The next middleware function.
21
+ * @param end - The end function.
22
+ * @param hooks - The hooks object.
23
+ * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.
24
+ * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.
25
+ * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.
26
+ * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.
27
+ * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.
28
+ * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.
29
+ * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.
30
+ * @returns A promise with wallet_createSession handler
31
+ */
32
+ declare function walletCreateSessionHandler(req: JsonRpcRequest<Caip25Authorization> & {
33
+ origin: string;
34
+ }, res: JsonRpcSuccess<{
35
+ sessionScopes: NormalizedScopesObject;
36
+ sessionProperties?: Record<string, Json>;
37
+ }>, _next: JsonRpcEngineNextCallback, end: JsonRpcEngineEndCallback, hooks: {
38
+ listAccounts: () => {
39
+ address: string;
40
+ }[];
41
+ findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];
42
+ requestPermissionsForOrigin: (requestedPermissions: RequestedPermissions, metadata?: Record<string, Json>) => Promise<[GrantedPermissions]>;
43
+ getNonEvmSupportedMethods: (scope: CaipChainId) => string[];
44
+ isNonEvmScopeSupported: (scope: CaipChainId) => boolean;
45
+ getNonEvmAccountAddresses: (scope: CaipChainId) => CaipAccountId[];
46
+ trackSessionCreatedEvent?: (approvedCaip25CaveatValue: Caip25CaveatValue) => void;
47
+ }): Promise<void>;
48
+ export declare const walletCreateSession: {
49
+ methodNames: string[];
50
+ implementation: typeof walletCreateSessionHandler;
51
+ hookNames: {
52
+ findNetworkClientIdByChainId: boolean;
53
+ listAccounts: boolean;
54
+ requestPermissionsForOrigin: boolean;
55
+ getNonEvmSupportedMethods: boolean;
56
+ isNonEvmScopeSupported: boolean;
57
+ getNonEvmAccountAddresses: boolean;
58
+ trackSessionCreatedEvent: boolean;
59
+ };
60
+ };
61
+ export {};
62
+ //# sourceMappingURL=wallet-createSession.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-createSession.d.mts","sourceRoot":"","sources":["../../src/handlers/wallet-createSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,mBAAmB,EAGxB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EAKvB,4CAA4C;AAE7C,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAC1B,kCAAkC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,wCAAwC;AAEzC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAGhB,KAAK,IAAI,EACT,KAAK,cAAc,EACnB,KAAK,cAAc,EAGpB,wBAAwB;AAEzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAgB;AAElD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,iBAAe,0BAA0B,CACvC,GAAG,EAAE,cAAc,CAAC,mBAAmB,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7D,GAAG,EAAE,cAAc,CAAC;IAClB,aAAa,EAAE,sBAAsB,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC1C,CAAC,EACF,KAAK,EAAE,yBAAyB,EAChC,GAAG,EAAE,wBAAwB,EAC7B,KAAK,EAAE;IACL,YAAY,EAAE,MAAM;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,2BAA2B,EAAE,CAC3B,oBAAoB,EAAE,oBAAoB,EAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAC5B,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACnC,yBAAyB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE,CAAC;IAC5D,sBAAsB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;IACxD,yBAAyB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,aAAa,EAAE,CAAC;IACnE,wBAAwB,CAAC,EAAE,CACzB,yBAAyB,EAAE,iBAAiB,KACzC,IAAI,CAAC;CACX,iBAsJF;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;CAY/B,CAAC"}
@@ -0,0 +1,147 @@
1
+ import { Caip25CaveatType, Caip25EndowmentPermissionName, bucketScopes, validateAndNormalizeScopes, getInternalScopesObject, getSessionScopes, getSupportedScopeObjects, isKnownSessionPropertyValue, getCaipAccountIdsFromScopesObjects, getAllScopesFromScopesObjects, setPermittedAccounts } from "@metamask/chain-agnostic-permission";
2
+ import { isEqualCaseInsensitive } from "@metamask/controller-utils";
3
+ import { invalidParams } from "@metamask/permission-controller";
4
+ import { JsonRpcError, rpcErrors } from "@metamask/rpc-errors";
5
+ import { isPlainObject, KnownCaipNamespace, parseCaipAccountId } from "@metamask/utils";
6
+ /**
7
+ * Handler for the `wallet_createSession` RPC method which is responsible
8
+ * for prompting for approval and granting a CAIP-25 permission.
9
+ *
10
+ * This implementation primarily deviates from the CAIP-25 handler
11
+ * specification by treating all scopes as optional regardless of
12
+ * if they were specified in `requiredScopes` or `optionalScopes`.
13
+ * Additionally, provided scopes, methods, notifications, and
14
+ * account values that are invalid/malformed are ignored rather than
15
+ * causing an error to be returned.
16
+ *
17
+ * @param req - The request object.
18
+ * @param res - The response object.
19
+ * @param _next - The next middleware function.
20
+ * @param end - The end function.
21
+ * @param hooks - The hooks object.
22
+ * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.
23
+ * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.
24
+ * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.
25
+ * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.
26
+ * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.
27
+ * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.
28
+ * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.
29
+ * @returns A promise with wallet_createSession handler
30
+ */
31
+ async function walletCreateSessionHandler(req, res, _next, end, hooks) {
32
+ if (!isPlainObject(req.params)) {
33
+ return end(invalidParams({ data: { request: req } }));
34
+ }
35
+ const { requiredScopes, optionalScopes, sessionProperties } = req.params;
36
+ if (sessionProperties && Object.keys(sessionProperties).length === 0) {
37
+ return end(new JsonRpcError(5302, 'Invalid sessionProperties requested'));
38
+ }
39
+ const filteredSessionProperties = Object.fromEntries(Object.entries(sessionProperties ?? {}).filter(([key]) => isKnownSessionPropertyValue(key)));
40
+ try {
41
+ const { normalizedRequiredScopes, normalizedOptionalScopes } = validateAndNormalizeScopes(requiredScopes || {}, optionalScopes || {});
42
+ const requiredScopesWithSupportedMethodsAndNotifications = getSupportedScopeObjects(normalizedRequiredScopes, {
43
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
44
+ });
45
+ const optionalScopesWithSupportedMethodsAndNotifications = getSupportedScopeObjects(normalizedOptionalScopes, {
46
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
47
+ });
48
+ const networkClientExistsForChainId = (chainId) => {
49
+ try {
50
+ hooks.findNetworkClientIdByChainId(chainId);
51
+ return true;
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ };
57
+ const { supportedScopes: supportedRequiredScopes } = bucketScopes(requiredScopesWithSupportedMethodsAndNotifications, {
58
+ isEvmChainIdSupported: networkClientExistsForChainId,
59
+ isEvmChainIdSupportable: () => false,
60
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
61
+ isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,
62
+ });
63
+ const { supportedScopes: supportedOptionalScopes } = bucketScopes(optionalScopesWithSupportedMethodsAndNotifications, {
64
+ isEvmChainIdSupported: networkClientExistsForChainId,
65
+ isEvmChainIdSupportable: () => false,
66
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
67
+ isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,
68
+ });
69
+ const allRequestedAccountAddresses = getCaipAccountIdsFromScopesObjects([
70
+ supportedRequiredScopes,
71
+ supportedOptionalScopes,
72
+ ]);
73
+ const allSupportedRequestedCaipChainIds = getAllScopesFromScopesObjects([
74
+ supportedRequiredScopes,
75
+ supportedOptionalScopes,
76
+ ]);
77
+ if (allSupportedRequestedCaipChainIds.length === 0) {
78
+ return end(new JsonRpcError(5100, 'Requested scopes are not supported'));
79
+ }
80
+ const existingEvmAddresses = hooks
81
+ .listAccounts()
82
+ .map((account) => account.address);
83
+ const supportedRequestedAccountAddresses = allRequestedAccountAddresses.filter((requestedAccountAddress) => {
84
+ const { address, chain: { namespace }, chainId: caipChainId, } = parseCaipAccountId(requestedAccountAddress);
85
+ if (namespace === KnownCaipNamespace.Eip155.toString()) {
86
+ return existingEvmAddresses.some((existingEvmAddress) => {
87
+ return isEqualCaseInsensitive(address, existingEvmAddress);
88
+ });
89
+ }
90
+ // If the namespace is not eip155 (EVM) we do a case sensitive check
91
+ return hooks
92
+ .getNonEvmAccountAddresses(caipChainId)
93
+ .some((existingCaipAddress) => {
94
+ return requestedAccountAddress === existingCaipAddress;
95
+ });
96
+ });
97
+ const requestedCaip25CaveatValue = {
98
+ requiredScopes: getInternalScopesObject(supportedRequiredScopes),
99
+ optionalScopes: getInternalScopesObject(supportedOptionalScopes),
100
+ isMultichainOrigin: true,
101
+ sessionProperties: filteredSessionProperties,
102
+ };
103
+ const requestedCaip25CaveatValueWithSupportedAccounts = setPermittedAccounts(requestedCaip25CaveatValue, supportedRequestedAccountAddresses);
104
+ const [grantedPermissions] = await hooks.requestPermissionsForOrigin({
105
+ [Caip25EndowmentPermissionName]: {
106
+ caveats: [
107
+ {
108
+ type: Caip25CaveatType,
109
+ value: requestedCaip25CaveatValueWithSupportedAccounts,
110
+ },
111
+ ],
112
+ },
113
+ });
114
+ const approvedCaip25Permission = grantedPermissions[Caip25EndowmentPermissionName];
115
+ const approvedCaip25CaveatValue = approvedCaip25Permission?.caveats?.find((caveat) => caveat.type === Caip25CaveatType)?.value;
116
+ if (!approvedCaip25CaveatValue) {
117
+ throw rpcErrors.internal();
118
+ }
119
+ const sessionScopes = getSessionScopes(approvedCaip25CaveatValue, {
120
+ getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,
121
+ });
122
+ const { sessionProperties: approvedSessionProperties = {} } = approvedCaip25CaveatValue;
123
+ hooks.trackSessionCreatedEvent?.(approvedCaip25CaveatValue);
124
+ res.result = {
125
+ sessionScopes,
126
+ sessionProperties: approvedSessionProperties,
127
+ };
128
+ return end();
129
+ }
130
+ catch (err) {
131
+ return end(err);
132
+ }
133
+ }
134
+ export const walletCreateSession = {
135
+ methodNames: ['wallet_createSession'],
136
+ implementation: walletCreateSessionHandler,
137
+ hookNames: {
138
+ findNetworkClientIdByChainId: true,
139
+ listAccounts: true,
140
+ requestPermissionsForOrigin: true,
141
+ getNonEvmSupportedMethods: true,
142
+ isNonEvmScopeSupported: true,
143
+ getNonEvmAccountAddresses: true,
144
+ trackSessionCreatedEvent: true,
145
+ },
146
+ };
147
+ //# sourceMappingURL=wallet-createSession.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-createSession.mjs","sourceRoot":"","sources":["../../src/handlers/wallet-createSession.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Caip25CaveatType,\n Caip25EndowmentPermissionName,\n bucketScopes,\n validateAndNormalizeScopes,\n type Caip25Authorization,\n getInternalScopesObject,\n getSessionScopes,\n type NormalizedScopesObject,\n getSupportedScopeObjects,\n type Caip25CaveatValue,\n isKnownSessionPropertyValue,\n getCaipAccountIdsFromScopesObjects,\n getAllScopesFromScopesObjects,\n setPermittedAccounts,\n} from '@metamask/chain-agnostic-permission';\nimport { isEqualCaseInsensitive } from '@metamask/controller-utils';\nimport type {\n JsonRpcEngineEndCallback,\n JsonRpcEngineNextCallback,\n} from '@metamask/json-rpc-engine';\nimport type { NetworkController } from '@metamask/network-controller';\nimport {\n invalidParams,\n type RequestedPermissions,\n} from '@metamask/permission-controller';\nimport { JsonRpcError, rpcErrors } from '@metamask/rpc-errors';\nimport {\n type CaipAccountId,\n type CaipChainId,\n type Hex,\n isPlainObject,\n type Json,\n type JsonRpcRequest,\n type JsonRpcSuccess,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\n\nimport type { GrantedPermissions } from './types';\n\n/**\n * Handler for the `wallet_createSession` RPC method which is responsible\n * for prompting for approval and granting a CAIP-25 permission.\n *\n * This implementation primarily deviates from the CAIP-25 handler\n * specification by treating all scopes as optional regardless of\n * if they were specified in `requiredScopes` or `optionalScopes`.\n * Additionally, provided scopes, methods, notifications, and\n * account values that are invalid/malformed are ignored rather than\n * causing an error to be returned.\n *\n * @param req - The request object.\n * @param res - The response object.\n * @param _next - The next middleware function.\n * @param end - The end function.\n * @param hooks - The hooks object.\n * @param hooks.listAccounts - The hook that returns an array of the wallet's evm accounts.\n * @param hooks.findNetworkClientIdByChainId - The hook that returns the networkClientId for a chainId.\n * @param hooks.requestPermissionsForOrigin - The hook that approves and grants requested permissions.\n * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.\n * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.\n * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.\n * @param hooks.trackSessionCreatedEvent - An optional hook for platform specific logic to run. Can be undefined.\n * @returns A promise with wallet_createSession handler\n */\nasync function walletCreateSessionHandler(\n req: JsonRpcRequest<Caip25Authorization> & { origin: string },\n res: JsonRpcSuccess<{\n sessionScopes: NormalizedScopesObject;\n sessionProperties?: Record<string, Json>;\n }>,\n _next: JsonRpcEngineNextCallback,\n end: JsonRpcEngineEndCallback,\n hooks: {\n listAccounts: () => { address: string }[];\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n requestPermissionsForOrigin: (\n requestedPermissions: RequestedPermissions,\n metadata?: Record<string, Json>,\n ) => Promise<[GrantedPermissions]>;\n getNonEvmSupportedMethods: (scope: CaipChainId) => string[];\n isNonEvmScopeSupported: (scope: CaipChainId) => boolean;\n getNonEvmAccountAddresses: (scope: CaipChainId) => CaipAccountId[];\n trackSessionCreatedEvent?: (\n approvedCaip25CaveatValue: Caip25CaveatValue,\n ) => void;\n },\n) {\n if (!isPlainObject(req.params)) {\n return end(invalidParams({ data: { request: req } }));\n }\n const { requiredScopes, optionalScopes, sessionProperties } = req.params;\n\n if (sessionProperties && Object.keys(sessionProperties).length === 0) {\n return end(new JsonRpcError(5302, 'Invalid sessionProperties requested'));\n }\n\n const filteredSessionProperties = Object.fromEntries(\n Object.entries(sessionProperties ?? {}).filter(([key]) =>\n isKnownSessionPropertyValue(key),\n ),\n );\n\n try {\n const { normalizedRequiredScopes, normalizedOptionalScopes } =\n validateAndNormalizeScopes(requiredScopes || {}, optionalScopes || {});\n\n const requiredScopesWithSupportedMethodsAndNotifications =\n getSupportedScopeObjects(normalizedRequiredScopes, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n const optionalScopesWithSupportedMethodsAndNotifications =\n getSupportedScopeObjects(normalizedOptionalScopes, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n\n const networkClientExistsForChainId = (chainId: Hex) => {\n try {\n hooks.findNetworkClientIdByChainId(chainId);\n return true;\n } catch {\n return false;\n }\n };\n\n const { supportedScopes: supportedRequiredScopes } = bucketScopes(\n requiredScopesWithSupportedMethodsAndNotifications,\n {\n isEvmChainIdSupported: networkClientExistsForChainId,\n isEvmChainIdSupportable: () => false, // intended for future usage with eip3085 scopedProperties\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,\n },\n );\n\n const { supportedScopes: supportedOptionalScopes } = bucketScopes(\n optionalScopesWithSupportedMethodsAndNotifications,\n {\n isEvmChainIdSupported: networkClientExistsForChainId,\n isEvmChainIdSupportable: () => false, // intended for future usage with eip3085 scopedProperties\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n isNonEvmScopeSupported: hooks.isNonEvmScopeSupported,\n },\n );\n\n const allRequestedAccountAddresses = getCaipAccountIdsFromScopesObjects([\n supportedRequiredScopes,\n supportedOptionalScopes,\n ]);\n\n const allSupportedRequestedCaipChainIds = getAllScopesFromScopesObjects([\n supportedRequiredScopes,\n supportedOptionalScopes,\n ]);\n\n if (allSupportedRequestedCaipChainIds.length === 0) {\n return end(new JsonRpcError(5100, 'Requested scopes are not supported'));\n }\n\n const existingEvmAddresses = hooks\n .listAccounts()\n .map((account) => account.address);\n\n const supportedRequestedAccountAddresses =\n allRequestedAccountAddresses.filter(\n (requestedAccountAddress: CaipAccountId) => {\n const {\n address,\n chain: { namespace },\n chainId: caipChainId,\n } = parseCaipAccountId(requestedAccountAddress);\n if (namespace === KnownCaipNamespace.Eip155.toString()) {\n return existingEvmAddresses.some((existingEvmAddress) => {\n return isEqualCaseInsensitive(address, existingEvmAddress);\n });\n }\n\n // If the namespace is not eip155 (EVM) we do a case sensitive check\n return hooks\n .getNonEvmAccountAddresses(caipChainId)\n .some((existingCaipAddress) => {\n return requestedAccountAddress === existingCaipAddress;\n });\n },\n );\n\n const requestedCaip25CaveatValue = {\n requiredScopes: getInternalScopesObject(supportedRequiredScopes),\n optionalScopes: getInternalScopesObject(supportedOptionalScopes),\n isMultichainOrigin: true,\n sessionProperties: filteredSessionProperties,\n };\n\n const requestedCaip25CaveatValueWithSupportedAccounts =\n setPermittedAccounts(\n requestedCaip25CaveatValue,\n supportedRequestedAccountAddresses,\n );\n\n const [grantedPermissions] = await hooks.requestPermissionsForOrigin({\n [Caip25EndowmentPermissionName]: {\n caveats: [\n {\n type: Caip25CaveatType,\n value: requestedCaip25CaveatValueWithSupportedAccounts,\n },\n ],\n },\n });\n\n const approvedCaip25Permission =\n grantedPermissions[Caip25EndowmentPermissionName];\n const approvedCaip25CaveatValue = approvedCaip25Permission?.caveats?.find(\n (caveat) => caveat.type === Caip25CaveatType,\n )?.value as Caip25CaveatValue;\n if (!approvedCaip25CaveatValue) {\n throw rpcErrors.internal();\n }\n\n const sessionScopes = getSessionScopes(approvedCaip25CaveatValue, {\n getNonEvmSupportedMethods: hooks.getNonEvmSupportedMethods,\n });\n\n const { sessionProperties: approvedSessionProperties = {} } =\n approvedCaip25CaveatValue;\n\n hooks.trackSessionCreatedEvent?.(approvedCaip25CaveatValue);\n\n res.result = {\n sessionScopes,\n sessionProperties: approvedSessionProperties,\n };\n return end();\n } catch (err) {\n return end(err);\n }\n}\n\nexport const walletCreateSession = {\n methodNames: ['wallet_createSession'],\n implementation: walletCreateSessionHandler,\n hookNames: {\n findNetworkClientIdByChainId: true,\n listAccounts: true,\n requestPermissionsForOrigin: true,\n getNonEvmSupportedMethods: true,\n isNonEvmScopeSupported: true,\n getNonEvmAccountAddresses: true,\n trackSessionCreatedEvent: true,\n },\n};\n"]}
package/dist/index.cjs CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MultichainSubscriptionManager = exports.MultichainMiddlewareManager = exports.multichainMethodCallValidatorMiddleware = exports.walletRevokeSession = exports.walletInvokeMethod = exports.walletGetSession = void 0;
3
+ exports.MultichainApiNotifications = exports.MultichainSubscriptionManager = exports.MultichainMiddlewareManager = exports.multichainMethodCallValidatorMiddleware = exports.walletRevokeSession = exports.walletInvokeMethod = exports.walletGetSession = exports.walletCreateSession = void 0;
4
+ var wallet_createSession_1 = require("./handlers/wallet-createSession.cjs");
5
+ Object.defineProperty(exports, "walletCreateSession", { enumerable: true, get: function () { return wallet_createSession_1.walletCreateSession; } });
4
6
  var wallet_getSession_1 = require("./handlers/wallet-getSession.cjs");
5
7
  Object.defineProperty(exports, "walletGetSession", { enumerable: true, get: function () { return wallet_getSession_1.walletGetSession; } });
6
8
  var wallet_invokeMethod_1 = require("./handlers/wallet-invokeMethod.cjs");
@@ -13,4 +15,6 @@ var MultichainMiddlewareManager_1 = require("./middlewares/MultichainMiddlewareM
13
15
  Object.defineProperty(exports, "MultichainMiddlewareManager", { enumerable: true, get: function () { return MultichainMiddlewareManager_1.MultichainMiddlewareManager; } });
14
16
  var MultichainSubscriptionManager_1 = require("./middlewares/MultichainSubscriptionManager.cjs");
15
17
  Object.defineProperty(exports, "MultichainSubscriptionManager", { enumerable: true, get: function () { return MultichainSubscriptionManager_1.MultichainSubscriptionManager; } });
18
+ var types_1 = require("./handlers/types.cjs");
19
+ Object.defineProperty(exports, "MultichainApiNotifications", { enumerable: true, get: function () { return types_1.MultichainApiNotifications; } });
16
20
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,sEAAgE;AAAvD,qHAAA,gBAAgB,OAAA;AACzB,0EAAoE;AAA3D,yHAAA,kBAAkB,OAAA;AAC3B,4EAAsE;AAA7D,2HAAA,mBAAmB,OAAA;AAE5B,qHAAgH;AAAvG,kKAAA,uCAAuC,OAAA;AAChD,6FAAwF;AAA/E,0IAAA,2BAA2B,OAAA;AACpC,iGAA4F;AAAnF,8IAAA,6BAA6B,OAAA","sourcesContent":["export { walletGetSession } from './handlers/wallet-getSession';\nexport { walletInvokeMethod } from './handlers/wallet-invokeMethod';\nexport { walletRevokeSession } from './handlers/wallet-revokeSession';\n\nexport { multichainMethodCallValidatorMiddleware } from './middlewares/multichainMethodCallValidatorMiddleware';\nexport { MultichainMiddlewareManager } from './middlewares/MultichainMiddlewareManager';\nexport { MultichainSubscriptionManager } from './middlewares/MultichainSubscriptionManager';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4EAAsE;AAA7D,2HAAA,mBAAmB,OAAA;AAC5B,sEAAgE;AAAvD,qHAAA,gBAAgB,OAAA;AACzB,0EAAoE;AAA3D,yHAAA,kBAAkB,OAAA;AAC3B,4EAAsE;AAA7D,2HAAA,mBAAmB,OAAA;AAE5B,qHAAgH;AAAvG,kKAAA,uCAAuC,OAAA;AAChD,6FAAwF;AAA/E,0IAAA,2BAA2B,OAAA;AACpC,iGAA4F;AAAnF,8IAAA,6BAA6B,OAAA;AACtC,8CAA8D;AAArD,mHAAA,0BAA0B,OAAA","sourcesContent":["export { walletCreateSession } from './handlers/wallet-createSession';\nexport { walletGetSession } from './handlers/wallet-getSession';\nexport { walletInvokeMethod } from './handlers/wallet-invokeMethod';\nexport { walletRevokeSession } from './handlers/wallet-revokeSession';\n\nexport { multichainMethodCallValidatorMiddleware } from './middlewares/multichainMethodCallValidatorMiddleware';\nexport { MultichainMiddlewareManager } from './middlewares/MultichainMiddlewareManager';\nexport { MultichainSubscriptionManager } from './middlewares/MultichainSubscriptionManager';\nexport { MultichainApiNotifications } from './handlers/types';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,9 @@
1
+ export { walletCreateSession } from "./handlers/wallet-createSession.cjs";
1
2
  export { walletGetSession } from "./handlers/wallet-getSession.cjs";
2
3
  export { walletInvokeMethod } from "./handlers/wallet-invokeMethod.cjs";
3
4
  export { walletRevokeSession } from "./handlers/wallet-revokeSession.cjs";
4
5
  export { multichainMethodCallValidatorMiddleware } from "./middlewares/multichainMethodCallValidatorMiddleware.cjs";
5
6
  export { MultichainMiddlewareManager } from "./middlewares/MultichainMiddlewareManager.cjs";
6
7
  export { MultichainSubscriptionManager } from "./middlewares/MultichainSubscriptionManager.cjs";
8
+ export { MultichainApiNotifications } from "./handlers/types.cjs";
7
9
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AACtE,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD;AAC5F,OAAO,EAAE,0BAA0B,EAAE,6BAAyB"}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,9 @@
1
+ export { walletCreateSession } from "./handlers/wallet-createSession.mjs";
1
2
  export { walletGetSession } from "./handlers/wallet-getSession.mjs";
2
3
  export { walletInvokeMethod } from "./handlers/wallet-invokeMethod.mjs";
3
4
  export { walletRevokeSession } from "./handlers/wallet-revokeSession.mjs";
4
5
  export { multichainMethodCallValidatorMiddleware } from "./middlewares/multichainMethodCallValidatorMiddleware.mjs";
5
6
  export { MultichainMiddlewareManager } from "./middlewares/MultichainMiddlewareManager.mjs";
6
7
  export { MultichainSubscriptionManager } from "./middlewares/MultichainSubscriptionManager.mjs";
8
+ export { MultichainApiNotifications } from "./handlers/types.mjs";
7
9
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AACtE,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD;AAC5F,OAAO,EAAE,0BAA0B,EAAE,6BAAyB"}
package/dist/index.mjs CHANGED
@@ -1,7 +1,9 @@
1
+ export { walletCreateSession } from "./handlers/wallet-createSession.mjs";
1
2
  export { walletGetSession } from "./handlers/wallet-getSession.mjs";
2
3
  export { walletInvokeMethod } from "./handlers/wallet-invokeMethod.mjs";
3
4
  export { walletRevokeSession } from "./handlers/wallet-revokeSession.mjs";
4
5
  export { multichainMethodCallValidatorMiddleware } from "./middlewares/multichainMethodCallValidatorMiddleware.mjs";
5
6
  export { MultichainMiddlewareManager } from "./middlewares/MultichainMiddlewareManager.mjs";
6
7
  export { MultichainSubscriptionManager } from "./middlewares/MultichainSubscriptionManager.mjs";
8
+ export { MultichainApiNotifications } from "./handlers/types.mjs";
7
9
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD","sourcesContent":["export { walletGetSession } from './handlers/wallet-getSession';\nexport { walletInvokeMethod } from './handlers/wallet-invokeMethod';\nexport { walletRevokeSession } from './handlers/wallet-revokeSession';\n\nexport { multichainMethodCallValidatorMiddleware } from './middlewares/multichainMethodCallValidatorMiddleware';\nexport { MultichainMiddlewareManager } from './middlewares/MultichainMiddlewareManager';\nexport { MultichainSubscriptionManager } from './middlewares/MultichainSubscriptionManager';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AACtE,OAAO,EAAE,gBAAgB,EAAE,yCAAqC;AAChE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,mBAAmB,EAAE,4CAAwC;AAEtE,OAAO,EAAE,uCAAuC,EAAE,kEAA8D;AAChH,OAAO,EAAE,2BAA2B,EAAE,sDAAkD;AACxF,OAAO,EAAE,6BAA6B,EAAE,wDAAoD;AAC5F,OAAO,EAAE,0BAA0B,EAAE,6BAAyB","sourcesContent":["export { walletCreateSession } from './handlers/wallet-createSession';\nexport { walletGetSession } from './handlers/wallet-getSession';\nexport { walletInvokeMethod } from './handlers/wallet-invokeMethod';\nexport { walletRevokeSession } from './handlers/wallet-revokeSession';\n\nexport { multichainMethodCallValidatorMiddleware } from './middlewares/multichainMethodCallValidatorMiddleware';\nexport { MultichainMiddlewareManager } from './middlewares/MultichainMiddlewareManager';\nexport { MultichainSubscriptionManager } from './middlewares/MultichainSubscriptionManager';\nexport { MultichainApiNotifications } from './handlers/types';\n"]}
@@ -20,6 +20,7 @@ const controller_utils_1 = require("@metamask/controller-utils");
20
20
  const subscriptionManager_1 = __importDefault(require("@metamask/eth-json-rpc-filters/subscriptionManager.js"));
21
21
  const safe_event_emitter_1 = __importDefault(require("@metamask/safe-event-emitter"));
22
22
  const utils_1 = require("@metamask/utils");
23
+ const types_1 = require("../handlers/types.cjs");
23
24
  /**
24
25
  * A helper that facilates the lifecycle of a SubscriptionManager instance that
25
26
  * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.
@@ -43,7 +44,7 @@ class MultichainSubscriptionManager extends safe_event_emitter_1.default {
43
44
  }
44
45
  notify({ scope, origin, tabId }, { method, params }) {
45
46
  this.emit('notification', origin, tabId, {
46
- method: 'wallet_notify',
47
+ method: types_1.MultichainApiNotifications.walletNotify,
47
48
  params: {
48
49
  scope,
49
50
  notification: { method, params },
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainSubscriptionManager.cjs","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExternalScopeString } from '@metamask/chain-agnostic-permission';\nimport { toHex } from '@metamask/controller-utils';\nimport createSubscriptionManager from '@metamask/eth-json-rpc-filters/subscriptionManager';\nimport type { NetworkController } from '@metamask/network-controller';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport { parseCaipChainId } from '@metamask/utils';\n\nimport type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager';\n\nexport type SubscriptionManager = {\n events: SafeEventEmitter;\n destroy?: () => void;\n middleware: ExtendedJsonRpcMiddleware;\n};\n\ntype SubscriptionNotificationEvent = {\n jsonrpc: '2.0';\n method: 'eth_subscription';\n params: {\n subscription: Hex;\n result: unknown;\n };\n};\n\ntype SubscriptionKey = {\n scope: ExternalScopeString;\n origin: string;\n tabId?: number;\n};\ntype SubscriptionEntry = SubscriptionKey & {\n subscriptionManager: SubscriptionManager;\n};\n\ntype MultichainSubscriptionManagerOptions = {\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n};\n\n/**\n * A helper that facilates the lifecycle of a SubscriptionManager instance that\n * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.\n */\nexport class MultichainSubscriptionManager extends SafeEventEmitter {\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n #subscriptions: SubscriptionEntry[] = [];\n\n /**\n * Construct a MultichainSubscriptionManager.\n *\n * @param options - The controller options.\n * @param options.findNetworkClientIdByChainId - The hook to get the networkClientId from a chainId.\n * @param options.getNetworkClientById - The hook to get the network client instance by its networkClientId.\n */\n constructor(options: MultichainSubscriptionManagerOptions) {\n super();\n this.#findNetworkClientIdByChainId = options.findNetworkClientIdByChainId;\n this.#getNetworkClientById = options.getNetworkClientById;\n }\n\n notify(\n { scope, origin, tabId }: SubscriptionKey,\n { method, params }: SubscriptionNotificationEvent,\n ) {\n this.emit('notification', origin, tabId, {\n method: 'wallet_notify',\n params: {\n scope,\n notification: { method, params },\n },\n });\n }\n\n #getSubscriptionEntry({\n scope,\n origin,\n tabId,\n }: SubscriptionKey): SubscriptionEntry | undefined {\n return this.#subscriptions.find((subscriptionEntry) => {\n return (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n );\n });\n }\n\n #removeSubscriptionEntry({ scope, origin, tabId }: SubscriptionEntry) {\n this.#subscriptions = this.#subscriptions.filter((subscriptionEntry) => {\n return (\n subscriptionEntry.scope !== scope ||\n subscriptionEntry.origin !== origin ||\n subscriptionEntry.tabId !== tabId\n );\n });\n }\n\n subscribe(subscriptionKey: SubscriptionKey) {\n const subscriptionEntry = this.#getSubscriptionEntry(subscriptionKey);\n if (subscriptionEntry) {\n return subscriptionEntry.subscriptionManager;\n }\n\n const networkClientId = this.#findNetworkClientIdByChainId(\n toHex(parseCaipChainId(subscriptionKey.scope as CaipChainId).reference),\n );\n const networkClient = this.#getNetworkClientById(networkClientId);\n const subscriptionManager = createSubscriptionManager({\n blockTracker: networkClient.blockTracker,\n provider: networkClient.provider,\n });\n\n subscriptionManager.events.on(\n 'notification',\n (message: SubscriptionNotificationEvent) => {\n this.notify(subscriptionKey, message);\n },\n );\n\n const newSubscriptionManagerEntry = {\n ...subscriptionKey,\n subscriptionManager,\n };\n subscriptionManager.destroy = subscriptionManager.middleware.destroy;\n subscriptionManager.middleware.destroy = this.#unsubscribe.bind(\n this,\n newSubscriptionManagerEntry,\n );\n\n this.#subscriptions.push(newSubscriptionManagerEntry);\n\n return subscriptionManager;\n }\n\n #unsubscribe(subscriptionEntry: SubscriptionEntry) {\n subscriptionEntry.subscriptionManager.destroy?.();\n\n this.#removeSubscriptionEntry(subscriptionEntry);\n }\n\n unsubscribeByScope(scope: ExternalScopeString) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (subscriptionEntry.scope === scope) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByScopeAndOrigin(scope: ExternalScopeString, origin: string) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByOriginAndTabId(origin: string, tabId?: number) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainSubscriptionManager.cjs","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExternalScopeString } from '@metamask/chain-agnostic-permission';\nimport { toHex } from '@metamask/controller-utils';\nimport createSubscriptionManager from '@metamask/eth-json-rpc-filters/subscriptionManager';\nimport type { NetworkController } from '@metamask/network-controller';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport { parseCaipChainId } from '@metamask/utils';\n\nimport type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager';\nimport { MultichainApiNotifications } from '../handlers/types';\n\nexport type SubscriptionManager = {\n events: SafeEventEmitter;\n destroy?: () => void;\n middleware: ExtendedJsonRpcMiddleware;\n};\n\ntype SubscriptionNotificationEvent = {\n jsonrpc: '2.0';\n method: 'eth_subscription';\n params: {\n subscription: Hex;\n result: unknown;\n };\n};\n\ntype SubscriptionKey = {\n scope: ExternalScopeString;\n origin: string;\n tabId?: number;\n};\ntype SubscriptionEntry = SubscriptionKey & {\n subscriptionManager: SubscriptionManager;\n};\n\ntype MultichainSubscriptionManagerOptions = {\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n};\n\n/**\n * A helper that facilates the lifecycle of a SubscriptionManager instance that\n * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.\n */\nexport class MultichainSubscriptionManager extends SafeEventEmitter {\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n #subscriptions: SubscriptionEntry[] = [];\n\n /**\n * Construct a MultichainSubscriptionManager.\n *\n * @param options - The controller options.\n * @param options.findNetworkClientIdByChainId - The hook to get the networkClientId from a chainId.\n * @param options.getNetworkClientById - The hook to get the network client instance by its networkClientId.\n */\n constructor(options: MultichainSubscriptionManagerOptions) {\n super();\n this.#findNetworkClientIdByChainId = options.findNetworkClientIdByChainId;\n this.#getNetworkClientById = options.getNetworkClientById;\n }\n\n notify(\n { scope, origin, tabId }: SubscriptionKey,\n { method, params }: SubscriptionNotificationEvent,\n ) {\n this.emit('notification', origin, tabId, {\n method: MultichainApiNotifications.walletNotify,\n params: {\n scope,\n notification: { method, params },\n },\n });\n }\n\n #getSubscriptionEntry({\n scope,\n origin,\n tabId,\n }: SubscriptionKey): SubscriptionEntry | undefined {\n return this.#subscriptions.find((subscriptionEntry) => {\n return (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n );\n });\n }\n\n #removeSubscriptionEntry({ scope, origin, tabId }: SubscriptionEntry) {\n this.#subscriptions = this.#subscriptions.filter((subscriptionEntry) => {\n return (\n subscriptionEntry.scope !== scope ||\n subscriptionEntry.origin !== origin ||\n subscriptionEntry.tabId !== tabId\n );\n });\n }\n\n subscribe(subscriptionKey: SubscriptionKey) {\n const subscriptionEntry = this.#getSubscriptionEntry(subscriptionKey);\n if (subscriptionEntry) {\n return subscriptionEntry.subscriptionManager;\n }\n\n const networkClientId = this.#findNetworkClientIdByChainId(\n toHex(parseCaipChainId(subscriptionKey.scope as CaipChainId).reference),\n );\n const networkClient = this.#getNetworkClientById(networkClientId);\n const subscriptionManager = createSubscriptionManager({\n blockTracker: networkClient.blockTracker,\n provider: networkClient.provider,\n });\n\n subscriptionManager.events.on(\n 'notification',\n (message: SubscriptionNotificationEvent) => {\n this.notify(subscriptionKey, message);\n },\n );\n\n const newSubscriptionManagerEntry = {\n ...subscriptionKey,\n subscriptionManager,\n };\n subscriptionManager.destroy = subscriptionManager.middleware.destroy;\n subscriptionManager.middleware.destroy = this.#unsubscribe.bind(\n this,\n newSubscriptionManagerEntry,\n );\n\n this.#subscriptions.push(newSubscriptionManagerEntry);\n\n return subscriptionManager;\n }\n\n #unsubscribe(subscriptionEntry: SubscriptionEntry) {\n subscriptionEntry.subscriptionManager.destroy?.();\n\n this.#removeSubscriptionEntry(subscriptionEntry);\n }\n\n unsubscribeByScope(scope: ExternalScopeString) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (subscriptionEntry.scope === scope) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByScopeAndOrigin(scope: ExternalScopeString, origin: string) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByOriginAndTabId(origin: string, tabId?: number) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainSubscriptionManager.d.cts","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4CAA4C;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,gBAAgB,qCAAqC;AAC5D,OAAO,KAAK,EAAe,GAAG,EAAE,wBAAwB;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,0CAAsC;AAE/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE;QACN,YAAY,EAAE,GAAG,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,KAAK,oCAAoC,GAAG;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;CACjE,CAAC;AAEF;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,gBAAgB;;IAOjE;;;;;;OAMG;gBACS,OAAO,EAAE,oCAAoC;IAMzD,MAAM,CACJ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EACzC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAmCnD,SAAS,CAAC,eAAe,EAAE,eAAe;IA2C1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB;IAQ7C,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM;IAWtE,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAU3D"}
1
+ {"version":3,"file":"MultichainSubscriptionManager.d.cts","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4CAA4C;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,gBAAgB,qCAAqC;AAC5D,OAAO,KAAK,EAAe,GAAG,EAAE,wBAAwB;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,0CAAsC;AAG/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE;QACN,YAAY,EAAE,GAAG,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,KAAK,oCAAoC,GAAG;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;CACjE,CAAC;AAEF;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,gBAAgB;;IAOjE;;;;;;OAMG;gBACS,OAAO,EAAE,oCAAoC;IAMzD,MAAM,CACJ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EACzC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAmCnD,SAAS,CAAC,eAAe,EAAE,eAAe;IA2C1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB;IAQ7C,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM;IAWtE,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAU3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainSubscriptionManager.d.mts","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4CAA4C;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,gBAAgB,qCAAqC;AAC5D,OAAO,KAAK,EAAe,GAAG,EAAE,wBAAwB;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,0CAAsC;AAE/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE;QACN,YAAY,EAAE,GAAG,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,KAAK,oCAAoC,GAAG;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;CACjE,CAAC;AAEF;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,gBAAgB;;IAOjE;;;;;;OAMG;gBACS,OAAO,EAAE,oCAAoC;IAMzD,MAAM,CACJ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EACzC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAmCnD,SAAS,CAAC,eAAe,EAAE,eAAe;IA2C1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB;IAQ7C,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM;IAWtE,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAU3D"}
1
+ {"version":3,"file":"MultichainSubscriptionManager.d.mts","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4CAA4C;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,qCAAqC;AACtE,OAAO,gBAAgB,qCAAqC;AAC5D,OAAO,KAAK,EAAe,GAAG,EAAE,wBAAwB;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,0CAAsC;AAG/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE;QACN,YAAY,EAAE,GAAG,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,KAAK,oCAAoC,GAAG;IAC1C,4BAA4B,EAAE,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAChF,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;CACjE,CAAC;AAEF;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,gBAAgB;;IAOjE;;;;;;OAMG;gBACS,OAAO,EAAE,oCAAoC;IAMzD,MAAM,CACJ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EACzC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAmCnD,SAAS,CAAC,eAAe,EAAE,eAAe;IA2C1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB;IAQ7C,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM;IAWtE,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAU3D"}
@@ -21,6 +21,7 @@ import $createSubscriptionManager from "@metamask/eth-json-rpc-filters/subscript
21
21
  const createSubscriptionManager = $importDefault($createSubscriptionManager);
22
22
  import SafeEventEmitter from "@metamask/safe-event-emitter";
23
23
  import { parseCaipChainId } from "@metamask/utils";
24
+ import { MultichainApiNotifications } from "../handlers/types.mjs";
24
25
  /**
25
26
  * A helper that facilates the lifecycle of a SubscriptionManager instance that
26
27
  * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.
@@ -44,7 +45,7 @@ export class MultichainSubscriptionManager extends SafeEventEmitter {
44
45
  }
45
46
  notify({ scope, origin, tabId }, { method, params }) {
46
47
  this.emit('notification', origin, tabId, {
47
- method: 'wallet_notify',
48
+ method: MultichainApiNotifications.walletNotify,
48
49
  params: {
49
50
  scope,
50
51
  notification: { method, params },
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainSubscriptionManager.mjs","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExternalScopeString } from '@metamask/chain-agnostic-permission';\nimport { toHex } from '@metamask/controller-utils';\nimport createSubscriptionManager from '@metamask/eth-json-rpc-filters/subscriptionManager';\nimport type { NetworkController } from '@metamask/network-controller';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport { parseCaipChainId } from '@metamask/utils';\n\nimport type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager';\n\nexport type SubscriptionManager = {\n events: SafeEventEmitter;\n destroy?: () => void;\n middleware: ExtendedJsonRpcMiddleware;\n};\n\ntype SubscriptionNotificationEvent = {\n jsonrpc: '2.0';\n method: 'eth_subscription';\n params: {\n subscription: Hex;\n result: unknown;\n };\n};\n\ntype SubscriptionKey = {\n scope: ExternalScopeString;\n origin: string;\n tabId?: number;\n};\ntype SubscriptionEntry = SubscriptionKey & {\n subscriptionManager: SubscriptionManager;\n};\n\ntype MultichainSubscriptionManagerOptions = {\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n};\n\n/**\n * A helper that facilates the lifecycle of a SubscriptionManager instance that\n * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.\n */\nexport class MultichainSubscriptionManager extends SafeEventEmitter {\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n #subscriptions: SubscriptionEntry[] = [];\n\n /**\n * Construct a MultichainSubscriptionManager.\n *\n * @param options - The controller options.\n * @param options.findNetworkClientIdByChainId - The hook to get the networkClientId from a chainId.\n * @param options.getNetworkClientById - The hook to get the network client instance by its networkClientId.\n */\n constructor(options: MultichainSubscriptionManagerOptions) {\n super();\n this.#findNetworkClientIdByChainId = options.findNetworkClientIdByChainId;\n this.#getNetworkClientById = options.getNetworkClientById;\n }\n\n notify(\n { scope, origin, tabId }: SubscriptionKey,\n { method, params }: SubscriptionNotificationEvent,\n ) {\n this.emit('notification', origin, tabId, {\n method: 'wallet_notify',\n params: {\n scope,\n notification: { method, params },\n },\n });\n }\n\n #getSubscriptionEntry({\n scope,\n origin,\n tabId,\n }: SubscriptionKey): SubscriptionEntry | undefined {\n return this.#subscriptions.find((subscriptionEntry) => {\n return (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n );\n });\n }\n\n #removeSubscriptionEntry({ scope, origin, tabId }: SubscriptionEntry) {\n this.#subscriptions = this.#subscriptions.filter((subscriptionEntry) => {\n return (\n subscriptionEntry.scope !== scope ||\n subscriptionEntry.origin !== origin ||\n subscriptionEntry.tabId !== tabId\n );\n });\n }\n\n subscribe(subscriptionKey: SubscriptionKey) {\n const subscriptionEntry = this.#getSubscriptionEntry(subscriptionKey);\n if (subscriptionEntry) {\n return subscriptionEntry.subscriptionManager;\n }\n\n const networkClientId = this.#findNetworkClientIdByChainId(\n toHex(parseCaipChainId(subscriptionKey.scope as CaipChainId).reference),\n );\n const networkClient = this.#getNetworkClientById(networkClientId);\n const subscriptionManager = createSubscriptionManager({\n blockTracker: networkClient.blockTracker,\n provider: networkClient.provider,\n });\n\n subscriptionManager.events.on(\n 'notification',\n (message: SubscriptionNotificationEvent) => {\n this.notify(subscriptionKey, message);\n },\n );\n\n const newSubscriptionManagerEntry = {\n ...subscriptionKey,\n subscriptionManager,\n };\n subscriptionManager.destroy = subscriptionManager.middleware.destroy;\n subscriptionManager.middleware.destroy = this.#unsubscribe.bind(\n this,\n newSubscriptionManagerEntry,\n );\n\n this.#subscriptions.push(newSubscriptionManagerEntry);\n\n return subscriptionManager;\n }\n\n #unsubscribe(subscriptionEntry: SubscriptionEntry) {\n subscriptionEntry.subscriptionManager.destroy?.();\n\n this.#removeSubscriptionEntry(subscriptionEntry);\n }\n\n unsubscribeByScope(scope: ExternalScopeString) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (subscriptionEntry.scope === scope) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByScopeAndOrigin(scope: ExternalScopeString, origin: string) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByOriginAndTabId(origin: string, tabId?: number) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainSubscriptionManager.mjs","sourceRoot":"","sources":["../../src/middlewares/MultichainSubscriptionManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,OAAO,EAAE,KAAK,EAAE,mCAAmC;AACnD,OAAO,0BAAyB,8DAA2D;;AAE3F,OAAO,gBAAgB,qCAAqC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,wBAAwB;AAGnD,OAAO,EAAE,0BAA0B,EAAE,8BAA0B;AA+B/D;;;GAGG;AACH,MAAM,OAAO,6BAA8B,SAAQ,gBAAgB;IAOjE;;;;;;OAMG;IACH,YAAY,OAA6C;QACvD,KAAK,EAAE,CAAC;;QAdD,8EAAiF;QAEjF,sEAAiE;QAE1E,uDAAsC,EAAE,EAAC;QAWvC,uBAAA,IAAI,+DAAiC,OAAO,CAAC,4BAA4B,MAAA,CAAC;QAC1E,uBAAA,IAAI,uDAAyB,OAAO,CAAC,oBAAoB,MAAA,CAAC;IAC5D,CAAC;IAED,MAAM,CACJ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAmB,EACzC,EAAE,MAAM,EAAE,MAAM,EAAiC;QAEjD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE;YACvC,MAAM,EAAE,0BAA0B,CAAC,YAAY;YAC/C,MAAM,EAAE;gBACN,KAAK;gBACL,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;aACjC;SACF,CAAC,CAAC;IACL,CAAC;IA0BD,SAAS,CAAC,eAAgC;QACxC,MAAM,iBAAiB,GAAG,uBAAA,IAAI,qGAAsB,MAA1B,IAAI,EAAuB,eAAe,CAAC,CAAC;QACtE,IAAI,iBAAiB,EAAE;YACrB,OAAO,iBAAiB,CAAC,mBAAmB,CAAC;SAC9C;QAED,MAAM,eAAe,GAAG,uBAAA,IAAI,mEAA8B,MAAlC,IAAI,EAC1B,KAAK,CAAC,gBAAgB,CAAC,eAAe,CAAC,KAAoB,CAAC,CAAC,SAAS,CAAC,CACxE,CAAC;QACF,MAAM,aAAa,GAAG,uBAAA,IAAI,2DAAsB,MAA1B,IAAI,EAAuB,eAAe,CAAC,CAAC;QAClE,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;YACpD,YAAY,EAAE,aAAa,CAAC,YAAY;YACxC,QAAQ,EAAE,aAAa,CAAC,QAAQ;SACjC,CAAC,CAAC;QAEH,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAC3B,cAAc,EACd,CAAC,OAAsC,EAAE,EAAE;YACzC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC,CACF,CAAC;QAEF,MAAM,2BAA2B,GAAG;YAClC,GAAG,eAAe;YAClB,mBAAmB;SACpB,CAAC;QACF,mBAAmB,CAAC,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,OAAO,CAAC;QACrE,mBAAmB,CAAC,UAAU,CAAC,OAAO,GAAG,uBAAA,IAAI,4FAAa,CAAC,IAAI,CAC7D,IAAI,EACJ,2BAA2B,CAC5B,CAAC;QAEF,uBAAA,IAAI,oDAAe,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAEtD,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAQD,kBAAkB,CAAC,KAA0B;QAC3C,uBAAA,IAAI,oDAAe,CAAC,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAChD,IAAI,iBAAiB,CAAC,KAAK,KAAK,KAAK,EAAE;gBACrC,uBAAA,IAAI,4FAAa,MAAjB,IAAI,EAAc,iBAAiB,CAAC,CAAC;aACtC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B,CAAC,KAA0B,EAAE,MAAc;QACpE,uBAAA,IAAI,oDAAe,CAAC,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAChD,IACE,iBAAiB,CAAC,KAAK,KAAK,KAAK;gBACjC,iBAAiB,CAAC,MAAM,KAAK,MAAM,EACnC;gBACA,uBAAA,IAAI,4FAAa,MAAjB,IAAI,EAAc,iBAAiB,CAAC,CAAC;aACtC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B,CAAC,MAAc,EAAE,KAAc;QACxD,uBAAA,IAAI,oDAAe,CAAC,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAChD,IACE,iBAAiB,CAAC,MAAM,KAAK,MAAM;gBACnC,iBAAiB,CAAC,KAAK,KAAK,KAAK,EACjC;gBACA,uBAAA,IAAI,4FAAa,MAAjB,IAAI,EAAc,iBAAiB,CAAC,CAAC;aACtC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;6XAhGuB,EACpB,KAAK,EACL,MAAM,EACN,KAAK,GACW;IAChB,OAAO,uBAAA,IAAI,oDAAe,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,EAAE;QACpD,OAAO,CACL,iBAAiB,CAAC,KAAK,KAAK,KAAK;YACjC,iBAAiB,CAAC,MAAM,KAAK,MAAM;YACnC,iBAAiB,CAAC,KAAK,KAAK,KAAK,CAClC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,2HAEwB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAqB;IAClE,uBAAA,IAAI,gDAAkB,uBAAA,IAAI,oDAAe,CAAC,MAAM,CAAC,CAAC,iBAAiB,EAAE,EAAE;QACrE,OAAO,CACL,iBAAiB,CAAC,KAAK,KAAK,KAAK;YACjC,iBAAiB,CAAC,MAAM,KAAK,MAAM;YACnC,iBAAiB,CAAC,KAAK,KAAK,KAAK,CAClC,CAAC;IACJ,CAAC,CAAC,MAAA,CAAC;AACL,CAAC,mGAuCY,iBAAoC;IAC/C,iBAAiB,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC;IAElD,uBAAA,IAAI,wGAAyB,MAA7B,IAAI,EAA0B,iBAAiB,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import type { ExternalScopeString } from '@metamask/chain-agnostic-permission';\nimport { toHex } from '@metamask/controller-utils';\nimport createSubscriptionManager from '@metamask/eth-json-rpc-filters/subscriptionManager';\nimport type { NetworkController } from '@metamask/network-controller';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type { CaipChainId, Hex } from '@metamask/utils';\nimport { parseCaipChainId } from '@metamask/utils';\n\nimport type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager';\nimport { MultichainApiNotifications } from '../handlers/types';\n\nexport type SubscriptionManager = {\n events: SafeEventEmitter;\n destroy?: () => void;\n middleware: ExtendedJsonRpcMiddleware;\n};\n\ntype SubscriptionNotificationEvent = {\n jsonrpc: '2.0';\n method: 'eth_subscription';\n params: {\n subscription: Hex;\n result: unknown;\n };\n};\n\ntype SubscriptionKey = {\n scope: ExternalScopeString;\n origin: string;\n tabId?: number;\n};\ntype SubscriptionEntry = SubscriptionKey & {\n subscriptionManager: SubscriptionManager;\n};\n\ntype MultichainSubscriptionManagerOptions = {\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n};\n\n/**\n * A helper that facilates the lifecycle of a SubscriptionManager instance that\n * is meant to handle subscriptons for only one specific scope, origin, and tabId combination.\n */\nexport class MultichainSubscriptionManager extends SafeEventEmitter {\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n #subscriptions: SubscriptionEntry[] = [];\n\n /**\n * Construct a MultichainSubscriptionManager.\n *\n * @param options - The controller options.\n * @param options.findNetworkClientIdByChainId - The hook to get the networkClientId from a chainId.\n * @param options.getNetworkClientById - The hook to get the network client instance by its networkClientId.\n */\n constructor(options: MultichainSubscriptionManagerOptions) {\n super();\n this.#findNetworkClientIdByChainId = options.findNetworkClientIdByChainId;\n this.#getNetworkClientById = options.getNetworkClientById;\n }\n\n notify(\n { scope, origin, tabId }: SubscriptionKey,\n { method, params }: SubscriptionNotificationEvent,\n ) {\n this.emit('notification', origin, tabId, {\n method: MultichainApiNotifications.walletNotify,\n params: {\n scope,\n notification: { method, params },\n },\n });\n }\n\n #getSubscriptionEntry({\n scope,\n origin,\n tabId,\n }: SubscriptionKey): SubscriptionEntry | undefined {\n return this.#subscriptions.find((subscriptionEntry) => {\n return (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n );\n });\n }\n\n #removeSubscriptionEntry({ scope, origin, tabId }: SubscriptionEntry) {\n this.#subscriptions = this.#subscriptions.filter((subscriptionEntry) => {\n return (\n subscriptionEntry.scope !== scope ||\n subscriptionEntry.origin !== origin ||\n subscriptionEntry.tabId !== tabId\n );\n });\n }\n\n subscribe(subscriptionKey: SubscriptionKey) {\n const subscriptionEntry = this.#getSubscriptionEntry(subscriptionKey);\n if (subscriptionEntry) {\n return subscriptionEntry.subscriptionManager;\n }\n\n const networkClientId = this.#findNetworkClientIdByChainId(\n toHex(parseCaipChainId(subscriptionKey.scope as CaipChainId).reference),\n );\n const networkClient = this.#getNetworkClientById(networkClientId);\n const subscriptionManager = createSubscriptionManager({\n blockTracker: networkClient.blockTracker,\n provider: networkClient.provider,\n });\n\n subscriptionManager.events.on(\n 'notification',\n (message: SubscriptionNotificationEvent) => {\n this.notify(subscriptionKey, message);\n },\n );\n\n const newSubscriptionManagerEntry = {\n ...subscriptionKey,\n subscriptionManager,\n };\n subscriptionManager.destroy = subscriptionManager.middleware.destroy;\n subscriptionManager.middleware.destroy = this.#unsubscribe.bind(\n this,\n newSubscriptionManagerEntry,\n );\n\n this.#subscriptions.push(newSubscriptionManagerEntry);\n\n return subscriptionManager;\n }\n\n #unsubscribe(subscriptionEntry: SubscriptionEntry) {\n subscriptionEntry.subscriptionManager.destroy?.();\n\n this.#removeSubscriptionEntry(subscriptionEntry);\n }\n\n unsubscribeByScope(scope: ExternalScopeString) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (subscriptionEntry.scope === scope) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByScopeAndOrigin(scope: ExternalScopeString, origin: string) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.scope === scope &&\n subscriptionEntry.origin === origin\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n\n unsubscribeByOriginAndTabId(origin: string, tabId?: number) {\n this.#subscriptions.forEach((subscriptionEntry) => {\n if (\n subscriptionEntry.origin === origin &&\n subscriptionEntry.tabId === tabId\n ) {\n this.#unsubscribe(subscriptionEntry);\n }\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/multichain-api-middleware",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "JSON-RPC methods and middleware to support the MetaMask Multichain API",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -48,9 +48,10 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@metamask/api-specs": "^0.10.12",
51
- "@metamask/chain-agnostic-permission": "^0.1.0",
51
+ "@metamask/chain-agnostic-permission": "^0.4.0",
52
+ "@metamask/controller-utils": "^11.7.0",
52
53
  "@metamask/json-rpc-engine": "^10.0.3",
53
- "@metamask/network-controller": "^22.2.1",
54
+ "@metamask/network-controller": "^23.2.0",
54
55
  "@metamask/permission-controller": "^11.0.6",
55
56
  "@metamask/rpc-errors": "^7.0.2",
56
57
  "@metamask/utils": "^11.2.0",
@@ -61,6 +62,7 @@
61
62
  "devDependencies": {
62
63
  "@metamask/auto-changelog": "^3.4.4",
63
64
  "@metamask/eth-json-rpc-filters": "^9.0.0",
65
+ "@metamask/multichain-transactions-controller": "^0.9.0",
64
66
  "@metamask/safe-event-emitter": "^3.0.0",
65
67
  "@types/jest": "^27.4.1",
66
68
  "deepmerge": "^4.2.2",