@metamask/snaps-controllers 12.1.0 → 12.3.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.
- package/CHANGELOG.md +27 -1
- package/dist/cronjob/CronjobController.cjs +13 -4
- package/dist/cronjob/CronjobController.cjs.map +1 -1
- package/dist/cronjob/CronjobController.d.cts.map +1 -1
- package/dist/cronjob/CronjobController.d.mts.map +1 -1
- package/dist/cronjob/CronjobController.mjs +15 -6
- package/dist/cronjob/CronjobController.mjs.map +1 -1
- package/dist/interface/SnapInterfaceController.cjs +15 -1
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +10 -2
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +10 -2
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +17 -3
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/interface/utils.cjs +104 -4
- package/dist/interface/utils.cjs.map +1 -1
- package/dist/interface/utils.d.cts +71 -2
- package/dist/interface/utils.d.cts.map +1 -1
- package/dist/interface/utils.d.mts +71 -2
- package/dist/interface/utils.d.mts.map +1 -1
- package/dist/interface/utils.mjs +101 -5
- package/dist/interface/utils.mjs.map +1 -1
- package/dist/multichain/MultichainRouter.cjs +1 -0
- package/dist/multichain/MultichainRouter.cjs.map +1 -1
- package/dist/multichain/MultichainRouter.d.cts +1 -0
- package/dist/multichain/MultichainRouter.d.cts.map +1 -1
- package/dist/multichain/MultichainRouter.d.mts +1 -0
- package/dist/multichain/MultichainRouter.d.mts.map +1 -1
- package/dist/multichain/MultichainRouter.mjs +1 -0
- package/dist/multichain/MultichainRouter.mjs.map +1 -1
- package/dist/services/AbstractExecutionService.cjs +127 -202
- package/dist/services/AbstractExecutionService.cjs.map +1 -1
- package/dist/services/AbstractExecutionService.d.cts +8 -53
- package/dist/services/AbstractExecutionService.d.cts.map +1 -1
- package/dist/services/AbstractExecutionService.d.mts +8 -53
- package/dist/services/AbstractExecutionService.d.mts.map +1 -1
- package/dist/services/AbstractExecutionService.mjs +127 -202
- package/dist/services/AbstractExecutionService.mjs.map +1 -1
- package/dist/services/iframe/IframeExecutionService.cjs +2 -2
- package/dist/services/iframe/IframeExecutionService.cjs.map +1 -1
- package/dist/services/iframe/IframeExecutionService.d.cts +1 -1
- package/dist/services/iframe/IframeExecutionService.d.cts.map +1 -1
- package/dist/services/iframe/IframeExecutionService.d.mts +1 -1
- package/dist/services/iframe/IframeExecutionService.d.mts.map +1 -1
- package/dist/services/iframe/IframeExecutionService.mjs +2 -2
- package/dist/services/iframe/IframeExecutionService.mjs.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.cjs +5 -5
- package/dist/services/offscreen/OffscreenExecutionService.cjs.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.cts +4 -4
- package/dist/services/offscreen/OffscreenExecutionService.d.cts.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.mts +4 -4
- package/dist/services/offscreen/OffscreenExecutionService.d.mts.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.mjs +5 -5
- package/dist/services/offscreen/OffscreenExecutionService.mjs.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.cjs +6 -6
- package/dist/services/proxy/ProxyExecutionService.cjs.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.d.cts +4 -4
- package/dist/services/proxy/ProxyExecutionService.d.cts.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.d.mts +4 -4
- package/dist/services/proxy/ProxyExecutionService.d.mts.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.mjs +6 -6
- package/dist/services/proxy/ProxyExecutionService.mjs.map +1 -1
- package/dist/services/webview/WebViewExecutionService.cjs +6 -6
- package/dist/services/webview/WebViewExecutionService.cjs.map +1 -1
- package/dist/services/webview/WebViewExecutionService.d.cts +5 -5
- package/dist/services/webview/WebViewExecutionService.d.cts.map +1 -1
- package/dist/services/webview/WebViewExecutionService.d.mts +5 -5
- package/dist/services/webview/WebViewExecutionService.d.mts.map +1 -1
- package/dist/services/webview/WebViewExecutionService.mjs +6 -6
- package/dist/services/webview/WebViewExecutionService.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +60 -72
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +19 -10
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +19 -10
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +61 -73
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/registry/json.cjs +4 -2
- package/dist/snaps/registry/json.cjs.map +1 -1
- package/dist/snaps/registry/json.d.cts.map +1 -1
- package/dist/snaps/registry/json.d.mts.map +1 -1
- package/dist/snaps/registry/json.mjs +4 -2
- package/dist/snaps/registry/json.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/snaps/RequestQueue.cjs +0 -44
- package/dist/snaps/RequestQueue.cjs.map +0 -1
- package/dist/snaps/RequestQueue.d.cts +0 -25
- package/dist/snaps/RequestQueue.d.cts.map +0 -1
- package/dist/snaps/RequestQueue.d.mts +0 -25
- package/dist/snaps/RequestQueue.d.mts.map +0 -1
- package/dist/snaps/RequestQueue.mjs +0 -40
- package/dist/snaps/RequestQueue.mjs.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { InterfaceState, ComponentOrElement, InterfaceContext, FungibleAssetMetadata, AssetSelectorState, CaipChainId } from "@metamask/snaps-sdk";
|
|
2
|
-
import type { JSXElement } from "@metamask/snaps-sdk/jsx";
|
|
2
|
+
import type { JSXElement, AccountSelectorElement } from "@metamask/snaps-sdk/jsx";
|
|
3
3
|
import type { InternalAccount } from "@metamask/snaps-utils";
|
|
4
4
|
import { type CaipAssetType, type CaipAccountId } from "@metamask/utils";
|
|
5
5
|
/**
|
|
6
6
|
* A list of stateful component types.
|
|
7
7
|
*/
|
|
8
|
-
declare const STATEFUL_COMPONENT_TYPES: readonly ["Input", "Dropdown", "RadioGroup", "FileInput", "Checkbox", "Selector", "AssetSelector", "AddressInput"];
|
|
8
|
+
declare const STATEFUL_COMPONENT_TYPES: readonly ["Input", "Dropdown", "RadioGroup", "FileInput", "Checkbox", "Selector", "AssetSelector", "AddressInput", "AccountSelector"];
|
|
9
9
|
/**
|
|
10
10
|
* Type for stateful component types.
|
|
11
11
|
*/
|
|
@@ -43,16 +43,36 @@ type GetAssetsState = () => {
|
|
|
43
43
|
* @returns The account or undefined if not found.
|
|
44
44
|
*/
|
|
45
45
|
type GetAccountByAddress = (address: CaipAccountId) => InternalAccount | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* A function to get the selected account in the client.
|
|
48
|
+
*
|
|
49
|
+
* @returns The selected account.
|
|
50
|
+
*/
|
|
51
|
+
type GetSelectedAccount = () => InternalAccount;
|
|
52
|
+
/**
|
|
53
|
+
* A function to get accounts for the provided chain IDs.
|
|
54
|
+
*/
|
|
55
|
+
type ListAccounts = (chainIds?: CaipChainId[]) => InternalAccount[];
|
|
56
|
+
/**
|
|
57
|
+
* A function to check if the snap owns the account.
|
|
58
|
+
*/
|
|
59
|
+
type SnapOwnsAccount = (account: InternalAccount) => boolean;
|
|
46
60
|
/**
|
|
47
61
|
* Data getters for elements.
|
|
48
62
|
* This is used to get data from elements that is not directly accessible from the element itself.
|
|
49
63
|
*
|
|
50
64
|
* @param getAssetState - A function to get the MultichainAssetController state.
|
|
51
65
|
* @param getAccountByAddress - A function to get an account by its address.
|
|
66
|
+
* @param getSelectedAccount - A function to get the selected account in the client.
|
|
67
|
+
* @param listAccounts - A function to list accounts for the provided chain IDs.
|
|
68
|
+
* @param snapOwnsAccount - A function to check if the snap owns the account.
|
|
52
69
|
*/
|
|
53
70
|
type ElementDataGetters = {
|
|
54
71
|
getAssetsState: GetAssetsState;
|
|
55
72
|
getAccountByAddress: GetAccountByAddress;
|
|
73
|
+
getSelectedAccount: GetSelectedAccount;
|
|
74
|
+
listAccounts: ListAccounts;
|
|
75
|
+
snapOwnsAccount: SnapOwnsAccount;
|
|
56
76
|
};
|
|
57
77
|
/**
|
|
58
78
|
* Get a JSX element from a component or JSX element. If the component is a
|
|
@@ -70,6 +90,28 @@ export declare function getJsxInterface(component: ComponentOrElement): JSXEleme
|
|
|
70
90
|
* @param name - The component name to verify.
|
|
71
91
|
*/
|
|
72
92
|
export declare function assertNameIsUnique(state: InterfaceState, name: string): void;
|
|
93
|
+
/**
|
|
94
|
+
* Check if the chain ID matches the scope.
|
|
95
|
+
* This function handles the case where a scope represents all EVM compatible chains.
|
|
96
|
+
* In this case, it returns true if the chain ID is an EIP-155 chain ID.
|
|
97
|
+
*
|
|
98
|
+
* @param scope - The scope to check.
|
|
99
|
+
* @param chainIds - The chain IDs to check against.
|
|
100
|
+
* @returns Whether one of the chain ID matches the scope.
|
|
101
|
+
*/
|
|
102
|
+
export declare function isMatchingChainId(scope: CaipChainId, chainIds: CaipChainId[]): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Format the state value for an account selector.
|
|
105
|
+
*
|
|
106
|
+
* @param account - The account to format.
|
|
107
|
+
* @param requestedChainIds - The requested chain IDs.
|
|
108
|
+
*
|
|
109
|
+
* @returns The state value for the account selector.
|
|
110
|
+
*/
|
|
111
|
+
export declare function formatAccountSelectorStateValue(account: InternalAccount, requestedChainIds?: CaipChainId[]): {
|
|
112
|
+
accountId: string;
|
|
113
|
+
addresses: `${string}:${string}:${string}`[];
|
|
114
|
+
};
|
|
73
115
|
/**
|
|
74
116
|
* Get a default asset for a given address.
|
|
75
117
|
*
|
|
@@ -86,6 +128,20 @@ export declare function getDefaultAsset(addresses: CaipAccountId[], chainIds: Ca
|
|
|
86
128
|
name: string | undefined;
|
|
87
129
|
symbol: string | undefined;
|
|
88
130
|
} | null;
|
|
131
|
+
/**
|
|
132
|
+
* Get the default state value for an account selector.
|
|
133
|
+
*
|
|
134
|
+
* @param element - The account selector element.
|
|
135
|
+
* @param elementDataGetters - Data getters for the element.
|
|
136
|
+
* @param elementDataGetters.getSelectedAccount - A function to get the selected account in the client.
|
|
137
|
+
* @param elementDataGetters.listAccounts - A function to list accounts for the provided chain IDs.
|
|
138
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
139
|
+
* @returns The default state for the account selector.
|
|
140
|
+
*/
|
|
141
|
+
export declare function getAccountSelectorDefaultStateValue(element: AccountSelectorElement, { getSelectedAccount, listAccounts, snapOwnsAccount }: ElementDataGetters): {
|
|
142
|
+
accountId: string;
|
|
143
|
+
addresses: `${string}:${string}:${string}`[];
|
|
144
|
+
} | null;
|
|
89
145
|
/**
|
|
90
146
|
* Get the state value for an asset selector.
|
|
91
147
|
*
|
|
@@ -94,6 +150,19 @@ export declare function getDefaultAsset(addresses: CaipAccountId[], chainIds: Ca
|
|
|
94
150
|
* @returns The state value for the asset selector or null.
|
|
95
151
|
*/
|
|
96
152
|
export declare function getAssetSelectorStateValue(value: CaipAssetType | undefined, getAssetState: GetAssetsState): AssetSelectorState | null;
|
|
153
|
+
/**
|
|
154
|
+
* Get the state value for an account selector.
|
|
155
|
+
*
|
|
156
|
+
* @param element - The account selector element.
|
|
157
|
+
* @param elementDataGetters - Data getters for the element.
|
|
158
|
+
* @param elementDataGetters.getAccountByAddress - A function to get an account by address.
|
|
159
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
160
|
+
* @returns The state value for the account selector.
|
|
161
|
+
*/
|
|
162
|
+
export declare function getAccountSelectorStateValue(element: AccountSelectorElement, { getAccountByAddress, snapOwnsAccount }: ElementDataGetters): {
|
|
163
|
+
accountId: string;
|
|
164
|
+
addresses: `${string}:${string}:${string}`[];
|
|
165
|
+
} | null;
|
|
97
166
|
/**
|
|
98
167
|
* Construct the interface state for a given component tree.
|
|
99
168
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACZ,4BAA4B;AAC7B,OAAO,KAAK,EAGV,UAAU,
|
|
1
|
+
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { InterfaceState, ComponentOrElement, InterfaceContext, FungibleAssetMetadata, AssetSelectorState, CaipChainId } from "@metamask/snaps-sdk";
|
|
2
|
-
import type { JSXElement } from "@metamask/snaps-sdk/jsx";
|
|
2
|
+
import type { JSXElement, AccountSelectorElement } from "@metamask/snaps-sdk/jsx";
|
|
3
3
|
import type { InternalAccount } from "@metamask/snaps-utils";
|
|
4
4
|
import { type CaipAssetType, type CaipAccountId } from "@metamask/utils";
|
|
5
5
|
/**
|
|
6
6
|
* A list of stateful component types.
|
|
7
7
|
*/
|
|
8
|
-
declare const STATEFUL_COMPONENT_TYPES: readonly ["Input", "Dropdown", "RadioGroup", "FileInput", "Checkbox", "Selector", "AssetSelector", "AddressInput"];
|
|
8
|
+
declare const STATEFUL_COMPONENT_TYPES: readonly ["Input", "Dropdown", "RadioGroup", "FileInput", "Checkbox", "Selector", "AssetSelector", "AddressInput", "AccountSelector"];
|
|
9
9
|
/**
|
|
10
10
|
* Type for stateful component types.
|
|
11
11
|
*/
|
|
@@ -43,16 +43,36 @@ type GetAssetsState = () => {
|
|
|
43
43
|
* @returns The account or undefined if not found.
|
|
44
44
|
*/
|
|
45
45
|
type GetAccountByAddress = (address: CaipAccountId) => InternalAccount | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* A function to get the selected account in the client.
|
|
48
|
+
*
|
|
49
|
+
* @returns The selected account.
|
|
50
|
+
*/
|
|
51
|
+
type GetSelectedAccount = () => InternalAccount;
|
|
52
|
+
/**
|
|
53
|
+
* A function to get accounts for the provided chain IDs.
|
|
54
|
+
*/
|
|
55
|
+
type ListAccounts = (chainIds?: CaipChainId[]) => InternalAccount[];
|
|
56
|
+
/**
|
|
57
|
+
* A function to check if the snap owns the account.
|
|
58
|
+
*/
|
|
59
|
+
type SnapOwnsAccount = (account: InternalAccount) => boolean;
|
|
46
60
|
/**
|
|
47
61
|
* Data getters for elements.
|
|
48
62
|
* This is used to get data from elements that is not directly accessible from the element itself.
|
|
49
63
|
*
|
|
50
64
|
* @param getAssetState - A function to get the MultichainAssetController state.
|
|
51
65
|
* @param getAccountByAddress - A function to get an account by its address.
|
|
66
|
+
* @param getSelectedAccount - A function to get the selected account in the client.
|
|
67
|
+
* @param listAccounts - A function to list accounts for the provided chain IDs.
|
|
68
|
+
* @param snapOwnsAccount - A function to check if the snap owns the account.
|
|
52
69
|
*/
|
|
53
70
|
type ElementDataGetters = {
|
|
54
71
|
getAssetsState: GetAssetsState;
|
|
55
72
|
getAccountByAddress: GetAccountByAddress;
|
|
73
|
+
getSelectedAccount: GetSelectedAccount;
|
|
74
|
+
listAccounts: ListAccounts;
|
|
75
|
+
snapOwnsAccount: SnapOwnsAccount;
|
|
56
76
|
};
|
|
57
77
|
/**
|
|
58
78
|
* Get a JSX element from a component or JSX element. If the component is a
|
|
@@ -70,6 +90,28 @@ export declare function getJsxInterface(component: ComponentOrElement): JSXEleme
|
|
|
70
90
|
* @param name - The component name to verify.
|
|
71
91
|
*/
|
|
72
92
|
export declare function assertNameIsUnique(state: InterfaceState, name: string): void;
|
|
93
|
+
/**
|
|
94
|
+
* Check if the chain ID matches the scope.
|
|
95
|
+
* This function handles the case where a scope represents all EVM compatible chains.
|
|
96
|
+
* In this case, it returns true if the chain ID is an EIP-155 chain ID.
|
|
97
|
+
*
|
|
98
|
+
* @param scope - The scope to check.
|
|
99
|
+
* @param chainIds - The chain IDs to check against.
|
|
100
|
+
* @returns Whether one of the chain ID matches the scope.
|
|
101
|
+
*/
|
|
102
|
+
export declare function isMatchingChainId(scope: CaipChainId, chainIds: CaipChainId[]): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Format the state value for an account selector.
|
|
105
|
+
*
|
|
106
|
+
* @param account - The account to format.
|
|
107
|
+
* @param requestedChainIds - The requested chain IDs.
|
|
108
|
+
*
|
|
109
|
+
* @returns The state value for the account selector.
|
|
110
|
+
*/
|
|
111
|
+
export declare function formatAccountSelectorStateValue(account: InternalAccount, requestedChainIds?: CaipChainId[]): {
|
|
112
|
+
accountId: string;
|
|
113
|
+
addresses: `${string}:${string}:${string}`[];
|
|
114
|
+
};
|
|
73
115
|
/**
|
|
74
116
|
* Get a default asset for a given address.
|
|
75
117
|
*
|
|
@@ -86,6 +128,20 @@ export declare function getDefaultAsset(addresses: CaipAccountId[], chainIds: Ca
|
|
|
86
128
|
name: string | undefined;
|
|
87
129
|
symbol: string | undefined;
|
|
88
130
|
} | null;
|
|
131
|
+
/**
|
|
132
|
+
* Get the default state value for an account selector.
|
|
133
|
+
*
|
|
134
|
+
* @param element - The account selector element.
|
|
135
|
+
* @param elementDataGetters - Data getters for the element.
|
|
136
|
+
* @param elementDataGetters.getSelectedAccount - A function to get the selected account in the client.
|
|
137
|
+
* @param elementDataGetters.listAccounts - A function to list accounts for the provided chain IDs.
|
|
138
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
139
|
+
* @returns The default state for the account selector.
|
|
140
|
+
*/
|
|
141
|
+
export declare function getAccountSelectorDefaultStateValue(element: AccountSelectorElement, { getSelectedAccount, listAccounts, snapOwnsAccount }: ElementDataGetters): {
|
|
142
|
+
accountId: string;
|
|
143
|
+
addresses: `${string}:${string}:${string}`[];
|
|
144
|
+
} | null;
|
|
89
145
|
/**
|
|
90
146
|
* Get the state value for an asset selector.
|
|
91
147
|
*
|
|
@@ -94,6 +150,19 @@ export declare function getDefaultAsset(addresses: CaipAccountId[], chainIds: Ca
|
|
|
94
150
|
* @returns The state value for the asset selector or null.
|
|
95
151
|
*/
|
|
96
152
|
export declare function getAssetSelectorStateValue(value: CaipAssetType | undefined, getAssetState: GetAssetsState): AssetSelectorState | null;
|
|
153
|
+
/**
|
|
154
|
+
* Get the state value for an account selector.
|
|
155
|
+
*
|
|
156
|
+
* @param element - The account selector element.
|
|
157
|
+
* @param elementDataGetters - Data getters for the element.
|
|
158
|
+
* @param elementDataGetters.getAccountByAddress - A function to get an account by address.
|
|
159
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
160
|
+
* @returns The state value for the account selector.
|
|
161
|
+
*/
|
|
162
|
+
export declare function getAccountSelectorStateValue(element: AccountSelectorElement, { getAccountByAddress, snapOwnsAccount }: ElementDataGetters): {
|
|
163
|
+
accountId: string;
|
|
164
|
+
addresses: `${string}:${string}:${string}`[];
|
|
165
|
+
} | null;
|
|
97
166
|
/**
|
|
98
167
|
* Construct the interface state for a given component tree.
|
|
99
168
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACZ,4BAA4B;AAC7B,OAAO,KAAK,EAGV,UAAU,
|
|
1
|
+
{"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/interface/utils.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assert } from "@metamask/snaps-sdk";
|
|
2
2
|
import { isJSXElementUnsafe } from "@metamask/snaps-sdk/jsx";
|
|
3
|
-
import { getJsonSizeUnsafe, getJsxChildren, getJsxElementFromComponent, walkJsx } from "@metamask/snaps-utils";
|
|
4
|
-
import { parseCaipAccountId, parseCaipAssetType, toCaipAccountId, parseCaipChainId } from "@metamask/utils";
|
|
3
|
+
import { createAccountList, createChainIdList, getJsonSizeUnsafe, getJsxChildren, getJsxElementFromComponent, walkJsx } from "@metamask/snaps-utils";
|
|
4
|
+
import { parseCaipAccountId, parseCaipAssetType, toCaipAccountId, parseCaipChainId, KnownCaipNamespace } from "@metamask/utils";
|
|
5
5
|
/**
|
|
6
6
|
* A list of stateful component types.
|
|
7
7
|
*/
|
|
@@ -14,6 +14,7 @@ const STATEFUL_COMPONENT_TYPES = [
|
|
|
14
14
|
'Selector',
|
|
15
15
|
'AssetSelector',
|
|
16
16
|
'AddressInput',
|
|
17
|
+
'AccountSelector',
|
|
17
18
|
];
|
|
18
19
|
/**
|
|
19
20
|
* Check if a component is a stateful component.
|
|
@@ -49,6 +50,40 @@ export function getJsxInterface(component) {
|
|
|
49
50
|
export function assertNameIsUnique(state, name) {
|
|
50
51
|
assert(state[name] === undefined, `Duplicate component names are not allowed, found multiple instances of: "${name}".`);
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if the chain ID matches the scope.
|
|
55
|
+
* This function handles the case where a scope represents all EVM compatible chains.
|
|
56
|
+
* In this case, it returns true if the chain ID is an EIP-155 chain ID.
|
|
57
|
+
*
|
|
58
|
+
* @param scope - The scope to check.
|
|
59
|
+
* @param chainIds - The chain IDs to check against.
|
|
60
|
+
* @returns Whether one of the chain ID matches the scope.
|
|
61
|
+
*/
|
|
62
|
+
export function isMatchingChainId(scope, chainIds) {
|
|
63
|
+
// if the scope represents all EVM compatible chains, return true if the namespace is EIP-155.
|
|
64
|
+
if (scope === 'eip155:0') {
|
|
65
|
+
return chainIds.some((chainId) => {
|
|
66
|
+
const { namespace } = parseCaipChainId(chainId);
|
|
67
|
+
return namespace === KnownCaipNamespace.Eip155;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Otherwise, check if the scope is in the chain IDs.
|
|
71
|
+
return chainIds.includes(scope);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Format the state value for an account selector.
|
|
75
|
+
*
|
|
76
|
+
* @param account - The account to format.
|
|
77
|
+
* @param requestedChainIds - The requested chain IDs.
|
|
78
|
+
*
|
|
79
|
+
* @returns The state value for the account selector.
|
|
80
|
+
*/
|
|
81
|
+
export function formatAccountSelectorStateValue(account, requestedChainIds) {
|
|
82
|
+
const { id, address, scopes } = account;
|
|
83
|
+
const chainIds = createChainIdList(scopes, requestedChainIds);
|
|
84
|
+
const addresses = createAccountList(address, chainIds);
|
|
85
|
+
return { accountId: id, addresses };
|
|
86
|
+
}
|
|
52
87
|
/**
|
|
53
88
|
* Get a default asset for a given address.
|
|
54
89
|
*
|
|
@@ -93,6 +128,41 @@ export function getDefaultAsset(addresses, chainIds, { getAccountByAddress, getA
|
|
|
93
128
|
symbol: assetsMetadata[accountAssets[0]].symbol,
|
|
94
129
|
};
|
|
95
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Get the default state value for an account selector.
|
|
133
|
+
*
|
|
134
|
+
* @param element - The account selector element.
|
|
135
|
+
* @param elementDataGetters - Data getters for the element.
|
|
136
|
+
* @param elementDataGetters.getSelectedAccount - A function to get the selected account in the client.
|
|
137
|
+
* @param elementDataGetters.listAccounts - A function to list accounts for the provided chain IDs.
|
|
138
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
139
|
+
* @returns The default state for the account selector.
|
|
140
|
+
*/
|
|
141
|
+
export function getAccountSelectorDefaultStateValue(element, { getSelectedAccount, listAccounts, snapOwnsAccount }) {
|
|
142
|
+
const { chainIds, hideExternalAccounts } = element.props;
|
|
143
|
+
const selectedAccount = getSelectedAccount();
|
|
144
|
+
// Use the selected account if it matches.
|
|
145
|
+
// The following conditions are checked:
|
|
146
|
+
// - If the selected account has any of the requested chain IDs in its scopes.
|
|
147
|
+
// - If the selected account is owned by the snap and hideExternalAccounts is true.
|
|
148
|
+
if ((!chainIds ||
|
|
149
|
+
chainIds.length === 0 ||
|
|
150
|
+
selectedAccount.scopes.some((scope) => isMatchingChainId(scope, chainIds))) &&
|
|
151
|
+
(!hideExternalAccounts ||
|
|
152
|
+
(hideExternalAccounts && snapOwnsAccount(selectedAccount)))) {
|
|
153
|
+
return formatAccountSelectorStateValue(selectedAccount, chainIds);
|
|
154
|
+
}
|
|
155
|
+
const accounts = listAccounts(chainIds);
|
|
156
|
+
const filteredAccounts = hideExternalAccounts
|
|
157
|
+
? accounts.filter((account) => snapOwnsAccount(account))
|
|
158
|
+
: accounts;
|
|
159
|
+
// The AccountSelector component in the UI will be disabled if there is no account available for the networks provided.
|
|
160
|
+
// In this case, we return null to indicate that there is no default selected account.
|
|
161
|
+
if (filteredAccounts.length === 0) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
return formatAccountSelectorStateValue(filteredAccounts[0], chainIds);
|
|
165
|
+
}
|
|
96
166
|
/**
|
|
97
167
|
* Construct default state for a component.
|
|
98
168
|
*
|
|
@@ -118,6 +188,8 @@ function constructComponentSpecificDefaultState(element, elementDataGetters) {
|
|
|
118
188
|
const children = getJsxChildren(element);
|
|
119
189
|
return children[0]?.props.value;
|
|
120
190
|
}
|
|
191
|
+
case 'AccountSelector':
|
|
192
|
+
return getAccountSelectorDefaultStateValue(element, elementDataGetters);
|
|
121
193
|
case 'Checkbox':
|
|
122
194
|
return false;
|
|
123
195
|
case 'AssetSelector':
|
|
@@ -148,6 +220,29 @@ export function getAssetSelectorStateValue(value, getAssetState) {
|
|
|
148
220
|
symbol: asset.symbol ?? 'Unknown',
|
|
149
221
|
};
|
|
150
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Get the state value for an account selector.
|
|
225
|
+
*
|
|
226
|
+
* @param element - The account selector element.
|
|
227
|
+
* @param elementDataGetters - Data getters for the element.
|
|
228
|
+
* @param elementDataGetters.getAccountByAddress - A function to get an account by address.
|
|
229
|
+
* @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.
|
|
230
|
+
* @returns The state value for the account selector.
|
|
231
|
+
*/
|
|
232
|
+
export function getAccountSelectorStateValue(element, { getAccountByAddress, snapOwnsAccount }) {
|
|
233
|
+
const { value, hideExternalAccounts } = element.props;
|
|
234
|
+
if (!value) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
const account = getAccountByAddress(value);
|
|
238
|
+
if (!account) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
if (hideExternalAccounts && !snapOwnsAccount(account)) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return formatAccountSelectorStateValue(account, element.props.chainIds);
|
|
245
|
+
}
|
|
151
246
|
/**
|
|
152
247
|
* Get the state value for a stateful component.
|
|
153
248
|
*
|
|
@@ -156,15 +251,14 @@ export function getAssetSelectorStateValue(value, getAssetState) {
|
|
|
156
251
|
*
|
|
157
252
|
* @param element - The input element.
|
|
158
253
|
* @param elementDataGetters - Data getters for the element.
|
|
159
|
-
* @param elementDataGetters.getAssetsState - A function to get the MultichainAssetController state.
|
|
160
254
|
* @returns The state value for a given component.
|
|
161
255
|
*/
|
|
162
|
-
function getComponentStateValue(element,
|
|
256
|
+
function getComponentStateValue(element, elementDataGetters) {
|
|
163
257
|
switch (element.type) {
|
|
164
258
|
case 'Checkbox':
|
|
165
259
|
return element.props.checked;
|
|
166
260
|
case 'AssetSelector':
|
|
167
|
-
return getAssetSelectorStateValue(element.props.value, getAssetsState);
|
|
261
|
+
return getAssetSelectorStateValue(element.props.value, elementDataGetters.getAssetsState);
|
|
168
262
|
case 'AddressInput': {
|
|
169
263
|
if (!element.props.value) {
|
|
170
264
|
return null;
|
|
@@ -173,6 +267,8 @@ function getComponentStateValue(element, { getAssetsState }) {
|
|
|
173
267
|
const { namespace, reference } = parseCaipChainId(element.props.chainId);
|
|
174
268
|
return toCaipAccountId(namespace, reference, element.props.value);
|
|
175
269
|
}
|
|
270
|
+
case 'AccountSelector':
|
|
271
|
+
return getAccountSelectorStateValue(element, elementDataGetters);
|
|
176
272
|
default:
|
|
177
273
|
return element.props.value;
|
|
178
274
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from '@metamask/snaps-sdk';\nimport type {\n FormState,\n InterfaceState,\n ComponentOrElement,\n InterfaceContext,\n State,\n FungibleAssetMetadata,\n AssetSelectorState,\n CaipChainId,\n} from '@metamask/snaps-sdk';\nimport type {\n DropdownElement,\n InputElement,\n JSXElement,\n OptionElement,\n FileInputElement,\n CheckboxElement,\n RadioGroupElement,\n RadioElement,\n SelectorElement,\n SelectorOptionElement,\n AssetSelectorElement,\n AddressInputElement,\n} from '@metamask/snaps-sdk/jsx';\nimport { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport {\n getJsonSizeUnsafe,\n getJsxChildren,\n getJsxElementFromComponent,\n walkJsx,\n} from '@metamask/snaps-utils';\nimport {\n type CaipAssetType,\n type CaipAccountId,\n parseCaipAccountId,\n parseCaipAssetType,\n toCaipAccountId,\n parseCaipChainId,\n} from '@metamask/utils';\n\n/**\n * A list of stateful component types.\n */\nconst STATEFUL_COMPONENT_TYPES = [\n 'Input',\n 'Dropdown',\n 'RadioGroup',\n 'FileInput',\n 'Checkbox',\n 'Selector',\n 'AssetSelector',\n 'AddressInput',\n] as const;\n\n/**\n * Type for stateful component types.\n */\ntype StatefulComponentType = (typeof STATEFUL_COMPONENT_TYPES)[number];\n\n/**\n * Check if a component is a stateful component.\n *\n * @param component - The component to check.\n * @param component.type - The type of the component.\n *\n * @returns Whether the component is a stateful component.\n */\nexport function isStatefulComponent(component: { type: string }): component is {\n type: StatefulComponentType;\n} {\n return STATEFUL_COMPONENT_TYPES.includes(\n component.type as StatefulComponentType,\n );\n}\n\n/**\n * A function to get the MultichainAssetController state.\n *\n * @returns The MultichainAssetController state.\n */\ntype GetAssetsState = () => {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n};\n\n/**\n * A function to get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\ntype GetAccountByAddress = (\n address: CaipAccountId,\n) => InternalAccount | undefined;\n\n/**\n * Data getters for elements.\n * This is used to get data from elements that is not directly accessible from the element itself.\n *\n * @param getAssetState - A function to get the MultichainAssetController state.\n * @param getAccountByAddress - A function to get an account by its address.\n */\ntype ElementDataGetters = {\n getAssetsState: GetAssetsState;\n getAccountByAddress: GetAccountByAddress;\n};\n\n/**\n * Get a JSX element from a component or JSX element. If the component is a\n * JSX element, it is returned as is. Otherwise, the component is converted to\n * a JSX element.\n *\n * @param component - The component to convert.\n * @returns The JSX element.\n */\nexport function getJsxInterface(component: ComponentOrElement): JSXElement {\n if (isJSXElementUnsafe(component)) {\n return component;\n }\n\n return getJsxElementFromComponent(component);\n}\n\n/**\n * Assert that the component name is unique in state.\n *\n * @param state - The interface state to verify against.\n * @param name - The component name to verify.\n */\nexport function assertNameIsUnique(state: InterfaceState, name: string) {\n assert(\n state[name] === undefined,\n `Duplicate component names are not allowed, found multiple instances of: \"${name}\".`,\n );\n}\n\n/**\n * Get a default asset for a given address.\n *\n * @param addresses - The account addresses.\n * @param chainIds - The chain IDs to filter the assets.\n * @param elementDataGetters - Data getters for the element.\n * @param elementDataGetters.getAccountByAddress - A function to get an account by its address.\n * @param elementDataGetters.getAssetsState - A function to get the MultichainAssetController state.\n *\n * @returns The default asset for the account or undefined if not found.\n */\nexport function getDefaultAsset(\n addresses: CaipAccountId[],\n chainIds: CaipChainId[] | undefined,\n { getAccountByAddress, getAssetsState }: ElementDataGetters,\n) {\n const { assetsMetadata, accountsAssets } = getAssetsState();\n\n const parsedAccounts = addresses.map((address) =>\n parseCaipAccountId(address),\n );\n\n const accountChainIds = parsedAccounts.map(({ chainId }) => chainId);\n\n const filteredChainIds =\n chainIds && chainIds.length > 0\n ? accountChainIds.filter((accountChainId) =>\n chainIds.includes(accountChainId),\n )\n : accountChainIds;\n\n const accountId = getAccountByAddress(addresses[0])?.id;\n\n // We should never fail on this assertion as the address is already validated.\n assert(accountId, `Account not found for address: ${addresses[0]}.`);\n\n const accountAssets = accountsAssets[accountId];\n\n // The AssetSelector component in the UI will be disabled if there is no asset available for the account\n // and networks provided. In this case, we return null to indicate that there is no default selected asset.\n if (accountAssets.length === 0) {\n return null;\n }\n\n const nativeAsset = accountAssets.find((asset) => {\n const { chainId, assetNamespace } = parseCaipAssetType(asset);\n\n return filteredChainIds.includes(chainId) && assetNamespace === 'slip44';\n });\n\n if (nativeAsset) {\n return {\n asset: nativeAsset,\n name: assetsMetadata[nativeAsset].name,\n symbol: assetsMetadata[nativeAsset].symbol,\n };\n }\n\n return {\n asset: accountAssets[0],\n name: assetsMetadata[accountAssets[0]].name,\n symbol: assetsMetadata[accountAssets[0]].symbol,\n };\n}\n\n/**\n * Construct default state for a component.\n *\n * This function is meant to be used inside constructInputState to account\n * for component specific defaults and will not override the component value or existing form state.\n *\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n *\n * @returns The default state for the specific component, if any.\n */\nfunction constructComponentSpecificDefaultState(\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement,\n elementDataGetters: ElementDataGetters,\n) {\n switch (element.type) {\n case 'Dropdown': {\n const children = getJsxChildren(element) as OptionElement[];\n return children[0]?.props.value;\n }\n\n case 'RadioGroup': {\n const children = getJsxChildren(element) as RadioElement[];\n return children[0]?.props.value;\n }\n\n case 'Selector': {\n const children = getJsxChildren(element) as SelectorOptionElement[];\n return children[0]?.props.value;\n }\n\n case 'Checkbox':\n return false;\n\n case 'AssetSelector':\n return getDefaultAsset(\n element.props.addresses,\n element.props.chainIds,\n elementDataGetters,\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Get the state value for an asset selector.\n *\n * @param value - The asset selector value.\n * @param getAssetState - A function to get the MultichainAssetController state.\n * @returns The state value for the asset selector or null.\n */\nexport function getAssetSelectorStateValue(\n value: CaipAssetType | undefined,\n getAssetState: GetAssetsState,\n): AssetSelectorState | null {\n if (!value) {\n return null;\n }\n\n const { assetsMetadata } = getAssetState();\n const asset = assetsMetadata[value];\n\n if (!asset) {\n return null;\n }\n\n return {\n asset: value,\n name: asset.name ?? asset.symbol ?? 'Unknown',\n symbol: asset.symbol ?? 'Unknown',\n };\n}\n\n/**\n * Get the state value for a stateful component.\n *\n * Most components store the state value as a `value` prop.\n * This function exists to account for components where that isn't the case.\n *\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n * @param elementDataGetters.getAssetsState - A function to get the MultichainAssetController state.\n * @returns The state value for a given component.\n */\nfunction getComponentStateValue(\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement,\n { getAssetsState }: ElementDataGetters,\n) {\n switch (element.type) {\n case 'Checkbox':\n return element.props.checked;\n\n case 'AssetSelector':\n return getAssetSelectorStateValue(element.props.value, getAssetsState);\n\n case 'AddressInput': {\n if (!element.props.value) {\n return null;\n }\n\n // Construct CAIP-10 Id\n const { namespace, reference } = parseCaipChainId(element.props.chainId);\n return toCaipAccountId(namespace, reference, element.props.value);\n }\n default:\n return element.props.value;\n }\n}\n\n/**\n * Construct the state for an input field.\n *\n * @param oldState - The previous state.\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n * @param form - An optional form that the input is enclosed in.\n * @returns The input state.\n */\nfunction constructInputState(\n oldState: InterfaceState,\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | FileInputElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement,\n elementDataGetters: ElementDataGetters,\n form?: string,\n) {\n const oldStateUnwrapped = form ? (oldState[form] as FormState) : oldState;\n const oldInputState = oldStateUnwrapped?.[element.props.name] as State;\n\n if (element.type === 'FileInput') {\n return oldInputState ?? null;\n }\n\n return (\n getComponentStateValue(element, elementDataGetters) ??\n oldInputState ??\n constructComponentSpecificDefaultState(element, elementDataGetters) ??\n null\n );\n}\n\n/**\n * Construct the interface state for a given component tree.\n *\n * @param oldState - The previous state.\n * @param rootComponent - The UI component to construct state from.\n * @param elementDataGetters - Data getters for the elements.\n * @returns The interface state of the passed component.\n */\nexport function constructState(\n oldState: InterfaceState,\n rootComponent: JSXElement,\n elementDataGetters: ElementDataGetters,\n): InterfaceState {\n const newState: InterfaceState = {};\n\n // Stack containing the forms we have visited and at which depth\n const formStack: { name: string; depth: number }[] = [];\n\n walkJsx(rootComponent, (component, depth) => {\n let currentForm = formStack[formStack.length - 1];\n\n // Pop the current form of the stack once we leave its depth.\n if (currentForm && depth <= currentForm.depth) {\n formStack.pop();\n currentForm = formStack[formStack.length - 1];\n }\n\n if (component.type === 'Form') {\n assertNameIsUnique(newState, component.props.name);\n formStack.push({ name: component.props.name, depth });\n newState[component.props.name] = {};\n return;\n }\n\n // Stateful components inside a form\n if (currentForm && isStatefulComponent(component)) {\n const formState = newState[currentForm.name] as FormState;\n assertNameIsUnique(formState, component.props.name);\n formState[component.props.name] = constructInputState(\n oldState,\n component,\n elementDataGetters,\n currentForm.name,\n );\n return;\n }\n\n // Stateful components outside a form\n if (isStatefulComponent(component)) {\n assertNameIsUnique(newState, component.props.name);\n newState[component.props.name] = constructInputState(\n oldState,\n component,\n elementDataGetters,\n );\n }\n });\n\n return newState;\n}\n\nconst MAX_CONTEXT_SIZE = 5_000_000; // 5 mb\n\n/**\n * Validate a JSON blob to be used as the interface context.\n *\n * @param context - The JSON blob.\n * @throws If the JSON blob is too large.\n */\nexport function validateInterfaceContext(context?: InterfaceContext) {\n if (!context) {\n return;\n }\n\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(context);\n assert(\n size <= MAX_CONTEXT_SIZE,\n `A Snap interface context may not be larger than ${\n MAX_CONTEXT_SIZE / 1000000\n } MB.`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../../src/interface/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from '@metamask/snaps-sdk';\nimport type {\n FormState,\n InterfaceState,\n ComponentOrElement,\n InterfaceContext,\n State,\n FungibleAssetMetadata,\n AssetSelectorState,\n CaipChainId,\n} from '@metamask/snaps-sdk';\nimport type {\n DropdownElement,\n InputElement,\n JSXElement,\n OptionElement,\n FileInputElement,\n CheckboxElement,\n RadioGroupElement,\n RadioElement,\n SelectorElement,\n SelectorOptionElement,\n AssetSelectorElement,\n AddressInputElement,\n AccountSelectorElement,\n} from '@metamask/snaps-sdk/jsx';\nimport { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport {\n createAccountList,\n createChainIdList,\n getJsonSizeUnsafe,\n getJsxChildren,\n getJsxElementFromComponent,\n walkJsx,\n} from '@metamask/snaps-utils';\nimport {\n type CaipAssetType,\n type CaipAccountId,\n parseCaipAccountId,\n parseCaipAssetType,\n toCaipAccountId,\n parseCaipChainId,\n KnownCaipNamespace,\n} from '@metamask/utils';\n\n/**\n * A list of stateful component types.\n */\nconst STATEFUL_COMPONENT_TYPES = [\n 'Input',\n 'Dropdown',\n 'RadioGroup',\n 'FileInput',\n 'Checkbox',\n 'Selector',\n 'AssetSelector',\n 'AddressInput',\n 'AccountSelector',\n] as const;\n\n/**\n * Type for stateful component types.\n */\ntype StatefulComponentType = (typeof STATEFUL_COMPONENT_TYPES)[number];\n\n/**\n * Check if a component is a stateful component.\n *\n * @param component - The component to check.\n * @param component.type - The type of the component.\n *\n * @returns Whether the component is a stateful component.\n */\nexport function isStatefulComponent(component: { type: string }): component is {\n type: StatefulComponentType;\n} {\n return STATEFUL_COMPONENT_TYPES.includes(\n component.type as StatefulComponentType,\n );\n}\n\n/**\n * A function to get the MultichainAssetController state.\n *\n * @returns The MultichainAssetController state.\n */\ntype GetAssetsState = () => {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n};\n\n/**\n * A function to get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\ntype GetAccountByAddress = (\n address: CaipAccountId,\n) => InternalAccount | undefined;\n\n/**\n * A function to get the selected account in the client.\n *\n * @returns The selected account.\n */\ntype GetSelectedAccount = () => InternalAccount;\n\n/**\n * A function to get accounts for the provided chain IDs.\n */\ntype ListAccounts = (chainIds?: CaipChainId[]) => InternalAccount[];\n\n/**\n * A function to check if the snap owns the account.\n */\ntype SnapOwnsAccount = (account: InternalAccount) => boolean;\n\n/**\n * Data getters for elements.\n * This is used to get data from elements that is not directly accessible from the element itself.\n *\n * @param getAssetState - A function to get the MultichainAssetController state.\n * @param getAccountByAddress - A function to get an account by its address.\n * @param getSelectedAccount - A function to get the selected account in the client.\n * @param listAccounts - A function to list accounts for the provided chain IDs.\n * @param snapOwnsAccount - A function to check if the snap owns the account.\n */\ntype ElementDataGetters = {\n getAssetsState: GetAssetsState;\n getAccountByAddress: GetAccountByAddress;\n getSelectedAccount: GetSelectedAccount;\n listAccounts: ListAccounts;\n snapOwnsAccount: SnapOwnsAccount;\n};\n\n/**\n * Get a JSX element from a component or JSX element. If the component is a\n * JSX element, it is returned as is. Otherwise, the component is converted to\n * a JSX element.\n *\n * @param component - The component to convert.\n * @returns The JSX element.\n */\nexport function getJsxInterface(component: ComponentOrElement): JSXElement {\n if (isJSXElementUnsafe(component)) {\n return component;\n }\n\n return getJsxElementFromComponent(component);\n}\n\n/**\n * Assert that the component name is unique in state.\n *\n * @param state - The interface state to verify against.\n * @param name - The component name to verify.\n */\nexport function assertNameIsUnique(state: InterfaceState, name: string) {\n assert(\n state[name] === undefined,\n `Duplicate component names are not allowed, found multiple instances of: \"${name}\".`,\n );\n}\n\n/**\n * Check if the chain ID matches the scope.\n * This function handles the case where a scope represents all EVM compatible chains.\n * In this case, it returns true if the chain ID is an EIP-155 chain ID.\n *\n * @param scope - The scope to check.\n * @param chainIds - The chain IDs to check against.\n * @returns Whether one of the chain ID matches the scope.\n */\nexport function isMatchingChainId(scope: CaipChainId, chainIds: CaipChainId[]) {\n // if the scope represents all EVM compatible chains, return true if the namespace is EIP-155.\n if (scope === 'eip155:0') {\n return chainIds.some((chainId) => {\n const { namespace } = parseCaipChainId(chainId);\n return namespace === KnownCaipNamespace.Eip155;\n });\n }\n\n // Otherwise, check if the scope is in the chain IDs.\n return chainIds.includes(scope);\n}\n\n/**\n * Format the state value for an account selector.\n *\n * @param account - The account to format.\n * @param requestedChainIds - The requested chain IDs.\n *\n * @returns The state value for the account selector.\n */\nexport function formatAccountSelectorStateValue(\n account: InternalAccount,\n requestedChainIds?: CaipChainId[],\n) {\n const { id, address, scopes } = account;\n\n const chainIds = createChainIdList(scopes, requestedChainIds);\n const addresses = createAccountList(address, chainIds);\n\n return { accountId: id, addresses };\n}\n\n/**\n * Get a default asset for a given address.\n *\n * @param addresses - The account addresses.\n * @param chainIds - The chain IDs to filter the assets.\n * @param elementDataGetters - Data getters for the element.\n * @param elementDataGetters.getAccountByAddress - A function to get an account by its address.\n * @param elementDataGetters.getAssetsState - A function to get the MultichainAssetController state.\n *\n * @returns The default asset for the account or undefined if not found.\n */\nexport function getDefaultAsset(\n addresses: CaipAccountId[],\n chainIds: CaipChainId[] | undefined,\n { getAccountByAddress, getAssetsState }: ElementDataGetters,\n) {\n const { assetsMetadata, accountsAssets } = getAssetsState();\n\n const parsedAccounts = addresses.map((address) =>\n parseCaipAccountId(address),\n );\n\n const accountChainIds = parsedAccounts.map(({ chainId }) => chainId);\n\n const filteredChainIds =\n chainIds && chainIds.length > 0\n ? accountChainIds.filter((accountChainId) =>\n chainIds.includes(accountChainId),\n )\n : accountChainIds;\n\n const accountId = getAccountByAddress(addresses[0])?.id;\n\n // We should never fail on this assertion as the address is already validated.\n assert(accountId, `Account not found for address: ${addresses[0]}.`);\n\n const accountAssets = accountsAssets[accountId];\n\n // The AssetSelector component in the UI will be disabled if there is no asset available for the account\n // and networks provided. In this case, we return null to indicate that there is no default selected asset.\n if (accountAssets.length === 0) {\n return null;\n }\n\n const nativeAsset = accountAssets.find((asset) => {\n const { chainId, assetNamespace } = parseCaipAssetType(asset);\n\n return filteredChainIds.includes(chainId) && assetNamespace === 'slip44';\n });\n\n if (nativeAsset) {\n return {\n asset: nativeAsset,\n name: assetsMetadata[nativeAsset].name,\n symbol: assetsMetadata[nativeAsset].symbol,\n };\n }\n\n return {\n asset: accountAssets[0],\n name: assetsMetadata[accountAssets[0]].name,\n symbol: assetsMetadata[accountAssets[0]].symbol,\n };\n}\n\n/**\n * Get the default state value for an account selector.\n *\n * @param element - The account selector element.\n * @param elementDataGetters - Data getters for the element.\n * @param elementDataGetters.getSelectedAccount - A function to get the selected account in the client.\n * @param elementDataGetters.listAccounts - A function to list accounts for the provided chain IDs.\n * @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.\n * @returns The default state for the account selector.\n */\nexport function getAccountSelectorDefaultStateValue(\n element: AccountSelectorElement,\n { getSelectedAccount, listAccounts, snapOwnsAccount }: ElementDataGetters,\n) {\n const { chainIds, hideExternalAccounts } = element.props;\n\n const selectedAccount = getSelectedAccount();\n\n // Use the selected account if it matches.\n // The following conditions are checked:\n // - If the selected account has any of the requested chain IDs in its scopes.\n // - If the selected account is owned by the snap and hideExternalAccounts is true.\n if (\n (!chainIds ||\n chainIds.length === 0 ||\n selectedAccount.scopes.some((scope) =>\n isMatchingChainId(scope, chainIds),\n )) &&\n (!hideExternalAccounts ||\n (hideExternalAccounts && snapOwnsAccount(selectedAccount)))\n ) {\n return formatAccountSelectorStateValue(selectedAccount, chainIds);\n }\n\n const accounts = listAccounts(chainIds);\n\n const filteredAccounts = hideExternalAccounts\n ? accounts.filter((account) => snapOwnsAccount(account))\n : accounts;\n\n // The AccountSelector component in the UI will be disabled if there is no account available for the networks provided.\n // In this case, we return null to indicate that there is no default selected account.\n if (filteredAccounts.length === 0) {\n return null;\n }\n\n return formatAccountSelectorStateValue(filteredAccounts[0], chainIds);\n}\n\n/**\n * Construct default state for a component.\n *\n * This function is meant to be used inside constructInputState to account\n * for component specific defaults and will not override the component value or existing form state.\n *\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n *\n * @returns The default state for the specific component, if any.\n */\nfunction constructComponentSpecificDefaultState(\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement\n | AccountSelectorElement,\n elementDataGetters: ElementDataGetters,\n) {\n switch (element.type) {\n case 'Dropdown': {\n const children = getJsxChildren(element) as OptionElement[];\n return children[0]?.props.value;\n }\n\n case 'RadioGroup': {\n const children = getJsxChildren(element) as RadioElement[];\n return children[0]?.props.value;\n }\n\n case 'Selector': {\n const children = getJsxChildren(element) as SelectorOptionElement[];\n return children[0]?.props.value;\n }\n\n case 'AccountSelector':\n return getAccountSelectorDefaultStateValue(element, elementDataGetters);\n\n case 'Checkbox':\n return false;\n\n case 'AssetSelector':\n return getDefaultAsset(\n element.props.addresses,\n element.props.chainIds,\n elementDataGetters,\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Get the state value for an asset selector.\n *\n * @param value - The asset selector value.\n * @param getAssetState - A function to get the MultichainAssetController state.\n * @returns The state value for the asset selector or null.\n */\nexport function getAssetSelectorStateValue(\n value: CaipAssetType | undefined,\n getAssetState: GetAssetsState,\n): AssetSelectorState | null {\n if (!value) {\n return null;\n }\n\n const { assetsMetadata } = getAssetState();\n const asset = assetsMetadata[value];\n\n if (!asset) {\n return null;\n }\n\n return {\n asset: value,\n name: asset.name ?? asset.symbol ?? 'Unknown',\n symbol: asset.symbol ?? 'Unknown',\n };\n}\n\n/**\n * Get the state value for an account selector.\n *\n * @param element - The account selector element.\n * @param elementDataGetters - Data getters for the element.\n * @param elementDataGetters.getAccountByAddress - A function to get an account by address.\n * @param elementDataGetters.snapOwnsAccount - A function to check if the snap owns the account.\n * @returns The state value for the account selector.\n */\nexport function getAccountSelectorStateValue(\n element: AccountSelectorElement,\n { getAccountByAddress, snapOwnsAccount }: ElementDataGetters,\n) {\n const { value, hideExternalAccounts } = element.props;\n\n if (!value) {\n return null;\n }\n\n const account = getAccountByAddress(value);\n\n if (!account) {\n return null;\n }\n\n if (hideExternalAccounts && !snapOwnsAccount(account)) {\n return null;\n }\n\n return formatAccountSelectorStateValue(account, element.props.chainIds);\n}\n\n/**\n * Get the state value for a stateful component.\n *\n * Most components store the state value as a `value` prop.\n * This function exists to account for components where that isn't the case.\n *\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n * @returns The state value for a given component.\n */\nfunction getComponentStateValue(\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement\n | AccountSelectorElement,\n elementDataGetters: ElementDataGetters,\n) {\n switch (element.type) {\n case 'Checkbox':\n return element.props.checked;\n\n case 'AssetSelector':\n return getAssetSelectorStateValue(\n element.props.value,\n elementDataGetters.getAssetsState,\n );\n\n case 'AddressInput': {\n if (!element.props.value) {\n return null;\n }\n\n // Construct CAIP-10 Id\n const { namespace, reference } = parseCaipChainId(element.props.chainId);\n return toCaipAccountId(namespace, reference, element.props.value);\n }\n\n case 'AccountSelector':\n return getAccountSelectorStateValue(element, elementDataGetters);\n\n default:\n return element.props.value;\n }\n}\n\n/**\n * Construct the state for an input field.\n *\n * @param oldState - The previous state.\n * @param element - The input element.\n * @param elementDataGetters - Data getters for the element.\n * @param form - An optional form that the input is enclosed in.\n * @returns The input state.\n */\nfunction constructInputState(\n oldState: InterfaceState,\n element:\n | InputElement\n | DropdownElement\n | RadioGroupElement\n | FileInputElement\n | CheckboxElement\n | SelectorElement\n | AssetSelectorElement\n | AddressInputElement\n | AccountSelectorElement,\n elementDataGetters: ElementDataGetters,\n form?: string,\n) {\n const oldStateUnwrapped = form ? (oldState[form] as FormState) : oldState;\n const oldInputState = oldStateUnwrapped?.[element.props.name] as State;\n\n if (element.type === 'FileInput') {\n return oldInputState ?? null;\n }\n\n return (\n getComponentStateValue(element, elementDataGetters) ??\n oldInputState ??\n constructComponentSpecificDefaultState(element, elementDataGetters) ??\n null\n );\n}\n\n/**\n * Construct the interface state for a given component tree.\n *\n * @param oldState - The previous state.\n * @param rootComponent - The UI component to construct state from.\n * @param elementDataGetters - Data getters for the elements.\n * @returns The interface state of the passed component.\n */\nexport function constructState(\n oldState: InterfaceState,\n rootComponent: JSXElement,\n elementDataGetters: ElementDataGetters,\n): InterfaceState {\n const newState: InterfaceState = {};\n\n // Stack containing the forms we have visited and at which depth\n const formStack: { name: string; depth: number }[] = [];\n\n walkJsx(rootComponent, (component, depth) => {\n let currentForm = formStack[formStack.length - 1];\n\n // Pop the current form of the stack once we leave its depth.\n if (currentForm && depth <= currentForm.depth) {\n formStack.pop();\n currentForm = formStack[formStack.length - 1];\n }\n\n if (component.type === 'Form') {\n assertNameIsUnique(newState, component.props.name);\n formStack.push({ name: component.props.name, depth });\n newState[component.props.name] = {};\n return;\n }\n\n // Stateful components inside a form\n if (currentForm && isStatefulComponent(component)) {\n const formState = newState[currentForm.name] as FormState;\n assertNameIsUnique(formState, component.props.name);\n formState[component.props.name] = constructInputState(\n oldState,\n component,\n elementDataGetters,\n currentForm.name,\n );\n return;\n }\n\n // Stateful components outside a form\n if (isStatefulComponent(component)) {\n assertNameIsUnique(newState, component.props.name);\n newState[component.props.name] = constructInputState(\n oldState,\n component,\n elementDataGetters,\n );\n }\n });\n\n return newState;\n}\n\nconst MAX_CONTEXT_SIZE = 5_000_000; // 5 mb\n\n/**\n * Validate a JSON blob to be used as the interface context.\n *\n * @param context - The JSON blob.\n * @throws If the JSON blob is too large.\n */\nexport function validateInterfaceContext(context?: InterfaceContext) {\n if (!context) {\n return;\n }\n\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(context);\n assert(\n size <= MAX_CONTEXT_SIZE,\n `A Snap interface context may not be larger than ${\n MAX_CONTEXT_SIZE / 1000000\n } MB.`,\n );\n}\n"]}
|
|
@@ -65,6 +65,7 @@ class MultichainRouter {
|
|
|
65
65
|
const accountId = await __classPrivateFieldGet(this, _MultichainRouter_instances, "m", _MultichainRouter_getSnapAccountId).call(this, connectedAddresses, scope, request);
|
|
66
66
|
if (accountId) {
|
|
67
67
|
return __classPrivateFieldGet(this, _MultichainRouter_withSnapKeyring, "f").call(this, async ({ keyring }) => keyring.submitRequest({
|
|
68
|
+
origin,
|
|
68
69
|
account: accountId,
|
|
69
70
|
scope,
|
|
70
71
|
method,
|