@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
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Address Validation Module for Access Control
3
+ *
4
+ * Centralizes address validation for access control operations.
5
+ * Uses Stellar-specific validation from the validation module and
6
+ * shared normalization utilities from @openzeppelin/ui-utils.
7
+ */
8
+
9
+ import { ConfigurationInvalid } from '@openzeppelin/ui-types';
10
+ import { normalizeAddress } from '@openzeppelin/ui-utils';
11
+
12
+ import { isValidAccountAddress, isValidContractAddress } from '../validation/address';
13
+
14
+ /**
15
+ * Validates a Stellar contract address
16
+ *
17
+ * @param address The contract address to validate
18
+ * @param paramName Optional parameter name for error messages (defaults to 'contractAddress')
19
+ * @throws ConfigurationInvalid if the address is invalid
20
+ */
21
+ export function validateContractAddress(address: string, paramName = 'contractAddress'): void {
22
+ if (!address || typeof address !== 'string' || address.trim() === '') {
23
+ throw new ConfigurationInvalid(
24
+ `${paramName} is required and must be a non-empty string`,
25
+ address,
26
+ paramName
27
+ );
28
+ }
29
+
30
+ if (!isValidContractAddress(address)) {
31
+ throw new ConfigurationInvalid(
32
+ `Invalid Stellar contract address: ${address}. Contract addresses must start with 'C' and be valid StrKey format.`,
33
+ address,
34
+ paramName
35
+ );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Validates a Stellar account address (for role grants, ownership transfers, etc.)
41
+ *
42
+ * @param address The account address to validate
43
+ * @param paramName Optional parameter name for error messages (defaults to 'account')
44
+ * @throws ConfigurationInvalid if the address is invalid
45
+ */
46
+ export function validateAccountAddress(address: string, paramName = 'account'): void {
47
+ if (!address || typeof address !== 'string' || address.trim() === '') {
48
+ throw new ConfigurationInvalid(
49
+ `${paramName} is required and must be a non-empty string`,
50
+ address,
51
+ paramName
52
+ );
53
+ }
54
+
55
+ if (!isValidAccountAddress(address)) {
56
+ throw new ConfigurationInvalid(
57
+ `Invalid Stellar account address: ${address}. Account addresses must start with 'G' and be valid Ed25519 public keys.`,
58
+ address,
59
+ paramName
60
+ );
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Validates a Stellar address that can be either an account or contract address
66
+ * (e.g., for ownership transfers where the new owner can be either type)
67
+ *
68
+ * @param address The address to validate (account or contract)
69
+ * @param paramName Optional parameter name for error messages (defaults to 'address')
70
+ * @throws ConfigurationInvalid if the address is invalid
71
+ */
72
+ export function validateAddress(address: string, paramName = 'address'): void {
73
+ if (!address || typeof address !== 'string' || address.trim() === '') {
74
+ throw new ConfigurationInvalid(
75
+ `${paramName} is required and must be a non-empty string`,
76
+ address,
77
+ paramName
78
+ );
79
+ }
80
+
81
+ // Check if it's a valid account address OR contract address
82
+ if (!isValidAccountAddress(address) && !isValidContractAddress(address)) {
83
+ throw new ConfigurationInvalid(
84
+ `Invalid Stellar address: ${address}. Address must be a valid account address (starts with 'G') or contract address (starts with 'C').`,
85
+ address,
86
+ paramName
87
+ );
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Validates both contract and account addresses for operations
93
+ *
94
+ * @param contractAddress The contract address
95
+ * @param accountAddress The account address
96
+ * @throws ConfigurationInvalid if either address is invalid
97
+ */
98
+ export function validateAddresses(contractAddress: string, accountAddress: string): void {
99
+ validateContractAddress(contractAddress);
100
+ validateAccountAddress(accountAddress);
101
+ }
102
+
103
+ /**
104
+ * Normalizes a Stellar address using shared utils
105
+ * This is useful for case-insensitive and whitespace-insensitive comparison
106
+ *
107
+ * @param address The address to normalize
108
+ * @returns The normalized address
109
+ */
110
+ export function normalizeStellarAddress(address: string): string {
111
+ return normalizeAddress(address);
112
+ }
113
+
114
+ /**
115
+ * Maximum length for a Soroban Symbol (role identifier)
116
+ * Soroban symbols are limited to 32 characters
117
+ */
118
+ const MAX_ROLE_ID_LENGTH = 32;
119
+
120
+ /**
121
+ * Valid pattern for Soroban Symbol characters
122
+ * Symbols can contain alphanumeric characters and underscores
123
+ */
124
+ const VALID_ROLE_ID_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
125
+
126
+ /**
127
+ * Validates a role identifier (Soroban Symbol)
128
+ *
129
+ * Role IDs must be:
130
+ * - Non-empty strings
131
+ * - Max 32 characters (Soroban Symbol limit)
132
+ * - Start with a letter or underscore
133
+ * - Contain only alphanumeric characters and underscores
134
+ *
135
+ * @param roleId The role identifier to validate
136
+ * @param paramName Optional parameter name for error messages
137
+ * @throws ConfigurationInvalid if the role ID is invalid
138
+ */
139
+ export function validateRoleId(roleId: string, paramName = 'roleId'): void {
140
+ if (!roleId || typeof roleId !== 'string') {
141
+ throw new ConfigurationInvalid(
142
+ `${paramName} is required and must be a non-empty string`,
143
+ roleId,
144
+ paramName
145
+ );
146
+ }
147
+
148
+ const trimmed = roleId.trim();
149
+ if (trimmed === '') {
150
+ throw new ConfigurationInvalid(
151
+ `${paramName} cannot be empty or whitespace-only`,
152
+ roleId,
153
+ paramName
154
+ );
155
+ }
156
+
157
+ if (trimmed.length > MAX_ROLE_ID_LENGTH) {
158
+ throw new ConfigurationInvalid(
159
+ `${paramName} exceeds maximum length of ${MAX_ROLE_ID_LENGTH} characters: "${trimmed}" (${trimmed.length} chars)`,
160
+ roleId,
161
+ paramName
162
+ );
163
+ }
164
+
165
+ if (!VALID_ROLE_ID_PATTERN.test(trimmed)) {
166
+ throw new ConfigurationInvalid(
167
+ `${paramName} contains invalid characters: "${trimmed}". Role IDs must start with a letter or underscore and contain only alphanumeric characters and underscores.`,
168
+ roleId,
169
+ paramName
170
+ );
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Validates an array of role identifiers
176
+ *
177
+ * @param roleIds The array of role identifiers to validate
178
+ * @param paramName Optional parameter name for error messages
179
+ * @throws ConfigurationInvalid if any role ID is invalid or if the array is invalid
180
+ * @returns The validated and deduplicated array of role IDs
181
+ */
182
+ export function validateRoleIds(roleIds: string[], paramName = 'roleIds'): string[] {
183
+ if (!Array.isArray(roleIds)) {
184
+ throw new ConfigurationInvalid(`${paramName} must be an array`, String(roleIds), paramName);
185
+ }
186
+
187
+ // Validate each role ID
188
+ for (let i = 0; i < roleIds.length; i++) {
189
+ validateRoleId(roleIds[i], `${paramName}[${i}]`);
190
+ }
191
+
192
+ // Deduplicate and return
193
+ return [...new Set(roleIds.map((r) => r.trim()))];
194
+ }
195
+
196
+ /**
197
+ * Result of expiration ledger validation
198
+ *
199
+ * Returned by {@link validateExpirationLedger} to indicate whether
200
+ * a proposed expiration ledger is valid for a two-step ownership transfer.
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const currentLedger = await getCurrentLedger(networkConfig);
205
+ * const result = validateExpirationLedger(expirationLedger, currentLedger);
206
+ * if (!result.valid) {
207
+ * throw new ConfigurationInvalid(result.error!, String(expirationLedger), 'expirationLedger');
208
+ * }
209
+ * ```
210
+ */
211
+ export interface ExpirationValidationResult {
212
+ /** Whether the expiration ledger is valid (must be strictly greater than current ledger) */
213
+ valid: boolean;
214
+ /** The current ledger sequence used for comparison */
215
+ currentLedger: number;
216
+ /** Human-readable error message if validation failed */
217
+ error?: string;
218
+ }
219
+
220
+ /**
221
+ * Validates an expiration ledger against the current ledger sequence
222
+ *
223
+ * For two-step Ownable contracts, the expiration ledger must be strictly greater
224
+ * than the current ledger (per FR-020: expirationLedger == currentLedger is invalid).
225
+ *
226
+ * @param expirationLedger The proposed expiration ledger sequence
227
+ * @param currentLedger The current ledger sequence number
228
+ * @returns Validation result with valid flag, currentLedger, and optional error message
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * const currentLedger = await getCurrentLedger(networkConfig);
233
+ * const result = validateExpirationLedger(expirationLedger, currentLedger);
234
+ * if (!result.valid) {
235
+ * throw new ConfigurationInvalid(result.error, 'expirationLedger');
236
+ * }
237
+ * ```
238
+ */
239
+ export function validateExpirationLedger(
240
+ expirationLedger: number,
241
+ currentLedger: number
242
+ ): ExpirationValidationResult {
243
+ // Per FR-020: expirationLedger must be strictly greater than currentLedger
244
+ if (expirationLedger <= currentLedger) {
245
+ return {
246
+ valid: false,
247
+ currentLedger,
248
+ error: `Expiration ledger ${expirationLedger} has already passed or equals current ledger. Current ledger is ${currentLedger}. Expiration must be strictly greater than current ledger.`,
249
+ };
250
+ }
251
+
252
+ return {
253
+ valid: true,
254
+ currentLedger,
255
+ };
256
+ }