@umituz/react-native-subscription 2.14.98 → 2.14.100
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/README.md +211 -395
- package/package.json +1 -1
- package/src/application/README.md +46 -225
- package/src/application/ports/README.md +42 -97
- package/src/domain/README.md +36 -384
- package/src/domain/constants/README.md +0 -56
- package/src/domain/entities/README.md +43 -169
- package/src/domain/errors/README.md +33 -287
- package/src/domain/value-objects/README.md +43 -179
- package/src/domains/README.md +52 -0
- package/src/domains/README.md.bak +274 -0
- package/src/domains/config/README.md +93 -383
- package/src/domains/config/domain/README.md +37 -0
- package/src/domains/config/domain/entities/README.md +41 -0
- package/src/domains/paywall/README.md +99 -369
- package/src/domains/paywall/components/README.md +34 -178
- package/src/domains/paywall/entities/README.md +34 -193
- package/src/domains/paywall/hooks/README.md +34 -122
- package/src/domains/wallet/README.md +34 -275
- package/src/domains/wallet/README.md.bak +209 -0
- package/src/domains/wallet/domain/README.md +34 -101
- package/src/domains/wallet/domain/entities/README.md +34 -115
- package/src/domains/wallet/domain/errors/README.md +34 -151
- package/src/domains/wallet/infrastructure/README.md +34 -89
- package/src/domains/wallet/presentation/components/README.md +34 -224
- package/src/domains/wallet/presentation/hooks/README.md +34 -248
- package/src/infrastructure/README.md +37 -496
- package/src/infrastructure/mappers/README.md +0 -13
- package/src/infrastructure/repositories/README.md +74 -360
- package/src/infrastructure/services/README.md +95 -370
- package/src/presentation/README.md +123 -408
- package/src/presentation/README.md.bak +172 -0
- package/src/presentation/components/README.md +151 -179
- package/src/presentation/components/README.md.bak +217 -0
- package/src/presentation/components/details/CreditRow.md +65 -310
- package/src/presentation/components/details/DetailRow.md +63 -255
- package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
- package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
- package/src/presentation/components/details/README.md +97 -447
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
- package/src/presentation/components/feedback/README.md +97 -445
- package/src/presentation/components/paywall/PaywallModal.md +66 -416
- package/src/presentation/components/paywall/README.md +50 -186
- package/src/presentation/components/sections/README.md +97 -466
- package/src/presentation/components/sections/SubscriptionSection.md +92 -244
- package/src/presentation/hooks/README.md +154 -741
- package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
- package/src/presentation/hooks/useAuthGate.md +61 -375
- package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
- package/src/presentation/hooks/useCreditChecker.md +73 -378
- package/src/presentation/hooks/useCredits.md +74 -313
- package/src/presentation/hooks/useCredits.md.bak +231 -0
- package/src/presentation/hooks/useCreditsGate.md +66 -318
- package/src/presentation/hooks/useDeductCredit.md +96 -156
- package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
- package/src/presentation/hooks/useFeatureGate.md +105 -150
- package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
- package/src/presentation/hooks/useInitializeCredits.md +64 -430
- package/src/presentation/hooks/usePaywall.md +61 -306
- package/src/presentation/hooks/usePaywallOperations.md +64 -458
- package/src/presentation/hooks/usePaywallVisibility.md +67 -316
- package/src/presentation/hooks/usePremium.md +84 -226
- package/src/presentation/hooks/usePremiumGate.md +60 -395
- package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
- package/src/presentation/hooks/useSubscription.md +66 -422
- package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
- package/src/presentation/hooks/useSubscriptionGate.md +80 -164
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
- package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
- package/src/presentation/hooks/useUserTier.md +63 -328
- package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
- package/src/presentation/screens/README.md +48 -190
- package/src/presentation/types/README.md +0 -16
- package/src/presentation/utils/README.md +0 -21
- package/src/revenuecat/README.md +99 -518
- package/src/revenuecat/application/README.md +43 -0
- package/src/revenuecat/application/ports/README.md +41 -0
- package/src/revenuecat/domain/README.md +42 -141
- package/src/revenuecat/domain/constants/README.md +41 -0
- package/src/revenuecat/domain/entities/README.md +42 -0
- package/src/revenuecat/domain/errors/README.md +47 -191
- package/src/revenuecat/domain/types/README.md +41 -0
- package/src/revenuecat/domain/value-objects/README.md +41 -0
- package/src/revenuecat/infrastructure/README.md +41 -0
- package/src/revenuecat/infrastructure/config/README.md +32 -23
- package/src/revenuecat/infrastructure/handlers/README.md +41 -0
- package/src/revenuecat/infrastructure/managers/README.md +34 -42
- package/src/revenuecat/infrastructure/services/README.md +42 -0
- package/src/revenuecat/infrastructure/utils/README.md +41 -0
- package/src/revenuecat/presentation/README.md +42 -0
- package/src/revenuecat/presentation/hooks/README.md +29 -35
- package/src/utils/README.md +38 -525
|
@@ -1,292 +1,51 @@
|
|
|
1
1
|
# Wallet Domain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Credit balance management, transaction history tracking, and product metadata management.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Location
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **İşlem Geçmişi**: Tüm kredi işlemlerini geçmişte takip edin
|
|
9
|
-
- **Ürün Metadata**: Satın alınan ürünler için metadata yönetimi
|
|
10
|
-
- **Tür Desteği**: Farklı kredi türlerini (AI, premium, vb.) destekleyin
|
|
7
|
+
`src/domains/wallet/`
|
|
11
8
|
|
|
12
|
-
##
|
|
9
|
+
## Strategy
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
Implements layered architecture for credit management with domain layer (entities, value objects, errors), infrastructure layer (repositories, Firebase services, mappers), and presentation layer (hooks, components). Handles initialization, operations, and transaction history with real-time updates.
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
import { configureProductMetadataService } from '@umituz/react-native-subscription';
|
|
13
|
+
## Restrictions
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
configureProductMetadataService({
|
|
21
|
-
firebase: firebaseInstance,
|
|
22
|
-
storage: storageInstance,
|
|
23
|
-
});
|
|
24
|
-
```
|
|
15
|
+
### REQUIRED
|
|
25
16
|
|
|
26
|
-
|
|
17
|
+
- All operations require authenticated user
|
|
18
|
+
- Credit operations MUST be validated server-side
|
|
19
|
+
- All credit changes MUST be recorded in transaction history
|
|
20
|
+
- MUST handle insufficient credits gracefully
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
import { createTransactionRepository } from '@umituz/react-native-subscription';
|
|
22
|
+
### PROHIBITED
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```
|
|
24
|
+
- MUST NOT allow client-side credit modifications without server validation
|
|
25
|
+
- MUST NOT deduct credits without sufficient balance
|
|
26
|
+
- MUST NOT expose internal repository logic to UI
|
|
27
|
+
- MUST NOT store credit balance in AsyncStorage (use secure backend)
|
|
36
28
|
|
|
37
|
-
|
|
29
|
+
### CRITICAL
|
|
38
30
|
|
|
39
|
-
|
|
31
|
+
- Always validate credit amounts (must be positive)
|
|
32
|
+
- Always implement optimistic updates with rollback
|
|
33
|
+
- Never trust client-side credit balance for security decisions
|
|
34
|
+
- Must implement retry logic for failed operations
|
|
35
|
+
- Always sanitize transaction reasons to prevent injection attacks
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
## AI Agent Guidelines
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
When implementing credit operations:
|
|
40
|
+
1. Always check balance before deducting
|
|
41
|
+
2. Always provide transaction reason and metadata
|
|
42
|
+
3. Always handle insufficient credits gracefully
|
|
43
|
+
4. Always implement optimistic updates with rollback
|
|
44
|
+
5. Never trust client-side balance for security
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
const { balance, loading, error, refresh } = useWallet({
|
|
48
|
-
userId: 'user-123',
|
|
49
|
-
});
|
|
46
|
+
## Related Documentation
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<View>
|
|
56
|
-
<Text>Balance: {balance.credits}</Text>
|
|
57
|
-
<Button onPress={refresh} title="Refresh" />
|
|
58
|
-
</View>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### useTransactionHistory Hook
|
|
64
|
-
|
|
65
|
-
İşlem geçmişini görüntülemek için:
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
import { useTransactionHistory } from '@umituz/react-native-subscription';
|
|
69
|
-
|
|
70
|
-
function TransactionHistory() {
|
|
71
|
-
const { transactions, loading, hasMore, loadMore } = useTransactionHistory({
|
|
72
|
-
userId: 'user-123',
|
|
73
|
-
limit: 20,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<FlatList
|
|
78
|
-
data={transactions}
|
|
79
|
-
keyExtractor={(item) => item.id}
|
|
80
|
-
onEndReached={hasMore ? loadMore : undefined}
|
|
81
|
-
renderItem={({ item }) => (
|
|
82
|
-
<View>
|
|
83
|
-
<Text>{item.reason}</Text>
|
|
84
|
-
<Text>{item.amount} credits</Text>
|
|
85
|
-
<Text>{new Date(item.timestamp).toLocaleString()}</Text>
|
|
86
|
-
</View>
|
|
87
|
-
)}
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### useProductMetadata Hook
|
|
94
|
-
|
|
95
|
-
Ürün metadata yönetimi için:
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
import { useProductMetadata } from '@umituz/react-native-subscription';
|
|
99
|
-
|
|
100
|
-
function ProductInfo() {
|
|
101
|
-
const { metadata, loading, updateMetadata } = useProductMetadata({
|
|
102
|
-
userId: 'user-123',
|
|
103
|
-
productId: 'premium_monthly',
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const handleUpdate = async () => {
|
|
107
|
-
await updateMetadata({
|
|
108
|
-
lastUsed: new Date().toISOString(),
|
|
109
|
-
usageCount: (metadata?.usageCount || 0) + 1,
|
|
110
|
-
});
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<View>
|
|
115
|
-
<Text>Product: {metadata?.productId}</Text>
|
|
116
|
-
<Text>Usage: {metadata?.usageCount} times</Text>
|
|
117
|
-
<Button onPress={handleUpdate} title="Update Usage" />
|
|
118
|
-
</View>
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Bileşenler
|
|
124
|
-
|
|
125
|
-
### BalanceCard
|
|
126
|
-
|
|
127
|
-
Kredi bakiyesini gösteren kart bileşeni:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { BalanceCard } from '@umituz/react-native-subscription';
|
|
131
|
-
|
|
132
|
-
<BalanceCard
|
|
133
|
-
balance={150}
|
|
134
|
-
currency="USD"
|
|
135
|
-
translations={{
|
|
136
|
-
title: "Your Balance",
|
|
137
|
-
subtitle: "Credits available",
|
|
138
|
-
}}
|
|
139
|
-
/>
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### TransactionItem
|
|
143
|
-
|
|
144
|
-
Tek işlem öğesi:
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
import { TransactionItem } from '@umituz/react-native-subscription';
|
|
148
|
-
|
|
149
|
-
<TransactionItem
|
|
150
|
-
transaction={{
|
|
151
|
-
id: 'tx-123',
|
|
152
|
-
amount: -50,
|
|
153
|
-
reason: 'purchase',
|
|
154
|
-
timestamp: '2024-01-01T00:00:00Z',
|
|
155
|
-
}}
|
|
156
|
-
translations={{
|
|
157
|
-
purchase: 'Purchase',
|
|
158
|
-
refund: 'Refund',
|
|
159
|
-
}}
|
|
160
|
-
/>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### TransactionList
|
|
164
|
-
|
|
165
|
-
İşlem listesi bileşeni:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
import { TransactionList } from '@umituz/react-native-subscription';
|
|
169
|
-
|
|
170
|
-
<TransactionList
|
|
171
|
-
transactions={transactions}
|
|
172
|
-
loading={loading}
|
|
173
|
-
onEndReached={loadMore}
|
|
174
|
-
translations={{
|
|
175
|
-
title: 'Transaction History',
|
|
176
|
-
empty: 'No transactions yet',
|
|
177
|
-
}}
|
|
178
|
-
/>
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### WalletScreen
|
|
182
|
-
|
|
183
|
-
Tam cüzdan ekranı:
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import { WalletScreen } from '@umituz/react-native-subscription';
|
|
187
|
-
|
|
188
|
-
<WalletScreen
|
|
189
|
-
userId="user-123"
|
|
190
|
-
config={{
|
|
191
|
-
showBalance: true,
|
|
192
|
-
showHistory: true,
|
|
193
|
-
enableRefresh: true,
|
|
194
|
-
}}
|
|
195
|
-
translations={{
|
|
196
|
-
title: 'My Wallet',
|
|
197
|
-
balance: 'Balance',
|
|
198
|
-
history: 'History',
|
|
199
|
-
}}
|
|
200
|
-
/>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## API Referansı
|
|
204
|
-
|
|
205
|
-
### Tip Tanımlamaları
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
interface CreditBalance {
|
|
209
|
-
credits: number;
|
|
210
|
-
lastUpdated: string;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
interface TransactionLog {
|
|
214
|
-
id: string;
|
|
215
|
-
amount: number;
|
|
216
|
-
reason: TransactionReason;
|
|
217
|
-
timestamp: string;
|
|
218
|
-
metadata?: Record<string, any>;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
type TransactionReason =
|
|
222
|
-
| 'purchase'
|
|
223
|
-
| 'refund'
|
|
224
|
-
| 'usage'
|
|
225
|
-
| 'bonus'
|
|
226
|
-
| 'expiration';
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Yardımcı Fonksiyonlar
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
// Kredi maliyeti hesaplama
|
|
233
|
-
import { getCreditCost, creditsToDollars } from '@umituz/react-native-subscription';
|
|
234
|
-
|
|
235
|
-
const cost = getCreditCost('ai_generation'); // AI işlem maliyeti
|
|
236
|
-
const dollars = creditsToDollars(150, 0.01); // 150 kredi = $1.50
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## Hata Yönetimi
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
import {
|
|
243
|
-
WalletError,
|
|
244
|
-
CreditLimitError,
|
|
245
|
-
handleWalletError,
|
|
246
|
-
} from '@umituz/react-native-subscription';
|
|
247
|
-
|
|
248
|
-
try {
|
|
249
|
-
// İşlem
|
|
250
|
-
} catch (error) {
|
|
251
|
-
if (error instanceof CreditLimitError) {
|
|
252
|
-
console.log('Yetersiz bakiye');
|
|
253
|
-
}
|
|
254
|
-
handleWalletError(error);
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
## Örnek Uygulama
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
import React from 'react';
|
|
262
|
-
import { View, Text, Button } from 'react-native';
|
|
263
|
-
import {
|
|
264
|
-
useWallet,
|
|
265
|
-
useTransactionHistory,
|
|
266
|
-
BalanceCard,
|
|
267
|
-
TransactionList,
|
|
268
|
-
} from '@umituz/react-native-subscription';
|
|
269
|
-
|
|
270
|
-
export default function WalletExample() {
|
|
271
|
-
const { balance, refresh } = useWallet({ userId: 'user-123' });
|
|
272
|
-
const { transactions, loading } = useTransactionHistory({
|
|
273
|
-
userId: 'user-123',
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return (
|
|
277
|
-
<View>
|
|
278
|
-
<BalanceCard balance={balance} />
|
|
279
|
-
<Button title="Refresh" onPress={refresh} />
|
|
280
|
-
<TransactionList transactions={transactions} loading={loading} />
|
|
281
|
-
</View>
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
## Best Practices
|
|
287
|
-
|
|
288
|
-
1. **Kredi Türleri**: Farklı kredi türleri için farklı cost config'leri kullanın
|
|
289
|
-
2. **Hata Yönetimi**: Tüm işlemleri try-catch blokları içinde sarın
|
|
290
|
-
3. **Loading State**: Yüklenme durumlarını her zaman gösterin
|
|
291
|
-
4. **Refresh**: Kullanıcıya manuel refresh imkanı verin
|
|
292
|
-
5. **Transaction Log**: Tüm işlemleri loglayın ve audit trail tutun
|
|
48
|
+
- [Credits Repository](infrastructure/README.md)
|
|
49
|
+
- [useCredits Hook](../../presentation/hooks/README.md)
|
|
50
|
+
- [UserCredits Entity](domain/entities/README.md)
|
|
51
|
+
- [Transaction Errors](domain/errors/README.md)
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Wallet Domain
|
|
2
|
+
|
|
3
|
+
Credit balance management, transaction history tracking, and product metadata management.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
**Directory**: `src/domains/wallet/`
|
|
8
|
+
|
|
9
|
+
**Type**: Domain
|
|
10
|
+
|
|
11
|
+
## Strategy
|
|
12
|
+
|
|
13
|
+
### Domain Architecture
|
|
14
|
+
|
|
15
|
+
The Wallet Domain implements a layered architecture for credit management:
|
|
16
|
+
|
|
17
|
+
1. **Domain Layer**
|
|
18
|
+
- Entities: `UserCredits`, `Transaction`, `CreditType`
|
|
19
|
+
- Value Objects: `CreditAmount`, `TransactionReason`
|
|
20
|
+
- Errors: `InsufficientCreditsError`, `InvalidCreditAmountError`
|
|
21
|
+
|
|
22
|
+
2. **Infrastructure Layer**
|
|
23
|
+
- Repositories: `CreditsRepository`, `TransactionsRepository`
|
|
24
|
+
- Firebase Services: Data persistence and real-time updates
|
|
25
|
+
- Mappers: Entity ↔ DTO transformations
|
|
26
|
+
|
|
27
|
+
3. **Presentation Layer**
|
|
28
|
+
- Hooks: `useCredits`, `useDeductCredit`, `useInitializeCredits`
|
|
29
|
+
- Components: Credit displays, transaction lists
|
|
30
|
+
|
|
31
|
+
### Credit Flow
|
|
32
|
+
|
|
33
|
+
1. **Initialization**
|
|
34
|
+
- Fetch initial credit balance from backend
|
|
35
|
+
- Subscribe to real-time credit updates
|
|
36
|
+
- Cache in TanStack Query
|
|
37
|
+
|
|
38
|
+
2. **Operations**
|
|
39
|
+
- Check balance before operations
|
|
40
|
+
- Deduct credits optimistically
|
|
41
|
+
- Sync with backend
|
|
42
|
+
- Rollback on failure
|
|
43
|
+
|
|
44
|
+
3. **Transaction History**
|
|
45
|
+
- Record all credit operations
|
|
46
|
+
- Provide audit trail
|
|
47
|
+
- Support pagination and filtering
|
|
48
|
+
|
|
49
|
+
### Integration Points
|
|
50
|
+
|
|
51
|
+
- **Firebase**: Real database for persistence
|
|
52
|
+
- **TanStack Query**: Client-side caching and state management
|
|
53
|
+
- **RevenueCat**: Purchase flow integration
|
|
54
|
+
- **Presentation Hooks**: UI integration layer
|
|
55
|
+
|
|
56
|
+
## Restrictions
|
|
57
|
+
|
|
58
|
+
### REQUIRED
|
|
59
|
+
|
|
60
|
+
- **User Authentication**: All operations require authenticated user
|
|
61
|
+
- **Server Validation**: Credit operations MUST be validated server-side
|
|
62
|
+
- **Transaction Recording**: All credit changes MUST be recorded in transaction history
|
|
63
|
+
- **Error Handling**: MUST handle insufficient credits gracefully
|
|
64
|
+
|
|
65
|
+
### PROHIBITED
|
|
66
|
+
|
|
67
|
+
- **NEVER** allow client-side credit modifications without server validation
|
|
68
|
+
- **NEVER** deduct credits without sufficient balance
|
|
69
|
+
- **DO NOT** expose internal repository logic to UI
|
|
70
|
+
- **NEVER** store credit balance in AsyncStorage (use secure backend)
|
|
71
|
+
|
|
72
|
+
### CRITICAL SAFETY
|
|
73
|
+
|
|
74
|
+
- **ALWAYS** validate credit amounts (must be positive)
|
|
75
|
+
- **ALWAYS** implement optimistic updates with rollback
|
|
76
|
+
- **NEVER** trust client-side credit balance for security decisions
|
|
77
|
+
- **MUST** implement retry logic for failed operations
|
|
78
|
+
- **ALWAYS** sanitize transaction reasons to prevent injection attacks
|
|
79
|
+
|
|
80
|
+
## Rules
|
|
81
|
+
|
|
82
|
+
### Repository Initialization
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// CORRECT - Proper repository setup
|
|
86
|
+
const creditsRepository = new CreditsRepository({
|
|
87
|
+
firebase: firebaseInstance,
|
|
88
|
+
userId: user.uid,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// INCORRECT - Missing userId
|
|
92
|
+
const creditsRepository = new CreditsRepository({
|
|
93
|
+
firebase: firebaseInstance,
|
|
94
|
+
// userId undefined
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Credit Operations
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// CORRECT - Check before deduct
|
|
102
|
+
const hasEnoughCredits = await creditsRepository.checkBalance(requiredAmount);
|
|
103
|
+
if (hasEnoughCredits) {
|
|
104
|
+
await creditsRepository.deductCredits(requiredAmount, 'feature_usage');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// INCORRECT - Deduct without checking
|
|
108
|
+
await creditsRepository.deductCredits(requiredAmount, 'feature_usage');
|
|
109
|
+
// May throw InsufficientCreditsError
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Transaction Recording
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// CORRECT - Record all operations
|
|
116
|
+
await creditsRepository.deductCredits(
|
|
117
|
+
amount,
|
|
118
|
+
reason,
|
|
119
|
+
{ featureId, metadata } // Include context
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// INCORRECT - Missing context
|
|
123
|
+
await creditsRepository.deductCredits(amount, reason);
|
|
124
|
+
// Lost audit trail
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Error Handling
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// CORRECT - Handle specific errors
|
|
131
|
+
try {
|
|
132
|
+
await creditsRepository.deductCredits(amount, reason);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof InsufficientCreditsError) {
|
|
135
|
+
showUpgradePrompt();
|
|
136
|
+
} else if (error instanceof InvalidCreditAmountError) {
|
|
137
|
+
showInvalidAmountError();
|
|
138
|
+
} else {
|
|
139
|
+
showGenericError();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// INCORRECT - Generic error handling
|
|
144
|
+
try {
|
|
145
|
+
await creditsRepository.deductCredits(amount, reason);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error(error); // Doesn't help user
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## AI Agent Guidelines
|
|
152
|
+
|
|
153
|
+
### When Implementing Credit Operations
|
|
154
|
+
|
|
155
|
+
1. **Always** check balance before deducting
|
|
156
|
+
2. **Always** provide transaction reason and metadata
|
|
157
|
+
3. **Always** handle insufficient credits gracefully
|
|
158
|
+
4. **Always** implement optimistic updates with rollback
|
|
159
|
+
5. **Never** trust client-side balance for security
|
|
160
|
+
|
|
161
|
+
### Integration Checklist
|
|
162
|
+
|
|
163
|
+
- [ ] Initialize repository with valid userId
|
|
164
|
+
- [ ] Implement error boundaries
|
|
165
|
+
- [ ] Handle loading states
|
|
166
|
+
- [ ] Provide user feedback for all operations
|
|
167
|
+
- [ ] Test with insufficient credits
|
|
168
|
+
- [ ] Test with zero balance
|
|
169
|
+
- [ ] Test transaction history
|
|
170
|
+
- [ ] Test real-time updates
|
|
171
|
+
- [ ] Implement retry logic
|
|
172
|
+
- [ ] Sanitize user inputs
|
|
173
|
+
|
|
174
|
+
### Common Patterns
|
|
175
|
+
|
|
176
|
+
1. **Pre-check**: Always verify balance before operations
|
|
177
|
+
2. **Optimistic Updates**: Update UI immediately, rollback on failure
|
|
178
|
+
3. **Transaction Context**: Include featureId and metadata in all operations
|
|
179
|
+
4. **Error Recovery**: Provide upgrade path when credits insufficient
|
|
180
|
+
5. **Real-time Sync**: Subscribe to credit changes for multi-device sync
|
|
181
|
+
6. **Audit Trail**: Maintain complete transaction history
|
|
182
|
+
7. **Caching**: Use TanStack Query for performance
|
|
183
|
+
8. **Validation**: Validate all inputs on both client and server
|
|
184
|
+
|
|
185
|
+
## Related Documentation
|
|
186
|
+
|
|
187
|
+
- **Credits Repository**: `infrastructure/repositories/README.md`
|
|
188
|
+
- **useCredits Hook**: `../../presentation/hooks/useCredits.md`
|
|
189
|
+
- **useDeductCredit Hook**: `../../presentation/hooks/useDeductCredit.md`
|
|
190
|
+
- **UserCredits Entity**: `domain/entities/README.md`
|
|
191
|
+
- **Transaction Errors**: `domain/errors/README.md`
|
|
192
|
+
|
|
193
|
+
## Domain Structure
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
src/domains/wallet/
|
|
197
|
+
├── domain/
|
|
198
|
+
│ ├── entities/ # Core entities
|
|
199
|
+
│ │ ├── UserCredits.ts
|
|
200
|
+
│ │ └── Transaction.ts
|
|
201
|
+
│ ├── value-objects/ # Value objects
|
|
202
|
+
│ └── errors/ # Domain errors
|
|
203
|
+
├── infrastructure/
|
|
204
|
+
│ ├── repositories/ # Data access
|
|
205
|
+
│ └── services/ # External services
|
|
206
|
+
└── presentation/
|
|
207
|
+
├── hooks/ # React hooks
|
|
208
|
+
└── components/ # UI components
|
|
209
|
+
```
|
|
@@ -1,108 +1,41 @@
|
|
|
1
1
|
# Wallet Domain
|
|
2
2
|
|
|
3
|
+
## Location
|
|
3
4
|
Wallet domain containing credits and transaction management logic.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Transactions
|
|
41
|
-
Record of credit transactions (additions and deductions).
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
interface Transaction {
|
|
45
|
-
id: string;
|
|
46
|
-
amount: number;
|
|
47
|
-
reason: string;
|
|
48
|
-
timestamp: Date;
|
|
49
|
-
type: 'purchase' | 'deduction' | 'bonus' | 'renewal';
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Allocation Modes
|
|
54
|
-
|
|
55
|
-
**ACCUMULATE**: Add credits to existing balance (renewals)
|
|
56
|
-
```typescript
|
|
57
|
-
// Renewal: 100 + 100 = 200 credits
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
**REPLACE**: Replace existing credits (new purchase)
|
|
61
|
-
```typescript
|
|
62
|
-
// New purchase: Old balance replaced with new amount
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Key Features
|
|
66
|
-
|
|
67
|
-
- **Duplicate Protection**: Prevent duplicate credit allocations
|
|
68
|
-
- **Transactional Operations**: Atomic credit updates
|
|
69
|
-
- **Optimistic Updates**: Immediate UI with rollback
|
|
70
|
-
- **Transaction History**: Complete audit trail
|
|
71
|
-
- **Monthly Reset**: Credits reset on subscription renewal
|
|
72
|
-
|
|
73
|
-
## Usage
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
// In hooks or components
|
|
77
|
-
import { useCredits } from './presentation/hooks/useCredits';
|
|
78
|
-
import { useDeductCredit } from './presentation/hooks/useDeductCredit';
|
|
79
|
-
|
|
80
|
-
function Feature() {
|
|
81
|
-
const { credits } = useCredits({ userId: user?.uid });
|
|
82
|
-
const { deductCredit } = useDeductCredit({
|
|
83
|
-
userId: user?.uid,
|
|
84
|
-
onCreditsExhausted: () => showPaywall(),
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const handleUseFeature = async () => {
|
|
88
|
-
const success = await deductCredit(5);
|
|
89
|
-
if (success) {
|
|
90
|
-
await executeFeature();
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Best Practices
|
|
97
|
-
|
|
98
|
-
1. **Check Balance First**: Verify credits before operations
|
|
99
|
-
2. **Handle Exhaustion**: Provide upgrade path when credits low
|
|
100
|
-
3. **Track Usage**: Log all credit transactions
|
|
101
|
-
4. **Reset Credits**: Clear credits on subscription renewal
|
|
102
|
-
5. **Test Edge Cases**: Zero credits, max credits, duplicates
|
|
103
|
-
|
|
104
|
-
## Related
|
|
105
|
-
|
|
6
|
+
## Strategy
|
|
7
|
+
The wallet domain manages user credits, transactions, and credit allocation strategies with duplicate protection, transactional operations, and complete audit trail.
|
|
8
|
+
|
|
9
|
+
## Restrictions
|
|
10
|
+
|
|
11
|
+
### REQUIRED
|
|
12
|
+
- Must check credit balance before operations
|
|
13
|
+
- Must handle credit exhaustion gracefully
|
|
14
|
+
- Must track all credit transactions
|
|
15
|
+
- Must reset credits on subscription renewal
|
|
16
|
+
|
|
17
|
+
### PROHIBITED
|
|
18
|
+
- DO NOT perform operations without balance check
|
|
19
|
+
- DO NOT allow duplicate credit allocations
|
|
20
|
+
- DO NOT skip transaction logging
|
|
21
|
+
- DO NOT bypass credit exhaustion handling
|
|
22
|
+
|
|
23
|
+
### CRITICAL SAFETY
|
|
24
|
+
- Credit allocations MUST be protected against duplicates
|
|
25
|
+
- All credit operations MUST be transactional
|
|
26
|
+
- Transaction history MUST be complete and accurate
|
|
27
|
+
- Credit exhaustion MUST trigger upgrade flow
|
|
28
|
+
|
|
29
|
+
## AI Agent Guidelines
|
|
30
|
+
1. Always verify credit balance before performing operations
|
|
31
|
+
2. Handle credit exhaustion with clear upgrade path
|
|
32
|
+
3. Log all credit transactions for audit trail
|
|
33
|
+
4. Implement monthly credit reset on subscription renewal
|
|
34
|
+
5. Test edge cases: zero credits, max credits, duplicates
|
|
35
|
+
6. Use ACCUMULATE mode for renewals, REPLACE for new purchases
|
|
36
|
+
7. Provide optimistic updates with rollback capability
|
|
37
|
+
|
|
38
|
+
## Related Documentation
|
|
106
39
|
- [Credits README](./README.md)
|
|
107
40
|
- [Credits Entity](./domain/entities/Credits.md)
|
|
108
41
|
- [useCredits Hook](../../presentation/hooks/useCredits.md)
|