@turtleclub/hooks 0.5.0-beta.2 → 0.5.0-beta.4

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@turtleclub/hooks",
3
3
  "type": "module",
4
- "version": "0.5.0-beta.2",
4
+ "version": "0.5.0-beta.4",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {
@@ -54,5 +54,5 @@
54
54
  "publishConfig": {
55
55
  "access": "public"
56
56
  },
57
- "gitHead": "09d5d186b6253d8315b6e69aae3921d6850cddb2"
57
+ "gitHead": "eb8863ed74fbff69137de45e4670779a4a4f11e6"
58
58
  }
@@ -11,12 +11,12 @@ import {
11
11
  uploadIncentiveIconResponseSchema,
12
12
  } from "./schema";
13
13
 
14
- // GET /admin/incentives
14
+ // GET /turtle/incentives
15
15
  export async function getIncentives(): Promise<IncentivesResponse> {
16
16
  const params = new URLSearchParams();
17
17
 
18
18
  const queryString = params.toString();
19
- const endpoint = `/admin/incentives${queryString ? `?${queryString}` : ""}`;
19
+ const endpoint = `/turtle/incentives${queryString ? `?${queryString}` : ""}`;
20
20
 
21
21
  const data = await apiClient.fetch(endpoint, {
22
22
  method: "GET",
package/src/v2/index.ts CHANGED
@@ -9,6 +9,7 @@ import { ensoBalancesQueries } from "./enso-balances/queries";
9
9
  import { widgetQueries } from "./widget/queries";
10
10
  import { supportedChainsQueries } from "./supported-chains/queries";
11
11
  import { supportedTokensQueries } from "./supported-tokens/queries";
12
+ import { usersQueries } from "./users/queries";
12
13
 
13
14
  // Merged query keys for cache invalidation
14
15
  export const queries = mergeQueryKeys(
@@ -21,7 +22,8 @@ export const queries = mergeQueryKeys(
21
22
  ensoBalancesQueries,
22
23
  widgetQueries,
23
24
  supportedChainsQueries,
24
- supportedTokensQueries
25
+ supportedTokensQueries,
26
+ usersQueries
25
27
  );
26
28
 
27
29
  // Features - Earn API
@@ -40,12 +42,13 @@ export * from "./supported-chains";
40
42
  export * from "./supported-tokens";
41
43
  export * from "./geocheck";
42
44
  export * from "./swap";
45
+ export * from "./users";
43
46
 
44
47
  // Shared schemas
45
48
  export * from "./schemas/shared";
46
49
 
47
50
  // Provider & Client
48
- export { TurtleProvider } from "./lib/turtle-provider";
49
- export type { TurtleProviderProps } from "./lib/turtle-provider";
51
+ export { TurtleHooksProvider } from "./lib/turtle-provider";
52
+ export type { TurtleHooksProviderProps } from "./lib/turtle-provider";
50
53
  export { apiClient, ApiError } from "./lib/api-client";
51
54
  export type { ApiClientConfig, ApiClientOptions, ApiDomain } from "./lib/api-client";
@@ -3,7 +3,7 @@
3
3
  import React, { useEffect, useMemo } from "react";
4
4
  import { apiClient, type ApiClientConfig } from "./api-client";
5
5
 
6
- export interface TurtleProviderProps extends ApiClientConfig {
6
+ export interface TurtleHooksProviderProps extends ApiClientConfig {
7
7
  children: React.ReactNode;
8
8
  }
9
9
 
@@ -28,13 +28,13 @@ export interface TurtleProviderProps extends ApiClientConfig {
28
28
  * }
29
29
  * ```
30
30
  */
31
- export function TurtleProvider({
31
+ export function TurtleHooksProvider({
32
32
  children,
33
33
  apiUrl,
34
34
  earnUrl,
35
35
  getToken,
36
36
  debug,
37
- }: TurtleProviderProps) {
37
+ }: TurtleHooksProviderProps) {
38
38
  const config = useMemo(
39
39
  () => ({ apiUrl, earnUrl, getToken, debug }),
40
40
  [apiUrl, earnUrl, getToken, debug]
@@ -16,16 +16,14 @@ import {
16
16
  UploadProductLogoResponseSchema,
17
17
  } from "./schema";
18
18
 
19
- // GET /admin/products
20
- export async function getProducts(
21
- filters?: ProductFilters
22
- ): Promise<ProductsResponse> {
19
+ // GET /turtle/products
20
+ export async function getProducts(filters?: ProductFilters): Promise<ProductsResponse> {
23
21
  const params = new URLSearchParams();
24
22
 
25
23
  if (filters?.organizationId) params.append("organizationId", filters.organizationId);
26
24
 
27
25
  const queryString = params.toString();
28
- const endpoint = `/admin/products${queryString ? `?${queryString}` : ""}`;
26
+ const endpoint = `/turtle/products${queryString ? `?${queryString}` : ""}`;
29
27
 
30
28
  const data = await apiClient.fetch(endpoint, {
31
29
  method: "GET",
@@ -41,9 +39,9 @@ export async function getProducts(
41
39
  return result.data;
42
40
  }
43
41
 
44
- // GET /admin/products/:id
42
+ // GET /turtle/products/:id
45
43
  export async function getProduct(id: string): Promise<ProductResponse> {
46
- const endpoint = `/admin/products/${id}`;
44
+ const endpoint = `/turtle/products/${id}`;
47
45
 
48
46
  const data = await apiClient.fetch(endpoint, {
49
47
  method: "GET",
@@ -60,9 +58,7 @@ export async function getProduct(id: string): Promise<ProductResponse> {
60
58
  }
61
59
 
62
60
  // POST /admin/products
63
- export async function createProduct(
64
- input: CreateProductInput
65
- ): Promise<CreateProductResponse> {
61
+ export async function createProduct(input: CreateProductInput): Promise<CreateProductResponse> {
66
62
  const endpoint = `/admin/products`;
67
63
 
68
64
  const data = await apiClient.fetch(endpoint, {
@@ -81,9 +77,7 @@ export async function createProduct(
81
77
  }
82
78
 
83
79
  // PUT /admin/products/:id
84
- export async function updateProduct(
85
- input: UpdateProductInput
86
- ): Promise<UpdateProductResponse> {
80
+ export async function updateProduct(input: UpdateProductInput): Promise<UpdateProductResponse> {
87
81
  const endpoint = `/admin/products/${input.product.id}`;
88
82
 
89
83
  const data = await apiClient.fetch(endpoint, {
@@ -0,0 +1,48 @@
1
+ import { apiClient } from "../lib/api-client";
2
+ import {
3
+ GetUserByIdInput,
4
+ GetUserByIdOutput,
5
+ getUserByIdOutputSchema,
6
+ GetUserTurtlePortfolioInput,
7
+ GetUserTurtlePortfolioOutput,
8
+ getUserTurtlePortfolioOutputSchema,
9
+ } from "./schemas";
10
+
11
+ // GET /admin/users/:userId
12
+ export async function getUserById(input: GetUserByIdInput): Promise<GetUserByIdOutput> {
13
+ console.log("input", input);
14
+ const endpoint = `/admin/users/${input.userId}`;
15
+
16
+ const data = await apiClient.fetch(endpoint, {
17
+ method: "GET",
18
+ });
19
+
20
+ // Validate response with Zod
21
+ const result = getUserByIdOutputSchema.safeParse(data);
22
+
23
+ if (result.success === false) {
24
+ console.log("[ZOD ERROR]", result.error);
25
+ throw new Error(`Failed to parse user: ${result.error.message}`);
26
+ }
27
+ return result.data;
28
+ }
29
+
30
+ // GET /admin/users/:userId/portfolio
31
+ export async function getUserPortfolio(
32
+ input: GetUserTurtlePortfolioInput
33
+ ): Promise<GetUserTurtlePortfolioOutput> {
34
+ const endpoint = `/admin/users/${input.userId}/portfolio`;
35
+
36
+ const data = await apiClient.fetch(endpoint, {
37
+ method: "GET",
38
+ });
39
+
40
+ // Validate response with Zod
41
+ const result = getUserTurtlePortfolioOutputSchema.safeParse(data);
42
+
43
+ if (result.success === false) {
44
+ console.log("[ZOD ERROR]", result.error);
45
+ throw new Error(`Failed to parse user portfolio: ${result.error.message}`);
46
+ }
47
+ return result.data;
48
+ }
@@ -0,0 +1,32 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { queryDefaults } from "../lib/query-config";
3
+ import type { GetUserByIdInput, GetUserTurtlePortfolioInput } from "./schemas";
4
+ import { usersQueries } from "./queries";
5
+
6
+ export interface UseUserByIdOptions {
7
+ userId: string;
8
+ enabled?: boolean;
9
+ }
10
+
11
+ export function useUserById({ userId, enabled = true }: UseUserByIdOptions) {
12
+ return useQuery({
13
+ ...usersQueries.byId({ userId }),
14
+ ...queryDefaults,
15
+ enabled,
16
+ });
17
+ }
18
+
19
+ export interface UseUserPortfolioOptions {
20
+ userId: string;
21
+ enabled?: boolean;
22
+ }
23
+
24
+ export function useUserPortfolio({ userId, enabled = true }: UseUserPortfolioOptions) {
25
+ const input: GetUserTurtlePortfolioInput = { userId };
26
+
27
+ return useQuery({
28
+ ...usersQueries.portfolio(input),
29
+ ...queryDefaults,
30
+ enabled,
31
+ });
32
+ }
@@ -0,0 +1,13 @@
1
+ // Hooks
2
+ export { useUserById, useUserPortfolio } from "./hooks";
3
+
4
+ export type { UseUserByIdOptions, UseUserPortfolioOptions } from "./hooks";
5
+
6
+ // Query keys
7
+ export { usersQueries } from "./queries";
8
+
9
+ // API functions
10
+ export { getUserById, getUserPortfolio } from "./api";
11
+
12
+ // Schemas and types
13
+ export * from "./schemas";
@@ -0,0 +1,14 @@
1
+ import { createQueryKeys } from "@lukemorales/query-key-factory";
2
+ import { getUserById, getUserPortfolio } from "./api";
3
+ import type { GetUserByIdInput, GetUserTurtlePortfolioInput } from "./schemas";
4
+
5
+ export const usersQueries = createQueryKeys("users", {
6
+ byId: (input: GetUserByIdInput) => ({
7
+ queryKey: [input.userId],
8
+ queryFn: () => getUserById(input),
9
+ }),
10
+ portfolio: (input: GetUserTurtlePortfolioInput) => ({
11
+ queryKey: ["portfolio", input.userId],
12
+ queryFn: () => getUserPortfolio(input),
13
+ }),
14
+ });
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { chainSchema, tokenSchema } from "../schemas/shared";
3
+
4
+ // Wallet Data Schema
5
+ const walletDataSchema = z.object({
6
+ address: z.string(),
7
+ totalAmountInUSD: z.string(),
8
+ tokens: z.array(tokenSchema),
9
+ });
10
+
11
+ // Holdings Data Schema
12
+ const holdingsDataSchema = z.object({
13
+ totalAmountInUSD: z.string(),
14
+ chains: z.array(chainSchema).nullish(),
15
+ wallets: z.array(walletDataSchema).nullish(),
16
+ });
17
+
18
+ // User Earnings Schema
19
+ const userEarningsSchema = z.object({
20
+ productId: z.string().uuid(),
21
+ value: z.number(),
22
+ referralsEarnings: z.number().nullish(),
23
+ rewardName: z.string().nullish(),
24
+ rewardType: z.string().nullish(),
25
+ });
26
+
27
+ // Portfolio Schema
28
+ const portfolioSchema = z.object({
29
+ productsEarnings: z.array(userEarningsSchema),
30
+ holdings: holdingsDataSchema.nullish(),
31
+ });
32
+
33
+ // Holding Info Schema
34
+ const holdingInfoSchema = z.object({
35
+ amount: z.number(),
36
+ usdValue: z.number(),
37
+ token: tokenSchema.nullish(),
38
+ });
39
+
40
+ // Wallet Info Schema
41
+ const walletInfoSchema = z.object({
42
+ address: z.string().nullish(),
43
+ ecosystem: z.string().nullish(),
44
+ isMain: z.boolean().nullish(),
45
+ holdings: z.array(holdingInfoSchema).nullish(),
46
+ });
47
+
48
+ // User With Details Schema
49
+ const userWithDetailsSchema = z.object({
50
+ id: z.string(),
51
+ email: z.string().nullable(),
52
+ username: z.string().nullish(),
53
+ firstName: z.string().nullish(),
54
+ lastName: z.string().nullish(),
55
+ avatarUrl: z.string().nullish(),
56
+ telegramHandle: z.string().nullish(),
57
+ xUsername: z.string().nullish(),
58
+ role: z.string(),
59
+ createdAt: z.string(),
60
+ updatedAt: z.string(),
61
+ tags: z.array(z.string()).nullish(),
62
+ wallets: z.array(walletInfoSchema).nullish(),
63
+ });
64
+
65
+ // GetUserTurtlePortfolioHandler Input Schema
66
+ export const getUserTurtlePortfolioInputSchema = z.object({
67
+ userId: z.string().uuid(),
68
+ });
69
+
70
+ // GetUserTurtlePortfolioHandler Output Schema
71
+ export const getUserTurtlePortfolioOutputSchema = z.object({
72
+ portfolio: portfolioSchema,
73
+ });
74
+
75
+ // Path Parameters Schema (for URL params)
76
+ export const getUserTurtlePortfolioPathSchema = z.object({
77
+ userId: z.string().uuid(),
78
+ });
79
+
80
+ // GetUserByIDHandler Input Schema
81
+ export const getUserByIdInputSchema = z.object({
82
+ userId: z.string().uuid(),
83
+ });
84
+
85
+ // GetUserByIDHandler Output Schema
86
+ export const getUserByIdOutputSchema = z.object({
87
+ user: userWithDetailsSchema.nullable(),
88
+ error: z.string().optional(),
89
+ });
90
+
91
+ // Type exports
92
+ export type GetUserByIdInput = z.infer<typeof getUserByIdInputSchema>;
93
+ export type GetUserByIdOutput = z.infer<typeof getUserByIdOutputSchema>;
94
+ export type GetUserTurtlePortfolioInput = z.infer<typeof getUserTurtlePortfolioInputSchema>;
95
+ export type GetUserTurtlePortfolioOutput = z.infer<typeof getUserTurtlePortfolioOutputSchema>;
96
+ export type UserWithDetails = z.infer<typeof userWithDetailsSchema>;
97
+ export type WalletData = z.infer<typeof walletDataSchema>;
98
+ export type HoldingsData = z.infer<typeof holdingsDataSchema>;
99
+ export type Portfolio = z.infer<typeof portfolioSchema>;
100
+ export type UserEarnings = z.infer<typeof userEarningsSchema>;
101
+
102
+ // Export individual schemas if needed
103
+ export {
104
+ walletDataSchema,
105
+ holdingsDataSchema,
106
+ userEarningsSchema,
107
+ portfolioSchema,
108
+ userWithDetailsSchema,
109
+ };