@openzeppelin/adapter-stellar 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.
Files changed (165) hide show
  1. package/README.md +272 -0
  2. package/dist/config.cjs +21 -0
  3. package/dist/config.cjs.map +1 -0
  4. package/dist/config.d.cts +8 -0
  5. package/dist/config.d.cts.map +1 -0
  6. package/dist/config.d.mts +8 -0
  7. package/dist/config.d.mts.map +1 -0
  8. package/dist/config.mjs +20 -0
  9. package/dist/config.mjs.map +1 -0
  10. package/dist/index.cjs +7564 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +261 -0
  13. package/dist/index.d.cts.map +1 -0
  14. package/dist/index.d.mts +263 -0
  15. package/dist/index.d.mts.map +1 -0
  16. package/dist/index.mjs +7529 -0
  17. package/dist/index.mjs.map +1 -0
  18. package/dist/metadata.cjs +22 -0
  19. package/dist/metadata.cjs.map +1 -0
  20. package/dist/metadata.d.cts +7 -0
  21. package/dist/metadata.d.cts.map +1 -0
  22. package/dist/metadata.d.mts +7 -0
  23. package/dist/metadata.d.mts.map +1 -0
  24. package/dist/metadata.mjs +21 -0
  25. package/dist/metadata.mjs.map +1 -0
  26. package/dist/networks-BrV516-R.d.cts +15 -0
  27. package/dist/networks-BrV516-R.d.cts.map +1 -0
  28. package/dist/networks-C0MmhJcu.d.mts +15 -0
  29. package/dist/networks-C0MmhJcu.d.mts.map +1 -0
  30. package/dist/networks-DgUFSTiC.cjs +76 -0
  31. package/dist/networks-DgUFSTiC.cjs.map +1 -0
  32. package/dist/networks-QbEPbaGT.mjs +46 -0
  33. package/dist/networks-QbEPbaGT.mjs.map +1 -0
  34. package/dist/networks.cjs +8 -0
  35. package/dist/networks.d.cts +2 -0
  36. package/dist/networks.d.mts +2 -0
  37. package/dist/networks.mjs +3 -0
  38. package/dist/vite-config.cjs +43 -0
  39. package/dist/vite-config.cjs.map +1 -0
  40. package/dist/vite-config.d.cts +35 -0
  41. package/dist/vite-config.d.cts.map +1 -0
  42. package/dist/vite-config.d.mts +35 -0
  43. package/dist/vite-config.d.mts.map +1 -0
  44. package/dist/vite-config.mjs +42 -0
  45. package/dist/vite-config.mjs.map +1 -0
  46. package/package.json +114 -0
  47. package/src/__tests__/getDefaultServiceConfig.test.ts +105 -0
  48. package/src/access-control/actions.ts +214 -0
  49. package/src/access-control/feature-detection.ts +238 -0
  50. package/src/access-control/index.ts +54 -0
  51. package/src/access-control/indexer-client.ts +1474 -0
  52. package/src/access-control/onchain-reader.ts +446 -0
  53. package/src/access-control/service.ts +1431 -0
  54. package/src/access-control/validation.ts +256 -0
  55. package/src/adapter.ts +659 -0
  56. package/src/config.ts +43 -0
  57. package/src/configuration/__tests__/explorer.test.ts +80 -0
  58. package/src/configuration/__tests__/rpc.test.ts +355 -0
  59. package/src/configuration/execution.ts +83 -0
  60. package/src/configuration/explorer.ts +105 -0
  61. package/src/configuration/index.ts +5 -0
  62. package/src/configuration/network-services.ts +210 -0
  63. package/src/configuration/rpc.ts +270 -0
  64. package/src/configuration.ts +2 -0
  65. package/src/contract/__tests__/complete-type-coverage.test.ts +78 -0
  66. package/src/contract/index.ts +3 -0
  67. package/src/contract/loader.ts +498 -0
  68. package/src/contract/transformer.ts +1 -0
  69. package/src/contract/type.ts +65 -0
  70. package/src/index.ts +23 -0
  71. package/src/mapping/constants.ts +89 -0
  72. package/src/mapping/enum-metadata.ts +237 -0
  73. package/src/mapping/field-generator.ts +296 -0
  74. package/src/mapping/index.ts +5 -0
  75. package/src/mapping/struct-fields.ts +106 -0
  76. package/src/mapping/tuple-components.ts +43 -0
  77. package/src/mapping/type-coverage-validator.ts +151 -0
  78. package/src/mapping/type-mapper.ts +203 -0
  79. package/src/metadata.ts +16 -0
  80. package/src/networks/README.md +84 -0
  81. package/src/networks/index.ts +19 -0
  82. package/src/networks/mainnet.ts +20 -0
  83. package/src/networks/testnet.ts +20 -0
  84. package/src/networks.ts +2 -0
  85. package/src/query/handler.ts +411 -0
  86. package/src/query/index.ts +4 -0
  87. package/src/query/view-checker.ts +32 -0
  88. package/src/sac/spec-cache.ts +68 -0
  89. package/src/sac/spec-source.ts +35 -0
  90. package/src/sac/xdr.ts +101 -0
  91. package/src/transaction/components/AdvancedInfo.tsx +34 -0
  92. package/src/transaction/components/FeeConfiguration.tsx +41 -0
  93. package/src/transaction/components/StellarRelayerOptions.tsx +60 -0
  94. package/src/transaction/components/TransactionTiming.tsx +77 -0
  95. package/src/transaction/components/index.ts +5 -0
  96. package/src/transaction/components/useStellarRelayerOptions.ts +114 -0
  97. package/src/transaction/eoa.ts +229 -0
  98. package/src/transaction/execution-strategy.ts +33 -0
  99. package/src/transaction/formatter.ts +296 -0
  100. package/src/transaction/index.ts +4 -0
  101. package/src/transaction/relayer.ts +575 -0
  102. package/src/transaction/sender.ts +156 -0
  103. package/src/transform/index.ts +4 -0
  104. package/src/transform/input-parser.ts +9 -0
  105. package/src/transform/output-formatter.ts +133 -0
  106. package/src/transform/parsers/complex-parser.ts +157 -0
  107. package/src/transform/parsers/generic-parser.ts +171 -0
  108. package/src/transform/parsers/index.ts +86 -0
  109. package/src/transform/parsers/primitive-parser.ts +123 -0
  110. package/src/transform/parsers/scval-converter.ts +405 -0
  111. package/src/transform/parsers/struct-parser.ts +324 -0
  112. package/src/transform/parsers/types.ts +35 -0
  113. package/src/types/__tests__/artifacts.test.ts +89 -0
  114. package/src/types/artifacts.ts +19 -0
  115. package/src/utils/__tests__/artifacts.test.ts +77 -0
  116. package/src/utils/artifacts.ts +30 -0
  117. package/src/utils/formatting.ts +122 -0
  118. package/src/utils/index.ts +6 -0
  119. package/src/utils/input-parsing.ts +336 -0
  120. package/src/utils/safe-type-parser.ts +303 -0
  121. package/src/utils/stellar-types.ts +35 -0
  122. package/src/utils/type-detection.ts +163 -0
  123. package/src/utils/xdr-ordering.ts +36 -0
  124. package/src/validation/__tests__/address.test.ts +267 -0
  125. package/src/validation/address.ts +136 -0
  126. package/src/validation/eoa.ts +33 -0
  127. package/src/validation/index.ts +3 -0
  128. package/src/validation/relayer.ts +13 -0
  129. package/src/vite-config.ts +67 -0
  130. package/src/wallet/README.md +93 -0
  131. package/src/wallet/__tests__/connection.test.ts +72 -0
  132. package/src/wallet/components/StellarWalletUiRoot.tsx +161 -0
  133. package/src/wallet/components/account/AccountDisplay.tsx +50 -0
  134. package/src/wallet/components/connect/ConnectButton.tsx +100 -0
  135. package/src/wallet/components/connect/ConnectorDialog.tsx +125 -0
  136. package/src/wallet/components/index.ts +3 -0
  137. package/src/wallet/connection.ts +151 -0
  138. package/src/wallet/context/StellarWalletContext.ts +32 -0
  139. package/src/wallet/context/index.ts +4 -0
  140. package/src/wallet/context/useStellarWalletContext.ts +17 -0
  141. package/src/wallet/hooks/facade-hooks.ts +31 -0
  142. package/src/wallet/hooks/index.ts +7 -0
  143. package/src/wallet/hooks/useStellarAccount.ts +27 -0
  144. package/src/wallet/hooks/useStellarConnect.ts +60 -0
  145. package/src/wallet/hooks/useStellarDisconnect.ts +47 -0
  146. package/src/wallet/hooks/useUiKitConfig.ts +40 -0
  147. package/src/wallet/implementation/wallets-kit-implementation.ts +379 -0
  148. package/src/wallet/index.ts +11 -0
  149. package/src/wallet/services/__tests__/configResolutionService.test.ts +163 -0
  150. package/src/wallet/services/configResolutionService.ts +65 -0
  151. package/src/wallet/stellar-wallets-kit/StellarWalletsKitConnectButton.tsx +82 -0
  152. package/src/wallet/stellar-wallets-kit/__mocks__/@creit.tech/stellar-wallets-kit.ts +48 -0
  153. package/src/wallet/stellar-wallets-kit/__tests__/export-service.test.ts +93 -0
  154. package/src/wallet/stellar-wallets-kit/__tests__/stellarUiKitManager.test.ts +0 -0
  155. package/src/wallet/stellar-wallets-kit/config-generator.ts +75 -0
  156. package/src/wallet/stellar-wallets-kit/export-service.ts +19 -0
  157. package/src/wallet/stellar-wallets-kit/index.ts +3 -0
  158. package/src/wallet/stellar-wallets-kit/stellarUiKitManager.ts +235 -0
  159. package/src/wallet/types.ts +19 -0
  160. package/src/wallet/utils/__tests__/filterWalletComponents.test.ts +150 -0
  161. package/src/wallet/utils/__tests__/uiKitService.test.ts +189 -0
  162. package/src/wallet/utils/filterWalletComponents.ts +89 -0
  163. package/src/wallet/utils/index.ts +3 -0
  164. package/src/wallet/utils/stellarWalletImplementationManager.ts +118 -0
  165. package/src/wallet/utils/uiKitService.ts +74 -0
package/src/adapter.ts ADDED
@@ -0,0 +1,659 @@
1
+ import type React from 'react';
2
+
3
+ import type {
4
+ AccessControlService,
5
+ AvailableUiKit,
6
+ Connector,
7
+ ContractAdapter,
8
+ ContractFunction,
9
+ ContractSchema,
10
+ EcosystemReactUiProviderProps,
11
+ EcosystemSpecificReactHooks,
12
+ EcosystemWalletComponents,
13
+ ExecutionConfig,
14
+ ExecutionMethodDetail,
15
+ FieldType,
16
+ FormFieldType,
17
+ FunctionParameter,
18
+ NativeConfigLoader,
19
+ NetworkServiceForm,
20
+ RelayerDetails,
21
+ RelayerDetailsRich,
22
+ StellarNetworkConfig,
23
+ TransactionStatusUpdate,
24
+ TxStatus,
25
+ TypeMappingInfo,
26
+ UiKitConfiguration,
27
+ UserRpcProviderConfig,
28
+ WalletConnectionStatus,
29
+ } from '@openzeppelin/ui-types';
30
+ import { isStellarNetworkConfig } from '@openzeppelin/ui-types';
31
+ import { logger } from '@openzeppelin/ui-utils';
32
+
33
+ import { getCurrentLedger } from './access-control/onchain-reader';
34
+ import { createStellarAccessControlService } from './access-control/service';
35
+ import {
36
+ getStellarDefaultServiceConfig,
37
+ getStellarNetworkServiceForms,
38
+ testStellarNetworkServiceConnection,
39
+ validateStellarNetworkServiceConfig,
40
+ } from './configuration/network-services';
41
+ // Import functions from modules
42
+ import { loadStellarContract, loadStellarContractWithMetadata } from './contract/loader';
43
+ import { StellarRelayerOptions } from './transaction/components';
44
+ import { RelayerExecutionStrategy } from './transaction/relayer';
45
+
46
+ import {
47
+ getStellarExplorerAddressUrl,
48
+ getStellarExplorerTxUrl,
49
+ getStellarSupportedExecutionMethods,
50
+ testStellarRpcConnection,
51
+ validateStellarExecutionConfig,
52
+ validateStellarRpcEndpoint,
53
+ } from './configuration';
54
+ import {
55
+ generateStellarDefaultField,
56
+ getStellarCompatibleFieldTypes,
57
+ getStellarTypeMappingInfo,
58
+ mapStellarParameterTypeToFieldType,
59
+ } from './mapping';
60
+ import {
61
+ getStellarWritableFunctions,
62
+ isStellarViewFunction,
63
+ queryStellarViewFunction,
64
+ } from './query';
65
+ import { formatStellarTransactionData, signAndBroadcastStellarTransaction } from './transaction';
66
+ import { formatStellarFunctionResult } from './transform';
67
+ import { validateAndConvertStellarArtifacts } from './utils';
68
+ import { isValidAddress as isStellarValidAddress, type StellarAddressType } from './validation';
69
+ import {
70
+ connectStellarWallet,
71
+ disconnectStellarWallet,
72
+ generateStellarWalletsKitExportables,
73
+ getInitializedStellarWalletImplementation,
74
+ getResolvedWalletComponents,
75
+ getStellarAvailableConnectors,
76
+ getStellarWalletImplementation,
77
+ loadInitialConfigFromAppService,
78
+ resolveFullUiKitConfiguration,
79
+ stellarFacadeHooks,
80
+ stellarUiKitManager,
81
+ StellarWalletConnectionStatus,
82
+ StellarWalletUiRoot,
83
+ supportsStellarWalletConnection,
84
+ } from './wallet';
85
+
86
+ /**
87
+ * Stellar-specific adapter implementation using explicit method delegation.
88
+ */
89
+ export class StellarAdapter implements ContractAdapter {
90
+ readonly networkConfig: StellarNetworkConfig;
91
+ readonly initialAppServiceKitName: UiKitConfiguration['kitName'];
92
+ private readonly accessControlService: AccessControlService;
93
+
94
+ constructor(networkConfig: StellarNetworkConfig) {
95
+ if (!isStellarNetworkConfig(networkConfig)) {
96
+ throw new Error('StellarAdapter requires a valid Stellar network configuration.');
97
+ }
98
+ this.networkConfig = networkConfig;
99
+
100
+ // Initialize Access Control Service
101
+ this.accessControlService = createStellarAccessControlService(networkConfig);
102
+
103
+ // Set the network config in the wallet UI kit manager
104
+ stellarUiKitManager.setNetworkConfig(networkConfig);
105
+
106
+ // Initialize wallet implementation with network config
107
+ getStellarWalletImplementation(networkConfig).catch((error) => {
108
+ logger.error(
109
+ 'StellarAdapter:constructor',
110
+ 'Failed to initialize wallet implementation:',
111
+ error
112
+ );
113
+ });
114
+
115
+ // Determine the initial kitName from AppConfigService at the time of adapter construction.
116
+ // This provides a baseline kitName preference from the application's static/global configuration.
117
+ // It defaults to 'custom' if no specific kitName is found in AppConfigService.
118
+ const initialGlobalConfig = loadInitialConfigFromAppService();
119
+ this.initialAppServiceKitName =
120
+ (initialGlobalConfig.kitName as UiKitConfiguration['kitName']) || 'custom';
121
+
122
+ logger.info(
123
+ 'StellarAdapter:constructor',
124
+ 'Initial kitName from AppConfigService noted:',
125
+ this.initialAppServiceKitName
126
+ );
127
+
128
+ logger.info(
129
+ 'StellarAdapter',
130
+ `Adapter initialized for network: ${networkConfig.name} (ID: ${networkConfig.id})`
131
+ );
132
+ }
133
+
134
+ /**
135
+ * @inheritdoc
136
+ */
137
+ public getNetworkServiceForms(): NetworkServiceForm[] {
138
+ return getStellarNetworkServiceForms();
139
+ }
140
+
141
+ /**
142
+ * @inheritdoc
143
+ */
144
+ public async validateNetworkServiceConfig(
145
+ serviceId: string,
146
+ values: Record<string, unknown>
147
+ ): Promise<boolean> {
148
+ return validateStellarNetworkServiceConfig(serviceId, values);
149
+ }
150
+
151
+ /**
152
+ * @inheritdoc
153
+ */
154
+ public async testNetworkServiceConnection(
155
+ serviceId: string,
156
+ values: Record<string, unknown>
157
+ ): Promise<{ success: boolean; latency?: number; error?: string }> {
158
+ return testStellarNetworkServiceConnection(serviceId, values);
159
+ }
160
+
161
+ /**
162
+ * @inheritdoc
163
+ */
164
+ public getDefaultServiceConfig(serviceId: string): Record<string, unknown> | null {
165
+ return getStellarDefaultServiceConfig(this.networkConfig, serviceId);
166
+ }
167
+
168
+ /**
169
+ * NOTE about artifact inputs (single input with auto-detection):
170
+ *
171
+ * The Builder renders the contract definition step using whatever fields the
172
+ * adapter returns here. EVM uses one optional ABI field; Midnight provides
173
+ * multiple fields. Stellar should use a single input approach with automatic
174
+ * content detection when we add manual-spec support:
175
+ *
176
+ * - Keep `contractAddress` (required)
177
+ * - Add optional `contractDefinition` (type: `code-editor`, language: `json`)
178
+ * with file upload support for both JSON and Wasm binary content
179
+ *
180
+ * When this field is added:
181
+ * - Extend `validateAndConvertStellarArtifacts(...)` to accept
182
+ * `{ contractAddress, contractDefinition? }`
183
+ * - In the loader, branch: if `contractDefinition` provided, auto-detect
184
+ * content type (JSON vs Wasm using magic bytes `\0asm`):
185
+ * - For JSON: Parse and validate as Soroban spec, use `transformStellarSpecToSchema`
186
+ * - For Wasm: Extract embedded spec from binary, parse locally (no RPC)
187
+ * - Set `source: 'manual'` with `contractDefinitionOriginal` to the raw
188
+ * user-provided content. This ensures auto-save captures and restores the
189
+ * manual contract definition exactly like the EVM/Midnight flows.
190
+ * - Provide clear UI hints about supported formats (JSON spec or Wasm binary).
191
+ */
192
+ /**
193
+ * @inheritdoc
194
+ */
195
+ public getContractDefinitionInputs(): FormFieldType[] {
196
+ return [
197
+ {
198
+ id: 'contractAddress',
199
+ name: 'contractAddress',
200
+ label: 'Contract ID',
201
+ type: 'blockchain-address',
202
+ validation: { required: true },
203
+ placeholder: 'C...',
204
+ helperText: 'Enter the Stellar contract ID (C...).',
205
+ },
206
+ ];
207
+ }
208
+
209
+ /**
210
+ * @inheritdoc
211
+ */
212
+ public async loadContract(source: string | Record<string, unknown>): Promise<ContractSchema> {
213
+ // Convert generic input to Stellar-specific artifacts
214
+ const artifacts = validateAndConvertStellarArtifacts(source);
215
+ const result = await loadStellarContract(artifacts, this.networkConfig);
216
+ return result.schema;
217
+ }
218
+
219
+ /**
220
+ * @inheritdoc
221
+ */
222
+ public async loadContractWithMetadata(source: string | Record<string, unknown>): Promise<{
223
+ schema: ContractSchema;
224
+ source: 'fetched' | 'manual';
225
+ contractDefinitionOriginal?: string;
226
+ metadata?: {
227
+ fetchedFrom?: string;
228
+ contractName?: string;
229
+ fetchTimestamp?: Date;
230
+ definitionHash?: string;
231
+ };
232
+ }> {
233
+ try {
234
+ // Convert generic input to Stellar-specific artifacts
235
+ const artifacts = validateAndConvertStellarArtifacts(source);
236
+ const result = await loadStellarContractWithMetadata(artifacts, this.networkConfig);
237
+
238
+ return {
239
+ schema: result.schema,
240
+ source: result.source,
241
+ contractDefinitionOriginal: result.contractDefinitionOriginal,
242
+ metadata: result.metadata,
243
+ };
244
+ } catch (error) {
245
+ // Re-throw errors consistently with EVM adapter
246
+ throw error;
247
+ }
248
+ }
249
+
250
+ /**
251
+ * @inheritdoc
252
+ */
253
+ getWritableFunctions(contractSchema: ContractSchema): ContractSchema['functions'] {
254
+ return getStellarWritableFunctions(contractSchema);
255
+ }
256
+
257
+ /**
258
+ * @inheritdoc
259
+ */
260
+ mapParameterTypeToFieldType(parameterType: string): FieldType {
261
+ return mapStellarParameterTypeToFieldType(parameterType);
262
+ }
263
+ getCompatibleFieldTypes(parameterType: string): FieldType[] {
264
+ return getStellarCompatibleFieldTypes(parameterType);
265
+ }
266
+ generateDefaultField<T extends FieldType = FieldType>(
267
+ parameter: FunctionParameter,
268
+ contractSchema?: ContractSchema
269
+ ): FormFieldType<T> {
270
+ return generateStellarDefaultField(parameter, contractSchema);
271
+ }
272
+
273
+ /**
274
+ * @inheritdoc
275
+ */
276
+ public formatTransactionData(
277
+ contractSchema: ContractSchema,
278
+ functionId: string,
279
+ submittedInputs: Record<string, unknown>,
280
+ fields: FormFieldType[]
281
+ ): unknown {
282
+ return formatStellarTransactionData(contractSchema, functionId, submittedInputs, fields);
283
+ }
284
+ async signAndBroadcast(
285
+ transactionData: unknown,
286
+ executionConfig: ExecutionConfig,
287
+ onStatusChange: (status: TxStatus, details: TransactionStatusUpdate) => void,
288
+ runtimeApiKey?: string
289
+ ): Promise<{ txHash: string }> {
290
+ return signAndBroadcastStellarTransaction(
291
+ transactionData,
292
+ executionConfig,
293
+ this.networkConfig,
294
+ onStatusChange,
295
+ runtimeApiKey
296
+ );
297
+ }
298
+
299
+ /**
300
+ * @inheritdoc
301
+ */
302
+ isViewFunction(functionDetails: ContractFunction): boolean {
303
+ return isStellarViewFunction(functionDetails);
304
+ }
305
+
306
+ /**
307
+ * @inheritdoc
308
+ */
309
+ async queryViewFunction(
310
+ contractAddress: string,
311
+ functionId: string,
312
+ params: unknown[] = [],
313
+ contractSchema?: ContractSchema
314
+ ): Promise<unknown> {
315
+ return queryStellarViewFunction(
316
+ contractAddress,
317
+ functionId,
318
+ this.networkConfig,
319
+ params,
320
+ contractSchema,
321
+ (address: string) => this.loadContract({ contractAddress: address })
322
+ );
323
+ }
324
+
325
+ /**
326
+ * @inheritdoc
327
+ */
328
+ formatFunctionResult(decodedValue: unknown, functionDetails: ContractFunction): string {
329
+ return formatStellarFunctionResult(decodedValue, functionDetails);
330
+ }
331
+
332
+ /**
333
+ * @inheritdoc
334
+ */
335
+ supportsWalletConnection(): boolean {
336
+ return supportsStellarWalletConnection();
337
+ }
338
+
339
+ /**
340
+ * @inheritdoc
341
+ */
342
+ async getAvailableConnectors(): Promise<Connector[]> {
343
+ return getStellarAvailableConnectors();
344
+ }
345
+
346
+ /**
347
+ * @inheritdoc
348
+ */
349
+ async connectWallet(
350
+ connectorId: string
351
+ ): Promise<{ connected: boolean; address?: string; error?: string }> {
352
+ return connectStellarWallet(connectorId);
353
+ }
354
+
355
+ /**
356
+ * @inheritdoc
357
+ */
358
+ async disconnectWallet(): Promise<{ disconnected: boolean; error?: string }> {
359
+ return disconnectStellarWallet();
360
+ }
361
+
362
+ /**
363
+ * @inheritdoc
364
+ */
365
+ getWalletConnectionStatus(): StellarWalletConnectionStatus {
366
+ const impl = getInitializedStellarWalletImplementation();
367
+ if (!impl) {
368
+ return {
369
+ isConnected: false,
370
+ address: undefined,
371
+ chainId: stellarUiKitManager.getState().networkConfig?.id || 'stellar-testnet',
372
+ };
373
+ }
374
+
375
+ const stellarStatus = impl.getWalletConnectionStatus();
376
+
377
+ // Return the rich Stellar-specific status directly
378
+ return stellarStatus;
379
+ }
380
+
381
+ /**
382
+ * @inheritdoc
383
+ */
384
+ onWalletConnectionChange(
385
+ callback: (
386
+ currentStatus: WalletConnectionStatus,
387
+ previousStatus: WalletConnectionStatus
388
+ ) => void
389
+ ): () => void {
390
+ const walletImplementation = getInitializedStellarWalletImplementation();
391
+ if (!walletImplementation) {
392
+ logger.warn(
393
+ 'StellarAdapter:onWalletConnectionChange',
394
+ 'Wallet implementation not ready. Subscription may not work.'
395
+ );
396
+ return () => {};
397
+ }
398
+
399
+ return walletImplementation.onWalletConnectionChange(
400
+ (currentImplStatus, previousImplStatus) => {
401
+ callback(currentImplStatus, previousImplStatus);
402
+ }
403
+ );
404
+ }
405
+
406
+ /**
407
+ * @inheritdoc
408
+ */
409
+ async getSupportedExecutionMethods(): Promise<ExecutionMethodDetail[]> {
410
+ return getStellarSupportedExecutionMethods();
411
+ }
412
+
413
+ /**
414
+ * @inheritdoc
415
+ */
416
+ async validateExecutionConfig(config: ExecutionConfig): Promise<true | string> {
417
+ const walletStatus = this.getWalletConnectionStatus();
418
+ return validateStellarExecutionConfig(config, walletStatus);
419
+ }
420
+
421
+ /**
422
+ * @inheritdoc
423
+ */
424
+ getExplorerUrl(address: string): string | null {
425
+ return getStellarExplorerAddressUrl(address, this.networkConfig);
426
+ }
427
+
428
+ /**
429
+ * @inheritdoc
430
+ */
431
+ getExplorerTxUrl?(txHash: string): string | null {
432
+ if (getStellarExplorerTxUrl) {
433
+ return getStellarExplorerTxUrl(txHash, this.networkConfig);
434
+ }
435
+ return null;
436
+ }
437
+
438
+ /**
439
+ * @inheritdoc
440
+ */
441
+ async getCurrentBlock(): Promise<number> {
442
+ return getCurrentLedger(this.networkConfig);
443
+ }
444
+
445
+ /**
446
+ * @inheritdoc
447
+ */
448
+ isValidAddress(address: string, addressType?: string): boolean {
449
+ return isStellarValidAddress(address, addressType as StellarAddressType);
450
+ }
451
+
452
+ /**
453
+ * @inheritdoc
454
+ */
455
+ public async getAvailableUiKits(): Promise<AvailableUiKit[]> {
456
+ return [
457
+ {
458
+ id: 'custom',
459
+ name: 'Stellar Wallets Kit Custom',
460
+ configFields: [],
461
+ },
462
+ {
463
+ id: 'stellar-wallets-kit',
464
+ name: 'Stellar Wallets Kit',
465
+ configFields: [],
466
+ },
467
+ ];
468
+ }
469
+
470
+ /**
471
+ * @inheritdoc
472
+ */
473
+ public async configureUiKit(
474
+ programmaticOverrides: Partial<UiKitConfiguration> = {},
475
+ options?: {
476
+ loadUiKitNativeConfig?: NativeConfigLoader;
477
+ }
478
+ ): Promise<void> {
479
+ const currentAppServiceConfig = loadInitialConfigFromAppService();
480
+
481
+ // Delegate the entire configuration resolution to the service function
482
+ const finalFullConfig = await resolveFullUiKitConfiguration(
483
+ programmaticOverrides,
484
+ this.initialAppServiceKitName,
485
+ currentAppServiceConfig,
486
+ options
487
+ );
488
+
489
+ // Configure the Stellar UI kit manager
490
+ await stellarUiKitManager.configure(finalFullConfig);
491
+ logger.info(
492
+ 'StellarAdapter:configureUiKit',
493
+ 'StellarUiKitManager configuration requested with final config:',
494
+ finalFullConfig
495
+ );
496
+ }
497
+
498
+ /**
499
+ * @inheritdoc
500
+ */
501
+ public async getExportableWalletConfigFiles(
502
+ uiKitConfig?: UiKitConfiguration
503
+ ): Promise<Record<string, string>> {
504
+ if (uiKitConfig?.kitName === 'stellar-wallets-kit') {
505
+ return generateStellarWalletsKitExportables(uiKitConfig);
506
+ }
507
+ return {};
508
+ }
509
+
510
+ /**
511
+ * @inheritdoc
512
+ */
513
+ public getEcosystemWalletComponents(): EcosystemWalletComponents | undefined {
514
+ const currentManagerState = stellarUiKitManager.getState();
515
+
516
+ // Only attempt to resolve components if the manager has a configuration set
517
+ if (!currentManagerState.currentFullUiKitConfig) {
518
+ logger.debug(
519
+ 'StellarAdapter:getEcosystemWalletComponents',
520
+ 'No UI kit configuration available in manager yet. Returning undefined components.'
521
+ );
522
+ return undefined;
523
+ }
524
+
525
+ // Use the service to resolve components based on the current UI kit configuration
526
+ const components = getResolvedWalletComponents(currentManagerState.currentFullUiKitConfig);
527
+ return components;
528
+ }
529
+
530
+ /**
531
+ * @inheritdoc
532
+ */
533
+ public getEcosystemReactUiContextProvider():
534
+ | React.ComponentType<EcosystemReactUiProviderProps>
535
+ | undefined {
536
+ logger.info(
537
+ 'StellarAdapter:getEcosystemReactUiContextProvider',
538
+ 'Returning StellarWalletUiRoot.'
539
+ );
540
+ return StellarWalletUiRoot;
541
+ }
542
+
543
+ /**
544
+ * @inheritdoc
545
+ */
546
+ public getEcosystemReactHooks(): EcosystemSpecificReactHooks | undefined {
547
+ // Always provide hooks for Stellar adapter regardless of UI kit
548
+ return stellarFacadeHooks;
549
+ }
550
+
551
+ /**
552
+ * @inheritdoc
553
+ */
554
+ public async getRelayers(serviceUrl: string, accessToken: string): Promise<RelayerDetails[]> {
555
+ const relayerStrategy = new RelayerExecutionStrategy();
556
+ try {
557
+ return await relayerStrategy.getStellarRelayers(serviceUrl, accessToken, this.networkConfig);
558
+ } catch (error) {
559
+ logger.error('StellarAdapter', 'Failed to fetch Stellar relayers:', error);
560
+ return Promise.resolve([]);
561
+ }
562
+ }
563
+
564
+ /**
565
+ * @inheritdoc
566
+ */
567
+ public async getRelayer(
568
+ serviceUrl: string,
569
+ accessToken: string,
570
+ relayerId: string
571
+ ): Promise<RelayerDetailsRich> {
572
+ const relayerStrategy = new RelayerExecutionStrategy();
573
+ try {
574
+ return await relayerStrategy.getStellarRelayer(
575
+ serviceUrl,
576
+ accessToken,
577
+ relayerId,
578
+ this.networkConfig
579
+ );
580
+ } catch (error) {
581
+ logger.error('StellarAdapter', 'Failed to fetch Stellar relayer details:', error);
582
+ return Promise.resolve({} as RelayerDetailsRich);
583
+ }
584
+ }
585
+
586
+ /**
587
+ * @inheritdoc
588
+ */
589
+ public getRelayerOptionsComponent():
590
+ | React.ComponentType<{
591
+ options: Record<string, unknown>;
592
+ onChange: (options: Record<string, unknown>) => void;
593
+ }>
594
+ | undefined {
595
+ return StellarRelayerOptions;
596
+ }
597
+
598
+ /**
599
+ * @inheritdoc
600
+ */
601
+ public async validateRpcEndpoint(rpcConfig: UserRpcProviderConfig): Promise<boolean> {
602
+ // TODO: Implement Stellar-specific RPC validation when needed
603
+ return validateStellarRpcEndpoint(rpcConfig);
604
+ }
605
+
606
+ /**
607
+ * @inheritdoc
608
+ */
609
+ public async testRpcConnection(rpcConfig: UserRpcProviderConfig): Promise<{
610
+ success: boolean;
611
+ latency?: number;
612
+ error?: string;
613
+ }> {
614
+ // TODO: Implement Stellar-specific RPC validation when needed
615
+ return testStellarRpcConnection(rpcConfig);
616
+ }
617
+
618
+ /**
619
+ * @inheritdoc
620
+ */
621
+ public getUiLabels(): Record<string, string> | undefined {
622
+ return {
623
+ relayerConfigTitle: 'Transaction Configuration',
624
+ relayerConfigActiveDesc: 'Customize transaction parameters for submission',
625
+ relayerConfigInactiveDesc: 'Using recommended transaction configuration for reliability',
626
+ relayerConfigPresetTitle: 'Recommended Preset Active',
627
+ relayerConfigPresetDesc: 'Transactions will use recommended parameters for quick inclusion',
628
+ relayerConfigCustomizeBtn: 'Customize Settings',
629
+ detailsTitle: 'Relayer Details',
630
+ network: 'Network',
631
+ relayerId: 'Relayer ID',
632
+ active: 'Active',
633
+ paused: 'Paused',
634
+ systemDisabled: 'System Disabled',
635
+ balance: 'Balance',
636
+ // For Stellar, sequence number is conceptually similar; adapters supply the value
637
+ nonce: 'Sequence',
638
+ pending: 'Pending Transactions',
639
+ lastTransaction: 'Last Transaction',
640
+ };
641
+ }
642
+
643
+ /**
644
+ * @inheritdoc
645
+ */
646
+ public getAccessControlService(): AccessControlService {
647
+ return this.accessControlService;
648
+ }
649
+
650
+ /**
651
+ * @inheritdoc
652
+ */
653
+ public getTypeMappingInfo(): TypeMappingInfo {
654
+ return getStellarTypeMappingInfo();
655
+ }
656
+ }
657
+
658
+ // Also export as default to ensure compatibility with various import styles
659
+ export default StellarAdapter;
package/src/config.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Configuration for the Stellar adapter
3
+ *
4
+ * This file defines the dependencies required by the Stellar adapter
5
+ * when generating exported projects. It follows the AdapterConfig
6
+ * interface to provide a structured approach to dependency management.
7
+ */
8
+ import type { AdapterConfig } from '@openzeppelin/ui-types';
9
+
10
+ export const stellarAdapterConfig: AdapterConfig = {
11
+ /**
12
+ * Dependencies required by the Stellar adapter
13
+ * These will be included in exported projects that use this adapter
14
+ */
15
+ dependencies: {
16
+ // Runtime dependencies
17
+ runtime: {
18
+ // Core Stellar libraries
19
+ '@stellar/stellar-sdk': '^14.1.1',
20
+
21
+ // SAC (Stellar Asset Contract) support - dynamically loaded from CDN
22
+ // These are needed for XDR encoding when working with SAC contracts
23
+ '@stellar/stellar-xdr-json': '^23.0.0',
24
+ 'lossless-json': '^4.0.2',
25
+
26
+ // Wallet connection and integration
27
+ '@creit.tech/stellar-wallets-kit': '^1.9.5',
28
+
29
+ // OpenZeppelin Relayer integration for gasless transactions
30
+ '@openzeppelin/relayer-sdk': '1.9.0',
31
+
32
+ // React integration for wallet components
33
+ react: '^19.0.0',
34
+ 'react-dom': '^19.0.0',
35
+ },
36
+
37
+ // Development dependencies
38
+ dev: {
39
+ '@types/react': '^19.0.0',
40
+ '@types/react-dom': '^19.0.0',
41
+ },
42
+ },
43
+ };