@explorins/pers-sdk-react-native 1.5.35 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +402 -13
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useBusiness.d.ts +5 -5
- package/dist/hooks/useBusiness.d.ts.map +1 -1
- package/dist/hooks/useCampaigns.d.ts +8 -8
- package/dist/hooks/useCampaigns.d.ts.map +1 -1
- package/dist/hooks/useCampaigns.js +3 -3
- package/dist/hooks/useDonations.d.ts +2 -2
- package/dist/hooks/useDonations.d.ts.map +1 -1
- package/dist/hooks/useEvents.d.ts +178 -0
- package/dist/hooks/useEvents.d.ts.map +1 -0
- package/dist/hooks/useEvents.js +312 -0
- package/dist/hooks/usePurchases.d.ts +3 -3
- package/dist/hooks/usePurchases.d.ts.map +1 -1
- package/dist/hooks/useRedemptions.d.ts +6 -5
- package/dist/hooks/useRedemptions.d.ts.map +1 -1
- package/dist/hooks/useRedemptions.js +13 -19
- package/dist/hooks/useTenants.d.ts +2 -2
- package/dist/hooks/useTenants.d.ts.map +1 -1
- package/dist/hooks/useTokens.d.ts +4 -4
- package/dist/hooks/useTokens.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.d.ts +2 -0
- package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.js +68 -0
- package/dist/hooks/useTransactions.d.ts +3 -3
- package/dist/hooks/useTransactions.d.ts.map +1 -1
- package/dist/hooks/useUserStatus.d.ts +3 -3
- package/dist/hooks/useUserStatus.d.ts.map +1 -1
- package/dist/hooks/useUsers.d.ts +3 -3
- package/dist/hooks/useUsers.d.ts.map +1 -1
- package/dist/hooks/useWeb3.d.ts +5 -53
- package/dist/hooks/useWeb3.d.ts.map +1 -1
- package/dist/hooks/useWeb3.js +82 -177
- package/dist/index.d.ts +83 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3227 -837
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useBusiness.ts +5 -5
- package/src/hooks/useCampaigns.ts +12 -11
- package/src/hooks/useDonations.ts +2 -2
- package/src/hooks/useEvents.ts +360 -0
- package/src/hooks/usePurchases.ts +3 -3
- package/src/hooks/useRedemptions.ts +16 -22
- package/src/hooks/useTenants.ts +2 -2
- package/src/hooks/useTokens.ts +4 -4
- package/src/hooks/useTransactionSigner.ts +73 -0
- package/src/hooks/useTransactions.ts +4 -3
- package/src/hooks/useUserStatus.ts +3 -3
- package/src/hooks/useUsers.ts +3 -3
- package/src/hooks/useWeb3.ts +98 -202
- package/src/index.ts +105 -2
package/README.md
CHANGED
|
@@ -51,19 +51,12 @@ npm install react-native-url-polyfill
|
|
|
51
51
|
|
|
52
52
|
## Critical Setup Requirement: Passkeys
|
|
53
53
|
|
|
54
|
-
To enable Passkey authentication (WebAuthn) on iOS and Android, you **must**
|
|
54
|
+
To enable Passkey authentication (WebAuthn) on iOS and Android, you **must** complete the setup in **[REACT_NATIVE_PASSKEY_SETUP.md](./REACT_NATIVE_PASSKEY_SETUP.md)**.
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
3. **Android Package Name**: e.g., `com.yourcompany.app`
|
|
61
|
-
4. **Android SHA-256 Certificate Fingerprint**:
|
|
62
|
-
* **Development**: The fingerprint from your local keystore or Expo development build.
|
|
63
|
-
* **Production**: The fingerprint from your Google Play Console signing key.
|
|
64
|
-
|
|
65
|
-
**Why is this required?**
|
|
66
|
-
The PERS Signer server must host an `apple-app-site-association` file (for iOS) and an `assetlinks.json` file (for Android) that explicitly trusts your application. Without this, the operating system will reject Passkey creation requests.
|
|
56
|
+
This includes:
|
|
57
|
+
- Registering your app with the PERS backend (required for OS trust)
|
|
58
|
+
- Native configuration (Info.plist, AndroidManifest.xml)
|
|
59
|
+
- Expo/development build setup
|
|
67
60
|
|
|
68
61
|
## Quick Start
|
|
69
62
|
|
|
@@ -312,7 +305,11 @@ const {
|
|
|
312
305
|
resolveIPFSUrl,
|
|
313
306
|
fetchAndProcessMetadata,
|
|
314
307
|
getChainDataById,
|
|
315
|
-
getExplorerUrl
|
|
308
|
+
getExplorerUrl,
|
|
309
|
+
// Helper methods for token collections
|
|
310
|
+
extractTokenIds, // Extract tokenIds from TokenDTO metadata
|
|
311
|
+
getAccountOwnedTokensFromContract, // Recommended: Get owned tokens automatically
|
|
312
|
+
buildCollectionRequest // Build request for getTokenCollection
|
|
316
313
|
} = useWeb3();
|
|
317
314
|
|
|
318
315
|
// User status & achievements
|
|
@@ -334,6 +331,250 @@ const {
|
|
|
334
331
|
const {
|
|
335
332
|
getDonationTypes
|
|
336
333
|
} = useDonations();
|
|
334
|
+
|
|
335
|
+
// Event subscriptions (notifications, logging)
|
|
336
|
+
const {
|
|
337
|
+
subscribe, // Subscribe to SDK events
|
|
338
|
+
once, // One-time event listener
|
|
339
|
+
clear, // Clear all subscriptions
|
|
340
|
+
isAvailable, // Event system available
|
|
341
|
+
subscriberCount // Active subscriber count
|
|
342
|
+
} = useEvents();
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Event System
|
|
346
|
+
|
|
347
|
+
The `useEvents` hook provides access to SDK-wide events for showing notifications, logging, and reacting to SDK operations. All events include a `userMessage` field ready for UI display.
|
|
348
|
+
|
|
349
|
+
### Basic Usage
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import { useEvents } from '@explorins/pers-sdk-react-native';
|
|
353
|
+
import { useEffect } from 'react';
|
|
354
|
+
|
|
355
|
+
function NotificationHandler() {
|
|
356
|
+
const { subscribe, isAvailable } = useEvents();
|
|
357
|
+
|
|
358
|
+
useEffect(() => {
|
|
359
|
+
if (!isAvailable) return;
|
|
360
|
+
|
|
361
|
+
// Subscribe to all events
|
|
362
|
+
const unsubscribe = subscribe((event) => {
|
|
363
|
+
showNotification(event.userMessage, event.level);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
return () => unsubscribe(); // Cleanup on unmount
|
|
367
|
+
}, [subscribe, isAvailable]);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Filtering Events
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
// Only transaction successes
|
|
375
|
+
subscribe(
|
|
376
|
+
(event) => {
|
|
377
|
+
playSuccessSound();
|
|
378
|
+
showConfetti();
|
|
379
|
+
},
|
|
380
|
+
{ domain: 'transaction', level: 'success' }
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Only errors (for logging)
|
|
384
|
+
subscribe(
|
|
385
|
+
(event) => {
|
|
386
|
+
logToSentry(event);
|
|
387
|
+
},
|
|
388
|
+
{ level: 'error' }
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
// One-time event (auto-unsubscribes)
|
|
392
|
+
once(
|
|
393
|
+
(event) => {
|
|
394
|
+
console.log('First transaction completed!');
|
|
395
|
+
},
|
|
396
|
+
{ domain: 'transaction', level: 'success' }
|
|
397
|
+
);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Event Domains
|
|
401
|
+
|
|
402
|
+
| Domain | Events |
|
|
403
|
+
|--------|--------|
|
|
404
|
+
| `auth` | Login, logout, token refresh |
|
|
405
|
+
| `user` | Profile updates |
|
|
406
|
+
| `transaction` | Created, completed, failed |
|
|
407
|
+
| `campaign` | Claimed, activated |
|
|
408
|
+
| `redemption` | Redeemed, expired |
|
|
409
|
+
| `business` | Created, updated, membership |
|
|
410
|
+
| `api` | Network errors, validation errors |
|
|
411
|
+
|
|
412
|
+
### Event Structure
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
interface PersEvent {
|
|
416
|
+
id: string; // Unique event ID
|
|
417
|
+
timestamp: number; // Unix timestamp (ms)
|
|
418
|
+
domain: string; // Event domain (transaction, auth, etc.)
|
|
419
|
+
type: string; // Event type within domain
|
|
420
|
+
level: 'success' | 'error';
|
|
421
|
+
userMessage: string; // Ready for UI display
|
|
422
|
+
action?: string; // Suggested action
|
|
423
|
+
details?: object; // Additional data
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## POS Transaction Flow
|
|
430
|
+
|
|
431
|
+
For Point-of-Sale scenarios where a **business submits a transaction on behalf of a user**, use the `buildPOSTransferRequest` helper:
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import {
|
|
435
|
+
useTransactions,
|
|
436
|
+
buildPOSTransferRequest,
|
|
437
|
+
useEvents
|
|
438
|
+
} from '@explorins/pers-sdk-react-native';
|
|
439
|
+
|
|
440
|
+
function POSScreen() {
|
|
441
|
+
const { createTransaction, signingStatus } = useTransactions();
|
|
442
|
+
const { subscribe, isAvailable } = useEvents();
|
|
443
|
+
|
|
444
|
+
// Listen for transaction events
|
|
445
|
+
useEffect(() => {
|
|
446
|
+
if (!isAvailable) return;
|
|
447
|
+
|
|
448
|
+
const unsubscribe = subscribe(
|
|
449
|
+
(event) => {
|
|
450
|
+
if (event.level === 'success') {
|
|
451
|
+
Alert.alert('Success', event.userMessage);
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
{ domain: 'transaction' }
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
return () => unsubscribe();
|
|
458
|
+
}, [subscribe, isAvailable]);
|
|
459
|
+
|
|
460
|
+
const handlePOSTransaction = async (
|
|
461
|
+
userAccountId: string,
|
|
462
|
+
businessAccountId: string,
|
|
463
|
+
amount: number,
|
|
464
|
+
token: TokenDTO
|
|
465
|
+
) => {
|
|
466
|
+
// Build POS transfer request
|
|
467
|
+
const request = buildPOSTransferRequest({
|
|
468
|
+
amount,
|
|
469
|
+
contractAddress: token.contractAddress,
|
|
470
|
+
chainId: token.chainId,
|
|
471
|
+
userAccountId, // User sending tokens
|
|
472
|
+
businessAccountId // Business receiving & authorized to submit
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// Create and sign transaction
|
|
476
|
+
const result = await createTransaction(request, (status, message) => {
|
|
477
|
+
console.log(`Signing: ${status} - ${message}`);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
console.log('Transaction created:', result.transaction?.id);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### POS Authorization Fields
|
|
486
|
+
|
|
487
|
+
The `buildPOSTransferRequest` helper automatically sets:
|
|
488
|
+
|
|
489
|
+
| Field | Value | Purpose |
|
|
490
|
+
|-------|-------|---------|
|
|
491
|
+
| `engagedBusinessId` | Business ID | Business commercially involved (for reporting) |
|
|
492
|
+
| `authorizedSubmitterId` | Business ID | Entity authorized to submit the signed tx |
|
|
493
|
+
| `authorizedSubmitterType` | `BUSINESS` | Type of authorized submitter |
|
|
494
|
+
|
|
495
|
+
For custom scenarios, use `buildTransferRequest` with manual POS fields:
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
import { buildTransferRequest, AccountOwnerType } from '@explorins/pers-sdk-react-native';
|
|
499
|
+
|
|
500
|
+
const request = buildTransferRequest({
|
|
501
|
+
amount: 100,
|
|
502
|
+
contractAddress: '0x...',
|
|
503
|
+
chainId: 137,
|
|
504
|
+
senderAccountId: 'user-123',
|
|
505
|
+
senderAccountType: AccountOwnerType.USER,
|
|
506
|
+
recipientAccountId: 'business-456',
|
|
507
|
+
recipientAccountType: AccountOwnerType.BUSINESS,
|
|
508
|
+
// POS authorization
|
|
509
|
+
engagedBusinessId: 'business-456',
|
|
510
|
+
authorizedSubmitterId: 'business-456',
|
|
511
|
+
authorizedSubmitterType: AccountOwnerType.BUSINESS
|
|
512
|
+
});
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Token Collection Helper Methods
|
|
518
|
+
|
|
519
|
+
The `useWeb3` hook includes helper methods for querying token balances from any blockchain address. These work with **all token standards** (ERC-20, ERC-721, ERC-1155).
|
|
520
|
+
|
|
521
|
+
### Recommended: getAccountOwnedTokensFromContract
|
|
522
|
+
|
|
523
|
+
A unified API to get all tokens owned by any blockchain address:
|
|
524
|
+
|
|
525
|
+
```typescript
|
|
526
|
+
import { useWeb3, useTokens, usePersSDK } from '@explorins/pers-sdk-react-native';
|
|
527
|
+
|
|
528
|
+
function RewardTokensScreen() {
|
|
529
|
+
const { user } = usePersSDK();
|
|
530
|
+
const { getRewardTokens } = useTokens();
|
|
531
|
+
const { getAccountOwnedTokensFromContract } = useWeb3();
|
|
532
|
+
|
|
533
|
+
const loadUserRewards = async () => {
|
|
534
|
+
const walletAddress = user?.wallets?.[0]?.address;
|
|
535
|
+
if (!walletAddress) return;
|
|
536
|
+
|
|
537
|
+
const rewardTokens = await getRewardTokens();
|
|
538
|
+
|
|
539
|
+
for (const token of rewardTokens) {
|
|
540
|
+
// Works with ERC-20, ERC-721, and ERC-1155 automatically
|
|
541
|
+
const result = await getAccountOwnedTokensFromContract(walletAddress, token);
|
|
542
|
+
|
|
543
|
+
console.log(`Token: ${token.symbol}`);
|
|
544
|
+
console.log(`Owned: ${result.totalOwned}`);
|
|
545
|
+
|
|
546
|
+
result.ownedTokens.forEach(owned => {
|
|
547
|
+
console.log(` - ${owned.metadata?.name}: ${owned.balance}`);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
return (
|
|
553
|
+
<TouchableOpacity onPress={loadUserRewards}>
|
|
554
|
+
<Text>Load My Rewards</Text>
|
|
555
|
+
</TouchableOpacity>
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### How It Handles Each Token Standard
|
|
561
|
+
|
|
562
|
+
| Token Type | What It Does |
|
|
563
|
+
|------------|--------------|
|
|
564
|
+
| **ERC-20** | Returns balance for fungible tokens |
|
|
565
|
+
| **ERC-721** | Enumerates all owned NFTs |
|
|
566
|
+
| **ERC-1155** | Extracts tokenIds from metadata, queries balances |
|
|
567
|
+
|
|
568
|
+
The helper abstracts away the complexity - especially for ERC-1155 which requires specific `tokenIds` that the helper extracts from `token.metadata[].tokenMetadataIncrementalId`.
|
|
569
|
+
|
|
570
|
+
### Return Type
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
interface AccountOwnedTokensResult {
|
|
574
|
+
token: TokenDTO; // The token definition
|
|
575
|
+
ownedTokens: TokenBalance[]; // Tokens with balance > 0
|
|
576
|
+
totalOwned: number; // Count of owned tokens
|
|
577
|
+
}
|
|
337
578
|
```
|
|
338
579
|
|
|
339
580
|
## EVM Blockchain Transaction Signing
|
|
@@ -538,6 +779,154 @@ function AnalyticsExample() {
|
|
|
538
779
|
}
|
|
539
780
|
```
|
|
540
781
|
|
|
782
|
+
## Migration Guide
|
|
783
|
+
|
|
784
|
+
### v2.0.0 Breaking Changes - Pagination
|
|
785
|
+
|
|
786
|
+
**Version 2.0.0 introduces standardized pagination** across all hooks that return lists. Previously, hooks returned raw arrays. Now they return `PaginatedResponseDTO<T>` with pagination metadata.
|
|
787
|
+
|
|
788
|
+
#### What Changed
|
|
789
|
+
|
|
790
|
+
All hooks returning lists now return paginated responses:
|
|
791
|
+
|
|
792
|
+
```typescript
|
|
793
|
+
// ❌ OLD (v1.x) - Direct array
|
|
794
|
+
const businesses: BusinessDTO[] = await getActiveBusinesses();
|
|
795
|
+
|
|
796
|
+
// ✅ NEW (v2.x) - Paginated response
|
|
797
|
+
const response: PaginatedResponseDTO<BusinessDTO> = await getActiveBusinesses();
|
|
798
|
+
const businesses: BusinessDTO[] = response.data;
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
#### Affected Hooks
|
|
802
|
+
|
|
803
|
+
| Hook | Method | Return Type |
|
|
804
|
+
|------|--------|-------------|
|
|
805
|
+
| `useBusiness` | `getActiveBusinesses()` | `PaginatedResponseDTO<BusinessDTO>` |
|
|
806
|
+
| `useBusiness` | `getBusinessTypes()` | `PaginatedResponseDTO<BusinessTypeDTO>` |
|
|
807
|
+
| `useCampaigns` | `getActiveCampaigns()` | `PaginatedResponseDTO<CampaignDTO>` |
|
|
808
|
+
| `useCampaigns` | `getUserClaims()` | `PaginatedResponseDTO<CampaignClaimDTO>` |
|
|
809
|
+
| `useTokens` | `getTokens()` | `PaginatedResponseDTO<TokenDTO>` |
|
|
810
|
+
| `useTokens` | `getRewardTokens()` | `PaginatedResponseDTO<TokenDTO>` |
|
|
811
|
+
| `useTokens` | `getStatusTokens()` | `PaginatedResponseDTO<TokenDTO>` |
|
|
812
|
+
| `useRedemptions` | `getActiveRedemptions()` | `PaginatedResponseDTO<RedemptionDTO>` |
|
|
813
|
+
| `useRedemptions` | `getUserRedemptions()` | `PaginatedResponseDTO<RedemptionDTO>` |
|
|
814
|
+
| `useTransactions` | `getUserTransactionHistory()` | `PaginatedResponseDTO<TransactionDTO>` |
|
|
815
|
+
| `usePurchases` | `getAllUserPurchases()` | `PaginatedResponseDTO<PurchaseDTO>` |
|
|
816
|
+
| `usePurchases` | `getActivePurchaseTokens()` | `PaginatedResponseDTO<PurchaseTokenDTO>` |
|
|
817
|
+
| `useDonations` | `getDonationTypes()` | `PaginatedResponseDTO<DonationTypeDTO>` |
|
|
818
|
+
|
|
819
|
+
#### PaginatedResponseDTO Structure
|
|
820
|
+
|
|
821
|
+
```typescript
|
|
822
|
+
import type { PaginatedResponseDTO } from '@explorins/pers-shared';
|
|
823
|
+
|
|
824
|
+
interface PaginatedResponseDTO<T> {
|
|
825
|
+
data: T[]; // Array of results
|
|
826
|
+
pagination: {
|
|
827
|
+
currentPage: number; // Current page number (1-indexed)
|
|
828
|
+
pageSize: number; // Items per page
|
|
829
|
+
totalItems: number; // Total number of items across all pages
|
|
830
|
+
totalPages: number; // Total number of pages
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
#### Migration Examples
|
|
836
|
+
|
|
837
|
+
**Before (v1.x):**
|
|
838
|
+
```typescript
|
|
839
|
+
const businesses = await getActiveBusinesses();
|
|
840
|
+
console.log('Business count:', businesses.length);
|
|
841
|
+
businesses.forEach(b => console.log(b.name));
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
**After (v2.x):**
|
|
845
|
+
```typescript
|
|
846
|
+
const response = await getActiveBusinesses();
|
|
847
|
+
console.log('Business count:', response.data.length);
|
|
848
|
+
console.log('Total businesses:', response.pagination.totalItems);
|
|
849
|
+
response.data.forEach(b => console.log(b.name));
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
**With Pagination Parameters:**
|
|
853
|
+
```typescript
|
|
854
|
+
// Fetch page 2 with 20 items per page
|
|
855
|
+
const response = await getActiveBusinesses({ page: 2, pageSize: 20 });
|
|
856
|
+
|
|
857
|
+
console.log(`Page ${response.pagination.currentPage} of ${response.pagination.totalPages}`);
|
|
858
|
+
console.log(`Showing ${response.data.length} businesses`);
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
#### React Native Component Example
|
|
862
|
+
|
|
863
|
+
```typescript
|
|
864
|
+
import { useState, useEffect } from 'react';
|
|
865
|
+
import { useBusiness } from '@explorins/pers-sdk-react-native';
|
|
866
|
+
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
|
|
867
|
+
|
|
868
|
+
function BusinessListScreen() {
|
|
869
|
+
const { getActiveBusinesses } = useBusiness();
|
|
870
|
+
const [businesses, setBusinesses] = useState<BusinessDTO[]>([]);
|
|
871
|
+
const [pagination, setPagination] = useState(null);
|
|
872
|
+
const [loading, setLoading] = useState(true);
|
|
873
|
+
|
|
874
|
+
useEffect(() => {
|
|
875
|
+
loadBusinesses();
|
|
876
|
+
}, []);
|
|
877
|
+
|
|
878
|
+
const loadBusinesses = async (page = 1) => {
|
|
879
|
+
try {
|
|
880
|
+
setLoading(true);
|
|
881
|
+
const response = await getActiveBusinesses({ page, pageSize: 20 });
|
|
882
|
+
setBusinesses(response.data);
|
|
883
|
+
setPagination(response.pagination);
|
|
884
|
+
} catch (error) {
|
|
885
|
+
console.error('Failed to load businesses:', error);
|
|
886
|
+
} finally {
|
|
887
|
+
setLoading(false);
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
if (loading) return <ActivityIndicator />;
|
|
892
|
+
|
|
893
|
+
return (
|
|
894
|
+
<View>
|
|
895
|
+
<Text>
|
|
896
|
+
Showing {businesses.length} of {pagination?.totalItems} businesses
|
|
897
|
+
</Text>
|
|
898
|
+
<FlatList
|
|
899
|
+
data={businesses}
|
|
900
|
+
keyExtractor={(item) => item.id}
|
|
901
|
+
renderItem={({ item }) => <BusinessCard business={item} />}
|
|
902
|
+
/>
|
|
903
|
+
<Text>Page {pagination?.currentPage} of {pagination?.totalPages}</Text>
|
|
904
|
+
</View>
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
#### Quick Fix for Existing Code
|
|
910
|
+
|
|
911
|
+
If you want minimal code changes, extract `.data` immediately:
|
|
912
|
+
|
|
913
|
+
```typescript
|
|
914
|
+
// Quick adaptation in your hooks
|
|
915
|
+
const businesses = (await getActiveBusinesses()).data;
|
|
916
|
+
const campaigns = (await getActiveCampaigns()).data;
|
|
917
|
+
const tokens = (await getTokens()).data;
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
#### Benefits of Pagination
|
|
921
|
+
|
|
922
|
+
- **Performance**: Load only what you need, not entire datasets
|
|
923
|
+
- **Consistency**: All list endpoints follow the same pattern
|
|
924
|
+
- **Metadata**: Access total counts without loading all items
|
|
925
|
+
- **Better UX**: Build proper pagination UI components
|
|
926
|
+
- **Memory Efficiency**: Reduced memory footprint for large datasets
|
|
927
|
+
|
|
928
|
+
---
|
|
929
|
+
|
|
541
930
|
## Contributing
|
|
542
931
|
|
|
543
932
|
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ export { useUserStatus } from './useUserStatus';
|
|
|
13
13
|
export { useFiles } from './useFiles';
|
|
14
14
|
export { useAnalytics } from './useAnalytics';
|
|
15
15
|
export { useDonations } from './useDonations';
|
|
16
|
+
export { useEvents } from './useEvents';
|
|
16
17
|
export type { RawUserData } from './useAuth';
|
|
17
18
|
export type { TransactionSignerHook, SubmissionResult, AuthenticatedUser, TransactionSigningResult, StatusUpdateData, OnStatusUpdateFn, SigningStatus as SigningStatusType } from './useTransactionSigner';
|
|
18
|
-
export type {
|
|
19
|
+
export type { AccountOwnedTokensResult, Web3Hook } from './useWeb3';
|
|
20
|
+
export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } from './useEvents';
|
|
19
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BusinessDTO, BusinessTypeDTO, BusinessUpdateRequestDTO, BusinessToggleActiveRequestDTO } from '@explorins/pers-shared';
|
|
1
|
+
import type { BusinessDTO, BusinessTypeDTO, BusinessUpdateRequestDTO, BusinessToggleActiveRequestDTO, PaginatedResponseDTO } from '@explorins/pers-shared';
|
|
2
2
|
/**
|
|
3
3
|
* React hook for business operations in the PERS SDK
|
|
4
4
|
*
|
|
@@ -34,12 +34,12 @@ import type { BusinessDTO, BusinessTypeDTO, BusinessUpdateRequestDTO, BusinessTo
|
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
36
|
export declare const useBusiness: () => {
|
|
37
|
-
getActiveBusinesses: () => Promise<BusinessDTO
|
|
38
|
-
getBusinessTypes: () => Promise<BusinessTypeDTO
|
|
39
|
-
getBusinesses: () => Promise<BusinessDTO
|
|
37
|
+
getActiveBusinesses: () => Promise<PaginatedResponseDTO<BusinessDTO>>;
|
|
38
|
+
getBusinessTypes: () => Promise<PaginatedResponseDTO<BusinessTypeDTO>>;
|
|
39
|
+
getBusinesses: () => Promise<PaginatedResponseDTO<BusinessDTO>>;
|
|
40
40
|
getBusinessById: (businessId: string) => Promise<BusinessDTO | null>;
|
|
41
41
|
getBusinessByAccount: (accountAddress: string) => Promise<BusinessDTO>;
|
|
42
|
-
getBusinessesByType: (typeId: string) => Promise<BusinessDTO
|
|
42
|
+
getBusinessesByType: (typeId: string) => Promise<PaginatedResponseDTO<BusinessDTO>>;
|
|
43
43
|
createBusiness: (displayName: string) => Promise<BusinessDTO>;
|
|
44
44
|
updateBusiness: (businessId: string, businessData: BusinessUpdateRequestDTO) => Promise<BusinessDTO>;
|
|
45
45
|
toggleBusinessStatus: (businessId: string, toggleData: BusinessToggleActiveRequestDTO) => Promise<BusinessDTO>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBusiness.d.ts","sourceRoot":"","sources":["../../src/hooks/useBusiness.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"useBusiness.d.ts","sourceRoot":"","sources":["../../src/hooks/useBusiness.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE3J;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,WAAW;+BAgB4B,QAAQ,qBAAqB,WAAW,CAAC,CAAC;4BA2B7C,QAAQ,qBAAqB,eAAe,CAAC,CAAC;yBA4BjD,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCAd/B,MAAM,KAAG,QAAQ,WAAW,GAAG,IAAI,CAAC;2CA4B3B,MAAM,KAAG,QAAQ,WAAW,CAAC;kCActC,MAAM,KAAG,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCA6BnD,MAAM,KAAG,QAAQ,WAAW,CAAC;iCAc9B,MAAM,gBAAgB,wBAAwB,KAAG,QAAQ,WAAW,CAAC;uCAc/D,MAAM,cAAc,8BAA8B,KAAG,QAAQ,WAAW,CAAC;;CA0BtI,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { CampaignClaimRequestDTO, CampaignDTO, CampaignClaimDTO, CampaignTriggerDTO } from '@explorins/pers-shared';
|
|
1
|
+
import type { CampaignClaimRequestDTO, CampaignDTO, CampaignClaimDTO, CampaignTriggerDTO, PaginatedResponseDTO } from '@explorins/pers-shared';
|
|
2
2
|
export declare const useCampaigns: () => {
|
|
3
|
-
getActiveCampaigns: () => Promise<CampaignDTO
|
|
3
|
+
getActiveCampaigns: () => Promise<PaginatedResponseDTO<CampaignDTO>>;
|
|
4
4
|
getCampaignById: (campaignId: string) => Promise<CampaignDTO | null>;
|
|
5
5
|
claimCampaign: (request: CampaignClaimRequestDTO) => Promise<CampaignClaimDTO | null>;
|
|
6
|
-
getUserClaims: () => Promise<CampaignClaimDTO
|
|
7
|
-
getCampaignTriggers: () => Promise<CampaignTriggerDTO
|
|
8
|
-
getAllCampaigns: (active?: boolean) => Promise<CampaignDTO
|
|
9
|
-
getCampaignClaims: () => Promise<CampaignClaimDTO
|
|
10
|
-
getCampaignClaimsByUserId: (userId: string) => Promise<CampaignClaimDTO
|
|
11
|
-
getCampaignClaimsByBusinessId: (businessId: string) => Promise<CampaignClaimDTO
|
|
6
|
+
getUserClaims: () => Promise<PaginatedResponseDTO<CampaignClaimDTO>>;
|
|
7
|
+
getCampaignTriggers: () => Promise<PaginatedResponseDTO<CampaignTriggerDTO>>;
|
|
8
|
+
getAllCampaigns: (active?: boolean) => Promise<PaginatedResponseDTO<CampaignDTO>>;
|
|
9
|
+
getCampaignClaims: () => Promise<PaginatedResponseDTO<CampaignClaimDTO>>;
|
|
10
|
+
getCampaignClaimsByUserId: (userId: string) => Promise<PaginatedResponseDTO<CampaignClaimDTO>>;
|
|
11
|
+
getCampaignClaimsByBusinessId: (businessId: string) => Promise<PaginatedResponseDTO<CampaignClaimDTO>>;
|
|
12
12
|
isAvailable: boolean;
|
|
13
13
|
};
|
|
14
14
|
export type CampaignHook = ReturnType<typeof useCampaigns>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCampaigns.d.ts","sourceRoot":"","sources":["../../src/hooks/useCampaigns.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"useCampaigns.d.ts","sourceRoot":"","sources":["../../src/hooks/useCampaigns.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAIlB,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAEhC,eAAO,MAAM,YAAY;8BAG0B,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCAcpC,MAAM,KAAG,QAAQ,WAAW,GAAG,IAAI,CAAC;6BAczC,uBAAuB,KAAG,QAAQ,gBAAgB,GAAG,IAAI,CAAC;yBAiBhE,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;+BAkBzC,QAAQ,qBAAqB,kBAAkB,CAAC,CAAC;+BAe/C,OAAO,KAAG,QAAQ,qBAAqB,WAAW,CAAC,CAAC;6BAcxD,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;wCAclC,MAAM,KAAG,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;gDAchD,MAAM,KAAG,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;;CA0B9H,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
|
@@ -7,7 +7,7 @@ export const useCampaigns = () => {
|
|
|
7
7
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
8
8
|
}
|
|
9
9
|
try {
|
|
10
|
-
const result = await sdk.campaigns.
|
|
10
|
+
const result = await sdk.campaigns.getCampaigns({ active: true });
|
|
11
11
|
return result;
|
|
12
12
|
}
|
|
13
13
|
catch (error) {
|
|
@@ -50,7 +50,7 @@ export const useCampaigns = () => {
|
|
|
50
50
|
}
|
|
51
51
|
if (!isAuthenticated) {
|
|
52
52
|
console.warn('SDK not authenticated. getUserClaims requires authentication.');
|
|
53
|
-
return [];
|
|
53
|
+
return { data: [], pagination: { page: 1, limit: 0, total: 0, pages: 0, hasNext: false, hasPrev: false } };
|
|
54
54
|
}
|
|
55
55
|
try {
|
|
56
56
|
const result = await sdk.campaigns.getUserClaims();
|
|
@@ -80,7 +80,7 @@ export const useCampaigns = () => {
|
|
|
80
80
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
81
81
|
}
|
|
82
82
|
try {
|
|
83
|
-
const result = await sdk.campaigns.
|
|
83
|
+
const result = await sdk.campaigns.getCampaigns({ active });
|
|
84
84
|
return result;
|
|
85
85
|
}
|
|
86
86
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DonationTypeDTO } from '@explorins/pers-shared';
|
|
1
|
+
import type { DonationTypeDTO, PaginatedResponseDTO } from '@explorins/pers-shared';
|
|
2
2
|
/**
|
|
3
3
|
* React hook for donation operations in the PERS SDK
|
|
4
4
|
*
|
|
@@ -26,7 +26,7 @@ import type { DonationTypeDTO } from '@explorins/pers-shared';
|
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
export declare const useDonations: () => {
|
|
29
|
-
getDonationTypes: () => Promise<DonationTypeDTO
|
|
29
|
+
getDonationTypes: () => Promise<PaginatedResponseDTO<DonationTypeDTO>>;
|
|
30
30
|
isAvailable: boolean;
|
|
31
31
|
};
|
|
32
32
|
export type DonationHook = ReturnType<typeof useDonations>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDonations.d.ts","sourceRoot":"","sources":["../../src/hooks/useDonations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"useDonations.d.ts","sourceRoot":"","sources":["../../src/hooks/useDonations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY;4BAgBwB,QAAQ,qBAAqB,eAAe,CAAC,CAAC;;CAkB9F,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
|