@metamask/eip-5792-middleware 1.0.0 → 1.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 (94) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/dist/constants.cjs +21 -1
  3. package/dist/constants.cjs.map +1 -1
  4. package/dist/constants.d.cts +15 -0
  5. package/dist/constants.d.cts.map +1 -1
  6. package/dist/constants.d.mts +15 -0
  7. package/dist/constants.d.mts.map +1 -1
  8. package/dist/constants.mjs +20 -0
  9. package/dist/constants.mjs.map +1 -1
  10. package/dist/{methods → hooks}/getCallsStatus.cjs +5 -6
  11. package/dist/hooks/getCallsStatus.cjs.map +1 -0
  12. package/dist/{methods → hooks}/getCallsStatus.d.cts +1 -2
  13. package/dist/hooks/getCallsStatus.d.cts.map +1 -0
  14. package/dist/{methods → hooks}/getCallsStatus.d.mts +1 -2
  15. package/dist/hooks/getCallsStatus.d.mts.map +1 -0
  16. package/dist/{methods → hooks}/getCallsStatus.mjs +1 -2
  17. package/dist/hooks/getCallsStatus.mjs.map +1 -0
  18. package/dist/{methods → hooks}/getCapabilities.cjs +10 -4
  19. package/dist/hooks/getCapabilities.cjs.map +1 -0
  20. package/dist/{methods → hooks}/getCapabilities.d.cts +3 -2
  21. package/dist/hooks/getCapabilities.d.cts.map +1 -0
  22. package/dist/{methods → hooks}/getCapabilities.d.mts +3 -2
  23. package/dist/hooks/getCapabilities.d.mts.map +1 -0
  24. package/dist/{methods → hooks}/getCapabilities.mjs +10 -4
  25. package/dist/hooks/getCapabilities.mjs.map +1 -0
  26. package/dist/{methods → hooks}/processSendCalls.cjs +104 -13
  27. package/dist/hooks/processSendCalls.cjs.map +1 -0
  28. package/dist/{methods → hooks}/processSendCalls.d.cts +4 -3
  29. package/dist/hooks/processSendCalls.d.cts.map +1 -0
  30. package/dist/{methods → hooks}/processSendCalls.d.mts +4 -3
  31. package/dist/hooks/processSendCalls.d.mts.map +1 -0
  32. package/dist/{methods → hooks}/processSendCalls.mjs +107 -15
  33. package/dist/hooks/processSendCalls.mjs.map +1 -0
  34. package/dist/index.cjs +10 -4
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +8 -4
  37. package/dist/index.d.cts.map +1 -1
  38. package/dist/index.d.mts +8 -4
  39. package/dist/index.d.mts.map +1 -1
  40. package/dist/index.mjs +6 -3
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/methods/wallet_getCallsStatus.cjs +24 -0
  43. package/dist/methods/wallet_getCallsStatus.cjs.map +1 -0
  44. package/dist/methods/wallet_getCallsStatus.d.cts +14 -0
  45. package/dist/methods/wallet_getCallsStatus.d.cts.map +1 -0
  46. package/dist/methods/wallet_getCallsStatus.d.mts +14 -0
  47. package/dist/methods/wallet_getCallsStatus.d.mts.map +1 -0
  48. package/dist/methods/wallet_getCallsStatus.mjs +20 -0
  49. package/dist/methods/wallet_getCallsStatus.mjs.map +1 -0
  50. package/dist/methods/wallet_getCapabilities.cjs +30 -0
  51. package/dist/methods/wallet_getCapabilities.cjs.map +1 -0
  52. package/dist/methods/wallet_getCapabilities.d.cts +16 -0
  53. package/dist/methods/wallet_getCapabilities.d.cts.map +1 -0
  54. package/dist/methods/wallet_getCapabilities.d.mts +16 -0
  55. package/dist/methods/wallet_getCapabilities.d.mts.map +1 -0
  56. package/dist/methods/wallet_getCapabilities.mjs +26 -0
  57. package/dist/methods/wallet_getCapabilities.mjs.map +1 -0
  58. package/dist/methods/wallet_sendCalls.cjs +34 -0
  59. package/dist/methods/wallet_sendCalls.cjs.map +1 -0
  60. package/dist/methods/wallet_sendCalls.d.cts +16 -0
  61. package/dist/methods/wallet_sendCalls.d.cts.map +1 -0
  62. package/dist/methods/wallet_sendCalls.d.mts +16 -0
  63. package/dist/methods/wallet_sendCalls.d.mts.map +1 -0
  64. package/dist/methods/wallet_sendCalls.mjs +30 -0
  65. package/dist/methods/wallet_sendCalls.mjs.map +1 -0
  66. package/dist/types.cjs +36 -0
  67. package/dist/types.cjs.map +1 -1
  68. package/dist/types.d.cts +82 -0
  69. package/dist/types.d.cts.map +1 -1
  70. package/dist/types.d.mts +82 -0
  71. package/dist/types.d.mts.map +1 -1
  72. package/dist/types.mjs +35 -1
  73. package/dist/types.mjs.map +1 -1
  74. package/dist/utils.cjs +70 -1
  75. package/dist/utils.cjs.map +1 -1
  76. package/dist/utils.d.cts +31 -1
  77. package/dist/utils.d.cts.map +1 -1
  78. package/dist/utils.d.mts +31 -1
  79. package/dist/utils.d.mts.map +1 -1
  80. package/dist/utils.mjs +67 -1
  81. package/dist/utils.mjs.map +1 -1
  82. package/package.json +7 -4
  83. package/dist/methods/getCallsStatus.cjs.map +0 -1
  84. package/dist/methods/getCallsStatus.d.cts.map +0 -1
  85. package/dist/methods/getCallsStatus.d.mts.map +0 -1
  86. package/dist/methods/getCallsStatus.mjs.map +0 -1
  87. package/dist/methods/getCapabilities.cjs.map +0 -1
  88. package/dist/methods/getCapabilities.d.cts.map +0 -1
  89. package/dist/methods/getCapabilities.d.mts.map +0 -1
  90. package/dist/methods/getCapabilities.mjs.map +0 -1
  91. package/dist/methods/processSendCalls.cjs.map +0 -1
  92. package/dist/methods/processSendCalls.d.cts.map +0 -1
  93. package/dist/methods/processSendCalls.d.mts.map +0 -1
  94. package/dist/methods/processSendCalls.mjs.map +0 -1
package/dist/types.d.cts CHANGED
@@ -2,8 +2,90 @@ import type { AccountsControllerGetSelectedAccountAction, AccountsControllerGetS
2
2
  import type { Messenger } from "@metamask/base-controller";
3
3
  import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction } from "@metamask/network-controller";
4
4
  import type { PreferencesControllerGetStateAction } from "@metamask/preferences-controller";
5
+ import type { Infer } from "@metamask/superstruct";
5
6
  import type { TransactionControllerGetStateAction } from "@metamask/transaction-controller";
7
+ import type { Hex, Json, JsonRpcRequest } from "@metamask/utils";
6
8
  type Actions = AccountsControllerGetStateAction | AccountsControllerGetSelectedAccountAction | NetworkControllerGetNetworkClientByIdAction | TransactionControllerGetStateAction | PreferencesControllerGetStateAction | NetworkControllerGetStateAction;
7
9
  export type EIP5792Messenger = Messenger<Actions, never>;
10
+ export type GetCallsStatusParams = Infer<typeof GetCallsStatusStruct>;
11
+ export type GetCallsStatusResult = {
12
+ version: string;
13
+ id: Hex;
14
+ chainId: Hex;
15
+ status: number;
16
+ atomic: boolean;
17
+ receipts?: {
18
+ logs: {
19
+ address: Hex;
20
+ data: Hex;
21
+ topics: Hex[];
22
+ }[];
23
+ status: '0x0' | '0x1';
24
+ blockHash: Hex;
25
+ blockNumber: Hex;
26
+ gasUsed: Hex;
27
+ transactionHash: Hex;
28
+ }[];
29
+ capabilities?: Record<string, Json>;
30
+ };
31
+ export type GetCallsStatusHook = (id: GetCallsStatusParams[0], req: JsonRpcRequest) => Promise<GetCallsStatusResult>;
32
+ export type GetCapabilitiesParams = Infer<typeof GetCapabilitiesStruct>;
33
+ export type GetCapabilitiesResult = Record<Hex, Record<string, Json>>;
34
+ export type GetCapabilitiesHook = (address: GetCapabilitiesParams[0], chainIds: GetCapabilitiesParams[1], req: JsonRpcRequest) => Promise<GetCapabilitiesResult>;
35
+ export type SendCallsParams = Infer<typeof SendCallsStruct>;
36
+ export type SendCallsPayload = SendCallsParams[0];
37
+ export type SendCallsRequiredAssetsParam = Infer<typeof RequiredAssetStruct>;
38
+ export type SendCallsResult = {
39
+ id: Hex;
40
+ capabilities?: Record<string, Json>;
41
+ };
42
+ export type ProcessSendCallsHook = (sendCalls: SendCallsPayload, req: JsonRpcRequest) => Promise<SendCallsResult>;
43
+ export declare const GetCallsStatusStruct: import("@metamask/superstruct").Struct<[`0x${string}`], null>;
44
+ export declare const GetCapabilitiesStruct: import("@metamask/superstruct").Struct<[`0x${string}`, `0x${string}`[] | undefined], null>;
45
+ declare const RequiredAssetStruct: import("@metamask/superstruct").Struct<{
46
+ address: `0x${string}`;
47
+ standard: string;
48
+ amount: `0x${string}`;
49
+ }, {
50
+ address: import("@metamask/superstruct").Struct<`0x${string}`, null>;
51
+ amount: import("@metamask/superstruct").Struct<`0x${string}`, null>;
52
+ standard: import("@metamask/superstruct").Struct<string, null>;
53
+ }>;
54
+ export declare const CapabilitiesStruct: import("@metamask/superstruct").Struct<Record<string, {
55
+ optional?: boolean | undefined;
56
+ requiredAssets?: {
57
+ address: `0x${string}`;
58
+ standard: string;
59
+ amount: `0x${string}`;
60
+ }[] | undefined;
61
+ }>, null>;
62
+ export declare const SendCallsStruct: import("@metamask/superstruct").Struct<[{
63
+ version: string;
64
+ chainId: `0x${string}`;
65
+ atomicRequired: boolean;
66
+ calls: {
67
+ data?: `0x${string}` | undefined;
68
+ value?: `0x${string}` | undefined;
69
+ to?: `0x${string}` | undefined;
70
+ capabilities?: Record<string, {
71
+ optional?: boolean | undefined;
72
+ requiredAssets?: {
73
+ address: `0x${string}`;
74
+ standard: string;
75
+ amount: `0x${string}`;
76
+ }[] | undefined;
77
+ }> | undefined;
78
+ }[];
79
+ id?: `0x${string}` | undefined;
80
+ from?: `0x${string}` | undefined;
81
+ capabilities?: Record<string, {
82
+ optional?: boolean | undefined;
83
+ requiredAssets?: {
84
+ address: `0x${string}`;
85
+ standard: string;
86
+ amount: `0x${string}`;
87
+ }[] | undefined;
88
+ }> | undefined;
89
+ }], null>;
8
90
  export {};
9
91
  //# sourceMappingURL=types.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0CAA0C,EAC1C,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AACtC,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAC5F,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAE5F,KAAK,OAAO,GACR,gCAAgC,GAChC,0CAA0C,GAC1C,2CAA2C,GAC3C,mCAAmC,GACnC,mCAAmC,GACnC,+BAA+B,CAAC;AAEpC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.d.mts CHANGED
@@ -2,8 +2,90 @@ import type { AccountsControllerGetSelectedAccountAction, AccountsControllerGetS
2
2
  import type { Messenger } from "@metamask/base-controller";
3
3
  import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction } from "@metamask/network-controller";
4
4
  import type { PreferencesControllerGetStateAction } from "@metamask/preferences-controller";
5
+ import type { Infer } from "@metamask/superstruct";
5
6
  import type { TransactionControllerGetStateAction } from "@metamask/transaction-controller";
7
+ import type { Hex, Json, JsonRpcRequest } from "@metamask/utils";
6
8
  type Actions = AccountsControllerGetStateAction | AccountsControllerGetSelectedAccountAction | NetworkControllerGetNetworkClientByIdAction | TransactionControllerGetStateAction | PreferencesControllerGetStateAction | NetworkControllerGetStateAction;
7
9
  export type EIP5792Messenger = Messenger<Actions, never>;
10
+ export type GetCallsStatusParams = Infer<typeof GetCallsStatusStruct>;
11
+ export type GetCallsStatusResult = {
12
+ version: string;
13
+ id: Hex;
14
+ chainId: Hex;
15
+ status: number;
16
+ atomic: boolean;
17
+ receipts?: {
18
+ logs: {
19
+ address: Hex;
20
+ data: Hex;
21
+ topics: Hex[];
22
+ }[];
23
+ status: '0x0' | '0x1';
24
+ blockHash: Hex;
25
+ blockNumber: Hex;
26
+ gasUsed: Hex;
27
+ transactionHash: Hex;
28
+ }[];
29
+ capabilities?: Record<string, Json>;
30
+ };
31
+ export type GetCallsStatusHook = (id: GetCallsStatusParams[0], req: JsonRpcRequest) => Promise<GetCallsStatusResult>;
32
+ export type GetCapabilitiesParams = Infer<typeof GetCapabilitiesStruct>;
33
+ export type GetCapabilitiesResult = Record<Hex, Record<string, Json>>;
34
+ export type GetCapabilitiesHook = (address: GetCapabilitiesParams[0], chainIds: GetCapabilitiesParams[1], req: JsonRpcRequest) => Promise<GetCapabilitiesResult>;
35
+ export type SendCallsParams = Infer<typeof SendCallsStruct>;
36
+ export type SendCallsPayload = SendCallsParams[0];
37
+ export type SendCallsRequiredAssetsParam = Infer<typeof RequiredAssetStruct>;
38
+ export type SendCallsResult = {
39
+ id: Hex;
40
+ capabilities?: Record<string, Json>;
41
+ };
42
+ export type ProcessSendCallsHook = (sendCalls: SendCallsPayload, req: JsonRpcRequest) => Promise<SendCallsResult>;
43
+ export declare const GetCallsStatusStruct: import("@metamask/superstruct").Struct<[`0x${string}`], null>;
44
+ export declare const GetCapabilitiesStruct: import("@metamask/superstruct").Struct<[`0x${string}`, `0x${string}`[] | undefined], null>;
45
+ declare const RequiredAssetStruct: import("@metamask/superstruct").Struct<{
46
+ address: `0x${string}`;
47
+ standard: string;
48
+ amount: `0x${string}`;
49
+ }, {
50
+ address: import("@metamask/superstruct").Struct<`0x${string}`, null>;
51
+ amount: import("@metamask/superstruct").Struct<`0x${string}`, null>;
52
+ standard: import("@metamask/superstruct").Struct<string, null>;
53
+ }>;
54
+ export declare const CapabilitiesStruct: import("@metamask/superstruct").Struct<Record<string, {
55
+ optional?: boolean | undefined;
56
+ requiredAssets?: {
57
+ address: `0x${string}`;
58
+ standard: string;
59
+ amount: `0x${string}`;
60
+ }[] | undefined;
61
+ }>, null>;
62
+ export declare const SendCallsStruct: import("@metamask/superstruct").Struct<[{
63
+ version: string;
64
+ chainId: `0x${string}`;
65
+ atomicRequired: boolean;
66
+ calls: {
67
+ data?: `0x${string}` | undefined;
68
+ value?: `0x${string}` | undefined;
69
+ to?: `0x${string}` | undefined;
70
+ capabilities?: Record<string, {
71
+ optional?: boolean | undefined;
72
+ requiredAssets?: {
73
+ address: `0x${string}`;
74
+ standard: string;
75
+ amount: `0x${string}`;
76
+ }[] | undefined;
77
+ }> | undefined;
78
+ }[];
79
+ id?: `0x${string}` | undefined;
80
+ from?: `0x${string}` | undefined;
81
+ capabilities?: Record<string, {
82
+ optional?: boolean | undefined;
83
+ requiredAssets?: {
84
+ address: `0x${string}`;
85
+ standard: string;
86
+ amount: `0x${string}`;
87
+ }[] | undefined;
88
+ }> | undefined;
89
+ }], null>;
8
90
  export {};
9
91
  //# sourceMappingURL=types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0CAA0C,EAC1C,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AACtC,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAC5F,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAE5F,KAAK,OAAO,GACR,gCAAgC,GAChC,0CAA0C,GAC1C,2CAA2C,GAC3C,mCAAmC,GACnC,mCAAmC,GACnC,+BAA+B,CAAC;AAEpC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.mjs CHANGED
@@ -1,2 +1,36 @@
1
- export {};
1
+ import { array, boolean, nonempty, object, optional, record, string, tuple, type } from "@metamask/superstruct";
2
+ import { HexChecksumAddressStruct, StrictHexStruct } from "@metamask/utils";
3
+ // /** Structs **/
4
+ // Even though these aren't actually typescript types, these structs essentially represent
5
+ // runtime types, so we keep them in this file.
6
+ export const GetCallsStatusStruct = tuple([StrictHexStruct]);
7
+ export const GetCapabilitiesStruct = tuple([
8
+ HexChecksumAddressStruct,
9
+ optional(array(StrictHexStruct)),
10
+ ]);
11
+ const RequiredAssetStruct = type({
12
+ address: nonempty(HexChecksumAddressStruct),
13
+ amount: nonempty(StrictHexStruct),
14
+ standard: nonempty(string()),
15
+ });
16
+ export const CapabilitiesStruct = record(string(), type({
17
+ optional: optional(boolean()),
18
+ requiredAssets: optional(array(RequiredAssetStruct)),
19
+ }));
20
+ export const SendCallsStruct = tuple([
21
+ object({
22
+ version: nonempty(string()),
23
+ id: optional(StrictHexStruct),
24
+ from: optional(HexChecksumAddressStruct),
25
+ chainId: StrictHexStruct,
26
+ atomicRequired: boolean(),
27
+ calls: array(object({
28
+ to: optional(HexChecksumAddressStruct),
29
+ data: optional(StrictHexStruct),
30
+ value: optional(StrictHexStruct),
31
+ capabilities: optional(CapabilitiesStruct),
32
+ })),
33
+ capabilities: optional(CapabilitiesStruct),
34
+ }),
35
+ ]);
2
36
  //# sourceMappingURL=types.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type { Messenger } from '@metamask/base-controller';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport type { TransactionControllerGetStateAction } from '@metamask/transaction-controller';\n\ntype Actions =\n | AccountsControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetNetworkClientByIdAction\n | TransactionControllerGetStateAction\n | PreferencesControllerGetStateAction\n | NetworkControllerGetStateAction;\n\nexport type EIP5792Messenger = Messenger<Actions, never>;\n"]}
1
+ {"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,EACN,KAAK,EACL,IAAI,EACL,8BAA8B;AAG/B,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,wBAAwB;AAmE5E,kBAAkB;AAClB,0FAA0F;AAC1F,+CAA+C;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;IACzC,wBAAwB;IACxB,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,QAAQ,CAAC,wBAAwB,CAAC;IAC3C,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;IACjC,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;CAC7B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CACtC,MAAM,EAAE,EACR,IAAI,CAAC;IACH,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC7B,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;CACrD,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;IACnC,MAAM,CAAC;QACL,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC3B,EAAE,EAAE,QAAQ,CAAC,eAAe,CAAC;QAC7B,IAAI,EAAE,QAAQ,CAAC,wBAAwB,CAAC;QACxC,OAAO,EAAE,eAAe;QACxB,cAAc,EAAE,OAAO,EAAE;QACzB,KAAK,EAAE,KAAK,CACV,MAAM,CAAC;YACL,EAAE,EAAE,QAAQ,CAAC,wBAAwB,CAAC;YACtC,IAAI,EAAE,QAAQ,CAAC,eAAe,CAAC;YAC/B,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC;YAChC,YAAY,EAAE,QAAQ,CAAC,kBAAkB,CAAC;SAC3C,CAAC,CACH;QACD,YAAY,EAAE,QAAQ,CAAC,kBAAkB,CAAC;KAC3C,CAAC;CACH,CAAC,CAAC","sourcesContent":["import type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type { Messenger } from '@metamask/base-controller';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport type { Infer } from '@metamask/superstruct';\nimport {\n array,\n boolean,\n nonempty,\n object,\n optional,\n record,\n string,\n tuple,\n type,\n} from '@metamask/superstruct';\nimport type { TransactionControllerGetStateAction } from '@metamask/transaction-controller';\nimport type { Hex, Json, JsonRpcRequest } from '@metamask/utils';\nimport { HexChecksumAddressStruct, StrictHexStruct } from '@metamask/utils';\n\ntype Actions =\n | AccountsControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetNetworkClientByIdAction\n | TransactionControllerGetStateAction\n | PreferencesControllerGetStateAction\n | NetworkControllerGetStateAction;\n\nexport type EIP5792Messenger = Messenger<Actions, never>;\n\n// wallet_getCallStatus\nexport type GetCallsStatusParams = Infer<typeof GetCallsStatusStruct>;\n\nexport type GetCallsStatusResult = {\n version: string;\n id: Hex;\n chainId: Hex;\n status: number;\n atomic: boolean;\n receipts?: {\n logs: {\n address: Hex;\n data: Hex;\n topics: Hex[];\n }[];\n status: '0x0' | '0x1';\n blockHash: Hex;\n blockNumber: Hex;\n gasUsed: Hex;\n transactionHash: Hex;\n }[];\n capabilities?: Record<string, Json>;\n};\n\nexport type GetCallsStatusHook = (\n id: GetCallsStatusParams[0],\n req: JsonRpcRequest,\n) => Promise<GetCallsStatusResult>;\n\n// wallet_getCapabilities\nexport type GetCapabilitiesParams = Infer<typeof GetCapabilitiesStruct>;\nexport type GetCapabilitiesResult = Record<Hex, Record<string, Json>>;\n\nexport type GetCapabilitiesHook = (\n address: GetCapabilitiesParams[0],\n chainIds: GetCapabilitiesParams[1],\n req: JsonRpcRequest,\n) => Promise<GetCapabilitiesResult>;\n\n// wallet_sendCalls\nexport type SendCallsParams = Infer<typeof SendCallsStruct>;\nexport type SendCallsPayload = SendCallsParams[0];\n\nexport type SendCallsRequiredAssetsParam = Infer<typeof RequiredAssetStruct>;\n\nexport type SendCallsResult = {\n id: Hex;\n capabilities?: Record<string, Json>;\n};\n\nexport type ProcessSendCallsHook = (\n sendCalls: SendCallsPayload,\n req: JsonRpcRequest,\n) => Promise<SendCallsResult>;\n\n// /** Structs **/\n// Even though these aren't actually typescript types, these structs essentially represent\n// runtime types, so we keep them in this file.\nexport const GetCallsStatusStruct = tuple([StrictHexStruct]);\n\nexport const GetCapabilitiesStruct = tuple([\n HexChecksumAddressStruct,\n optional(array(StrictHexStruct)),\n]);\n\nconst RequiredAssetStruct = type({\n address: nonempty(HexChecksumAddressStruct),\n amount: nonempty(StrictHexStruct),\n standard: nonempty(string()),\n});\n\nexport const CapabilitiesStruct = record(\n string(),\n type({\n optional: optional(boolean()),\n requiredAssets: optional(array(RequiredAssetStruct)),\n }),\n);\n\nexport const SendCallsStruct = tuple([\n object({\n version: nonempty(string()),\n id: optional(StrictHexStruct),\n from: optional(HexChecksumAddressStruct),\n chainId: StrictHexStruct,\n atomicRequired: boolean(),\n calls: array(\n object({\n to: optional(HexChecksumAddressStruct),\n data: optional(StrictHexStruct),\n value: optional(StrictHexStruct),\n capabilities: optional(CapabilitiesStruct),\n }),\n ),\n capabilities: optional(CapabilitiesStruct),\n }),\n]);\n"]}
package/dist/utils.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAccountKeyringType = void 0;
3
+ exports.resemblesAddress = exports.validateParams = exports.validateAndNormalizeKeyholder = exports.getAccountKeyringType = void 0;
4
4
  const rpc_errors_1 = require("@metamask/rpc-errors");
5
+ const superstruct_1 = require("@metamask/superstruct");
5
6
  const constants_1 = require("./constants.cjs");
6
7
  /**
7
8
  * Retrieves the keyring type for a given account address.
@@ -21,4 +22,72 @@ function getAccountKeyringType(accountAddress, messenger) {
21
22
  return keyringType;
22
23
  }
23
24
  exports.getAccountKeyringType = getAccountKeyringType;
25
+ /**
26
+ * Validates and normalizes a keyholder address for EIP-5792 operations.
27
+ *
28
+ * @param address - The Ethereum address to validate and normalize.
29
+ * @param req - The JSON-RPC request object for permission checking.
30
+ * @param options - Configuration object containing the getAccounts function.
31
+ * @param options.getAccounts - Function to retrieve accounts for the requester.
32
+ * @returns A normalized (lowercase) hex address if valid and authorized.
33
+ * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.
34
+ * @throws JsonRpcError with invalid params if the address format is invalid.
35
+ */
36
+ async function validateAndNormalizeKeyholder(address, req, { getAccounts }) {
37
+ if (typeof address === 'string' &&
38
+ address.length > 0 &&
39
+ resemblesAddress(address)) {
40
+ // Ensure that an "unauthorized" error is thrown if the requester
41
+ // does not have the `eth_accounts` permission.
42
+ const accounts = await getAccounts(req);
43
+ const normalizedAccounts = accounts.map((_address) => _address.toLowerCase());
44
+ const normalizedAddress = address.toLowerCase();
45
+ if (normalizedAccounts.includes(normalizedAddress)) {
46
+ return normalizedAddress;
47
+ }
48
+ throw rpc_errors_1.providerErrors.unauthorized();
49
+ }
50
+ throw rpc_errors_1.rpcErrors.invalidParams({
51
+ message: `Invalid parameters: must provide an Ethereum address.`,
52
+ });
53
+ }
54
+ exports.validateAndNormalizeKeyholder = validateAndNormalizeKeyholder;
55
+ /**
56
+ * Validates parameters against a Superstruct schema and throws an error if validation fails.
57
+ *
58
+ * @param value - The value to validate against the struct schema.
59
+ * @param struct - The Superstruct schema to validate against.
60
+ * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.
61
+ */
62
+ function validateParams(value, struct) {
63
+ const [error] = (0, superstruct_1.validate)(value, struct);
64
+ if (error) {
65
+ throw rpc_errors_1.rpcErrors.invalidParams(formatValidationError(error, `Invalid params`));
66
+ }
67
+ }
68
+ exports.validateParams = validateParams;
69
+ /**
70
+ * Checks if a string resembles an Ethereum address format.
71
+ *
72
+ * @param str - The string to check for address-like format.
73
+ * @returns True if the string has the correct length for an Ethereum address.
74
+ */
75
+ function resemblesAddress(str) {
76
+ // hex prefix 2 + 20 bytes
77
+ return str.length === 2 + 20 * 2;
78
+ }
79
+ exports.resemblesAddress = resemblesAddress;
80
+ /**
81
+ * Formats a Superstruct validation error into a human-readable string.
82
+ *
83
+ * @param error - The Superstruct validation error to format.
84
+ * @param message - The base error message to prepend to the formatted details.
85
+ * @returns A formatted error message string with validation failure details.
86
+ */
87
+ function formatValidationError(error, message) {
88
+ return `${message}\n\n${error
89
+ .failures()
90
+ .map((f) => `${f.path.join(' > ')}${f.path.length ? ' - ' : ''}${f.message}`)
91
+ .join('\n')}`;
92
+ }
24
93
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AACA,qDAAoD;AAGpD,+CAA+C;AAG/C;;;;;;;GAOG;AACH,SAAgB,qBAAqB,CACnC,cAAmB,EACnB,SAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CACjC,6BAA6B,CAC9B,CAAC,gBAAgB,CAAC;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,WAAW,EAAE,CACpE,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;IAErD,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,yBAAY,CACpB,4BAAgB,CAAC,eAAe,EAChC,2DAA2D,CAC5D,CAAC;KACH;IAED,OAAO,WAA2B,CAAC;AACrC,CAAC;AAtBD,sDAsBC","sourcesContent":["import type { KeyringTypes } from '@metamask/keyring-controller';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\n\nimport { EIP5792ErrorCode } from './constants';\nimport type { EIP5792Messenger } from './types';\n\n/**\n * Retrieves the keyring type for a given account address.\n *\n * @param accountAddress - The account address to look up.\n * @param messenger - Messenger instance for controller communication.\n * @returns The keyring type associated with the account.\n * @throws JsonRpcError if the account type is unknown or not found.\n */\nexport function getAccountKeyringType(\n accountAddress: Hex,\n messenger: EIP5792Messenger,\n): KeyringTypes {\n const { accounts } = messenger.call(\n 'AccountsController:getState',\n ).internalAccounts;\n\n const account = Object.values(accounts).find(\n (acc) => acc.address.toLowerCase() === accountAddress.toLowerCase(),\n );\n\n const keyringType = account?.metadata?.keyring?.type;\n\n if (!keyringType) {\n throw new JsonRpcError(\n EIP5792ErrorCode.RejectedUpgrade,\n 'EIP-7702 upgrade not supported as account type is unknown',\n );\n }\n\n return keyringType as KeyringTypes;\n}\n"]}
1
+ {"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AACA,qDAA+E;AAE/E,uDAAiD;AAGjD,+CAA+C;AAG/C;;;;;;;GAOG;AACH,SAAgB,qBAAqB,CACnC,cAAmB,EACnB,SAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CACjC,6BAA6B,CAC9B,CAAC,gBAAgB,CAAC;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,WAAW,EAAE,CACpE,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;IAErD,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,yBAAY,CACpB,4BAAgB,CAAC,eAAe,EAChC,2DAA2D,CAC5D,CAAC;KACH;IAED,OAAO,WAA2B,CAAC;AACrC,CAAC;AAtBD,sDAsBC;AAED;;;;;;;;;;GAUG;AACI,KAAK,UAAU,6BAA6B,CACjD,OAAY,EACZ,GAAmB,EACnB,EAAE,WAAW,EAA+D;IAE5E,IACE,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,CAAC,MAAM,GAAG,CAAC;QAClB,gBAAgB,CAAC,OAAO,CAAC,EACzB;QACA,iEAAiE;QACjE,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QAExC,MAAM,kBAAkB,GAAa,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC7D,QAAQ,CAAC,WAAW,EAAE,CACvB,CAAC;QAEF,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAS,CAAC;QAEvD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;YAClD,OAAO,iBAAiB,CAAC;SAC1B;QAED,MAAM,2BAAc,CAAC,YAAY,EAAE,CAAC;KACrC;IAED,MAAM,sBAAS,CAAC,aAAa,CAAC;QAC5B,OAAO,EAAE,uDAAuD;KACjE,CAAC,CAAC;AACL,CAAC;AA9BD,sEA8BC;AAED;;;;;;GAMG;AACH,SAAgB,cAAc,CAC5B,KAA2B,EAC3B,MAA0B;IAE1B,MAAM,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAQ,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAExC,IAAI,KAAK,EAAE;QACT,MAAM,sBAAS,CAAC,aAAa,CAC3B,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAC/C,CAAC;KACH;AACH,CAAC;AAXD,wCAWC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,0BAA0B;IAC1B,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAHD,4CAGC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,KAAkB,EAAE,OAAe;IAChE,OAAO,GAAG,OAAO,OAAO,KAAK;SAC1B,QAAQ,EAAE;SACV,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CACxE;SACA,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClB,CAAC","sourcesContent":["import type { KeyringTypes } from '@metamask/keyring-controller';\nimport { JsonRpcError, providerErrors, rpcErrors } from '@metamask/rpc-errors';\nimport type { Struct, StructError } from '@metamask/superstruct';\nimport { validate } from '@metamask/superstruct';\nimport type { Hex, JsonRpcRequest } from '@metamask/utils';\n\nimport { EIP5792ErrorCode } from './constants';\nimport type { EIP5792Messenger } from './types';\n\n/**\n * Retrieves the keyring type for a given account address.\n *\n * @param accountAddress - The account address to look up.\n * @param messenger - Messenger instance for controller communication.\n * @returns The keyring type associated with the account.\n * @throws JsonRpcError if the account type is unknown or not found.\n */\nexport function getAccountKeyringType(\n accountAddress: Hex,\n messenger: EIP5792Messenger,\n): KeyringTypes {\n const { accounts } = messenger.call(\n 'AccountsController:getState',\n ).internalAccounts;\n\n const account = Object.values(accounts).find(\n (acc) => acc.address.toLowerCase() === accountAddress.toLowerCase(),\n );\n\n const keyringType = account?.metadata?.keyring?.type;\n\n if (!keyringType) {\n throw new JsonRpcError(\n EIP5792ErrorCode.RejectedUpgrade,\n 'EIP-7702 upgrade not supported as account type is unknown',\n );\n }\n\n return keyringType as KeyringTypes;\n}\n\n/**\n * Validates and normalizes a keyholder address for EIP-5792 operations.\n *\n * @param address - The Ethereum address to validate and normalize.\n * @param req - The JSON-RPC request object for permission checking.\n * @param options - Configuration object containing the getAccounts function.\n * @param options.getAccounts - Function to retrieve accounts for the requester.\n * @returns A normalized (lowercase) hex address if valid and authorized.\n * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.\n * @throws JsonRpcError with invalid params if the address format is invalid.\n */\nexport async function validateAndNormalizeKeyholder(\n address: Hex,\n req: JsonRpcRequest,\n { getAccounts }: { getAccounts: (req: JsonRpcRequest) => Promise<string[]> },\n): Promise<Hex> {\n if (\n typeof address === 'string' &&\n address.length > 0 &&\n resemblesAddress(address)\n ) {\n // Ensure that an \"unauthorized\" error is thrown if the requester\n // does not have the `eth_accounts` permission.\n const accounts = await getAccounts(req);\n\n const normalizedAccounts: string[] = accounts.map((_address) =>\n _address.toLowerCase(),\n );\n\n const normalizedAddress = address.toLowerCase() as Hex;\n\n if (normalizedAccounts.includes(normalizedAddress)) {\n return normalizedAddress;\n }\n\n throw providerErrors.unauthorized();\n }\n\n throw rpcErrors.invalidParams({\n message: `Invalid parameters: must provide an Ethereum address.`,\n });\n}\n\n/**\n * Validates parameters against a Superstruct schema and throws an error if validation fails.\n *\n * @param value - The value to validate against the struct schema.\n * @param struct - The Superstruct schema to validate against.\n * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.\n */\nexport function validateParams<ParamsType>(\n value: unknown | ParamsType,\n struct: Struct<ParamsType>,\n): asserts value is ParamsType {\n const [error] = validate(value, struct);\n\n if (error) {\n throw rpcErrors.invalidParams(\n formatValidationError(error, `Invalid params`),\n );\n }\n}\n\n/**\n * Checks if a string resembles an Ethereum address format.\n *\n * @param str - The string to check for address-like format.\n * @returns True if the string has the correct length for an Ethereum address.\n */\nexport function resemblesAddress(str: string): boolean {\n // hex prefix 2 + 20 bytes\n return str.length === 2 + 20 * 2;\n}\n\n/**\n * Formats a Superstruct validation error into a human-readable string.\n *\n * @param error - The Superstruct validation error to format.\n * @param message - The base error message to prepend to the formatted details.\n * @returns A formatted error message string with validation failure details.\n */\nfunction formatValidationError(error: StructError, message: string): string {\n return `${message}\\n\\n${error\n .failures()\n .map(\n (f) => `${f.path.join(' > ')}${f.path.length ? ' - ' : ''}${f.message}`,\n )\n .join('\\n')}`;\n}\n"]}
package/dist/utils.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { KeyringTypes } from "@metamask/keyring-controller";
2
- import type { Hex } from "@metamask/utils";
2
+ import type { Struct } from "@metamask/superstruct";
3
+ import type { Hex, JsonRpcRequest } from "@metamask/utils";
3
4
  import type { EIP5792Messenger } from "./types.cjs";
4
5
  /**
5
6
  * Retrieves the keyring type for a given account address.
@@ -10,4 +11,33 @@ import type { EIP5792Messenger } from "./types.cjs";
10
11
  * @throws JsonRpcError if the account type is unknown or not found.
11
12
  */
12
13
  export declare function getAccountKeyringType(accountAddress: Hex, messenger: EIP5792Messenger): KeyringTypes;
14
+ /**
15
+ * Validates and normalizes a keyholder address for EIP-5792 operations.
16
+ *
17
+ * @param address - The Ethereum address to validate and normalize.
18
+ * @param req - The JSON-RPC request object for permission checking.
19
+ * @param options - Configuration object containing the getAccounts function.
20
+ * @param options.getAccounts - Function to retrieve accounts for the requester.
21
+ * @returns A normalized (lowercase) hex address if valid and authorized.
22
+ * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.
23
+ * @throws JsonRpcError with invalid params if the address format is invalid.
24
+ */
25
+ export declare function validateAndNormalizeKeyholder(address: Hex, req: JsonRpcRequest, { getAccounts }: {
26
+ getAccounts: (req: JsonRpcRequest) => Promise<string[]>;
27
+ }): Promise<Hex>;
28
+ /**
29
+ * Validates parameters against a Superstruct schema and throws an error if validation fails.
30
+ *
31
+ * @param value - The value to validate against the struct schema.
32
+ * @param struct - The Superstruct schema to validate against.
33
+ * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.
34
+ */
35
+ export declare function validateParams<ParamsType>(value: unknown | ParamsType, struct: Struct<ParamsType>): asserts value is ParamsType;
36
+ /**
37
+ * Checks if a string resembles an Ethereum address format.
38
+ *
39
+ * @param str - The string to check for address-like format.
40
+ * @returns True if the string has the correct length for an Ethereum address.
41
+ */
42
+ export declare function resemblesAddress(str: string): boolean;
13
43
  //# sourceMappingURL=utils.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qCAAqC;AAEjE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAgB;AAEhD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,gBAAgB,GAC1B,YAAY,CAmBd"}
1
+ {"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qCAAqC;AAEjE,OAAO,KAAK,EAAE,MAAM,EAAe,8BAA8B;AAEjE,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,wBAAwB;AAG3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAgB;AAEhD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,gBAAgB,GAC1B,YAAY,CAmBd;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,cAAc,EACnB,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC,GAAG,CAAC,CA0Bd;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,UAAU,EACvC,KAAK,EAAE,OAAO,GAAG,UAAU,EAC3B,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,GACzB,OAAO,CAAC,KAAK,IAAI,UAAU,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGrD"}
package/dist/utils.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { KeyringTypes } from "@metamask/keyring-controller";
2
- import type { Hex } from "@metamask/utils";
2
+ import type { Struct } from "@metamask/superstruct";
3
+ import type { Hex, JsonRpcRequest } from "@metamask/utils";
3
4
  import type { EIP5792Messenger } from "./types.mjs";
4
5
  /**
5
6
  * Retrieves the keyring type for a given account address.
@@ -10,4 +11,33 @@ import type { EIP5792Messenger } from "./types.mjs";
10
11
  * @throws JsonRpcError if the account type is unknown or not found.
11
12
  */
12
13
  export declare function getAccountKeyringType(accountAddress: Hex, messenger: EIP5792Messenger): KeyringTypes;
14
+ /**
15
+ * Validates and normalizes a keyholder address for EIP-5792 operations.
16
+ *
17
+ * @param address - The Ethereum address to validate and normalize.
18
+ * @param req - The JSON-RPC request object for permission checking.
19
+ * @param options - Configuration object containing the getAccounts function.
20
+ * @param options.getAccounts - Function to retrieve accounts for the requester.
21
+ * @returns A normalized (lowercase) hex address if valid and authorized.
22
+ * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.
23
+ * @throws JsonRpcError with invalid params if the address format is invalid.
24
+ */
25
+ export declare function validateAndNormalizeKeyholder(address: Hex, req: JsonRpcRequest, { getAccounts }: {
26
+ getAccounts: (req: JsonRpcRequest) => Promise<string[]>;
27
+ }): Promise<Hex>;
28
+ /**
29
+ * Validates parameters against a Superstruct schema and throws an error if validation fails.
30
+ *
31
+ * @param value - The value to validate against the struct schema.
32
+ * @param struct - The Superstruct schema to validate against.
33
+ * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.
34
+ */
35
+ export declare function validateParams<ParamsType>(value: unknown | ParamsType, struct: Struct<ParamsType>): asserts value is ParamsType;
36
+ /**
37
+ * Checks if a string resembles an Ethereum address format.
38
+ *
39
+ * @param str - The string to check for address-like format.
40
+ * @returns True if the string has the correct length for an Ethereum address.
41
+ */
42
+ export declare function resemblesAddress(str: string): boolean;
13
43
  //# sourceMappingURL=utils.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qCAAqC;AAEjE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAgB;AAEhD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,gBAAgB,GAC1B,YAAY,CAmBd"}
1
+ {"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qCAAqC;AAEjE,OAAO,KAAK,EAAE,MAAM,EAAe,8BAA8B;AAEjE,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,wBAAwB;AAG3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAgB;AAEhD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,gBAAgB,GAC1B,YAAY,CAmBd;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,cAAc,EACnB,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC,GAAG,CAAC,CA0Bd;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,UAAU,EACvC,KAAK,EAAE,OAAO,GAAG,UAAU,EAC3B,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,GACzB,OAAO,CAAC,KAAK,IAAI,UAAU,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGrD"}
package/dist/utils.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { JsonRpcError } from "@metamask/rpc-errors";
1
+ import { JsonRpcError, providerErrors, rpcErrors } from "@metamask/rpc-errors";
2
+ import { validate } from "@metamask/superstruct";
2
3
  import { EIP5792ErrorCode } from "./constants.mjs";
3
4
  /**
4
5
  * Retrieves the keyring type for a given account address.
@@ -17,4 +18,69 @@ export function getAccountKeyringType(accountAddress, messenger) {
17
18
  }
18
19
  return keyringType;
19
20
  }
21
+ /**
22
+ * Validates and normalizes a keyholder address for EIP-5792 operations.
23
+ *
24
+ * @param address - The Ethereum address to validate and normalize.
25
+ * @param req - The JSON-RPC request object for permission checking.
26
+ * @param options - Configuration object containing the getAccounts function.
27
+ * @param options.getAccounts - Function to retrieve accounts for the requester.
28
+ * @returns A normalized (lowercase) hex address if valid and authorized.
29
+ * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.
30
+ * @throws JsonRpcError with invalid params if the address format is invalid.
31
+ */
32
+ export async function validateAndNormalizeKeyholder(address, req, { getAccounts }) {
33
+ if (typeof address === 'string' &&
34
+ address.length > 0 &&
35
+ resemblesAddress(address)) {
36
+ // Ensure that an "unauthorized" error is thrown if the requester
37
+ // does not have the `eth_accounts` permission.
38
+ const accounts = await getAccounts(req);
39
+ const normalizedAccounts = accounts.map((_address) => _address.toLowerCase());
40
+ const normalizedAddress = address.toLowerCase();
41
+ if (normalizedAccounts.includes(normalizedAddress)) {
42
+ return normalizedAddress;
43
+ }
44
+ throw providerErrors.unauthorized();
45
+ }
46
+ throw rpcErrors.invalidParams({
47
+ message: `Invalid parameters: must provide an Ethereum address.`,
48
+ });
49
+ }
50
+ /**
51
+ * Validates parameters against a Superstruct schema and throws an error if validation fails.
52
+ *
53
+ * @param value - The value to validate against the struct schema.
54
+ * @param struct - The Superstruct schema to validate against.
55
+ * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.
56
+ */
57
+ export function validateParams(value, struct) {
58
+ const [error] = validate(value, struct);
59
+ if (error) {
60
+ throw rpcErrors.invalidParams(formatValidationError(error, `Invalid params`));
61
+ }
62
+ }
63
+ /**
64
+ * Checks if a string resembles an Ethereum address format.
65
+ *
66
+ * @param str - The string to check for address-like format.
67
+ * @returns True if the string has the correct length for an Ethereum address.
68
+ */
69
+ export function resemblesAddress(str) {
70
+ // hex prefix 2 + 20 bytes
71
+ return str.length === 2 + 20 * 2;
72
+ }
73
+ /**
74
+ * Formats a Superstruct validation error into a human-readable string.
75
+ *
76
+ * @param error - The Superstruct validation error to format.
77
+ * @param message - The base error message to prepend to the formatted details.
78
+ * @returns A formatted error message string with validation failure details.
79
+ */
80
+ function formatValidationError(error, message) {
81
+ return `${message}\n\n${error
82
+ .failures()
83
+ .map((f) => `${f.path.join(' > ')}${f.path.length ? ' - ' : ''}${f.message}`)
84
+ .join('\n')}`;
85
+ }
20
86
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,6BAA6B;AAGpD,OAAO,EAAE,gBAAgB,EAAE,wBAAoB;AAG/C;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,cAAmB,EACnB,SAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CACjC,6BAA6B,CAC9B,CAAC,gBAAgB,CAAC;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,WAAW,EAAE,CACpE,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;IAErD,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,YAAY,CACpB,gBAAgB,CAAC,eAAe,EAChC,2DAA2D,CAC5D,CAAC;KACH;IAED,OAAO,WAA2B,CAAC;AACrC,CAAC","sourcesContent":["import type { KeyringTypes } from '@metamask/keyring-controller';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\n\nimport { EIP5792ErrorCode } from './constants';\nimport type { EIP5792Messenger } from './types';\n\n/**\n * Retrieves the keyring type for a given account address.\n *\n * @param accountAddress - The account address to look up.\n * @param messenger - Messenger instance for controller communication.\n * @returns The keyring type associated with the account.\n * @throws JsonRpcError if the account type is unknown or not found.\n */\nexport function getAccountKeyringType(\n accountAddress: Hex,\n messenger: EIP5792Messenger,\n): KeyringTypes {\n const { accounts } = messenger.call(\n 'AccountsController:getState',\n ).internalAccounts;\n\n const account = Object.values(accounts).find(\n (acc) => acc.address.toLowerCase() === accountAddress.toLowerCase(),\n );\n\n const keyringType = account?.metadata?.keyring?.type;\n\n if (!keyringType) {\n throw new JsonRpcError(\n EIP5792ErrorCode.RejectedUpgrade,\n 'EIP-7702 upgrade not supported as account type is unknown',\n );\n }\n\n return keyringType as KeyringTypes;\n}\n"]}
1
+ {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,6BAA6B;AAE/E,OAAO,EAAE,QAAQ,EAAE,8BAA8B;AAGjD,OAAO,EAAE,gBAAgB,EAAE,wBAAoB;AAG/C;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,cAAmB,EACnB,SAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CACjC,6BAA6B,CAC9B,CAAC,gBAAgB,CAAC;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,WAAW,EAAE,CACpE,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;IAErD,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,YAAY,CACpB,gBAAgB,CAAC,eAAe,EAChC,2DAA2D,CAC5D,CAAC;KACH;IAED,OAAO,WAA2B,CAAC;AACrC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAY,EACZ,GAAmB,EACnB,EAAE,WAAW,EAA+D;IAE5E,IACE,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,CAAC,MAAM,GAAG,CAAC;QAClB,gBAAgB,CAAC,OAAO,CAAC,EACzB;QACA,iEAAiE;QACjE,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QAExC,MAAM,kBAAkB,GAAa,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC7D,QAAQ,CAAC,WAAW,EAAE,CACvB,CAAC;QAEF,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAS,CAAC;QAEvD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;YAClD,OAAO,iBAAiB,CAAC;SAC1B;QAED,MAAM,cAAc,CAAC,YAAY,EAAE,CAAC;KACrC;IAED,MAAM,SAAS,CAAC,aAAa,CAAC;QAC5B,OAAO,EAAE,uDAAuD;KACjE,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,KAA2B,EAC3B,MAA0B;IAE1B,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAExC,IAAI,KAAK,EAAE;QACT,MAAM,SAAS,CAAC,aAAa,CAC3B,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAC/C,CAAC;KACH;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,0BAA0B;IAC1B,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,KAAkB,EAAE,OAAe;IAChE,OAAO,GAAG,OAAO,OAAO,KAAK;SAC1B,QAAQ,EAAE;SACV,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CACxE;SACA,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClB,CAAC","sourcesContent":["import type { KeyringTypes } from '@metamask/keyring-controller';\nimport { JsonRpcError, providerErrors, rpcErrors } from '@metamask/rpc-errors';\nimport type { Struct, StructError } from '@metamask/superstruct';\nimport { validate } from '@metamask/superstruct';\nimport type { Hex, JsonRpcRequest } from '@metamask/utils';\n\nimport { EIP5792ErrorCode } from './constants';\nimport type { EIP5792Messenger } from './types';\n\n/**\n * Retrieves the keyring type for a given account address.\n *\n * @param accountAddress - The account address to look up.\n * @param messenger - Messenger instance for controller communication.\n * @returns The keyring type associated with the account.\n * @throws JsonRpcError if the account type is unknown or not found.\n */\nexport function getAccountKeyringType(\n accountAddress: Hex,\n messenger: EIP5792Messenger,\n): KeyringTypes {\n const { accounts } = messenger.call(\n 'AccountsController:getState',\n ).internalAccounts;\n\n const account = Object.values(accounts).find(\n (acc) => acc.address.toLowerCase() === accountAddress.toLowerCase(),\n );\n\n const keyringType = account?.metadata?.keyring?.type;\n\n if (!keyringType) {\n throw new JsonRpcError(\n EIP5792ErrorCode.RejectedUpgrade,\n 'EIP-7702 upgrade not supported as account type is unknown',\n );\n }\n\n return keyringType as KeyringTypes;\n}\n\n/**\n * Validates and normalizes a keyholder address for EIP-5792 operations.\n *\n * @param address - The Ethereum address to validate and normalize.\n * @param req - The JSON-RPC request object for permission checking.\n * @param options - Configuration object containing the getAccounts function.\n * @param options.getAccounts - Function to retrieve accounts for the requester.\n * @returns A normalized (lowercase) hex address if valid and authorized.\n * @throws JsonRpcError with unauthorized error if the requester doesn't have permission to access the address.\n * @throws JsonRpcError with invalid params if the address format is invalid.\n */\nexport async function validateAndNormalizeKeyholder(\n address: Hex,\n req: JsonRpcRequest,\n { getAccounts }: { getAccounts: (req: JsonRpcRequest) => Promise<string[]> },\n): Promise<Hex> {\n if (\n typeof address === 'string' &&\n address.length > 0 &&\n resemblesAddress(address)\n ) {\n // Ensure that an \"unauthorized\" error is thrown if the requester\n // does not have the `eth_accounts` permission.\n const accounts = await getAccounts(req);\n\n const normalizedAccounts: string[] = accounts.map((_address) =>\n _address.toLowerCase(),\n );\n\n const normalizedAddress = address.toLowerCase() as Hex;\n\n if (normalizedAccounts.includes(normalizedAddress)) {\n return normalizedAddress;\n }\n\n throw providerErrors.unauthorized();\n }\n\n throw rpcErrors.invalidParams({\n message: `Invalid parameters: must provide an Ethereum address.`,\n });\n}\n\n/**\n * Validates parameters against a Superstruct schema and throws an error if validation fails.\n *\n * @param value - The value to validate against the struct schema.\n * @param struct - The Superstruct schema to validate against.\n * @throws JsonRpcError with invalid params if the value doesn't match the struct schema.\n */\nexport function validateParams<ParamsType>(\n value: unknown | ParamsType,\n struct: Struct<ParamsType>,\n): asserts value is ParamsType {\n const [error] = validate(value, struct);\n\n if (error) {\n throw rpcErrors.invalidParams(\n formatValidationError(error, `Invalid params`),\n );\n }\n}\n\n/**\n * Checks if a string resembles an Ethereum address format.\n *\n * @param str - The string to check for address-like format.\n * @returns True if the string has the correct length for an Ethereum address.\n */\nexport function resemblesAddress(str: string): boolean {\n // hex prefix 2 + 20 bytes\n return str.length === 2 + 20 * 2;\n}\n\n/**\n * Formats a Superstruct validation error into a human-readable string.\n *\n * @param error - The Superstruct validation error to format.\n * @param message - The base error message to prepend to the formatted details.\n * @returns A formatted error message string with validation failure details.\n */\nfunction formatValidationError(error: StructError, message: string): string {\n return `${message}\\n\\n${error\n .failures()\n .map(\n (f) => `${f.path.join(' > ')}${f.path.length ? ' - ' : ''}${f.message}`,\n )\n .join('\\n')}`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/eip-5792-middleware",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Implements the JSON-RPC methods for sending multiple calls from the user's wallet, and checking their status, as referenced in EIP-5792",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -48,17 +48,20 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@metamask/eth-json-rpc-middleware": "^17.0.1",
51
- "@metamask/transaction-controller": "^60.2.0",
52
- "@metamask/utils": "^11.4.2",
51
+ "@metamask/superstruct": "^3.1.0",
52
+ "@metamask/transaction-controller": "^60.4.0",
53
+ "@metamask/utils": "^11.8.0",
54
+ "lodash": "^4.17.21",
53
55
  "uuid": "^8.3.2"
54
56
  },
55
57
  "devDependencies": {
56
58
  "@metamask/auto-changelog": "^3.4.4",
57
- "@metamask/keyring-controller": "^23.0.0",
59
+ "@metamask/keyring-controller": "^23.1.0",
58
60
  "@metamask/rpc-errors": "^7.0.2",
59
61
  "@types/jest": "^27.4.1",
60
62
  "deepmerge": "^4.2.2",
61
63
  "jest": "^27.5.1",
64
+ "klona": "^2.0.6",
62
65
  "ts-jest": "^27.1.4",
63
66
  "typedoc": "^0.24.8",
64
67
  "typedoc-plugin-missing-exports": "^2.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"getCallsStatus.cjs","sourceRoot":"","sources":["../../src/methods/getCallsStatus.ts"],"names":[],"mappings":";;;AACA,+EAAuE;AACvE,qDAAoD;AAMpD,6EAAqE;AAGrE,gDAAyD;AAGzD;;;;;;;GAOG;AACH,SAAgB,cAAc,CAC5B,SAA2B,EAC3B,EAAO;IAEP,MAAM,YAAY,GAAG,SAAS;SAC3B,IAAI,CAAC,gCAAgC,CAAC;SACtC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE;QACzB,MAAM,IAAI,yBAAY,CACpB,4BAAgB,CAAC,eAAe,EAChC,0BAA0B,CAC3B,CAAC;KACH;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC;IACzD,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,YAAwD,CAAC;IAC3E,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAoB,CAAC;IAExD,MAAM,QAAQ,GAAqC,SAAS,IAAI;QAC9D;YACE,SAAS,EAAE,SAAS,CAAC,SAAgB;YACrC,WAAW,EAAE,SAAS,CAAC,WAAkB;YACzC,OAAO,EAAE,SAAS,CAAC,OAAc;YACjC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAkC,EAAE,EAAE,CAAC,CAAC;gBACtD,OAAO,EAAE,GAAG,CAAC,OAAc;gBAC3B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAA0B;aACvC,CAAC,CAAC;YACH,MAAM,EAAE,SAAS,CAAC,MAAuB;YACzC,eAAe,EAAE,SAAS,CAAC,eAAe;SAC3C;KACF,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,mBAAO;QAChB,EAAE;QACF,OAAO;QACP,MAAM,EAAE,IAAI;QACZ,MAAM;QACN,QAAQ;KACT,CAAC;AACJ,CAAC;AA5CD,wCA4CC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,eAAgC;IACrD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CAAC;IAEzC,IAAI,MAAM,KAAK,0CAAiB,CAAC,SAAS,EAAE;QAC1C,OAAO,4CAAkB,CAAC,SAAS,CAAC;KACrC;IAED,IAAI,MAAM,KAAK,0CAAiB,CAAC,MAAM,EAAE;QACvC,OAAO,IAAI;YACT,CAAC,CAAC,4CAAkB,CAAC,QAAQ;YAC7B,CAAC,CAAC,4CAAkB,CAAC,eAAe,CAAC;KACxC;IAED,IAAI,MAAM,KAAK,0CAAiB,CAAC,OAAO,EAAE;QACxC,OAAO,4CAAkB,CAAC,QAAQ,CAAC;KACpC;IAED,OAAO,4CAAkB,CAAC,OAAO,CAAC;AACpC,CAAC","sourcesContent":["import type { GetCallsStatusResult } from '@metamask/eth-json-rpc-middleware';\nimport { GetCallsStatusCode } from '@metamask/eth-json-rpc-middleware';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type {\n Log,\n TransactionMeta,\n TransactionReceipt,\n} from '@metamask/transaction-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { EIP5792ErrorCode, VERSION } from '../constants';\nimport type { EIP5792Messenger } from '../types';\n\n/**\n * Retrieves the status of a transaction batch by its ID.\n *\n * @param messenger - Messenger instance for controller communication.\n * @param id - The batch ID to look up (hexadecimal string).\n * @returns GetCallsStatusResult containing the batch status, receipts, and metadata.\n * @throws JsonRpcError with EIP5792ErrorCode.UnknownBundleId if no matching bundle is found.\n */\nexport function getCallsStatus(\n messenger: EIP5792Messenger,\n id: Hex,\n): GetCallsStatusResult {\n const transactions = messenger\n .call('TransactionController:getState')\n .transactions.filter((tx) => tx.batchId === id);\n\n if (!transactions?.length) {\n throw new JsonRpcError(\n EIP5792ErrorCode.UnknownBundleId,\n `No matching bundle found`,\n );\n }\n\n const transaction = transactions[0];\n const { chainId, txReceipt: rawTxReceipt } = transaction;\n const status = getStatusCode(transaction);\n const txReceipt = rawTxReceipt as Required<TransactionReceipt> | undefined;\n const logs = (txReceipt?.logs ?? []) as Required<Log>[];\n\n const receipts: GetCallsStatusResult['receipts'] = txReceipt && [\n {\n blockHash: txReceipt.blockHash as Hex,\n blockNumber: txReceipt.blockNumber as Hex,\n gasUsed: txReceipt.gasUsed as Hex,\n logs: logs.map((log: Required<Log> & { data: Hex }) => ({\n address: log.address as Hex,\n data: log.data,\n topics: log.topics as unknown as Hex[],\n })),\n status: txReceipt.status as '0x0' | '0x1',\n transactionHash: txReceipt.transactionHash,\n },\n ];\n\n return {\n version: VERSION,\n id,\n chainId,\n atomic: true, // Always atomic as we currently only support EIP-7702 batches\n status,\n receipts,\n };\n}\n\n/**\n * Maps transaction status to EIP-5792 call status codes.\n *\n * @param transactionMeta - The transaction metadata containing status and hash information.\n * @returns GetCallsStatusCode representing the current status of the transaction.\n */\nfunction getStatusCode(transactionMeta: TransactionMeta) {\n const { hash, status } = transactionMeta;\n\n if (status === TransactionStatus.confirmed) {\n return GetCallsStatusCode.CONFIRMED;\n }\n\n if (status === TransactionStatus.failed) {\n return hash\n ? GetCallsStatusCode.REVERTED\n : GetCallsStatusCode.FAILED_OFFCHAIN;\n }\n\n if (status === TransactionStatus.dropped) {\n return GetCallsStatusCode.REVERTED;\n }\n\n return GetCallsStatusCode.PENDING;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"getCallsStatus.d.cts","sourceRoot":"","sources":["../../src/methods/getCallsStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0CAA0C;AAS9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAiB;AAEjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,gBAAgB,EAC3B,EAAE,EAAE,GAAG,GACN,oBAAoB,CAyCtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"getCallsStatus.d.mts","sourceRoot":"","sources":["../../src/methods/getCallsStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,0CAA0C;AAS9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAiB;AAEjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,gBAAgB,EAC3B,EAAE,EAAE,GAAG,GACN,oBAAoB,CAyCtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"getCallsStatus.mjs","sourceRoot":"","sources":["../../src/methods/getCallsStatus.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,0CAA0C;AACvE,OAAO,EAAE,YAAY,EAAE,6BAA6B;AAMpD,OAAO,EAAE,iBAAiB,EAAE,yCAAyC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,yBAAqB;AAGzD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,SAA2B,EAC3B,EAAO;IAEP,MAAM,YAAY,GAAG,SAAS;SAC3B,IAAI,CAAC,gCAAgC,CAAC;SACtC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE;QACzB,MAAM,IAAI,YAAY,CACpB,gBAAgB,CAAC,eAAe,EAChC,0BAA0B,CAC3B,CAAC;KACH;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC;IACzD,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,YAAwD,CAAC;IAC3E,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAoB,CAAC;IAExD,MAAM,QAAQ,GAAqC,SAAS,IAAI;QAC9D;YACE,SAAS,EAAE,SAAS,CAAC,SAAgB;YACrC,WAAW,EAAE,SAAS,CAAC,WAAkB;YACzC,OAAO,EAAE,SAAS,CAAC,OAAc;YACjC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAkC,EAAE,EAAE,CAAC,CAAC;gBACtD,OAAO,EAAE,GAAG,CAAC,OAAc;gBAC3B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAA0B;aACvC,CAAC,CAAC;YACH,MAAM,EAAE,SAAS,CAAC,MAAuB;YACzC,eAAe,EAAE,SAAS,CAAC,eAAe;SAC3C;KACF,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,EAAE;QACF,OAAO;QACP,MAAM,EAAE,IAAI;QACZ,MAAM;QACN,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,eAAgC;IACrD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CAAC;IAEzC,IAAI,MAAM,KAAK,iBAAiB,CAAC,SAAS,EAAE;QAC1C,OAAO,kBAAkB,CAAC,SAAS,CAAC;KACrC;IAED,IAAI,MAAM,KAAK,iBAAiB,CAAC,MAAM,EAAE;QACvC,OAAO,IAAI;YACT,CAAC,CAAC,kBAAkB,CAAC,QAAQ;YAC7B,CAAC,CAAC,kBAAkB,CAAC,eAAe,CAAC;KACxC;IAED,IAAI,MAAM,KAAK,iBAAiB,CAAC,OAAO,EAAE;QACxC,OAAO,kBAAkB,CAAC,QAAQ,CAAC;KACpC;IAED,OAAO,kBAAkB,CAAC,OAAO,CAAC;AACpC,CAAC","sourcesContent":["import type { GetCallsStatusResult } from '@metamask/eth-json-rpc-middleware';\nimport { GetCallsStatusCode } from '@metamask/eth-json-rpc-middleware';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type {\n Log,\n TransactionMeta,\n TransactionReceipt,\n} from '@metamask/transaction-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { EIP5792ErrorCode, VERSION } from '../constants';\nimport type { EIP5792Messenger } from '../types';\n\n/**\n * Retrieves the status of a transaction batch by its ID.\n *\n * @param messenger - Messenger instance for controller communication.\n * @param id - The batch ID to look up (hexadecimal string).\n * @returns GetCallsStatusResult containing the batch status, receipts, and metadata.\n * @throws JsonRpcError with EIP5792ErrorCode.UnknownBundleId if no matching bundle is found.\n */\nexport function getCallsStatus(\n messenger: EIP5792Messenger,\n id: Hex,\n): GetCallsStatusResult {\n const transactions = messenger\n .call('TransactionController:getState')\n .transactions.filter((tx) => tx.batchId === id);\n\n if (!transactions?.length) {\n throw new JsonRpcError(\n EIP5792ErrorCode.UnknownBundleId,\n `No matching bundle found`,\n );\n }\n\n const transaction = transactions[0];\n const { chainId, txReceipt: rawTxReceipt } = transaction;\n const status = getStatusCode(transaction);\n const txReceipt = rawTxReceipt as Required<TransactionReceipt> | undefined;\n const logs = (txReceipt?.logs ?? []) as Required<Log>[];\n\n const receipts: GetCallsStatusResult['receipts'] = txReceipt && [\n {\n blockHash: txReceipt.blockHash as Hex,\n blockNumber: txReceipt.blockNumber as Hex,\n gasUsed: txReceipt.gasUsed as Hex,\n logs: logs.map((log: Required<Log> & { data: Hex }) => ({\n address: log.address as Hex,\n data: log.data,\n topics: log.topics as unknown as Hex[],\n })),\n status: txReceipt.status as '0x0' | '0x1',\n transactionHash: txReceipt.transactionHash,\n },\n ];\n\n return {\n version: VERSION,\n id,\n chainId,\n atomic: true, // Always atomic as we currently only support EIP-7702 batches\n status,\n receipts,\n };\n}\n\n/**\n * Maps transaction status to EIP-5792 call status codes.\n *\n * @param transactionMeta - The transaction metadata containing status and hash information.\n * @returns GetCallsStatusCode representing the current status of the transaction.\n */\nfunction getStatusCode(transactionMeta: TransactionMeta) {\n const { hash, status } = transactionMeta;\n\n if (status === TransactionStatus.confirmed) {\n return GetCallsStatusCode.CONFIRMED;\n }\n\n if (status === TransactionStatus.failed) {\n return hash\n ? GetCallsStatusCode.REVERTED\n : GetCallsStatusCode.FAILED_OFFCHAIN;\n }\n\n if (status === TransactionStatus.dropped) {\n return GetCallsStatusCode.REVERTED;\n }\n\n return GetCallsStatusCode.PENDING;\n}\n"]}