@mantle-rwa/react 0.1.1 → 0.1.3

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 (73) hide show
  1. package/dist/cjs/components/ConnectWalletPrompt.js +13 -0
  2. package/dist/cjs/components/ConnectWalletPrompt.js.map +1 -0
  3. package/dist/cjs/components/ErrorDisplay.js +42 -0
  4. package/dist/cjs/components/ErrorDisplay.js.map +1 -0
  5. package/dist/cjs/components/InvestorDashboard.js +156 -0
  6. package/dist/cjs/components/InvestorDashboard.js.map +1 -0
  7. package/dist/cjs/components/KYCFlow.js +146 -0
  8. package/dist/cjs/components/KYCFlow.js.map +1 -0
  9. package/dist/cjs/components/LoadingSpinner.js +18 -0
  10. package/dist/cjs/components/LoadingSpinner.js.map +1 -0
  11. package/dist/cjs/components/TokenMintForm.js +163 -0
  12. package/dist/cjs/components/TokenMintForm.js.map +1 -0
  13. package/dist/cjs/components/YieldCalculator.js +97 -0
  14. package/dist/cjs/components/YieldCalculator.js.map +1 -0
  15. package/dist/cjs/hooks/useRWA.js +87 -40
  16. package/dist/cjs/hooks/useRWA.js.map +1 -1
  17. package/dist/cjs/index.js +11 -1
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/types/index.js +2 -2
  20. package/dist/cjs/types/index.js.map +1 -1
  21. package/dist/esm/components/ConnectWalletPrompt.js +10 -0
  22. package/dist/esm/components/ConnectWalletPrompt.js.map +1 -0
  23. package/dist/esm/components/ErrorDisplay.js +38 -0
  24. package/dist/esm/components/ErrorDisplay.js.map +1 -0
  25. package/dist/esm/components/InvestorDashboard.js +153 -0
  26. package/dist/esm/components/InvestorDashboard.js.map +1 -0
  27. package/dist/esm/components/KYCFlow.js +143 -0
  28. package/dist/esm/components/KYCFlow.js.map +1 -0
  29. package/dist/esm/components/LoadingSpinner.js +15 -0
  30. package/dist/esm/components/LoadingSpinner.js.map +1 -0
  31. package/dist/esm/components/TokenMintForm.js +158 -0
  32. package/dist/esm/components/TokenMintForm.js.map +1 -0
  33. package/dist/esm/components/YieldCalculator.js +94 -0
  34. package/dist/esm/components/YieldCalculator.js.map +1 -0
  35. package/dist/esm/hooks/useRWA.js +86 -39
  36. package/dist/esm/hooks/useRWA.js.map +1 -1
  37. package/dist/esm/index.js +4 -0
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/types/index.js +3 -3
  40. package/dist/esm/types/index.js.map +1 -1
  41. package/dist/styles.css +3 -1
  42. package/dist/types/components/ConnectWalletPrompt.d.ts +15 -0
  43. package/dist/types/components/ConnectWalletPrompt.d.ts.map +1 -0
  44. package/dist/types/components/ErrorDisplay.d.ts +16 -0
  45. package/dist/types/components/ErrorDisplay.d.ts.map +1 -0
  46. package/dist/types/components/InvestorDashboard.d.ts +7 -0
  47. package/dist/types/components/InvestorDashboard.d.ts.map +1 -0
  48. package/dist/types/components/KYCFlow.d.ts +7 -0
  49. package/dist/types/components/KYCFlow.d.ts.map +1 -0
  50. package/dist/types/components/LoadingSpinner.d.ts +10 -0
  51. package/dist/types/components/LoadingSpinner.d.ts.map +1 -0
  52. package/dist/types/components/TokenMintForm.d.ts +15 -0
  53. package/dist/types/components/TokenMintForm.d.ts.map +1 -0
  54. package/dist/types/components/YieldCalculator.d.ts +7 -0
  55. package/dist/types/components/YieldCalculator.d.ts.map +1 -0
  56. package/dist/types/hooks/useRWA.d.ts +7 -19
  57. package/dist/types/hooks/useRWA.d.ts.map +1 -1
  58. package/dist/types/index.d.ts +5 -1
  59. package/dist/types/index.d.ts.map +1 -1
  60. package/dist/types/types/index.d.ts +113 -131
  61. package/dist/types/types/index.d.ts.map +1 -1
  62. package/package.json +5 -3
  63. package/src/components/ConnectWalletPrompt.tsx +47 -0
  64. package/src/components/ErrorDisplay.tsx +90 -0
  65. package/src/components/InvestorDashboard.tsx +315 -0
  66. package/src/components/KYCFlow.tsx +267 -0
  67. package/src/components/LoadingSpinner.tsx +33 -0
  68. package/src/components/TokenMintForm.tsx +291 -0
  69. package/src/components/YieldCalculator.tsx +250 -0
  70. package/src/hooks/useRWA.ts +110 -0
  71. package/src/index.ts +4 -0
  72. package/src/styles/index.css +68 -14
  73. package/src/types/index.ts +200 -0
@@ -0,0 +1,250 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * YieldCalculator - Calculator for previewing yield distributions
5
+ *
6
+ * Shows how yields will be allocated to token holders before creating a distribution.
7
+ */
8
+
9
+ import { useState, useCallback, useEffect, useRef } from 'react';
10
+ import { formatUnits } from 'viem';
11
+ import { useRWA } from '../hooks/useRWA';
12
+ import type { YieldCalculatorProps } from '../types';
13
+ import type { DistributionPreview, HolderDistribution } from '@mantle-rwa/sdk';
14
+
15
+ /**
16
+ * Format address for display
17
+ */
18
+ function formatAddress(address: string): string {
19
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
20
+ }
21
+
22
+ /**
23
+ * Format token amount for display
24
+ */
25
+ function formatAmount(amount: bigint, decimals: number = 18): string {
26
+ const formatted = formatUnits(amount, decimals);
27
+ const num = parseFloat(formatted);
28
+ return num.toLocaleString(undefined, { maximumFractionDigits: 4 });
29
+ }
30
+
31
+ /**
32
+ * YieldCalculator component
33
+ */
34
+ export function YieldCalculator({
35
+ tokenAddress,
36
+ yieldDistributorAddress: _yieldDistributorAddress,
37
+ holderAddresses,
38
+ onCalculate,
39
+ onError,
40
+ className = '',
41
+ }: YieldCalculatorProps): JSX.Element {
42
+ const { client, isInitialized } = useRWA();
43
+
44
+ const [amount, setAmount] = useState<string>('');
45
+ const [preview, setPreview] = useState<DistributionPreview | null>(null);
46
+ const [isLoading, setIsLoading] = useState(false);
47
+ const [error, setError] = useState<Error | null>(null);
48
+
49
+ // Debounce timer ref
50
+ const debounceRef = useRef<NodeJS.Timeout | null>(null);
51
+
52
+ // Calculate preview
53
+ const calculatePreview = useCallback(async (distributionAmount: string) => {
54
+ if (!client || !isInitialized || !distributionAmount || parseFloat(distributionAmount) <= 0) {
55
+ setPreview(null);
56
+ return;
57
+ }
58
+
59
+ setIsLoading(true);
60
+ setError(null);
61
+
62
+ try {
63
+ const result = await client.yield.previewDistribution(
64
+ tokenAddress,
65
+ distributionAmount,
66
+ undefined, // snapshotId
67
+ holderAddresses
68
+ );
69
+ setPreview(result);
70
+ onCalculate?.(result);
71
+ } catch (err) {
72
+ const errorObj = err instanceof Error ? err : new Error('Failed to calculate preview');
73
+ setError(errorObj);
74
+ onError?.(errorObj);
75
+ setPreview(null);
76
+ } finally {
77
+ setIsLoading(false);
78
+ }
79
+ }, [client, isInitialized, tokenAddress, holderAddresses, onCalculate, onError]);
80
+
81
+ // Handle amount change with debounce
82
+ const handleAmountChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
83
+ const value = e.target.value;
84
+ setAmount(value);
85
+
86
+ // Clear previous debounce
87
+ if (debounceRef.current) {
88
+ clearTimeout(debounceRef.current);
89
+ }
90
+
91
+ // Debounce the calculation
92
+ debounceRef.current = setTimeout(() => {
93
+ calculatePreview(value);
94
+ }, 500);
95
+ }, [calculatePreview]);
96
+
97
+ // Cleanup debounce on unmount
98
+ useEffect(() => {
99
+ return () => {
100
+ if (debounceRef.current) {
101
+ clearTimeout(debounceRef.current);
102
+ }
103
+ };
104
+ }, []);
105
+
106
+ // Recalculate when holder addresses change
107
+ useEffect(() => {
108
+ if (amount && parseFloat(amount) > 0) {
109
+ calculatePreview(amount);
110
+ }
111
+ }, [holderAddresses]); // eslint-disable-line react-hooks/exhaustive-deps
112
+
113
+ // Handle manual calculate button
114
+ const handleCalculate = useCallback(() => {
115
+ calculatePreview(amount);
116
+ }, [amount, calculatePreview]);
117
+
118
+ return (
119
+ <div className={`rwa-yield-calculator ${className}`}>
120
+ <div className="space-y-6">
121
+ {/* Amount Input */}
122
+ <div>
123
+ <label htmlFor="distribution-amount" className="block text-sm font-medium text-gray-700 dark:text-gray-300">
124
+ Total Distribution Amount
125
+ </label>
126
+ <div className="mt-1 flex rounded-md shadow-sm">
127
+ <input
128
+ type="text"
129
+ id="distribution-amount"
130
+ value={amount}
131
+ onChange={handleAmountChange}
132
+ placeholder="Enter amount to distribute"
133
+ className="flex-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white"
134
+ />
135
+ <button
136
+ type="button"
137
+ onClick={handleCalculate}
138
+ disabled={isLoading || !amount}
139
+ className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white rounded-r-md transition-colors"
140
+ >
141
+ {isLoading ? 'Calculating...' : 'Calculate'}
142
+ </button>
143
+ </div>
144
+ </div>
145
+
146
+ {/* Loading State */}
147
+ {isLoading && (
148
+ <div className="flex items-center justify-center p-4">
149
+ <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600" />
150
+ <span className="ml-2 text-gray-600 dark:text-gray-300">Calculating distribution...</span>
151
+ </div>
152
+ )}
153
+
154
+ {/* Error State */}
155
+ {error && (
156
+ <div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
157
+ <p className="text-red-700 dark:text-red-300">{error.message}</p>
158
+ <button
159
+ onClick={handleCalculate}
160
+ className="mt-2 text-sm text-red-600 dark:text-red-400 underline hover:no-underline"
161
+ >
162
+ Retry
163
+ </button>
164
+ </div>
165
+ )}
166
+
167
+ {/* Preview Results */}
168
+ {preview && !isLoading && (
169
+ <div className="space-y-4">
170
+ {/* Summary */}
171
+ <div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
172
+ <h4 className="text-sm font-medium text-gray-700 dark:text-gray-300">Distribution Summary</h4>
173
+ <div className="mt-2 grid grid-cols-2 gap-4">
174
+ <div>
175
+ <p className="text-xs text-gray-500 dark:text-gray-400">Total Holders</p>
176
+ <p className="text-lg font-semibold text-gray-900 dark:text-white">{preview.totalHolders}</p>
177
+ </div>
178
+ <div>
179
+ <p className="text-xs text-gray-500 dark:text-gray-400">Total Supply</p>
180
+ <p className="text-lg font-semibold text-gray-900 dark:text-white">
181
+ {formatAmount(preview.totalSupplyAtSnapshot)}
182
+ </p>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
187
+ {/* Holder Distributions Table */}
188
+ {preview.distributions.length > 0 && (
189
+ <div className="overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
190
+ <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
191
+ <thead className="bg-gray-50 dark:bg-gray-800">
192
+ <tr>
193
+ <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
194
+ Address
195
+ </th>
196
+ <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
197
+ Balance
198
+ </th>
199
+ <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
200
+ Yield Amount
201
+ </th>
202
+ <th className="px-4 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
203
+ Share
204
+ </th>
205
+ </tr>
206
+ </thead>
207
+ <tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
208
+ {preview.distributions.map((dist: HolderDistribution) => (
209
+ <tr key={dist.address}>
210
+ <td className="px-4 py-3 whitespace-nowrap text-sm font-mono text-gray-900 dark:text-white">
211
+ {formatAddress(dist.address)}
212
+ </td>
213
+ <td className="px-4 py-3 whitespace-nowrap text-sm text-right text-gray-600 dark:text-gray-300">
214
+ {formatAmount(dist.balance)}
215
+ </td>
216
+ <td className="px-4 py-3 whitespace-nowrap text-sm text-right font-medium text-green-600 dark:text-green-400">
217
+ {formatAmount(dist.yieldAmount)}
218
+ </td>
219
+ <td className="px-4 py-3 whitespace-nowrap text-sm text-right text-gray-600 dark:text-gray-300">
220
+ {dist.percentage.toFixed(2)}%
221
+ </td>
222
+ </tr>
223
+ ))}
224
+ </tbody>
225
+ </table>
226
+ </div>
227
+ )}
228
+
229
+ {preview.distributions.length === 0 && (
230
+ <div className="p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg border border-yellow-200 dark:border-yellow-800">
231
+ <p className="text-yellow-700 dark:text-yellow-300">
232
+ No holder addresses provided or no holders have balances.
233
+ </p>
234
+ </div>
235
+ )}
236
+ </div>
237
+ )}
238
+
239
+ {/* Empty State */}
240
+ {!preview && !isLoading && !error && (
241
+ <div className="p-6 text-center text-gray-500 dark:text-gray-400">
242
+ <p>Enter a distribution amount to preview how yields will be allocated.</p>
243
+ </div>
244
+ )}
245
+ </div>
246
+ </div>
247
+ );
248
+ }
249
+
250
+ export default YieldCalculator;
@@ -0,0 +1,110 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * useRWA - Core hook for accessing the RWA SDK client
5
+ *
6
+ * Provides access to the @mantle-rwa/sdk RWAClient instance with
7
+ * automatic wagmi wallet integration.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { useRWA } from '@mantle-rwa/react';
12
+ *
13
+ * function MyComponent() {
14
+ * const { client, isInitialized, hasSigner } = useRWA();
15
+ *
16
+ * if (!isInitialized) return <div>Loading...</div>;
17
+ *
18
+ * // Use client.token, client.kyc, client.yield, client.compliance
19
+ * }
20
+ * ```
21
+ */
22
+
23
+ import { useState, useEffect, useCallback, useMemo } from 'react';
24
+ import { useAccount, useWalletClient } from 'wagmi';
25
+ import { BrowserProvider } from 'ethers';
26
+ import { RWAClient } from '@mantle-rwa/sdk';
27
+ import type { UseRWAConfig, UseRWAReturn, ContractAddresses } from '../types';
28
+
29
+ // Default contract addresses (can be overridden via config)
30
+ const DEFAULT_CONTRACTS: ContractAddresses = {
31
+ token: undefined,
32
+ kycRegistry: undefined,
33
+ yieldDistributor: undefined,
34
+ assetVault: undefined,
35
+ factory: undefined,
36
+ };
37
+
38
+ /**
39
+ * Hook for initializing and managing the RWA SDK client
40
+ *
41
+ * @param config - Optional configuration for network and contract addresses
42
+ * @returns UseRWAReturn object with client, state, and utilities
43
+ */
44
+ export function useRWA(config?: UseRWAConfig): UseRWAReturn {
45
+ const { isConnected } = useAccount();
46
+ const { data: walletClient } = useWalletClient();
47
+
48
+ const [client, setClient] = useState<RWAClient | null>(null);
49
+ const [isLoading, setIsLoading] = useState(true);
50
+ const [error, setError] = useState<Error | null>(null);
51
+
52
+ const network = config?.network ?? 'mantle-sepolia';
53
+
54
+ // Initialize or reinitialize the client
55
+ const initializeClient = useCallback(async () => {
56
+ setIsLoading(true);
57
+ setError(null);
58
+
59
+ try {
60
+ let rwaClient: RWAClient;
61
+
62
+ if (walletClient && isConnected) {
63
+ // Create client with wallet signer for write operations
64
+ const provider = new BrowserProvider(walletClient.transport);
65
+ const signer = await provider.getSigner();
66
+
67
+ rwaClient = new RWAClient({
68
+ network,
69
+ signer,
70
+ });
71
+ } else {
72
+ // Create read-only client (no signer)
73
+ rwaClient = new RWAClient({
74
+ network,
75
+ });
76
+ }
77
+
78
+ setClient(rwaClient);
79
+ } catch (err) {
80
+ const errorMessage = err instanceof Error ? err.message : 'Failed to initialize RWA client';
81
+ setError(new Error(errorMessage));
82
+ setClient(null);
83
+ } finally {
84
+ setIsLoading(false);
85
+ }
86
+ }, [walletClient, isConnected, network]);
87
+
88
+ // Initialize client on mount and when wallet changes
89
+ useEffect(() => {
90
+ initializeClient();
91
+ }, [initializeClient]);
92
+
93
+ // Memoized contract addresses
94
+ const contracts = useMemo<ContractAddresses>(() => ({
95
+ ...DEFAULT_CONTRACTS,
96
+ ...config?.contracts,
97
+ }), [config?.contracts]);
98
+
99
+ return {
100
+ client,
101
+ isInitialized: client !== null && !isLoading,
102
+ isLoading,
103
+ error,
104
+ hasSigner: client?.hasSigner ?? false,
105
+ contracts,
106
+ reinitialize: initializeClient,
107
+ };
108
+ }
109
+
110
+ export default useRWA;
package/src/index.ts CHANGED
@@ -7,7 +7,11 @@
7
7
  export { KYCFlow } from './components/KYCFlow';
8
8
  export { InvestorDashboard } from './components/InvestorDashboard';
9
9
  export { TokenMintForm } from './components/TokenMintForm';
10
+ export { isValidAddress, isValidAmount } from './components/TokenMintForm';
10
11
  export { YieldCalculator } from './components/YieldCalculator';
12
+ export { ErrorDisplay, formatErrorMessage } from './components/ErrorDisplay';
13
+ export { LoadingSpinner } from './components/LoadingSpinner';
14
+ export { ConnectWalletPrompt } from './components/ConnectWalletPrompt';
11
15
 
12
16
  // Hooks
13
17
  export { useRWA } from './hooks/useRWA';
@@ -1,28 +1,82 @@
1
+ /**
2
+ * @mantle-rwa/react - Default Styles
3
+ *
4
+ * Tailwind CSS styles for RWA React components.
5
+ * Import this file in your application to use default styling.
6
+ */
7
+
1
8
  @tailwind base;
2
9
  @tailwind components;
3
10
  @tailwind utilities;
4
11
 
5
- /* Custom component styles */
6
- .rwa-card {
7
- @apply rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800;
8
- }
12
+ /* Base component styles */
13
+ @layer components {
14
+
15
+ /* KYC Flow */
16
+ .rwa-kyc-flow {
17
+ @apply w-full;
18
+ }
19
+
20
+ /* Investor Dashboard */
21
+ .rwa-investor-dashboard {
22
+ @apply w-full;
23
+ }
24
+
25
+ /* Token Mint Form */
26
+ .rwa-token-mint-form {
27
+ @apply w-full max-w-md;
28
+ }
9
29
 
10
- .rwa-button {
11
- @apply inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2;
30
+ /* Yield Calculator */
31
+ .rwa-yield-calculator {
32
+ @apply w-full;
33
+ }
34
+
35
+ /* Error Display */
36
+ .rwa-error-display {
37
+ @apply w-full;
38
+ }
39
+
40
+ /* Loading Spinner */
41
+ .rwa-loading-spinner {
42
+ @apply inline-flex items-center justify-center;
43
+ }
44
+
45
+ /* Connect Wallet Prompt */
46
+ .rwa-connect-wallet-prompt {
47
+ @apply w-full;
48
+ }
12
49
  }
13
50
 
14
- .rwa-button-primary {
15
- @apply rwa-button bg-mantle-600 text-white hover:bg-mantle-700 focus:ring-mantle-500;
51
+ /* Dark mode support */
52
+ @layer utilities {
53
+
54
+ .dark .rwa-kyc-flow,
55
+ .dark .rwa-investor-dashboard,
56
+ .dark .rwa-token-mint-form,
57
+ .dark .rwa-yield-calculator {
58
+ @apply text-gray-100;
59
+ }
16
60
  }
17
61
 
18
- .rwa-button-secondary {
19
- @apply rwa-button border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 focus:ring-mantle-500 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700;
62
+ /* Custom animations */
63
+ @keyframes rwa-spin {
64
+ to {
65
+ transform: rotate(360deg);
66
+ }
20
67
  }
21
68
 
22
- .rwa-input {
23
- @apply block w-full rounded-md border border-gray-300 px-3 py-2 text-sm placeholder-gray-400 focus:border-mantle-500 focus:outline-none focus:ring-1 focus:ring-mantle-500 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500;
69
+ .rwa-animate-spin {
70
+ animation: rwa-spin 1s linear infinite;
24
71
  }
25
72
 
26
- .rwa-label {
27
- @apply block text-sm font-medium text-gray-700 dark:text-gray-200;
73
+ /* Focus styles for accessibility */
74
+ @layer utilities {
75
+ .rwa-focus-ring {
76
+ @apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2;
77
+ }
78
+
79
+ .dark .rwa-focus-ring {
80
+ @apply focus:ring-offset-gray-900;
81
+ }
28
82
  }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Type definitions for @mantle-rwa/react
3
+ */
4
+
5
+ // Re-export relevant types from SDK
6
+ export {
7
+ AccreditationTier,
8
+ type TokenInfo,
9
+ type InvestorData,
10
+ type TransactionResult,
11
+ type Distribution,
12
+ type DistributionPreview,
13
+ type HolderDistribution,
14
+ type PendingClaim,
15
+ type VerificationSession,
16
+ type NetworkConfig,
17
+ } from '@mantle-rwa/sdk';
18
+
19
+ import type { RWAClient, TransactionResult, AccreditationTier, DistributionPreview } from '@mantle-rwa/sdk';
20
+
21
+ /*//////////////////////////////////////////////////////////////
22
+ CONTRACT ADDRESSES
23
+ //////////////////////////////////////////////////////////////*/
24
+
25
+ /**
26
+ * Contract addresses configuration
27
+ */
28
+ export interface ContractAddresses {
29
+ /** RWA token contract address */
30
+ token?: string;
31
+ /** KYC registry contract address */
32
+ kycRegistry?: string;
33
+ /** Yield distributor contract address */
34
+ yieldDistributor?: string;
35
+ /** Asset vault contract address */
36
+ assetVault?: string;
37
+ /** RWA factory contract address */
38
+ factory?: string;
39
+ }
40
+
41
+ /*//////////////////////////////////////////////////////////////
42
+ HOOK TYPES
43
+ //////////////////////////////////////////////////////////////*/
44
+
45
+ /**
46
+ * Configuration for useRWA hook
47
+ */
48
+ export interface UseRWAConfig {
49
+ /** Network to connect to (default: 'mantle-sepolia') */
50
+ network?: 'mantle' | 'mantle-sepolia';
51
+ /** Contract addresses configuration */
52
+ contracts?: ContractAddresses;
53
+ }
54
+
55
+ /**
56
+ * Return type for useRWA hook
57
+ */
58
+ export interface UseRWAReturn {
59
+ /** The RWAClient instance (null if not initialized) */
60
+ client: RWAClient | null;
61
+ /** Whether the client is initialized and ready */
62
+ isInitialized: boolean;
63
+ /** Whether the client is currently initializing */
64
+ isLoading: boolean;
65
+ /** Error that occurred during initialization */
66
+ error: Error | null;
67
+ /** Whether a signer is available (wallet connected) */
68
+ hasSigner: boolean;
69
+ /** Contract addresses */
70
+ contracts: ContractAddresses;
71
+ /** Reinitialize the client */
72
+ reinitialize: () => Promise<void>;
73
+ }
74
+
75
+ /*//////////////////////////////////////////////////////////////
76
+ COMPONENT PROPS
77
+ //////////////////////////////////////////////////////////////*/
78
+
79
+ /**
80
+ * Verification status for KYC flow
81
+ */
82
+ export type VerificationStatus = 'idle' | 'pending' | 'in_progress' | 'completed' | 'failed';
83
+
84
+ /**
85
+ * Props for KYCFlow component
86
+ */
87
+ export interface KYCFlowProps {
88
+ /** KYC registry contract address */
89
+ registryAddress: string;
90
+ /** Investor address to verify (defaults to connected wallet) */
91
+ investorAddress?: string;
92
+ /** Callback when verification status changes */
93
+ onStatusChange?: (status: VerificationStatus) => void;
94
+ /** Callback when verification completes successfully */
95
+ onComplete?: (tier: AccreditationTier) => void;
96
+ /** Callback when an error occurs */
97
+ onError?: (error: Error) => void;
98
+ /** Custom CSS class */
99
+ className?: string;
100
+ }
101
+
102
+ /**
103
+ * Props for InvestorDashboard component
104
+ */
105
+ export interface InvestorDashboardProps {
106
+ /** RWA token contract address */
107
+ tokenAddress: string;
108
+ /** KYC registry contract address */
109
+ kycRegistryAddress: string;
110
+ /** Yield distributor contract address */
111
+ yieldDistributorAddress: string;
112
+ /** Investor address (defaults to connected wallet) */
113
+ investorAddress?: string;
114
+ /** Callback when yield claim succeeds */
115
+ onClaimSuccess?: (result: TransactionResult) => void;
116
+ /** Callback when an error occurs */
117
+ onError?: (error: Error) => void;
118
+ /** Custom CSS class */
119
+ className?: string;
120
+ }
121
+
122
+ /**
123
+ * Props for TokenMintForm component
124
+ */
125
+ export interface TokenMintFormProps {
126
+ /** RWA token contract address */
127
+ tokenAddress: string;
128
+ /** KYC registry contract address */
129
+ kycRegistryAddress: string;
130
+ /** Callback when mint succeeds */
131
+ onSuccess?: (result: TransactionResult) => void;
132
+ /** Callback when an error occurs */
133
+ onError?: (error: Error) => void;
134
+ /** Custom CSS class */
135
+ className?: string;
136
+ }
137
+
138
+ /**
139
+ * Props for YieldCalculator component
140
+ */
141
+ export interface YieldCalculatorProps {
142
+ /** RWA token contract address */
143
+ tokenAddress: string;
144
+ /** Yield distributor contract address */
145
+ yieldDistributorAddress: string;
146
+ /** Optional list of holder addresses to include in preview */
147
+ holderAddresses?: string[];
148
+ /** Callback when calculation completes */
149
+ onCalculate?: (preview: DistributionPreview) => void;
150
+ /** Callback when an error occurs */
151
+ onError?: (error: Error) => void;
152
+ /** Custom CSS class */
153
+ className?: string;
154
+ }
155
+
156
+ /*//////////////////////////////////////////////////////////////
157
+ UTILITY TYPES
158
+ //////////////////////////////////////////////////////////////*/
159
+
160
+ /**
161
+ * Common loading state interface
162
+ */
163
+ export interface LoadingState {
164
+ /** Whether data is loading */
165
+ isLoading: boolean;
166
+ /** Error that occurred */
167
+ error: Error | null;
168
+ }
169
+
170
+ /**
171
+ * Transaction state interface
172
+ */
173
+ export interface TransactionState extends LoadingState {
174
+ /** Whether a transaction is pending */
175
+ isPending: boolean;
176
+ /** Transaction hash if available */
177
+ txHash: string | null;
178
+ }
179
+
180
+ /**
181
+ * Props for ErrorDisplay component
182
+ */
183
+ export interface ErrorDisplayProps {
184
+ /** Error to display */
185
+ error: Error;
186
+ /** Callback for retry action */
187
+ onRetry?: () => void;
188
+ /** Custom CSS class */
189
+ className?: string;
190
+ }
191
+
192
+ /**
193
+ * Props for LoadingSpinner component
194
+ */
195
+ export interface LoadingSpinnerProps {
196
+ /** Size of the spinner */
197
+ size?: 'sm' | 'md' | 'lg';
198
+ /** Custom CSS class */
199
+ className?: string;
200
+ }