@openzeppelin/ui-types 1.0.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/LICENSE +661 -0
- package/README.md +174 -0
- package/dist/index-BvxkLrGC.d.cts +2965 -0
- package/dist/index-BvxkLrGC.d.cts.map +1 -0
- package/dist/index-yVZ0ZDGy.d.ts +2965 -0
- package/dist/index-yVZ0ZDGy.d.ts.map +1 -0
- package/dist/index.cjs +380 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2965 -0
- package/dist/index.d.ts +2965 -0
- package/dist/index.js +361 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
//#region src/adapters/ui-enhancements.ts
|
|
2
|
+
/**
|
|
3
|
+
* Valid component keys for EcosystemWalletComponents.
|
|
4
|
+
* Used for type-safe runtime validation of component exclusion lists.
|
|
5
|
+
*/
|
|
6
|
+
const ECOSYSTEM_WALLET_COMPONENT_KEYS = [
|
|
7
|
+
"ConnectButton",
|
|
8
|
+
"AccountDisplay",
|
|
9
|
+
"NetworkSwitcher"
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/adapters/access-control-errors.ts
|
|
14
|
+
/**
|
|
15
|
+
* Access Control Error Types
|
|
16
|
+
*
|
|
17
|
+
* Chain-agnostic error classes for access control operations.
|
|
18
|
+
* These errors can be used across any adapter (EVM, Stellar, Solana, Midnight, etc.)
|
|
19
|
+
* that implements access control functionality.
|
|
20
|
+
*
|
|
21
|
+
* Each error type provides specific context for debugging and user-friendly error messages.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Base class for all Access Control errors
|
|
25
|
+
*
|
|
26
|
+
* This abstract class serves as the foundation for all access control-related errors.
|
|
27
|
+
* It provides a common structure with optional contract address context.
|
|
28
|
+
*/
|
|
29
|
+
var AccessControlError = class extends Error {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new AccessControlError.
|
|
32
|
+
* @param message - Error message describing the issue
|
|
33
|
+
* @param contractAddress - Optional contract address for context
|
|
34
|
+
*/
|
|
35
|
+
constructor(message, contractAddress) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.contractAddress = contractAddress;
|
|
38
|
+
this.name = this.constructor.name;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Error thrown when a contract does not implement required interfaces
|
|
43
|
+
*
|
|
44
|
+
* This error indicates that a contract is missing necessary access control functionality
|
|
45
|
+
* or has a partial/incompatible implementation.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* throw new UnsupportedContractFeatures(
|
|
50
|
+
* 'Contract missing required Ownable methods',
|
|
51
|
+
* contractAddress,
|
|
52
|
+
* ['transfer_ownership', 'renounce_ownership']
|
|
53
|
+
* );
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* Common use cases:
|
|
57
|
+
* - Contract missing Ownable or AccessControl methods
|
|
58
|
+
* - Contract has partial implementation that doesn't conform to standards
|
|
59
|
+
* - Contract is a custom access control implementation not compatible with expected interfaces
|
|
60
|
+
*/
|
|
61
|
+
var UnsupportedContractFeatures = class extends AccessControlError {
|
|
62
|
+
/**
|
|
63
|
+
* Creates a new UnsupportedContractFeatures error.
|
|
64
|
+
* @param message - Error message describing the issue
|
|
65
|
+
* @param contractAddress - Optional contract address for context
|
|
66
|
+
* @param missingFeatures - Optional list of missing feature names
|
|
67
|
+
*/
|
|
68
|
+
constructor(message, contractAddress, missingFeatures) {
|
|
69
|
+
super(message, contractAddress);
|
|
70
|
+
this.missingFeatures = missingFeatures;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Error thrown when the caller lacks required permissions for an operation
|
|
75
|
+
*
|
|
76
|
+
* This error indicates an authorization failure where the calling account doesn't
|
|
77
|
+
* have the necessary permissions to execute the requested operation.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* throw new PermissionDenied(
|
|
82
|
+
* 'Caller is not an admin',
|
|
83
|
+
* contractAddress,
|
|
84
|
+
* 'ADMIN_ROLE',
|
|
85
|
+
* callerAddress
|
|
86
|
+
* );
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* Common use cases:
|
|
90
|
+
* - Attempting to grant/revoke roles without admin rights
|
|
91
|
+
* - Trying to transfer ownership without being the owner
|
|
92
|
+
* - Executing operations that require specific role membership
|
|
93
|
+
*/
|
|
94
|
+
var PermissionDenied = class extends AccessControlError {
|
|
95
|
+
/**
|
|
96
|
+
* Creates a new PermissionDenied error.
|
|
97
|
+
* @param message - Error message describing the issue
|
|
98
|
+
* @param contractAddress - Optional contract address for context
|
|
99
|
+
* @param requiredRole - Optional role that was required
|
|
100
|
+
* @param callerAddress - Optional address of the caller who lacked permission
|
|
101
|
+
*/
|
|
102
|
+
constructor(message, contractAddress, requiredRole, callerAddress) {
|
|
103
|
+
super(message, contractAddress);
|
|
104
|
+
this.requiredRole = requiredRole;
|
|
105
|
+
this.callerAddress = callerAddress;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Error thrown when an indexer is required but not available
|
|
110
|
+
*
|
|
111
|
+
* This error indicates that an operation requires indexer support (e.g., for historical data),
|
|
112
|
+
* but the indexer is not configured, unreachable, or not functioning properly.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* throw new IndexerUnavailable(
|
|
117
|
+
* 'History queries require indexer support',
|
|
118
|
+
* contractAddress,
|
|
119
|
+
* networkId,
|
|
120
|
+
* indexerEndpoint
|
|
121
|
+
* );
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* Common use cases:
|
|
125
|
+
* - No indexer endpoint configured in network config
|
|
126
|
+
* - Indexer endpoint is unreachable or returning errors
|
|
127
|
+
* - Indexer health check fails
|
|
128
|
+
* - Network doesn't have indexer support
|
|
129
|
+
*/
|
|
130
|
+
var IndexerUnavailable = class extends AccessControlError {
|
|
131
|
+
/**
|
|
132
|
+
* Creates a new IndexerUnavailable error.
|
|
133
|
+
* @param message - Error message describing the issue
|
|
134
|
+
* @param contractAddress - Optional contract address for context
|
|
135
|
+
* @param networkId - Optional network identifier
|
|
136
|
+
* @param endpointUrl - Optional indexer endpoint URL that was unavailable
|
|
137
|
+
*/
|
|
138
|
+
constructor(message, contractAddress, networkId, endpointUrl) {
|
|
139
|
+
super(message, contractAddress);
|
|
140
|
+
this.networkId = networkId;
|
|
141
|
+
this.endpointUrl = endpointUrl;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Error thrown when configuration is invalid or incomplete
|
|
146
|
+
*
|
|
147
|
+
* This error indicates a problem with the configuration provided to access control operations,
|
|
148
|
+
* such as invalid addresses, missing required config, or malformed parameters.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* throw new ConfigurationInvalid(
|
|
153
|
+
* 'Contract not registered',
|
|
154
|
+
* contractAddress,
|
|
155
|
+
* 'contractAddress',
|
|
156
|
+
* providedAddress
|
|
157
|
+
* );
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* Common use cases:
|
|
161
|
+
* - Invalid contract address format
|
|
162
|
+
* - Missing required network configuration
|
|
163
|
+
* - Invalid role identifier
|
|
164
|
+
* - Malformed indexer endpoint
|
|
165
|
+
* - Contract not registered before use
|
|
166
|
+
*/
|
|
167
|
+
var ConfigurationInvalid = class extends AccessControlError {
|
|
168
|
+
/**
|
|
169
|
+
* Creates a new ConfigurationInvalid error.
|
|
170
|
+
* @param message - Error message describing the issue
|
|
171
|
+
* @param contractAddress - Optional contract address for context
|
|
172
|
+
* @param configField - Optional name of the invalid configuration field
|
|
173
|
+
* @param providedValue - Optional value that was invalid
|
|
174
|
+
*/
|
|
175
|
+
constructor(message, contractAddress, configField, providedValue) {
|
|
176
|
+
super(message, contractAddress);
|
|
177
|
+
this.configField = configField;
|
|
178
|
+
this.providedValue = providedValue;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Error thrown when an operation fails during execution
|
|
183
|
+
*
|
|
184
|
+
* This error indicates a runtime failure during an access control operation.
|
|
185
|
+
* It includes the operation name and can chain the underlying cause for debugging.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* try {
|
|
190
|
+
* // ... operation code
|
|
191
|
+
* } catch (err) {
|
|
192
|
+
* throw new OperationFailed(
|
|
193
|
+
* 'Failed to read ownership',
|
|
194
|
+
* contractAddress,
|
|
195
|
+
* 'readOwnership',
|
|
196
|
+
* err as Error
|
|
197
|
+
* );
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* Common use cases:
|
|
202
|
+
* - Transaction assembly fails
|
|
203
|
+
* - RPC call returns an error
|
|
204
|
+
* - Transaction simulation fails
|
|
205
|
+
* - On-chain read operation fails
|
|
206
|
+
* - GraphQL query to indexer fails
|
|
207
|
+
* - Snapshot validation fails
|
|
208
|
+
*/
|
|
209
|
+
var OperationFailed = class extends AccessControlError {
|
|
210
|
+
/**
|
|
211
|
+
* Creates a new OperationFailed error.
|
|
212
|
+
* @param message - Error message describing the issue
|
|
213
|
+
* @param contractAddress - Optional contract address for context
|
|
214
|
+
* @param operation - Optional name of the operation that failed
|
|
215
|
+
* @param cause - Optional underlying error that caused the failure
|
|
216
|
+
*/
|
|
217
|
+
constructor(message, contractAddress, operation, cause) {
|
|
218
|
+
super(message, contractAddress);
|
|
219
|
+
this.operation = operation;
|
|
220
|
+
this.cause = cause;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/common/ecosystem.ts
|
|
226
|
+
/**
|
|
227
|
+
* Type guards for ecosystem types
|
|
228
|
+
*/
|
|
229
|
+
const isEvmEcosystem = (ecosystem) => ecosystem === "evm";
|
|
230
|
+
const isSolanaEcosystem = (ecosystem) => ecosystem === "solana";
|
|
231
|
+
const isStellarEcosystem = (ecosystem) => ecosystem === "stellar";
|
|
232
|
+
const isMidnightEcosystem = (ecosystem) => ecosystem === "midnight";
|
|
233
|
+
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/common/enum.ts
|
|
236
|
+
/**
|
|
237
|
+
* Type guard to check if a value is an EnumValue
|
|
238
|
+
*/
|
|
239
|
+
function isEnumValue(value) {
|
|
240
|
+
return typeof value === "object" && value !== null && "tag" in value && typeof value.tag === "string" && (!("values" in value) || Array.isArray(value.values));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/common/map.ts
|
|
245
|
+
/**
|
|
246
|
+
* Type guard to check if a value is a MapEntry
|
|
247
|
+
*/
|
|
248
|
+
function isMapEntry(value) {
|
|
249
|
+
return typeof value === "object" && value !== null && "key" in value && "value" in value && Object.keys(value).length >= 2;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Type guard to check if a value is an array of MapEntry objects
|
|
253
|
+
*/
|
|
254
|
+
function isMapEntryArray(value) {
|
|
255
|
+
return Array.isArray(value) && value.every(isMapEntry);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region src/networks/config.ts
|
|
260
|
+
/**
|
|
261
|
+
* Type guard to check if a network config is for EVM
|
|
262
|
+
* @param config The network configuration to check
|
|
263
|
+
* @returns True if the config is for EVM
|
|
264
|
+
*/
|
|
265
|
+
const isEvmNetworkConfig = (config) => config.ecosystem === "evm";
|
|
266
|
+
/**
|
|
267
|
+
* Type guard to check if a network config is for Solana
|
|
268
|
+
* @param config The network configuration to check
|
|
269
|
+
* @returns True if the config is for Solana
|
|
270
|
+
*/
|
|
271
|
+
const isSolanaNetworkConfig = (config) => config.ecosystem === "solana";
|
|
272
|
+
/**
|
|
273
|
+
* Type guard to check if a network config is for Stellar
|
|
274
|
+
* @param config The network configuration to check
|
|
275
|
+
* @returns True if the config is for Stellar
|
|
276
|
+
*/
|
|
277
|
+
const isStellarNetworkConfig = (config) => config.ecosystem === "stellar";
|
|
278
|
+
/**
|
|
279
|
+
* Type guard to check if a network config is for Midnight
|
|
280
|
+
* @param config The network configuration to check
|
|
281
|
+
* @returns True if the config is for Midnight
|
|
282
|
+
*/
|
|
283
|
+
const isMidnightNetworkConfig = (config) => config.ecosystem === "midnight";
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region src/networks/validation.ts
|
|
287
|
+
/**
|
|
288
|
+
* Network Configuration Validation
|
|
289
|
+
*
|
|
290
|
+
* This file contains utilities for validating network configurations to ensure they have
|
|
291
|
+
* all required fields and properly typed values for each ecosystem.
|
|
292
|
+
*/
|
|
293
|
+
/**
|
|
294
|
+
* Validate a network configuration
|
|
295
|
+
* @param config The network configuration to validate
|
|
296
|
+
* @returns True if the configuration is valid
|
|
297
|
+
*/
|
|
298
|
+
function validateNetworkConfig(config) {
|
|
299
|
+
if (!validateBaseNetworkConfig(config)) return false;
|
|
300
|
+
if (isEvmNetworkConfig(config)) return validateEvmNetworkConfig(config);
|
|
301
|
+
else if (isSolanaNetworkConfig(config)) return validateSolanaNetworkConfig(config);
|
|
302
|
+
else if (isStellarNetworkConfig(config)) return validateStellarNetworkConfig(config);
|
|
303
|
+
else if (isMidnightNetworkConfig(config)) return validateMidnightNetworkConfig(config);
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Validate the base fields common to all network configurations
|
|
308
|
+
* @param config The network configuration to validate
|
|
309
|
+
* @returns True if the base configuration is valid
|
|
310
|
+
*/
|
|
311
|
+
function validateBaseNetworkConfig(config) {
|
|
312
|
+
return typeof config.id === "string" && config.id.trim().length > 0 && typeof config.name === "string" && config.name.trim().length > 0 && typeof config.network === "string" && config.network.trim().length > 0 && [
|
|
313
|
+
"mainnet",
|
|
314
|
+
"testnet",
|
|
315
|
+
"devnet"
|
|
316
|
+
].includes(config.type) && typeof config.isTestnet === "boolean" && (config.explorerUrl === void 0 || typeof config.explorerUrl === "string");
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Validate an EVM network configuration
|
|
320
|
+
* @param config The EVM network configuration to validate
|
|
321
|
+
* @returns True if the configuration is valid
|
|
322
|
+
*/
|
|
323
|
+
function validateEvmNetworkConfig(config) {
|
|
324
|
+
return typeof config.chainId === "number" && config.chainId > 0 && typeof config.rpcUrl === "string" && config.rpcUrl.trim().length > 0 && validateEvmNativeCurrency(config.nativeCurrency);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Validate the native currency object in an EVM network configuration
|
|
328
|
+
* @param currency The native currency object to validate
|
|
329
|
+
* @returns True if the native currency is valid
|
|
330
|
+
*/
|
|
331
|
+
function validateEvmNativeCurrency(currency) {
|
|
332
|
+
return typeof currency === "object" && currency !== null && typeof currency.name === "string" && currency.name.trim().length > 0 && typeof currency.symbol === "string" && currency.symbol.trim().length > 0 && typeof currency.decimals === "number" && currency.decimals >= 0;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Validate a Solana network configuration
|
|
336
|
+
* @param config The Solana network configuration to validate
|
|
337
|
+
* @returns True if the configuration is valid
|
|
338
|
+
*/
|
|
339
|
+
function validateSolanaNetworkConfig(config) {
|
|
340
|
+
return typeof config.rpcEndpoint === "string" && config.rpcEndpoint.trim().length > 0 && ["confirmed", "finalized"].includes(config.commitment);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Validate a Stellar network configuration
|
|
344
|
+
* @param config The Stellar network configuration to validate
|
|
345
|
+
* @returns True if the configuration is valid
|
|
346
|
+
*/
|
|
347
|
+
function validateStellarNetworkConfig(config) {
|
|
348
|
+
return typeof config.horizonUrl === "string" && config.horizonUrl.trim().length > 0 && typeof config.networkPassphrase === "string" && config.networkPassphrase.trim().length > 0;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Validate a Midnight network configuration
|
|
352
|
+
* @param config The Midnight network configuration to validate
|
|
353
|
+
* @returns True if the configuration is valid
|
|
354
|
+
*/
|
|
355
|
+
function validateMidnightNetworkConfig(_config) {
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
//#endregion
|
|
360
|
+
export { AccessControlError, ConfigurationInvalid, ECOSYSTEM_WALLET_COMPONENT_KEYS, IndexerUnavailable, OperationFailed, PermissionDenied, UnsupportedContractFeatures, isEnumValue, isEvmEcosystem, isEvmNetworkConfig, isMapEntry, isMapEntryArray, isMidnightEcosystem, isMidnightNetworkConfig, isSolanaEcosystem, isSolanaNetworkConfig, isStellarEcosystem, isStellarNetworkConfig, validateNetworkConfig };
|
|
361
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/adapters/ui-enhancements.ts","../src/adapters/access-control-errors.ts","../src/common/ecosystem.ts","../src/common/enum.ts","../src/common/map.ts","../src/networks/config.ts","../src/networks/validation.ts"],"sourcesContent":["import type React from 'react';\n\nimport type { FormFieldType, FormValues } from '../forms';\n\n/**\n * Configuration for excluding specific wallet components provided by an adapter for its 'custom' kit.\n */\nexport interface ComponentExclusionConfig {\n /**\n * Array of component keys (e.g., 'ConnectButton', 'NetworkSwitcher') to exclude\n * when the adapter provides its 'custom' set of UI components.\n */\n exclude?: Array<keyof EcosystemWalletComponents>;\n}\n\n/**\n * Configuration for the desired UI kit to be used by an adapter.\n */\nexport interface UiKitConfiguration {\n /** Name of the chosen UI kit (e.g., 'rainbowkit', 'connectkit'). Use 'custom' for adapter-provided default components or 'none' to disable adapter UI. */\n kitName: UiKitName;\n\n /**\n * Kit-specific configuration options.\n * This is an open-ended object to allow adapters to define their own configuration.\n * The adapter is responsible for validating and type-checking these values.\n */\n kitConfig: FormValues;\n\n customCode?: string;\n}\n\n/**\n * A generic hook function type that can be called with any parameters and returns any result.\n * This allows us to maintain flexibility for adapter implementations while avoiding the use of 'any'.\n */\ntype GenericHook<TParams extends unknown[] = [], TResult = unknown> = (...args: TParams) => TResult;\n\n/**\n * Defines the shape of facade hooks provided by an adapter for its ecosystem.\n * These typically wrap underlying library hooks (e.g., from wagmi for EVM).\n *\n * We use generic hook signatures to allow direct use of library hooks\n * without tightly coupling to their specific parameter and return types.\n *\n * Adapters implementing these facade hooks are responsible for mapping their native\n * library's return values to a conventional set of properties expected by consumers.\n * This ensures that UI components using these facade hooks can remain chain-agnostic.\n *\n * @example For `useSwitchChain`:\n * Consumers will expect an object like:\n * ```typescript\n * {\n * switchChain: (args: { chainId: number }) => void; // Function to initiate the switch\n * isPending: boolean; // True if the switch is in progress\n * error: Error | null; // Error object if the switch failed\n * // chains?: Chain[]; // Optional: array of available chains, if provided by underlying hook\n * }\n * ```\n * If an adapter's underlying library uses `isLoading` instead of `isPending`,\n * the adapter's facade implementation for `useSwitchChain` should map `isLoading` to `isPending`.\n *\n * @example For `useAccount`:\n * Consumers will expect an object like:\n * ```typescript\n * {\n * isConnected: boolean;\n * address?: string;\n * chainId?: number;\n * // Other properties like `connector`, `status` might also be conventionally expected.\n * }\n * ```\n */\nexport interface EcosystemSpecificReactHooks {\n // Hooks that don't require parameters\n useAccount?: GenericHook;\n useConnect?: GenericHook;\n useDisconnect?: GenericHook;\n useSwitchChain?: GenericHook;\n useChainId?: GenericHook;\n useChains?: GenericHook;\n\n // Hooks that typically require parameters\n useBalance?: GenericHook;\n useSendTransaction?: GenericHook;\n useWaitForTransactionReceipt?: GenericHook;\n useSignMessage?: GenericHook;\n useSignTypedData?: GenericHook;\n // Other ecosystem-specific hooks can be added as needed\n}\n\n/**\n * Props for the ecosystem-specific UI context provider component.\n */\nexport interface EcosystemReactUiProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Base props interface that all component props should be compatible with.\n * Components can extend this with additional props as needed.\n */\nexport interface BaseComponentProps {\n className?: string;\n}\n\n/**\n * Defines standardized names for commonly needed wallet UI components\n * that an adapter might provide.\n */\nexport interface EcosystemWalletComponents {\n // Using a generic type parameter with a default of BaseComponentProps\n // This allows components with more specific props that include at least className\n ConnectButton?: React.ComponentType<BaseComponentProps>;\n AccountDisplay?: React.ComponentType<BaseComponentProps>;\n NetworkSwitcher?: React.ComponentType<BaseComponentProps>;\n}\n\n/**\n * Valid component keys for EcosystemWalletComponents.\n * Used for type-safe runtime validation of component exclusion lists.\n */\nexport const ECOSYSTEM_WALLET_COMPONENT_KEYS = [\n 'ConnectButton',\n 'AccountDisplay',\n 'NetworkSwitcher',\n] as const satisfies Array<keyof EcosystemWalletComponents>;\n\nexport type EcosystemWalletComponentKey = (typeof ECOSYSTEM_WALLET_COMPONENT_KEYS)[number];\n\nexport type NativeConfigLoader = (relativePath: string) => Promise<Record<string, unknown> | null>;\n\n/**\n * Describes a UI kit available for a specific adapter, providing all necessary\n * metadata for the builder app to render its configuration options.\n */\nexport interface AvailableUiKit {\n /** A unique identifier for the UI kit (e.g., 'rainbowkit'). */\n id: string;\n\n /** The display name of the UI kit (e.g., 'RainbowKit'). */\n name: string;\n\n /** An optional link to the UI kit's documentation. */\n linkToDocs?: string;\n\n /**\n * An optional description of the UI kit and its configuration.\n * This can contain HTML for formatting (e.g., code blocks, links).\n */\n description?: string;\n\n /** An array of form fields required to configure the UI kit. */\n configFields: FormFieldType[];\n\n /**\n * If true, indicates that this UI kit supports advanced configuration via a code editor.\n * @default false\n */\n hasCodeEditor?: boolean;\n\n /**\n * The default boilerplate code to display if `hasCodeEditor` is true.\n */\n defaultCode?: string;\n}\n\nexport type UiKitName =\n // EVM UI Kits\n | 'rainbowkit'\n | 'connectkit'\n | 'appkit'\n // Stellar UI Kits\n | 'stellar-wallets-kit'\n // Generic options\n | 'custom'\n | 'none';\n\n/**\n * Badge variant for function decorations\n */\nexport type FunctionBadgeVariant = 'info' | 'warning' | 'neutral';\n\n/**\n * Badge displayed next to a function in the UI\n */\nexport interface FunctionBadge {\n /** Display text for the badge */\n text: string;\n /** Visual variant of the badge */\n variant?: FunctionBadgeVariant;\n /** Optional tooltip text shown on hover */\n tooltip?: string;\n}\n\n/**\n * Decoration for a contract function (badges, notes, etc.)\n */\nexport interface FunctionDecoration {\n /** Array of badges to display next to the function */\n badges?: FunctionBadge[];\n /** Optional note to display when the function is selected */\n note?: {\n /** Optional title for the note */\n title?: string;\n /** Body text of the note */\n body: string;\n };\n /**\n * (Optional) If true, the form should auto-add a runtime secret field (if adapter provides getRuntimeFieldBinding).\n * Used to mark functions like organizer-only circuits that require credentials.\n * User can customize (hide, hardcode) or remove the field after auto-add.\n */\n requiresRuntimeSecret?: boolean;\n}\n\n/**\n * Map of function IDs to their decorations\n */\nexport type FunctionDecorationsMap = Record<string, FunctionDecoration>;\n","/**\n * Access Control Error Types\n *\n * Chain-agnostic error classes for access control operations.\n * These errors can be used across any adapter (EVM, Stellar, Solana, Midnight, etc.)\n * that implements access control functionality.\n *\n * Each error type provides specific context for debugging and user-friendly error messages.\n */\n\n/**\n * Base class for all Access Control errors\n *\n * This abstract class serves as the foundation for all access control-related errors.\n * It provides a common structure with optional contract address context.\n */\nexport abstract class AccessControlError extends Error {\n /**\n * Creates a new AccessControlError.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n */\n constructor(\n message: string,\n public readonly contractAddress?: string\n ) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\n/**\n * Error thrown when a contract does not implement required interfaces\n *\n * This error indicates that a contract is missing necessary access control functionality\n * or has a partial/incompatible implementation.\n *\n * @example\n * ```typescript\n * throw new UnsupportedContractFeatures(\n * 'Contract missing required Ownable methods',\n * contractAddress,\n * ['transfer_ownership', 'renounce_ownership']\n * );\n * ```\n *\n * Common use cases:\n * - Contract missing Ownable or AccessControl methods\n * - Contract has partial implementation that doesn't conform to standards\n * - Contract is a custom access control implementation not compatible with expected interfaces\n */\nexport class UnsupportedContractFeatures extends AccessControlError {\n /**\n * Creates a new UnsupportedContractFeatures error.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n * @param missingFeatures - Optional list of missing feature names\n */\n constructor(\n message: string,\n contractAddress?: string,\n public readonly missingFeatures?: string[]\n ) {\n super(message, contractAddress);\n }\n}\n\n/**\n * Error thrown when the caller lacks required permissions for an operation\n *\n * This error indicates an authorization failure where the calling account doesn't\n * have the necessary permissions to execute the requested operation.\n *\n * @example\n * ```typescript\n * throw new PermissionDenied(\n * 'Caller is not an admin',\n * contractAddress,\n * 'ADMIN_ROLE',\n * callerAddress\n * );\n * ```\n *\n * Common use cases:\n * - Attempting to grant/revoke roles without admin rights\n * - Trying to transfer ownership without being the owner\n * - Executing operations that require specific role membership\n */\nexport class PermissionDenied extends AccessControlError {\n /**\n * Creates a new PermissionDenied error.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n * @param requiredRole - Optional role that was required\n * @param callerAddress - Optional address of the caller who lacked permission\n */\n constructor(\n message: string,\n contractAddress?: string,\n public readonly requiredRole?: string,\n public readonly callerAddress?: string\n ) {\n super(message, contractAddress);\n }\n}\n\n/**\n * Error thrown when an indexer is required but not available\n *\n * This error indicates that an operation requires indexer support (e.g., for historical data),\n * but the indexer is not configured, unreachable, or not functioning properly.\n *\n * @example\n * ```typescript\n * throw new IndexerUnavailable(\n * 'History queries require indexer support',\n * contractAddress,\n * networkId,\n * indexerEndpoint\n * );\n * ```\n *\n * Common use cases:\n * - No indexer endpoint configured in network config\n * - Indexer endpoint is unreachable or returning errors\n * - Indexer health check fails\n * - Network doesn't have indexer support\n */\nexport class IndexerUnavailable extends AccessControlError {\n /**\n * Creates a new IndexerUnavailable error.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n * @param networkId - Optional network identifier\n * @param endpointUrl - Optional indexer endpoint URL that was unavailable\n */\n constructor(\n message: string,\n contractAddress?: string,\n public readonly networkId?: string,\n public readonly endpointUrl?: string\n ) {\n super(message, contractAddress);\n }\n}\n\n/**\n * Error thrown when configuration is invalid or incomplete\n *\n * This error indicates a problem with the configuration provided to access control operations,\n * such as invalid addresses, missing required config, or malformed parameters.\n *\n * @example\n * ```typescript\n * throw new ConfigurationInvalid(\n * 'Contract not registered',\n * contractAddress,\n * 'contractAddress',\n * providedAddress\n * );\n * ```\n *\n * Common use cases:\n * - Invalid contract address format\n * - Missing required network configuration\n * - Invalid role identifier\n * - Malformed indexer endpoint\n * - Contract not registered before use\n */\nexport class ConfigurationInvalid extends AccessControlError {\n /**\n * Creates a new ConfigurationInvalid error.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n * @param configField - Optional name of the invalid configuration field\n * @param providedValue - Optional value that was invalid\n */\n constructor(\n message: string,\n contractAddress?: string,\n public readonly configField?: string,\n public readonly providedValue?: unknown\n ) {\n super(message, contractAddress);\n }\n}\n\n/**\n * Error thrown when an operation fails during execution\n *\n * This error indicates a runtime failure during an access control operation.\n * It includes the operation name and can chain the underlying cause for debugging.\n *\n * @example\n * ```typescript\n * try {\n * // ... operation code\n * } catch (err) {\n * throw new OperationFailed(\n * 'Failed to read ownership',\n * contractAddress,\n * 'readOwnership',\n * err as Error\n * );\n * }\n * ```\n *\n * Common use cases:\n * - Transaction assembly fails\n * - RPC call returns an error\n * - Transaction simulation fails\n * - On-chain read operation fails\n * - GraphQL query to indexer fails\n * - Snapshot validation fails\n */\nexport class OperationFailed extends AccessControlError {\n /**\n * Creates a new OperationFailed error.\n * @param message - Error message describing the issue\n * @param contractAddress - Optional contract address for context\n * @param operation - Optional name of the operation that failed\n * @param cause - Optional underlying error that caused the failure\n */\n constructor(\n message: string,\n contractAddress?: string,\n public readonly operation?: string,\n public readonly cause?: Error\n ) {\n super(message, contractAddress);\n }\n}\n","/**\n * Blockchain Ecosystem Types\n *\n * This file defines core types related to blockchain ecosystems supported\n * by the OpenZeppelin UI ecosystem. It consolidates previously scattered\n * ecosystem-related types into a single source of truth.\n */\n\n/**\n * Supported blockchain ecosystems\n */\nexport type Ecosystem = 'evm' | 'solana' | 'stellar' | 'midnight';\n\n/**\n * Network environment types\n */\nexport type NetworkType = 'mainnet' | 'testnet' | 'devnet';\n\n/**\n * Configuration for ecosystem feature flags\n */\nexport interface EcosystemFeatureConfig {\n /** Whether the ecosystem is enabled and functional */\n enabled: boolean;\n /** Whether to show the ecosystem in the UI (even if disabled) */\n showInUI: boolean;\n /** Label to display when the ecosystem is disabled */\n disabledLabel?: string;\n /** Description to show when the ecosystem is disabled */\n disabledDescription?: string;\n}\n\n/**\n * Interface for ecosystem-specific data in the registry\n */\nexport interface EcosystemInfo {\n /** Display name (e.g., 'Ethereum (EVM)') */\n name: string;\n\n /** Detailed description of the blockchain */\n description: string;\n\n /** Explorer/verification platform guidance */\n explorerGuidance: string;\n\n /** Address format example (if applicable) */\n addressExample?: string;\n\n /** Icon path for the ecosystem (if available) */\n iconPath?: string;\n\n /** Network icon name for @web3icons/react NetworkIcon component */\n networkIconName?: string;\n\n /** Background color class for UI elements */\n bgColorClass?: string;\n\n /** Text color class for UI elements */\n textColorClass?: string;\n\n /** Default feature flag configuration */\n defaultFeatureConfig: EcosystemFeatureConfig;\n}\n\n/**\n * Blockchain ecosystem metadata for UI display and configuration\n */\nexport interface EcosystemDefinition {\n /**\n * Unique identifier for the ecosystem\n */\n id: Ecosystem;\n\n /**\n * Human-readable name of the ecosystem\n */\n name: string;\n\n /**\n * Description of the ecosystem's purpose or characteristics\n */\n description: string;\n\n /**\n * Optional icon for UI display\n * Note: This uses a generic type as we don't want to introduce React dependencies\n */\n icon?: unknown;\n}\n\n/**\n * Type guards for ecosystem types\n */\n\nexport const isEvmEcosystem = (ecosystem: Ecosystem): ecosystem is 'evm' => ecosystem === 'evm';\n\nexport const isSolanaEcosystem = (ecosystem: Ecosystem): ecosystem is 'solana' =>\n ecosystem === 'solana';\n\nexport const isStellarEcosystem = (ecosystem: Ecosystem): ecosystem is 'stellar' =>\n ecosystem === 'stellar';\n\nexport const isMidnightEcosystem = (ecosystem: Ecosystem): ecosystem is 'midnight' =>\n ecosystem === 'midnight';\n","/**\n * Chain-Agnostic Enum Types\n *\n * This module defines standardized enum types that work across all blockchain adapters.\n * These types represent the UI layer's understanding of enums before they are converted\n * to blockchain-specific formats by individual adapters.\n */\n\n/**\n * Chain-agnostic enum value representation.\n * This is the standardized format that enum fields produce, regardless of the target blockchain.\n * Each adapter transforms this generic format into its blockchain-specific representation.\n *\n * @example Basic Usage\n * ```typescript\n * Unit variant (no payload)\n * const unitEnum: EnumValue = { tag: \"None\" };\n *\n * Tuple variant (with payload)\n * const tupleEnum: EnumValue = {\n * tag: \"Some\",\n * values: [\"hello\", 42]\n * };\n * ```\n *\n * @example Cross-Chain Compatibility\n * ```typescript\n * Stellar/Soroban: Transforms to ScVec([Symbol(\"Active\"), payload?])\n * const stellarEnum: EnumValue = { tag: \"Active\", values: [123] };\n * → ScVec([Symbol(\"Active\"), ScU32(123)])\n *\n * EVM/Solidity: Transforms to integer or struct\n * const evmEnum: EnumValue = { tag: \"Pending\" };\n * → uint8(0) for simple enums\n * → { variant: 0, data: [...] } for complex enums\n *\n * Solana/Rust: Transforms to Borsh-encoded enum\n * const solanaEnum: EnumValue = { tag: \"Ok\", values: [\"success\"] };\n * → Result::Ok(\"success\") via Borsh serialization\n *\n * Complex nested example\n * const complexEnum: EnumValue = {\n * tag: \"TransferResult\",\n * values: [\n * { tag: \"Success\", values: [\"0x123...\", 1000] },\n * { tag: \"Error\", values: [\"Insufficient funds\"] }\n * ]\n * };\n * ```\n */\nexport interface EnumValue {\n /** The variant name (e.g., 'None', 'Some', 'Success', 'Error') */\n tag: string;\n /** Optional payload values for tuple variants */\n values?: unknown[];\n}\n\n/**\n * Type guard to check if a value is an EnumValue\n */\nexport function isEnumValue(value: unknown): value is EnumValue {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'tag' in value &&\n typeof (value as Record<string, unknown>).tag === 'string' &&\n (!('values' in value) || Array.isArray((value as Record<string, unknown>).values))\n );\n}\n","/**\n * Chain-Agnostic Map Types\n *\n * This module defines standardized map types that work across all blockchain adapters.\n * These types represent the UI layer's understanding of maps before they are converted\n * to blockchain-specific formats by individual adapters.\n */\n\n/**\n * Chain-agnostic map entry representation.\n * This is the standardized format that map fields produce, regardless of the target blockchain.\n * Each adapter transforms this generic format into its blockchain-specific representation.\n *\n * @example Basic Usage\n * ```typescript\n * Simple key-value pairs\n * const stringMap: MapEntry[] = [\n * { key: \"name\", value: \"Alice\" },\n * { key: \"age\", value: 30 }\n * ];\n *\n * Mixed type pairs\n * const mixedMap: MapEntry[] = [\n * { key: \"config\", value: { enabled: true, timeout: 5000 } },\n * { key: \"tags\", value: [\"production\", \"api\"] }\n * ];\n * ```\n *\n * @example Cross-Chain Compatibility\n * ```typescript\n * Stellar/Soroban: Transforms to SorobanMapEntry[]\n * const stellarMap: MapEntry[] = [\n * { key: \"symbol\", value: \"USDC\" },\n * { key: \"decimals\", value: 6 }\n * ];\n * → [\n * { key: ScSymbol(\"symbol\"), value: ScSymbol(\"USDC\") },\n * { key: ScSymbol(\"decimals\"), value: ScU32(6) }\n * ]\n *\n * EVM/Solidity: Transforms to struct array (mappings not supported in function params)\n * const evmMap: MapEntry[] = [\n * { key: \"0x123...\", value: 1000 },\n * { key: \"0x456...\", value: 2000 }\n * ];\n * → AddressAmount[] struct array for function parameters\n *\n * Complex nested maps\n * const nestedMap: MapEntry[] = [\n * {\n * key: \"user_data\",\n * value: [\n * { key: \"balance\", value: \"1000\" },\n * { key: \"permissions\", value: [\"read\", \"write\"] }\n * ]\n * }\n * ];\n * ```\n */\nexport interface MapEntry {\n /** The map key (can be any serializable type) */\n key: unknown;\n /** The map value (can be any serializable type) */\n value: unknown;\n}\n\n/**\n * Type guard to check if a value is a MapEntry\n */\nexport function isMapEntry(value: unknown): value is MapEntry {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'key' in value &&\n 'value' in value &&\n Object.keys(value).length >= 2\n );\n}\n\n/**\n * Type guard to check if a value is an array of MapEntry objects\n */\nexport function isMapEntryArray(value: unknown): value is MapEntry[] {\n return Array.isArray(value) && value.every(isMapEntry);\n}\n","/**\n * Network Configuration Types\n *\n * This file defines the TypeScript types for network configurations across different blockchain ecosystems.\n * It uses a discriminated union pattern with the 'ecosystem' property as the discriminant to ensure type safety.\n */\nimport type React from 'react';\n\nimport { Ecosystem, NetworkType } from '../common/ecosystem';\n\n/**\n * Base interface with common properties shared across all network configurations\n */\nexport interface BaseNetworkConfig {\n /**\n * Unique identifier for the network, e.g., 'ethereum-mainnet', 'polygon-amoy'\n */\n id: string;\n\n /**\n * User-friendly network name, e.g., 'Ethereum Mainnet'\n */\n name: string;\n\n /**\n * The blockchain ecosystem this network belongs to (discriminant for the union type)\n */\n ecosystem: Ecosystem;\n\n /**\n * Parent network name, e.g., 'ethereum', 'polygon'\n */\n network: string;\n\n /**\n * Network type/environment: 'mainnet', 'testnet', or 'devnet'\n */\n type: NetworkType;\n\n /**\n * Explicit flag for easy filtering of test networks\n */\n isTestnet: boolean;\n\n /**\n * The constant name under which this specific network configuration object\n * is exported from its adapter package's network index file.\n * Used by the export system to dynamically import the correct config.\n * Example: 'ethereumMainnet', 'ethereumSepolia'\n */\n exportConstName: string;\n\n /**\n * Base URL for the block explorer (common across ecosystems)\n */\n explorerUrl?: string;\n\n /**\n * Optional React component for the network icon.\n * This allows embedding the icon component directly in the network config,\n * avoiding dynamic imports and improving build performance.\n * If provided, this takes precedence over the icon string.\n */\n iconComponent?: React.ComponentType<{\n size?: number;\n className?: string;\n variant?: 'mono' | 'branded';\n }>;\n\n /**\n * A unique identifier for the specific explorer API service used by this network.\n * This is used by the AppConfigService to fetch the correct API key.\n * Examples: \"etherscan-mainnet\", \"polygonscan-mainnet\", \"bscscan-mainnet\"\n * Should align with keys in AppRuntimeConfig.networkServiceConfigs\n */\n primaryExplorerApiIdentifier?: string;\n\n /**\n * Optional indexer GraphQL HTTP endpoint\n * Used for querying historical blockchain data (e.g., access control events)\n */\n indexerUri?: string;\n\n /**\n * Optional indexer GraphQL WebSocket endpoint\n * Used for real-time blockchain data subscriptions\n */\n indexerWsUri?: string;\n}\n\n/**\n * EVM-specific network configuration\n */\nexport interface EvmNetworkConfig extends BaseNetworkConfig {\n ecosystem: 'evm';\n\n /**\n * EVM chain ID, e.g., 1 for Ethereum Mainnet, 11155111 for Sepolia\n */\n chainId: number;\n\n /**\n * JSON-RPC endpoint for the network (can be a base URL if API key is resolved from env)\n */\n rpcUrl: string;\n\n /**\n * Native currency information\n */\n nativeCurrency: {\n name: string; // e.g., 'Ether'\n symbol: string; // e.g., 'ETH'\n decimals: number; // typically 18\n };\n\n /**\n * Optional icon name for the network (for use with @web3icons/react or similar)\n * If not provided, the network property will be used as a fallback\n */\n apiUrl?: string;\n\n /**\n * Whether this network supports Etherscan V2 API (default: true for all Etherscan-compatible explorers)\n */\n supportsEtherscanV2?: boolean;\n\n /**\n * Whether this network's explorer requires an API key for basic operations (default: true)\n * Some explorers like routescan.io provide free access without API keys\n */\n requiresExplorerApiKey?: boolean;\n\n /**\n * Optional chain-specific configuration object for this network.\n * For EVM networks, this should be a Viem Chain object.\n * If provided, this will be used directly by the chain's clients.\n * If not provided, a fallback or minimal custom chain object might be used.\n */\n viemChain?: unknown;\n}\n\n/**\n * Solana-specific network configuration\n */\nexport interface SolanaNetworkConfig extends BaseNetworkConfig {\n ecosystem: 'solana';\n\n /**\n * RPC endpoint for Solana network\n */\n rpcEndpoint: string;\n\n /**\n * Solana transaction confirmation commitment level\n */\n commitment: 'confirmed' | 'finalized';\n}\n\n/**\n * Stellar-specific network configuration\n */\nexport interface StellarNetworkConfig extends BaseNetworkConfig {\n ecosystem: 'stellar';\n\n /**\n * Horizon server URL (for Stellar Classic operations)\n */\n horizonUrl: string;\n\n /**\n * Soroban RPC server URL (for smart contract operations)\n */\n sorobanRpcUrl: string;\n\n /**\n * Stellar network passphrase\n */\n networkPassphrase: string;\n}\n\n/**\n * Midnight-specific network configuration\n */\nexport interface MidnightNetworkConfig extends BaseNetworkConfig {\n ecosystem: 'midnight';\n\n /**\n * Midnight Network ID enum value\n * Maps to @midnight-ntwrk/midnight-js-network-id NetworkId enum\n * Single source of truth for network identity when mapping is not provided.\n */\n /**\n * Mapping of numeric network ID to its enum name.\n * Example: { 2: 'TestNet' }\n */\n networkId: Partial<Record<2 | 3 | 1 | 0, 'TestNet' | 'MainNet' | 'DevNet' | 'Undeployed'>>;\n\n /**\n * RPC endpoints for the Midnight network\n */\n rpcEndpoints?: {\n default?: string;\n [key: string]: string | undefined;\n };\n\n // Additional Midnight-specific properties can be added here as the protocol evolves\n}\n\n/**\n * Union type for all network configurations\n * This allows us to handle network configurations in a type-safe manner\n */\nexport type NetworkConfig =\n | EvmNetworkConfig\n | SolanaNetworkConfig\n | StellarNetworkConfig\n | MidnightNetworkConfig;\n\n/**\n * Type guard to check if a network config is for EVM\n * @param config The network configuration to check\n * @returns True if the config is for EVM\n */\nexport const isEvmNetworkConfig = (config: NetworkConfig): config is EvmNetworkConfig =>\n config.ecosystem === 'evm';\n\n/**\n * Type guard to check if a network config is for Solana\n * @param config The network configuration to check\n * @returns True if the config is for Solana\n */\nexport const isSolanaNetworkConfig = (config: NetworkConfig): config is SolanaNetworkConfig =>\n config.ecosystem === 'solana';\n\n/**\n * Type guard to check if a network config is for Stellar\n * @param config The network configuration to check\n * @returns True if the config is for Stellar\n */\nexport const isStellarNetworkConfig = (config: NetworkConfig): config is StellarNetworkConfig =>\n config.ecosystem === 'stellar';\n\n/**\n * Type guard to check if a network config is for Midnight\n * @param config The network configuration to check\n * @returns True if the config is for Midnight\n */\nexport const isMidnightNetworkConfig = (config: NetworkConfig): config is MidnightNetworkConfig =>\n config.ecosystem === 'midnight';\n","/**\n * Network Configuration Validation\n *\n * This file contains utilities for validating network configurations to ensure they have\n * all required fields and properly typed values for each ecosystem.\n */\nimport {\n EvmNetworkConfig,\n isEvmNetworkConfig,\n isMidnightNetworkConfig,\n isSolanaNetworkConfig,\n isStellarNetworkConfig,\n MidnightNetworkConfig,\n NetworkConfig,\n SolanaNetworkConfig,\n StellarNetworkConfig,\n} from './config';\n\n/**\n * Validate a network configuration\n * @param config The network configuration to validate\n * @returns True if the configuration is valid\n */\nexport function validateNetworkConfig(config: NetworkConfig): boolean {\n // Validate common fields required for all networks\n if (!validateBaseNetworkConfig(config)) {\n return false;\n }\n\n // Ecosystem-specific validation\n if (isEvmNetworkConfig(config)) {\n return validateEvmNetworkConfig(config);\n } else if (isSolanaNetworkConfig(config)) {\n return validateSolanaNetworkConfig(config);\n } else if (isStellarNetworkConfig(config)) {\n return validateStellarNetworkConfig(config);\n } else if (isMidnightNetworkConfig(config)) {\n return validateMidnightNetworkConfig(config);\n }\n\n // Unknown ecosystem\n return false;\n}\n\n/**\n * Validate the base fields common to all network configurations\n * @param config The network configuration to validate\n * @returns True if the base configuration is valid\n */\nfunction validateBaseNetworkConfig(config: NetworkConfig): boolean {\n return (\n typeof config.id === 'string' &&\n config.id.trim().length > 0 &&\n typeof config.name === 'string' &&\n config.name.trim().length > 0 &&\n typeof config.network === 'string' &&\n config.network.trim().length > 0 &&\n ['mainnet', 'testnet', 'devnet'].includes(config.type) &&\n typeof config.isTestnet === 'boolean' &&\n (config.explorerUrl === undefined || typeof config.explorerUrl === 'string')\n );\n}\n\n/**\n * Validate an EVM network configuration\n * @param config The EVM network configuration to validate\n * @returns True if the configuration is valid\n */\nfunction validateEvmNetworkConfig(config: EvmNetworkConfig): boolean {\n return (\n typeof config.chainId === 'number' &&\n config.chainId > 0 &&\n typeof config.rpcUrl === 'string' &&\n config.rpcUrl.trim().length > 0 &&\n validateEvmNativeCurrency(config.nativeCurrency)\n );\n}\n\n/**\n * Validate the native currency object in an EVM network configuration\n * @param currency The native currency object to validate\n * @returns True if the native currency is valid\n */\nfunction validateEvmNativeCurrency(currency: EvmNetworkConfig['nativeCurrency']): boolean {\n return (\n typeof currency === 'object' &&\n currency !== null &&\n typeof currency.name === 'string' &&\n currency.name.trim().length > 0 &&\n typeof currency.symbol === 'string' &&\n currency.symbol.trim().length > 0 &&\n typeof currency.decimals === 'number' &&\n currency.decimals >= 0\n );\n}\n\n/**\n * Validate a Solana network configuration\n * @param config The Solana network configuration to validate\n * @returns True if the configuration is valid\n */\nfunction validateSolanaNetworkConfig(config: SolanaNetworkConfig): boolean {\n return (\n typeof config.rpcEndpoint === 'string' &&\n config.rpcEndpoint.trim().length > 0 &&\n ['confirmed', 'finalized'].includes(config.commitment)\n );\n}\n\n/**\n * Validate a Stellar network configuration\n * @param config The Stellar network configuration to validate\n * @returns True if the configuration is valid\n */\nfunction validateStellarNetworkConfig(config: StellarNetworkConfig): boolean {\n return (\n typeof config.horizonUrl === 'string' &&\n config.horizonUrl.trim().length > 0 &&\n typeof config.networkPassphrase === 'string' &&\n config.networkPassphrase.trim().length > 0\n );\n}\n\n/**\n * Validate a Midnight network configuration\n * @param config The Midnight network configuration to validate\n * @returns True if the configuration is valid\n */\nfunction validateMidnightNetworkConfig(_config: MidnightNetworkConfig): boolean {\n // Currently just validates the base fields\n // Add more validation as Midnight-specific fields are added\n return true;\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openzeppelin/ui-types",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Shared TypeScript type definitions for the OpenZeppelin UI ecosystem.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"types",
|
|
27
|
+
"blockchain",
|
|
28
|
+
"form",
|
|
29
|
+
"typescript"
|
|
30
|
+
],
|
|
31
|
+
"author": "OpenZeppelin",
|
|
32
|
+
"license": "AGPL-3.0",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/OpenZeppelin/openzeppelin-ui",
|
|
36
|
+
"directory": "packages/types"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/react": "^19.1.9",
|
|
40
|
+
"react": "^19.2.1",
|
|
41
|
+
"typescript": "^5.8.3",
|
|
42
|
+
"vitest": "^3.2.4"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsdown && pnpm build:dts-fix",
|
|
46
|
+
"build:dts-fix": "cd dist && for f in index-*.d.ts; do [ -f \"$f\" ] && cp \"$f\" index.d.ts; done && for f in index-*.d.cts; do [ -f \"$f\" ] && cp \"$f\" index.d.cts; done || true",
|
|
47
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run --passWithNoTests",
|
|
50
|
+
"test:watch": "vitest",
|
|
51
|
+
"test:coverage": "vitest run --coverage --passWithNoTests",
|
|
52
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\" --report-unused-disable-directives --max-warnings 0",
|
|
53
|
+
"lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
|
|
54
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,css}\"",
|
|
55
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,css}\""
|
|
56
|
+
}
|
|
57
|
+
}
|