@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/dist/index.cjs +187 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +169 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/v2/incentives/api.ts +2 -2
- package/src/v2/index.ts +6 -3
- package/src/v2/lib/turtle-provider.tsx +3 -3
- package/src/v2/products/api.ts +7 -13
- package/src/v2/users/api.ts +48 -0
- package/src/v2/users/hooks.ts +32 -0
- package/src/v2/users/index.ts +13 -0
- package/src/v2/users/queries.ts +14 -0
- package/src/v2/users/schemas.ts +109 -0
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.
|
|
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": "
|
|
57
|
+
"gitHead": "eb8863ed74fbff69137de45e4670779a4a4f11e6"
|
|
58
58
|
}
|
package/src/v2/incentives/api.ts
CHANGED
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
uploadIncentiveIconResponseSchema,
|
|
12
12
|
} from "./schema";
|
|
13
13
|
|
|
14
|
-
// GET /
|
|
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 = `/
|
|
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 {
|
|
49
|
-
export type {
|
|
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
|
|
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
|
|
31
|
+
export function TurtleHooksProvider({
|
|
32
32
|
children,
|
|
33
33
|
apiUrl,
|
|
34
34
|
earnUrl,
|
|
35
35
|
getToken,
|
|
36
36
|
debug,
|
|
37
|
-
}:
|
|
37
|
+
}: TurtleHooksProviderProps) {
|
|
38
38
|
const config = useMemo(
|
|
39
39
|
() => ({ apiUrl, earnUrl, getToken, debug }),
|
|
40
40
|
[apiUrl, earnUrl, getToken, debug]
|
package/src/v2/products/api.ts
CHANGED
|
@@ -16,16 +16,14 @@ import {
|
|
|
16
16
|
UploadProductLogoResponseSchema,
|
|
17
17
|
} from "./schema";
|
|
18
18
|
|
|
19
|
-
// GET /
|
|
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 = `/
|
|
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 /
|
|
42
|
+
// GET /turtle/products/:id
|
|
45
43
|
export async function getProduct(id: string): Promise<ProductResponse> {
|
|
46
|
-
const endpoint = `/
|
|
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
|
+
};
|