atfi 1.0.0 → 1.1.1

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 CHANGED
@@ -1,6 +1,18 @@
1
1
  # ATFi SDK
2
2
 
3
- TypeScript SDK for interacting with ATFi commitment vaults on Base.
3
+ TypeScript SDK for interacting with ATFi commitment vaults on Base. Stake tokens, verify attendance, earn rewards.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/atfi.svg)](https://www.npmjs.com/package/atfi)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Features
9
+
10
+ - **Simulation-first** - Know results before wallet popup
11
+ - **Transaction callbacks** - Loading states for UX
12
+ - **Read-only mode** - Show data before wallet connection
13
+ - **User-centric queries** - Dashboard, registered events, claimable rewards
14
+ - **Real-time watching** - Subscribe to live vault events
15
+ - **TypeScript** - Full type safety
4
16
 
5
17
  ## Installation
6
18
 
package/dist/index.d.mts CHANGED
@@ -1,47 +1,58 @@
1
1
  import { Address, Hash, PublicClient, WalletClient } from 'viem';
2
2
 
3
- declare const CHAIN_ID = 8453;
3
+ type Network = 'mainnet' | 'testnet';
4
+ interface NetworkConfig {
5
+ chainId: number;
6
+ name: string;
7
+ factory: Address;
8
+ morphoVault: Address | null;
9
+ supportsYield: boolean;
10
+ tokens: {
11
+ USDC: TokenConfig;
12
+ IDRX?: TokenConfig;
13
+ };
14
+ }
15
+ interface TokenConfig {
16
+ address: Address;
17
+ decimals: number;
18
+ symbol: string;
19
+ supportsYield: boolean;
20
+ }
21
+ /**
22
+ * Network configurations for Base Mainnet and Sepolia Testnet
23
+ */
24
+ declare const NETWORKS: Record<Network, NetworkConfig>;
25
+ declare const CHAIN_ID: number;
4
26
  declare const CONTRACTS: {
5
- readonly FACTORY: Address;
6
- readonly MORPHO_VAULT: Address;
27
+ readonly FACTORY: `0x${string}`;
28
+ readonly MORPHO_VAULT: `0x${string}` | null;
7
29
  };
8
30
  declare const TOKENS: {
9
- readonly USDC: {
10
- readonly address: Address;
11
- readonly decimals: 6;
12
- readonly symbol: "USDC";
13
- readonly supportsYield: true;
14
- };
15
- readonly IDRX: {
16
- readonly address: Address;
17
- readonly decimals: 2;
18
- readonly symbol: "IDRX";
19
- readonly supportsYield: false;
20
- };
31
+ readonly USDC: TokenConfig;
32
+ readonly IDRX: TokenConfig;
21
33
  };
22
34
  type TokenSymbol = keyof typeof TOKENS;
35
+ /**
36
+ * Get network configuration by network name or chain ID
37
+ */
38
+ declare function getNetworkConfig(networkOrChainId: Network | number): NetworkConfig | null;
39
+ /**
40
+ * Get token config by address (searches all networks)
41
+ */
23
42
  declare const getTokenByAddress: (address: Address) => {
24
43
  symbol: TokenSymbol;
25
44
  address: Address;
26
- decimals: 6;
27
- supportsYield: true;
28
- } | {
29
- symbol: TokenSymbol;
30
- address: Address;
31
- decimals: 2;
32
- supportsYield: false;
45
+ decimals: number;
46
+ supportsYield: boolean;
33
47
  } | null;
34
- declare const getTokenBySymbol: (symbol: TokenSymbol) => {
35
- readonly address: Address;
36
- readonly decimals: 6;
37
- readonly symbol: "USDC";
38
- readonly supportsYield: true;
39
- } | {
40
- readonly address: Address;
41
- readonly decimals: 2;
42
- readonly symbol: "IDRX";
43
- readonly supportsYield: false;
44
- };
48
+ /**
49
+ * Get token config by symbol
50
+ */
51
+ declare const getTokenBySymbol: (symbol: TokenSymbol) => TokenConfig;
52
+ /**
53
+ * Check if yield is available on a network
54
+ */
55
+ declare function isYieldSupported(networkOrChainId: Network | number): boolean;
45
56
 
46
57
  declare enum ParticipantStatus {
47
58
  NOT_STAKED = 0,
@@ -186,6 +197,8 @@ interface EventSummary {
186
197
  maxParticipants: number;
187
198
  currentParticipants: number;
188
199
  status: EventStatus;
200
+ tokenSymbol: string;
201
+ tokenDecimals: number;
189
202
  }
190
203
  interface ATFiSDKConfig {
191
204
  /** Custom factory address (optional, defaults to mainnet) */
@@ -344,6 +357,26 @@ interface VaultWatchCallbacks {
344
357
  /** Function to stop watching events */
345
358
  type UnwatchFn = () => void;
346
359
 
360
+ /**
361
+ * Flexible public client type - accepts any viem-compatible client
362
+ * This allows SDK to work with different viem versions (e.g., from wagmi)
363
+ */
364
+ type CompatiblePublicClient = PublicClient | {
365
+ readContract: any;
366
+ simulateContract: any;
367
+ waitForTransactionReceipt: any;
368
+ watchContractEvent: any;
369
+ estimateContractGas: any;
370
+ };
371
+ /**
372
+ * Flexible wallet client type - accepts any viem-compatible wallet
373
+ */
374
+ type CompatibleWalletClient = WalletClient | {
375
+ account?: {
376
+ address: Address;
377
+ };
378
+ writeContract: any;
379
+ } | null;
347
380
  /**
348
381
  * ATFi SDK - TypeScript SDK for interacting with ATFi Protocol
349
382
  *
@@ -357,7 +390,7 @@ type UnwatchFn = () => void;
357
390
  *
358
391
  * @example
359
392
  * ```ts
360
- * // Full mode (with wallet)
393
+ * // Full mode (with wallet) - works with wagmi clients directly!
361
394
  * const sdk = new ATFiSDK(publicClient, walletClient);
362
395
  *
363
396
  * // Read-only mode (no wallet needed)
@@ -378,7 +411,13 @@ declare class ATFiSDK {
378
411
  private walletClient;
379
412
  private factoryAddress;
380
413
  private _isReadOnly;
381
- constructor(publicClient: PublicClient, walletClient?: WalletClient | null, config?: ATFiSDKConfig);
414
+ /**
415
+ * Create a new ATFi SDK instance
416
+ * @param publicClient - viem PublicClient (or wagmi's usePublicClient result)
417
+ * @param walletClient - viem WalletClient (or wagmi's useWalletClient result), optional for read-only
418
+ * @param config - Optional SDK configuration
419
+ */
420
+ constructor(publicClient: CompatiblePublicClient, walletClient?: CompatibleWalletClient, config?: ATFiSDKConfig);
382
421
  /**
383
422
  * Create a read-only SDK instance (no wallet required)
384
423
  * Use this to show event data before user connects wallet
@@ -390,7 +429,7 @@ declare class ATFiSDK {
390
429
  * const info = await sdk.getEventInfo(vaultAddress);
391
430
  * ```
392
431
  */
393
- static readOnly(publicClient: PublicClient, config?: ATFiSDKConfig): ATFiSDK;
432
+ static readOnly(publicClient: CompatiblePublicClient, config?: ATFiSDKConfig): ATFiSDK;
394
433
  /** Check if SDK is in read-only mode */
395
434
  get isReadOnly(): boolean;
396
435
  /** Get connected wallet address (null if read-only) */
@@ -592,6 +631,136 @@ declare class ATFiError extends Error {
592
631
  */
593
632
  declare function parseContractError(error: unknown): ATFiError;
594
633
 
634
+ /**
635
+ * Shorten an address for display
636
+ * @param address Full address
637
+ * @param chars Number of characters to show on each side (default 4)
638
+ * @returns Shortened address like "0x1234...5678"
639
+ *
640
+ * @example
641
+ * shortenAddress('0x1234567890abcdef1234567890abcdef12345678')
642
+ * // => "0x1234...5678"
643
+ */
644
+ declare function shortenAddress(address: Address | string, chars?: number): string;
645
+ /**
646
+ * Format amount for USD display
647
+ * @param amount Amount string or number
648
+ * @param decimals Decimal places (default 2)
649
+ * @returns Formatted string like "$10.50"
650
+ *
651
+ * @example
652
+ * formatUSD('1234.5')
653
+ * // => "$1,234.50"
654
+ */
655
+ declare function formatUSD(amount: string | number, decimals?: number): string;
656
+ /**
657
+ * Format token amount with symbol
658
+ * @param amount Amount string or number
659
+ * @param symbol Token symbol
660
+ * @param decimals Decimal places (default 2)
661
+ * @returns Formatted string like "10.50 USDC"
662
+ *
663
+ * @example
664
+ * formatTokenAmount('1234.567', 'USDC')
665
+ * // => "1,234.57 USDC"
666
+ */
667
+ declare function formatTokenAmount(amount: string | number, symbol: string, decimals?: number): string;
668
+ /**
669
+ * Format large numbers with abbreviations
670
+ * @param amount Amount to format
671
+ * @returns Abbreviated string like "1.2K", "3.4M"
672
+ *
673
+ * @example
674
+ * formatCompact(1234567)
675
+ * // => "1.2M"
676
+ */
677
+ declare function formatCompact(amount: string | number): string;
678
+ /**
679
+ * Format percentage
680
+ * @param value Value to format (e.g., 0.15 for 15%)
681
+ * @param decimals Decimal places (default 2)
682
+ * @returns Formatted percentage like "15.00%"
683
+ *
684
+ * @example
685
+ * formatPercent(0.1567)
686
+ * // => "15.67%"
687
+ */
688
+ declare function formatPercent(value: number, decimals?: number): string;
689
+
690
+ /**
691
+ * Hook to create ATFi SDK from wagmi clients
692
+ *
693
+ * @example
694
+ * ```tsx
695
+ * import { usePublicClient, useWalletClient } from 'wagmi';
696
+ * import { useATFiSDK } from 'atfi/react';
697
+ *
698
+ * function MyComponent() {
699
+ * const publicClient = usePublicClient();
700
+ * const { data: walletClient } = useWalletClient();
701
+ * const { sdk, isReadOnly } = useATFiSDK(publicClient, walletClient);
702
+ *
703
+ * // Use sdk...
704
+ * }
705
+ * ```
706
+ */
707
+ declare function useATFiSDK(publicClient: any, walletClient?: any, config?: ATFiSDKConfig): {
708
+ sdk: ATFiSDK | null;
709
+ isReadOnly: boolean;
710
+ };
711
+
712
+ interface UseEventInfoResult {
713
+ data: EventInfo | null;
714
+ isLoading: boolean;
715
+ error: Error | null;
716
+ refetch: () => Promise<void>;
717
+ }
718
+ /**
719
+ * Hook to fetch and cache event info
720
+ *
721
+ * @example
722
+ * ```tsx
723
+ * const { data, isLoading, error, refetch } = useEventInfo(sdk, vaultAddress);
724
+ *
725
+ * if (isLoading) return <Spinner />;
726
+ * if (error) return <Error message={error.message} />;
727
+ *
728
+ * return <EventCard event={data} />;
729
+ * ```
730
+ */
731
+ declare function useEventInfo(sdk: ATFiSDK | null, vaultAddress: Address | string | undefined): UseEventInfoResult;
732
+
733
+ interface WatchState {
734
+ participantCount: number;
735
+ verifiedCount: number;
736
+ isSettled: boolean;
737
+ lastClaim: {
738
+ participant: Address;
739
+ amount: string;
740
+ } | null;
741
+ }
742
+ interface UseWatchVaultResult extends WatchState {
743
+ isWatching: boolean;
744
+ }
745
+ /**
746
+ * Hook to watch vault events in real-time
747
+ * Automatically cleans up subscriptions on unmount
748
+ *
749
+ * @example
750
+ * ```tsx
751
+ * const { participantCount, verifiedCount, isSettled, isWatching } = useWatchVault(sdk, vaultAddress);
752
+ *
753
+ * return (
754
+ * <div>
755
+ * <p>Participants: {participantCount}</p>
756
+ * <p>Verified: {verifiedCount}</p>
757
+ * {isSettled && <ClaimButton />}
758
+ * </div>
759
+ * );
760
+ * ```
761
+ */
762
+ declare function useWatchVault(sdk: ATFiSDK | null, vaultAddress: Address | string | undefined): UseWatchVaultResult;
763
+
595
764
  declare const FactoryATFiABI: readonly [{
596
765
  readonly inputs: readonly [{
597
766
  readonly internalType: "address";
@@ -1754,4 +1923,4 @@ declare const ERC20ABI: readonly [{
1754
1923
  readonly stateMutability: "view";
1755
1924
  }];
1756
1925
 
1757
- export { ATFiError, ATFiErrorCode, ATFiSDK, type ATFiSDKConfig, type ActionResult, CHAIN_ID, CONTRACTS, type ClaimAction, type ClaimParams, type ClaimResult, type CreateEventAction, type CreateEventParams, type CreateEventResult, ERC20ABI, type EventInfo, EventStatus, type EventSummary, FactoryATFiABI, type ParticipantInfo, ParticipantStatus, type RegisterAction, type RegisterParams, type RegisterResult, type SettleAction, type SettleEventParams, type SettleEventResult, type SimulateClaimResult, type SimulateCreateEventResult, type SimulateRegisterResult, type SimulateSettleResult, type SimulateStartEventResult, type SimulateVerifyResult, type SimulationBase, type StartEventAction, type StartEventParams, type StartEventResult, TOKENS, type TokenSymbol, type TransactionCallbacks, type UnwatchFn, type UserEventInfo, VaultATFiABI, type VaultWatchCallbacks, type VerifyAction, type VerifyParticipantParams, type VerifyParticipantResult, formatAmount, fromTokenUnits, getTokenByAddress, getTokenBySymbol, parseContractError, toTokenUnits };
1926
+ export { ATFiError, ATFiErrorCode, ATFiSDK, type ATFiSDKConfig, type ActionResult, CHAIN_ID, CONTRACTS, type ClaimAction, type ClaimParams, type ClaimResult, type CreateEventAction, type CreateEventParams, type CreateEventResult, ERC20ABI, type EventInfo, EventStatus, type EventSummary, FactoryATFiABI, NETWORKS, type Network, type NetworkConfig, type ParticipantInfo, ParticipantStatus, type RegisterAction, type RegisterParams, type RegisterResult, type SettleAction, type SettleEventParams, type SettleEventResult, type SimulateClaimResult, type SimulateCreateEventResult, type SimulateRegisterResult, type SimulateSettleResult, type SimulateStartEventResult, type SimulateVerifyResult, type SimulationBase, type StartEventAction, type StartEventParams, type StartEventResult, TOKENS, type TokenConfig, type TokenSymbol, type TransactionCallbacks, type UnwatchFn, type UserEventInfo, VaultATFiABI, type VaultWatchCallbacks, type VerifyAction, type VerifyParticipantParams, type VerifyParticipantResult, formatAmount, formatCompact, formatPercent, formatTokenAmount, formatUSD, fromTokenUnits, getNetworkConfig, getTokenByAddress, getTokenBySymbol, isYieldSupported, parseContractError, shortenAddress, toTokenUnits, useATFiSDK, useEventInfo, useWatchVault };
package/dist/index.d.ts CHANGED
@@ -1,47 +1,58 @@
1
1
  import { Address, Hash, PublicClient, WalletClient } from 'viem';
2
2
 
3
- declare const CHAIN_ID = 8453;
3
+ type Network = 'mainnet' | 'testnet';
4
+ interface NetworkConfig {
5
+ chainId: number;
6
+ name: string;
7
+ factory: Address;
8
+ morphoVault: Address | null;
9
+ supportsYield: boolean;
10
+ tokens: {
11
+ USDC: TokenConfig;
12
+ IDRX?: TokenConfig;
13
+ };
14
+ }
15
+ interface TokenConfig {
16
+ address: Address;
17
+ decimals: number;
18
+ symbol: string;
19
+ supportsYield: boolean;
20
+ }
21
+ /**
22
+ * Network configurations for Base Mainnet and Sepolia Testnet
23
+ */
24
+ declare const NETWORKS: Record<Network, NetworkConfig>;
25
+ declare const CHAIN_ID: number;
4
26
  declare const CONTRACTS: {
5
- readonly FACTORY: Address;
6
- readonly MORPHO_VAULT: Address;
27
+ readonly FACTORY: `0x${string}`;
28
+ readonly MORPHO_VAULT: `0x${string}` | null;
7
29
  };
8
30
  declare const TOKENS: {
9
- readonly USDC: {
10
- readonly address: Address;
11
- readonly decimals: 6;
12
- readonly symbol: "USDC";
13
- readonly supportsYield: true;
14
- };
15
- readonly IDRX: {
16
- readonly address: Address;
17
- readonly decimals: 2;
18
- readonly symbol: "IDRX";
19
- readonly supportsYield: false;
20
- };
31
+ readonly USDC: TokenConfig;
32
+ readonly IDRX: TokenConfig;
21
33
  };
22
34
  type TokenSymbol = keyof typeof TOKENS;
35
+ /**
36
+ * Get network configuration by network name or chain ID
37
+ */
38
+ declare function getNetworkConfig(networkOrChainId: Network | number): NetworkConfig | null;
39
+ /**
40
+ * Get token config by address (searches all networks)
41
+ */
23
42
  declare const getTokenByAddress: (address: Address) => {
24
43
  symbol: TokenSymbol;
25
44
  address: Address;
26
- decimals: 6;
27
- supportsYield: true;
28
- } | {
29
- symbol: TokenSymbol;
30
- address: Address;
31
- decimals: 2;
32
- supportsYield: false;
45
+ decimals: number;
46
+ supportsYield: boolean;
33
47
  } | null;
34
- declare const getTokenBySymbol: (symbol: TokenSymbol) => {
35
- readonly address: Address;
36
- readonly decimals: 6;
37
- readonly symbol: "USDC";
38
- readonly supportsYield: true;
39
- } | {
40
- readonly address: Address;
41
- readonly decimals: 2;
42
- readonly symbol: "IDRX";
43
- readonly supportsYield: false;
44
- };
48
+ /**
49
+ * Get token config by symbol
50
+ */
51
+ declare const getTokenBySymbol: (symbol: TokenSymbol) => TokenConfig;
52
+ /**
53
+ * Check if yield is available on a network
54
+ */
55
+ declare function isYieldSupported(networkOrChainId: Network | number): boolean;
45
56
 
46
57
  declare enum ParticipantStatus {
47
58
  NOT_STAKED = 0,
@@ -186,6 +197,8 @@ interface EventSummary {
186
197
  maxParticipants: number;
187
198
  currentParticipants: number;
188
199
  status: EventStatus;
200
+ tokenSymbol: string;
201
+ tokenDecimals: number;
189
202
  }
190
203
  interface ATFiSDKConfig {
191
204
  /** Custom factory address (optional, defaults to mainnet) */
@@ -344,6 +357,26 @@ interface VaultWatchCallbacks {
344
357
  /** Function to stop watching events */
345
358
  type UnwatchFn = () => void;
346
359
 
360
+ /**
361
+ * Flexible public client type - accepts any viem-compatible client
362
+ * This allows SDK to work with different viem versions (e.g., from wagmi)
363
+ */
364
+ type CompatiblePublicClient = PublicClient | {
365
+ readContract: any;
366
+ simulateContract: any;
367
+ waitForTransactionReceipt: any;
368
+ watchContractEvent: any;
369
+ estimateContractGas: any;
370
+ };
371
+ /**
372
+ * Flexible wallet client type - accepts any viem-compatible wallet
373
+ */
374
+ type CompatibleWalletClient = WalletClient | {
375
+ account?: {
376
+ address: Address;
377
+ };
378
+ writeContract: any;
379
+ } | null;
347
380
  /**
348
381
  * ATFi SDK - TypeScript SDK for interacting with ATFi Protocol
349
382
  *
@@ -357,7 +390,7 @@ type UnwatchFn = () => void;
357
390
  *
358
391
  * @example
359
392
  * ```ts
360
- * // Full mode (with wallet)
393
+ * // Full mode (with wallet) - works with wagmi clients directly!
361
394
  * const sdk = new ATFiSDK(publicClient, walletClient);
362
395
  *
363
396
  * // Read-only mode (no wallet needed)
@@ -378,7 +411,13 @@ declare class ATFiSDK {
378
411
  private walletClient;
379
412
  private factoryAddress;
380
413
  private _isReadOnly;
381
- constructor(publicClient: PublicClient, walletClient?: WalletClient | null, config?: ATFiSDKConfig);
414
+ /**
415
+ * Create a new ATFi SDK instance
416
+ * @param publicClient - viem PublicClient (or wagmi's usePublicClient result)
417
+ * @param walletClient - viem WalletClient (or wagmi's useWalletClient result), optional for read-only
418
+ * @param config - Optional SDK configuration
419
+ */
420
+ constructor(publicClient: CompatiblePublicClient, walletClient?: CompatibleWalletClient, config?: ATFiSDKConfig);
382
421
  /**
383
422
  * Create a read-only SDK instance (no wallet required)
384
423
  * Use this to show event data before user connects wallet
@@ -390,7 +429,7 @@ declare class ATFiSDK {
390
429
  * const info = await sdk.getEventInfo(vaultAddress);
391
430
  * ```
392
431
  */
393
- static readOnly(publicClient: PublicClient, config?: ATFiSDKConfig): ATFiSDK;
432
+ static readOnly(publicClient: CompatiblePublicClient, config?: ATFiSDKConfig): ATFiSDK;
394
433
  /** Check if SDK is in read-only mode */
395
434
  get isReadOnly(): boolean;
396
435
  /** Get connected wallet address (null if read-only) */
@@ -592,6 +631,136 @@ declare class ATFiError extends Error {
592
631
  */
593
632
  declare function parseContractError(error: unknown): ATFiError;
594
633
 
634
+ /**
635
+ * Shorten an address for display
636
+ * @param address Full address
637
+ * @param chars Number of characters to show on each side (default 4)
638
+ * @returns Shortened address like "0x1234...5678"
639
+ *
640
+ * @example
641
+ * shortenAddress('0x1234567890abcdef1234567890abcdef12345678')
642
+ * // => "0x1234...5678"
643
+ */
644
+ declare function shortenAddress(address: Address | string, chars?: number): string;
645
+ /**
646
+ * Format amount for USD display
647
+ * @param amount Amount string or number
648
+ * @param decimals Decimal places (default 2)
649
+ * @returns Formatted string like "$10.50"
650
+ *
651
+ * @example
652
+ * formatUSD('1234.5')
653
+ * // => "$1,234.50"
654
+ */
655
+ declare function formatUSD(amount: string | number, decimals?: number): string;
656
+ /**
657
+ * Format token amount with symbol
658
+ * @param amount Amount string or number
659
+ * @param symbol Token symbol
660
+ * @param decimals Decimal places (default 2)
661
+ * @returns Formatted string like "10.50 USDC"
662
+ *
663
+ * @example
664
+ * formatTokenAmount('1234.567', 'USDC')
665
+ * // => "1,234.57 USDC"
666
+ */
667
+ declare function formatTokenAmount(amount: string | number, symbol: string, decimals?: number): string;
668
+ /**
669
+ * Format large numbers with abbreviations
670
+ * @param amount Amount to format
671
+ * @returns Abbreviated string like "1.2K", "3.4M"
672
+ *
673
+ * @example
674
+ * formatCompact(1234567)
675
+ * // => "1.2M"
676
+ */
677
+ declare function formatCompact(amount: string | number): string;
678
+ /**
679
+ * Format percentage
680
+ * @param value Value to format (e.g., 0.15 for 15%)
681
+ * @param decimals Decimal places (default 2)
682
+ * @returns Formatted percentage like "15.00%"
683
+ *
684
+ * @example
685
+ * formatPercent(0.1567)
686
+ * // => "15.67%"
687
+ */
688
+ declare function formatPercent(value: number, decimals?: number): string;
689
+
690
+ /**
691
+ * Hook to create ATFi SDK from wagmi clients
692
+ *
693
+ * @example
694
+ * ```tsx
695
+ * import { usePublicClient, useWalletClient } from 'wagmi';
696
+ * import { useATFiSDK } from 'atfi/react';
697
+ *
698
+ * function MyComponent() {
699
+ * const publicClient = usePublicClient();
700
+ * const { data: walletClient } = useWalletClient();
701
+ * const { sdk, isReadOnly } = useATFiSDK(publicClient, walletClient);
702
+ *
703
+ * // Use sdk...
704
+ * }
705
+ * ```
706
+ */
707
+ declare function useATFiSDK(publicClient: any, walletClient?: any, config?: ATFiSDKConfig): {
708
+ sdk: ATFiSDK | null;
709
+ isReadOnly: boolean;
710
+ };
711
+
712
+ interface UseEventInfoResult {
713
+ data: EventInfo | null;
714
+ isLoading: boolean;
715
+ error: Error | null;
716
+ refetch: () => Promise<void>;
717
+ }
718
+ /**
719
+ * Hook to fetch and cache event info
720
+ *
721
+ * @example
722
+ * ```tsx
723
+ * const { data, isLoading, error, refetch } = useEventInfo(sdk, vaultAddress);
724
+ *
725
+ * if (isLoading) return <Spinner />;
726
+ * if (error) return <Error message={error.message} />;
727
+ *
728
+ * return <EventCard event={data} />;
729
+ * ```
730
+ */
731
+ declare function useEventInfo(sdk: ATFiSDK | null, vaultAddress: Address | string | undefined): UseEventInfoResult;
732
+
733
+ interface WatchState {
734
+ participantCount: number;
735
+ verifiedCount: number;
736
+ isSettled: boolean;
737
+ lastClaim: {
738
+ participant: Address;
739
+ amount: string;
740
+ } | null;
741
+ }
742
+ interface UseWatchVaultResult extends WatchState {
743
+ isWatching: boolean;
744
+ }
745
+ /**
746
+ * Hook to watch vault events in real-time
747
+ * Automatically cleans up subscriptions on unmount
748
+ *
749
+ * @example
750
+ * ```tsx
751
+ * const { participantCount, verifiedCount, isSettled, isWatching } = useWatchVault(sdk, vaultAddress);
752
+ *
753
+ * return (
754
+ * <div>
755
+ * <p>Participants: {participantCount}</p>
756
+ * <p>Verified: {verifiedCount}</p>
757
+ * {isSettled && <ClaimButton />}
758
+ * </div>
759
+ * );
760
+ * ```
761
+ */
762
+ declare function useWatchVault(sdk: ATFiSDK | null, vaultAddress: Address | string | undefined): UseWatchVaultResult;
763
+
595
764
  declare const FactoryATFiABI: readonly [{
596
765
  readonly inputs: readonly [{
597
766
  readonly internalType: "address";
@@ -1754,4 +1923,4 @@ declare const ERC20ABI: readonly [{
1754
1923
  readonly stateMutability: "view";
1755
1924
  }];
1756
1925
 
1757
- export { ATFiError, ATFiErrorCode, ATFiSDK, type ATFiSDKConfig, type ActionResult, CHAIN_ID, CONTRACTS, type ClaimAction, type ClaimParams, type ClaimResult, type CreateEventAction, type CreateEventParams, type CreateEventResult, ERC20ABI, type EventInfo, EventStatus, type EventSummary, FactoryATFiABI, type ParticipantInfo, ParticipantStatus, type RegisterAction, type RegisterParams, type RegisterResult, type SettleAction, type SettleEventParams, type SettleEventResult, type SimulateClaimResult, type SimulateCreateEventResult, type SimulateRegisterResult, type SimulateSettleResult, type SimulateStartEventResult, type SimulateVerifyResult, type SimulationBase, type StartEventAction, type StartEventParams, type StartEventResult, TOKENS, type TokenSymbol, type TransactionCallbacks, type UnwatchFn, type UserEventInfo, VaultATFiABI, type VaultWatchCallbacks, type VerifyAction, type VerifyParticipantParams, type VerifyParticipantResult, formatAmount, fromTokenUnits, getTokenByAddress, getTokenBySymbol, parseContractError, toTokenUnits };
1926
+ export { ATFiError, ATFiErrorCode, ATFiSDK, type ATFiSDKConfig, type ActionResult, CHAIN_ID, CONTRACTS, type ClaimAction, type ClaimParams, type ClaimResult, type CreateEventAction, type CreateEventParams, type CreateEventResult, ERC20ABI, type EventInfo, EventStatus, type EventSummary, FactoryATFiABI, NETWORKS, type Network, type NetworkConfig, type ParticipantInfo, ParticipantStatus, type RegisterAction, type RegisterParams, type RegisterResult, type SettleAction, type SettleEventParams, type SettleEventResult, type SimulateClaimResult, type SimulateCreateEventResult, type SimulateRegisterResult, type SimulateSettleResult, type SimulateStartEventResult, type SimulateVerifyResult, type SimulationBase, type StartEventAction, type StartEventParams, type StartEventResult, TOKENS, type TokenConfig, type TokenSymbol, type TransactionCallbacks, type UnwatchFn, type UserEventInfo, VaultATFiABI, type VaultWatchCallbacks, type VerifyAction, type VerifyParticipantParams, type VerifyParticipantResult, formatAmount, formatCompact, formatPercent, formatTokenAmount, formatUSD, fromTokenUnits, getNetworkConfig, getTokenByAddress, getTokenBySymbol, isYieldSupported, parseContractError, shortenAddress, toTokenUnits, useATFiSDK, useEventInfo, useWatchVault };
package/dist/index.js CHANGED
@@ -28,15 +28,26 @@ __export(index_exports, {
28
28
  ERC20ABI: () => ERC20ABI,
29
29
  EventStatus: () => EventStatus,
30
30
  FactoryATFiABI: () => FactoryATFiABI,
31
+ NETWORKS: () => NETWORKS,
31
32
  ParticipantStatus: () => ParticipantStatus,
32
33
  TOKENS: () => TOKENS,
33
34
  VaultATFiABI: () => VaultATFiABI,
34
35
  formatAmount: () => formatAmount,
36
+ formatCompact: () => formatCompact,
37
+ formatPercent: () => formatPercent,
38
+ formatTokenAmount: () => formatTokenAmount,
39
+ formatUSD: () => formatUSD,
35
40
  fromTokenUnits: () => fromTokenUnits,
41
+ getNetworkConfig: () => getNetworkConfig,
36
42
  getTokenByAddress: () => getTokenByAddress,
37
43
  getTokenBySymbol: () => getTokenBySymbol,
44
+ isYieldSupported: () => isYieldSupported,
38
45
  parseContractError: () => parseContractError,
39
- toTokenUnits: () => toTokenUnits
46
+ shortenAddress: () => shortenAddress,
47
+ toTokenUnits: () => toTokenUnits,
48
+ useATFiSDK: () => useATFiSDK,
49
+ useEventInfo: () => useEventInfo,
50
+ useWatchVault: () => useWatchVault
40
51
  });
41
52
  module.exports = __toCommonJS(index_exports);
42
53
 
@@ -95,30 +106,74 @@ var ERC20ABI = [
95
106
  ];
96
107
 
97
108
  // src/constants/addresses.ts
98
- var CHAIN_ID = 8453;
109
+ var NETWORKS = {
110
+ mainnet: {
111
+ chainId: 8453,
112
+ name: "Base",
113
+ factory: "0x0be05a5fa7116c1b33f2b0036eb0d9690db9075f",
114
+ morphoVault: "0x050cE30b927Da55177A4914EC73480238BAD56f0",
115
+ supportsYield: true,
116
+ tokens: {
117
+ USDC: {
118
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
119
+ decimals: 6,
120
+ symbol: "USDC",
121
+ supportsYield: true
122
+ },
123
+ IDRX: {
124
+ address: "0x18Bc5bcC660cf2B9cE3cd51a404aFe1a0cBD3C22",
125
+ decimals: 2,
126
+ symbol: "IDRX",
127
+ supportsYield: false
128
+ }
129
+ }
130
+ },
131
+ testnet: {
132
+ chainId: 84532,
133
+ // Base Sepolia
134
+ name: "Base Sepolia",
135
+ factory: "0xf1EA206029549A8c4e2EB960F7ac43A98E922A49",
136
+ morphoVault: null,
137
+ // No Morpho on testnet
138
+ supportsYield: false,
139
+ tokens: {
140
+ USDC: {
141
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
142
+ // Base Sepolia USDC
143
+ decimals: 6,
144
+ symbol: "USDC",
145
+ supportsYield: false
146
+ }
147
+ }
148
+ }
149
+ };
150
+ var CHAIN_ID = NETWORKS.mainnet.chainId;
99
151
  var CONTRACTS = {
100
- FACTORY: "0x0be05a5fa7116c1b33f2b0036eb0d9690db9075f",
101
- MORPHO_VAULT: "0x050cE30b927Da55177A4914EC73480238BAD56f0"
152
+ FACTORY: NETWORKS.mainnet.factory,
153
+ MORPHO_VAULT: NETWORKS.mainnet.morphoVault
102
154
  };
103
155
  var TOKENS = {
104
- USDC: {
105
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
106
- decimals: 6,
107
- symbol: "USDC",
108
- supportsYield: true
109
- },
110
- IDRX: {
111
- address: "0x18Bc5bcC660cf2B9cE3cd51a404aFe1a0cBD3C22",
112
- decimals: 2,
113
- symbol: "IDRX",
114
- supportsYield: false
115
- }
156
+ USDC: NETWORKS.mainnet.tokens.USDC,
157
+ IDRX: NETWORKS.mainnet.tokens.IDRX
116
158
  };
159
+ function getNetworkConfig(networkOrChainId) {
160
+ if (typeof networkOrChainId === "string") {
161
+ return NETWORKS[networkOrChainId] || null;
162
+ }
163
+ for (const config of Object.values(NETWORKS)) {
164
+ if (config.chainId === networkOrChainId) {
165
+ return config;
166
+ }
167
+ }
168
+ return null;
169
+ }
117
170
  var getTokenByAddress = (address) => {
118
171
  const normalizedAddress = address.toLowerCase();
119
- for (const [sym, token] of Object.entries(TOKENS)) {
120
- if (token.address.toLowerCase() === normalizedAddress) {
121
- return { ...token, symbol: sym };
172
+ for (const network of Object.values(NETWORKS)) {
173
+ for (const [sym, token] of Object.entries(network.tokens)) {
174
+ if (token.address.toLowerCase() === normalizedAddress) {
175
+ return { ...token, symbol: sym };
176
+ }
122
177
  }
123
178
  }
124
179
  return null;
@@ -126,6 +181,10 @@ var getTokenByAddress = (address) => {
126
181
  var getTokenBySymbol = (symbol) => {
127
182
  return TOKENS[symbol];
128
183
  };
184
+ function isYieldSupported(networkOrChainId) {
185
+ const config = getNetworkConfig(networkOrChainId);
186
+ return config?.supportsYield ?? false;
187
+ }
129
188
 
130
189
  // src/utils/decimals.ts
131
190
  var import_viem = require("viem");
@@ -241,6 +300,12 @@ var EventStatus = /* @__PURE__ */ ((EventStatus2) => {
241
300
 
242
301
  // src/ATFiSDK.ts
243
302
  var ATFiSDK = class _ATFiSDK {
303
+ /**
304
+ * Create a new ATFi SDK instance
305
+ * @param publicClient - viem PublicClient (or wagmi's usePublicClient result)
306
+ * @param walletClient - viem WalletClient (or wagmi's useWalletClient result), optional for read-only
307
+ * @param config - Optional SDK configuration
308
+ */
244
309
  constructor(publicClient, walletClient, config) {
245
310
  this.publicClient = publicClient;
246
311
  this.walletClient = walletClient ? walletClient : null;
@@ -822,7 +887,9 @@ var ATFiSDK = class _ATFiSDK {
822
887
  stakeAmount: info.stakeAmount,
823
888
  maxParticipants: info.maxParticipants,
824
889
  currentParticipants: info.currentParticipants,
825
- status
890
+ status,
891
+ tokenSymbol: info.tokenSymbol,
892
+ tokenDecimals: info.tokenDecimals
826
893
  };
827
894
  });
828
895
  }
@@ -1388,6 +1455,150 @@ var ATFiSDK = class _ATFiSDK {
1388
1455
  return { txHash: hash, amountClaimed: fromTokenUnits(claimable, decimals) };
1389
1456
  }
1390
1457
  };
1458
+
1459
+ // src/utils/formatting.ts
1460
+ function shortenAddress(address, chars = 4) {
1461
+ if (!address) return "";
1462
+ const start = address.slice(0, chars + 2);
1463
+ const end = address.slice(-chars);
1464
+ return `${start}...${end}`;
1465
+ }
1466
+ function formatUSD(amount, decimals = 2) {
1467
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1468
+ if (isNaN(num)) return "$0.00";
1469
+ return new Intl.NumberFormat("en-US", {
1470
+ style: "currency",
1471
+ currency: "USD",
1472
+ minimumFractionDigits: decimals,
1473
+ maximumFractionDigits: decimals
1474
+ }).format(num);
1475
+ }
1476
+ function formatTokenAmount(amount, symbol, decimals = 2) {
1477
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1478
+ if (isNaN(num)) return `0 ${symbol}`;
1479
+ const formatted = new Intl.NumberFormat("en-US", {
1480
+ minimumFractionDigits: decimals,
1481
+ maximumFractionDigits: decimals
1482
+ }).format(num);
1483
+ return `${formatted} ${symbol}`;
1484
+ }
1485
+ function formatCompact(amount) {
1486
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1487
+ if (isNaN(num)) return "0";
1488
+ return new Intl.NumberFormat("en-US", {
1489
+ notation: "compact",
1490
+ maximumFractionDigits: 1
1491
+ }).format(num);
1492
+ }
1493
+ function formatPercent(value, decimals = 2) {
1494
+ return `${(value * 100).toFixed(decimals)}%`;
1495
+ }
1496
+
1497
+ // src/react/useATFiSDK.ts
1498
+ var import_react = require("react");
1499
+ function useATFiSDK(publicClient, walletClient, config) {
1500
+ const sdk = (0, import_react.useMemo)(() => {
1501
+ if (!publicClient) return null;
1502
+ if (walletClient) {
1503
+ return new ATFiSDK(publicClient, walletClient, config);
1504
+ }
1505
+ return ATFiSDK.readOnly(publicClient, config);
1506
+ }, [publicClient, walletClient, config]);
1507
+ return {
1508
+ sdk,
1509
+ isReadOnly: !walletClient
1510
+ };
1511
+ }
1512
+
1513
+ // src/react/useEventInfo.ts
1514
+ var import_react2 = require("react");
1515
+ function useEventInfo(sdk, vaultAddress) {
1516
+ const [data, setData] = (0, import_react2.useState)(null);
1517
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
1518
+ const [error, setError] = (0, import_react2.useState)(null);
1519
+ const fetchData = (0, import_react2.useCallback)(async () => {
1520
+ if (!sdk || !vaultAddress) {
1521
+ setData(null);
1522
+ return;
1523
+ }
1524
+ setIsLoading(true);
1525
+ setError(null);
1526
+ try {
1527
+ const info = await sdk.getEventInfo(vaultAddress);
1528
+ setData(info);
1529
+ } catch (err) {
1530
+ setError(err instanceof Error ? err : new Error("Failed to fetch event info"));
1531
+ setData(null);
1532
+ } finally {
1533
+ setIsLoading(false);
1534
+ }
1535
+ }, [sdk, vaultAddress]);
1536
+ (0, import_react2.useEffect)(() => {
1537
+ fetchData();
1538
+ }, [fetchData]);
1539
+ return {
1540
+ data,
1541
+ isLoading,
1542
+ error,
1543
+ refetch: fetchData
1544
+ };
1545
+ }
1546
+
1547
+ // src/react/useWatchVault.ts
1548
+ var import_react3 = require("react");
1549
+ function useWatchVault(sdk, vaultAddress) {
1550
+ const [state, setState] = (0, import_react3.useState)({
1551
+ participantCount: 0,
1552
+ verifiedCount: 0,
1553
+ isSettled: false,
1554
+ lastClaim: null
1555
+ });
1556
+ const [isWatching, setIsWatching] = (0, import_react3.useState)(false);
1557
+ const unwatchRef = (0, import_react3.useRef)(null);
1558
+ (0, import_react3.useEffect)(() => {
1559
+ if (!sdk || !vaultAddress) {
1560
+ setIsWatching(false);
1561
+ return;
1562
+ }
1563
+ if (unwatchRef.current) {
1564
+ unwatchRef.current();
1565
+ }
1566
+ try {
1567
+ unwatchRef.current = sdk.watchVault(vaultAddress, {
1568
+ onParticipantJoined: (_participant, totalParticipants) => {
1569
+ setState((prev) => ({ ...prev, participantCount: totalParticipants }));
1570
+ },
1571
+ onParticipantVerified: (_participant, totalVerified) => {
1572
+ setState((prev) => ({ ...prev, verifiedCount: totalVerified }));
1573
+ },
1574
+ onSettled: () => {
1575
+ setState((prev) => ({ ...prev, isSettled: true }));
1576
+ },
1577
+ onClaimed: (participant, amount) => {
1578
+ setState((prev) => ({ ...prev, lastClaim: { participant, amount } }));
1579
+ },
1580
+ onError: (error) => {
1581
+ console.error("[useWatchVault]", error);
1582
+ }
1583
+ });
1584
+ setIsWatching(true);
1585
+ } catch (err) {
1586
+ console.error("[useWatchVault] Failed to start watching:", err);
1587
+ setIsWatching(false);
1588
+ }
1589
+ return () => {
1590
+ if (unwatchRef.current) {
1591
+ unwatchRef.current();
1592
+ unwatchRef.current = null;
1593
+ }
1594
+ setIsWatching(false);
1595
+ };
1596
+ }, [sdk, vaultAddress]);
1597
+ return {
1598
+ ...state,
1599
+ isWatching
1600
+ };
1601
+ }
1391
1602
  // Annotate the CommonJS export names for ESM import in node:
1392
1603
  0 && (module.exports = {
1393
1604
  ATFiError,
@@ -1398,13 +1609,24 @@ var ATFiSDK = class _ATFiSDK {
1398
1609
  ERC20ABI,
1399
1610
  EventStatus,
1400
1611
  FactoryATFiABI,
1612
+ NETWORKS,
1401
1613
  ParticipantStatus,
1402
1614
  TOKENS,
1403
1615
  VaultATFiABI,
1404
1616
  formatAmount,
1617
+ formatCompact,
1618
+ formatPercent,
1619
+ formatTokenAmount,
1620
+ formatUSD,
1405
1621
  fromTokenUnits,
1622
+ getNetworkConfig,
1406
1623
  getTokenByAddress,
1407
1624
  getTokenBySymbol,
1625
+ isYieldSupported,
1408
1626
  parseContractError,
1409
- toTokenUnits
1627
+ shortenAddress,
1628
+ toTokenUnits,
1629
+ useATFiSDK,
1630
+ useEventInfo,
1631
+ useWatchVault
1410
1632
  });
package/dist/index.mjs CHANGED
@@ -55,30 +55,74 @@ var ERC20ABI = [
55
55
  ];
56
56
 
57
57
  // src/constants/addresses.ts
58
- var CHAIN_ID = 8453;
58
+ var NETWORKS = {
59
+ mainnet: {
60
+ chainId: 8453,
61
+ name: "Base",
62
+ factory: "0x0be05a5fa7116c1b33f2b0036eb0d9690db9075f",
63
+ morphoVault: "0x050cE30b927Da55177A4914EC73480238BAD56f0",
64
+ supportsYield: true,
65
+ tokens: {
66
+ USDC: {
67
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
68
+ decimals: 6,
69
+ symbol: "USDC",
70
+ supportsYield: true
71
+ },
72
+ IDRX: {
73
+ address: "0x18Bc5bcC660cf2B9cE3cd51a404aFe1a0cBD3C22",
74
+ decimals: 2,
75
+ symbol: "IDRX",
76
+ supportsYield: false
77
+ }
78
+ }
79
+ },
80
+ testnet: {
81
+ chainId: 84532,
82
+ // Base Sepolia
83
+ name: "Base Sepolia",
84
+ factory: "0xf1EA206029549A8c4e2EB960F7ac43A98E922A49",
85
+ morphoVault: null,
86
+ // No Morpho on testnet
87
+ supportsYield: false,
88
+ tokens: {
89
+ USDC: {
90
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
91
+ // Base Sepolia USDC
92
+ decimals: 6,
93
+ symbol: "USDC",
94
+ supportsYield: false
95
+ }
96
+ }
97
+ }
98
+ };
99
+ var CHAIN_ID = NETWORKS.mainnet.chainId;
59
100
  var CONTRACTS = {
60
- FACTORY: "0x0be05a5fa7116c1b33f2b0036eb0d9690db9075f",
61
- MORPHO_VAULT: "0x050cE30b927Da55177A4914EC73480238BAD56f0"
101
+ FACTORY: NETWORKS.mainnet.factory,
102
+ MORPHO_VAULT: NETWORKS.mainnet.morphoVault
62
103
  };
63
104
  var TOKENS = {
64
- USDC: {
65
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
66
- decimals: 6,
67
- symbol: "USDC",
68
- supportsYield: true
69
- },
70
- IDRX: {
71
- address: "0x18Bc5bcC660cf2B9cE3cd51a404aFe1a0cBD3C22",
72
- decimals: 2,
73
- symbol: "IDRX",
74
- supportsYield: false
75
- }
105
+ USDC: NETWORKS.mainnet.tokens.USDC,
106
+ IDRX: NETWORKS.mainnet.tokens.IDRX
76
107
  };
108
+ function getNetworkConfig(networkOrChainId) {
109
+ if (typeof networkOrChainId === "string") {
110
+ return NETWORKS[networkOrChainId] || null;
111
+ }
112
+ for (const config of Object.values(NETWORKS)) {
113
+ if (config.chainId === networkOrChainId) {
114
+ return config;
115
+ }
116
+ }
117
+ return null;
118
+ }
77
119
  var getTokenByAddress = (address) => {
78
120
  const normalizedAddress = address.toLowerCase();
79
- for (const [sym, token] of Object.entries(TOKENS)) {
80
- if (token.address.toLowerCase() === normalizedAddress) {
81
- return { ...token, symbol: sym };
121
+ for (const network of Object.values(NETWORKS)) {
122
+ for (const [sym, token] of Object.entries(network.tokens)) {
123
+ if (token.address.toLowerCase() === normalizedAddress) {
124
+ return { ...token, symbol: sym };
125
+ }
82
126
  }
83
127
  }
84
128
  return null;
@@ -86,6 +130,10 @@ var getTokenByAddress = (address) => {
86
130
  var getTokenBySymbol = (symbol) => {
87
131
  return TOKENS[symbol];
88
132
  };
133
+ function isYieldSupported(networkOrChainId) {
134
+ const config = getNetworkConfig(networkOrChainId);
135
+ return config?.supportsYield ?? false;
136
+ }
89
137
 
90
138
  // src/utils/decimals.ts
91
139
  import { parseUnits, formatUnits } from "viem";
@@ -201,6 +249,12 @@ var EventStatus = /* @__PURE__ */ ((EventStatus2) => {
201
249
 
202
250
  // src/ATFiSDK.ts
203
251
  var ATFiSDK = class _ATFiSDK {
252
+ /**
253
+ * Create a new ATFi SDK instance
254
+ * @param publicClient - viem PublicClient (or wagmi's usePublicClient result)
255
+ * @param walletClient - viem WalletClient (or wagmi's useWalletClient result), optional for read-only
256
+ * @param config - Optional SDK configuration
257
+ */
204
258
  constructor(publicClient, walletClient, config) {
205
259
  this.publicClient = publicClient;
206
260
  this.walletClient = walletClient ? walletClient : null;
@@ -782,7 +836,9 @@ var ATFiSDK = class _ATFiSDK {
782
836
  stakeAmount: info.stakeAmount,
783
837
  maxParticipants: info.maxParticipants,
784
838
  currentParticipants: info.currentParticipants,
785
- status
839
+ status,
840
+ tokenSymbol: info.tokenSymbol,
841
+ tokenDecimals: info.tokenDecimals
786
842
  };
787
843
  });
788
844
  }
@@ -1348,6 +1404,150 @@ var ATFiSDK = class _ATFiSDK {
1348
1404
  return { txHash: hash, amountClaimed: fromTokenUnits(claimable, decimals) };
1349
1405
  }
1350
1406
  };
1407
+
1408
+ // src/utils/formatting.ts
1409
+ function shortenAddress(address, chars = 4) {
1410
+ if (!address) return "";
1411
+ const start = address.slice(0, chars + 2);
1412
+ const end = address.slice(-chars);
1413
+ return `${start}...${end}`;
1414
+ }
1415
+ function formatUSD(amount, decimals = 2) {
1416
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1417
+ if (isNaN(num)) return "$0.00";
1418
+ return new Intl.NumberFormat("en-US", {
1419
+ style: "currency",
1420
+ currency: "USD",
1421
+ minimumFractionDigits: decimals,
1422
+ maximumFractionDigits: decimals
1423
+ }).format(num);
1424
+ }
1425
+ function formatTokenAmount(amount, symbol, decimals = 2) {
1426
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1427
+ if (isNaN(num)) return `0 ${symbol}`;
1428
+ const formatted = new Intl.NumberFormat("en-US", {
1429
+ minimumFractionDigits: decimals,
1430
+ maximumFractionDigits: decimals
1431
+ }).format(num);
1432
+ return `${formatted} ${symbol}`;
1433
+ }
1434
+ function formatCompact(amount) {
1435
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
1436
+ if (isNaN(num)) return "0";
1437
+ return new Intl.NumberFormat("en-US", {
1438
+ notation: "compact",
1439
+ maximumFractionDigits: 1
1440
+ }).format(num);
1441
+ }
1442
+ function formatPercent(value, decimals = 2) {
1443
+ return `${(value * 100).toFixed(decimals)}%`;
1444
+ }
1445
+
1446
+ // src/react/useATFiSDK.ts
1447
+ import { useMemo } from "react";
1448
+ function useATFiSDK(publicClient, walletClient, config) {
1449
+ const sdk = useMemo(() => {
1450
+ if (!publicClient) return null;
1451
+ if (walletClient) {
1452
+ return new ATFiSDK(publicClient, walletClient, config);
1453
+ }
1454
+ return ATFiSDK.readOnly(publicClient, config);
1455
+ }, [publicClient, walletClient, config]);
1456
+ return {
1457
+ sdk,
1458
+ isReadOnly: !walletClient
1459
+ };
1460
+ }
1461
+
1462
+ // src/react/useEventInfo.ts
1463
+ import { useState, useEffect, useCallback } from "react";
1464
+ function useEventInfo(sdk, vaultAddress) {
1465
+ const [data, setData] = useState(null);
1466
+ const [isLoading, setIsLoading] = useState(false);
1467
+ const [error, setError] = useState(null);
1468
+ const fetchData = useCallback(async () => {
1469
+ if (!sdk || !vaultAddress) {
1470
+ setData(null);
1471
+ return;
1472
+ }
1473
+ setIsLoading(true);
1474
+ setError(null);
1475
+ try {
1476
+ const info = await sdk.getEventInfo(vaultAddress);
1477
+ setData(info);
1478
+ } catch (err) {
1479
+ setError(err instanceof Error ? err : new Error("Failed to fetch event info"));
1480
+ setData(null);
1481
+ } finally {
1482
+ setIsLoading(false);
1483
+ }
1484
+ }, [sdk, vaultAddress]);
1485
+ useEffect(() => {
1486
+ fetchData();
1487
+ }, [fetchData]);
1488
+ return {
1489
+ data,
1490
+ isLoading,
1491
+ error,
1492
+ refetch: fetchData
1493
+ };
1494
+ }
1495
+
1496
+ // src/react/useWatchVault.ts
1497
+ import { useState as useState2, useEffect as useEffect2, useRef } from "react";
1498
+ function useWatchVault(sdk, vaultAddress) {
1499
+ const [state, setState] = useState2({
1500
+ participantCount: 0,
1501
+ verifiedCount: 0,
1502
+ isSettled: false,
1503
+ lastClaim: null
1504
+ });
1505
+ const [isWatching, setIsWatching] = useState2(false);
1506
+ const unwatchRef = useRef(null);
1507
+ useEffect2(() => {
1508
+ if (!sdk || !vaultAddress) {
1509
+ setIsWatching(false);
1510
+ return;
1511
+ }
1512
+ if (unwatchRef.current) {
1513
+ unwatchRef.current();
1514
+ }
1515
+ try {
1516
+ unwatchRef.current = sdk.watchVault(vaultAddress, {
1517
+ onParticipantJoined: (_participant, totalParticipants) => {
1518
+ setState((prev) => ({ ...prev, participantCount: totalParticipants }));
1519
+ },
1520
+ onParticipantVerified: (_participant, totalVerified) => {
1521
+ setState((prev) => ({ ...prev, verifiedCount: totalVerified }));
1522
+ },
1523
+ onSettled: () => {
1524
+ setState((prev) => ({ ...prev, isSettled: true }));
1525
+ },
1526
+ onClaimed: (participant, amount) => {
1527
+ setState((prev) => ({ ...prev, lastClaim: { participant, amount } }));
1528
+ },
1529
+ onError: (error) => {
1530
+ console.error("[useWatchVault]", error);
1531
+ }
1532
+ });
1533
+ setIsWatching(true);
1534
+ } catch (err) {
1535
+ console.error("[useWatchVault] Failed to start watching:", err);
1536
+ setIsWatching(false);
1537
+ }
1538
+ return () => {
1539
+ if (unwatchRef.current) {
1540
+ unwatchRef.current();
1541
+ unwatchRef.current = null;
1542
+ }
1543
+ setIsWatching(false);
1544
+ };
1545
+ }, [sdk, vaultAddress]);
1546
+ return {
1547
+ ...state,
1548
+ isWatching
1549
+ };
1550
+ }
1351
1551
  export {
1352
1552
  ATFiError,
1353
1553
  ATFiErrorCode,
@@ -1357,13 +1557,24 @@ export {
1357
1557
  ERC20ABI,
1358
1558
  EventStatus,
1359
1559
  FactoryATFiABI,
1560
+ NETWORKS,
1360
1561
  ParticipantStatus,
1361
1562
  TOKENS,
1362
1563
  VaultATFiABI,
1363
1564
  formatAmount,
1565
+ formatCompact,
1566
+ formatPercent,
1567
+ formatTokenAmount,
1568
+ formatUSD,
1364
1569
  fromTokenUnits,
1570
+ getNetworkConfig,
1365
1571
  getTokenByAddress,
1366
1572
  getTokenBySymbol,
1573
+ isYieldSupported,
1367
1574
  parseContractError,
1368
- toTokenUnits
1575
+ shortenAddress,
1576
+ toTokenUnits,
1577
+ useATFiSDK,
1578
+ useEventInfo,
1579
+ useWatchVault
1369
1580
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atfi",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "TypeScript SDK for ATFi commitment vaults on Base",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -18,8 +18,17 @@
18
18
  "dependencies": {
19
19
  "viem": "^2.21.0"
20
20
  },
21
+ "peerDependencies": {
22
+ "react": ">=17.0.0"
23
+ },
24
+ "peerDependenciesMeta": {
25
+ "react": {
26
+ "optional": true
27
+ }
28
+ },
21
29
  "devDependencies": {
22
30
  "@types/node": "^20.0.0",
31
+ "@types/react": "^18.0.0",
23
32
  "tsup": "^8.0.0",
24
33
  "typescript": "^5.0.0",
25
34
  "vitest": "^1.0.0"