@frak-labs/react-sdk 0.2.1 → 1.0.0-beta.7f085fb7
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 +1 -1
- package/dist/index.d.cts +163 -25
- package/dist/index.d.ts +163 -25
- package/dist/index.js +1 -1
- package/package.json +13 -14
- package/src/hook/helper/useReferralInteraction.test.ts +22 -191
- package/src/hook/helper/useReferralInteraction.ts +9 -27
- package/src/hook/index.ts +4 -0
- package/src/hook/useDisplayModal.ts +6 -4
- package/src/hook/useDisplaySharingPage.ts +64 -0
- package/src/hook/useGetMerchantInformation.ts +6 -1
- package/src/hook/useGetMergeToken.ts +59 -0
- package/src/hook/useGetUserReferralStatus.ts +63 -0
- package/src/hook/useSetupReferral.ts +35 -0
- package/src/index.ts +4 -0
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{displayModal as e,
|
|
1
|
+
import{displayModal as e,displaySharingPage as t,getMerchantInformation as n,getMergeToken as r,getUserReferralStatus as i,openSso as a,prepareSso as o,referralInteraction as s,sendTransaction as c,setupReferral as l,siweAuthenticate as u,watchWalletStatus as d}from"@frak-labs/core-sdk/actions";import{ClientNotFound as f,FrakRpcError as p,RpcErrorCodes as m}from"@frak-labs/frame-connector";import{useMutation as h,useQuery as g,useQueryClient as _}from"@tanstack/react-query";import{Fragment as v,createContext as y,createElement as b,useCallback as x,useContext as S,useMemo as C,useState as w}from"react";import{baseIframeProps as T,createIFrameFrakClient as E}from"@frak-labs/core-sdk";const D=y(void 0);function O(e){let{children:t,config:n}=e;return b(D.Provider,{value:{...n,walletUrl:n.walletUrl??`https://wallet.frak.id`,domain:n.domain??(typeof window<`u`?window?.location?.host:void 0)??`not-found`}},t)}const k=y(void 0);function A({style:e,children:t}){let n=F(),[r,i]=w(void 0);return b(v,null,b(`iframe`,{...T,src:`${n.walletUrl}/listener`,style:e??T.style,ref:e=>{!e||r||i(E({iframe:e,config:n}))}}),b(k.Provider,{value:r},t))}function j(){return S(k)}function M({options:e}={}){let t=j(),{data:n,error:r,status:i}=g({queryKey:[`frak-sdk`,`auto-referral-interaction`],queryFn:async()=>{if(!t)throw new f;return s(t,{options:e})},enabled:!!t,staleTime:1/0});return C(()=>i===`pending`?`processing`:i===`error`?r:n||`idle`,[n,i,r])}function N({mutations:t}={}){let n=j();return h({...t,mutationKey:[`frak-sdk`,`display-modal`],mutationFn:async({placement:t,...r})=>{if(!n)throw new f;return e(n,r,t)}})}function P({mutations:e}={}){let n=j();return h({...e,mutationKey:[`frak-sdk`,`display-sharing-page`],mutationFn:async({placement:e,...r})=>{if(!n)throw new f;return t(n,r,e)}})}function F(){let e=S(D);if(!e)throw new p(m.configError,`Frak config not found`);return e}function I({query:e,cacheTime:t}={}){let r=j();return g({...e,queryKey:[`frak-sdk`,`get-merchant-information`],queryFn:async()=>{if(!r)throw new f;return n(r,{cacheTime:t})}})}function L({query:e,cacheTime:t}={}){let n=j();return g({...e,queryKey:[`frak-sdk`,`get-merge-token`],queryFn:async()=>{if(!n)throw new f;return r(n,{cacheTime:t})}})}function R({query:e,cacheTime:t}={}){let n=j();return g({...e,queryKey:[`frak-sdk`,`get-user-referral-status`],queryFn:async()=>{if(!n)throw new f;return i(n,{cacheTime:t})}})}function z({mutations:e}={}){let t=j();return h({...e,mutationKey:[`frak-sdk`,`open-sso`],mutationFn:async e=>{if(!t)throw new f;return a(t,e)}})}function B(e){let t=j();return g({queryKey:[`frak-sdk`,`prepare-sso`,e],queryFn:async()=>{if(!t)throw new f;return o(t,e)}})}function V({mutations:e}={}){let t=j();return h({...e,mutationKey:[`frak-sdk`,`send-transaction`],mutationFn:async e=>{if(!t)throw new f;return c(t,e)}})}function H(){let e=j();return g({queryKey:[`frak-sdk`,`setup-referral`],queryFn:async()=>{if(!e)throw new f;return await l(e),null},enabled:!!e,staleTime:1/0})}function U({mutations:e}={}){let t=j();return h({...e,mutationKey:[`frak-sdk`,`siwe-authenticate`,t?.config.domain??`no-domain`],mutationFn:async e=>{if(!t)throw new f;return u(t,e)}})}function W(){let e=_(),t=j(),n=x(t=>{e.setQueryData([`frak-sdk`,`wallet-status-listener`],t)},[e]);return g({gcTime:0,staleTime:0,queryKey:[`frak-sdk`,`wallet-status-listener`],queryFn:async()=>{if(!t)throw new f;return d(t,n)},enabled:!!t})}export{D as FrakConfigContext,O as FrakConfigProvider,k as FrakIFrameClientContext,A as FrakIFrameClientProvider,N as useDisplayModal,P as useDisplaySharingPage,j as useFrakClient,F as useFrakConfig,I as useGetMerchantInformation,L as useGetMergeToken,R as useGetUserReferralStatus,z as useOpenSso,B as usePrepareSso,M as useReferralInteraction,V as useSendTransactionAction,H as useSetupReferral,U as useSiweAuthenticate,W as useWalletStatus};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://twitter.com/QNivelais"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "1.0.0-beta.7f085fb7",
|
|
15
15
|
"description": "React SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.",
|
|
16
16
|
"repository": {
|
|
17
17
|
"url": "https://github.com/frak-id/wallet",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"publish": "echo 'Publishing react...'"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@frak-labs/
|
|
71
|
-
"@frak-labs/
|
|
70
|
+
"@frak-labs/core-sdk": "1.0.0-beta.7f085fb7",
|
|
71
|
+
"@frak-labs/frame-connector": "0.2.0-beta.7f085fb7"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"viem": "^2.x",
|
|
@@ -77,24 +77,23 @@
|
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
80
|
-
"@frak-labs/dev-tooling": "0.0.0",
|
|
81
80
|
"@frak-labs/test-foundation": "0.1.0",
|
|
82
|
-
"@frak-labs/wallet-shared": "0.0.
|
|
81
|
+
"@frak-labs/wallet-shared": "0.0.4",
|
|
83
82
|
"@tanstack/react-query": "^5.90.20",
|
|
84
83
|
"@testing-library/jest-dom": "^6.9.1",
|
|
85
84
|
"@testing-library/react": "^16.3.2",
|
|
86
85
|
"@testing-library/react-hooks": "^8.0.1",
|
|
87
86
|
"@testing-library/user-event": "^14.6.1",
|
|
88
|
-
"@types/jsdom": "^
|
|
89
|
-
"@types/node": "^
|
|
87
|
+
"@types/jsdom": "^28.0.0",
|
|
88
|
+
"@types/node": "^25.6.0",
|
|
90
89
|
"@types/react": "19.2.13",
|
|
91
|
-
"@vitest/coverage-v8": "^4.0
|
|
92
|
-
"@vitest/ui": "^4.0
|
|
93
|
-
"jsdom": "^
|
|
90
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
91
|
+
"@vitest/ui": "^4.1.0",
|
|
92
|
+
"jsdom": "^29.0.0",
|
|
94
93
|
"react": "^19.2.4",
|
|
95
|
-
"tsdown": "^0.
|
|
96
|
-
"typescript": "^
|
|
97
|
-
"viem": "^2.
|
|
98
|
-
"vitest": "^4.
|
|
94
|
+
"tsdown": "^0.21.8",
|
|
95
|
+
"typescript": "^6.0.2",
|
|
96
|
+
"viem": "^2.47.16",
|
|
97
|
+
"vitest": "^4.1.4"
|
|
99
98
|
}
|
|
100
99
|
}
|
|
@@ -7,40 +7,24 @@ import { vi } from "vitest";
|
|
|
7
7
|
|
|
8
8
|
vi.mock("@frak-labs/core-sdk/actions");
|
|
9
9
|
vi.mock("../useFrakClient");
|
|
10
|
-
vi.mock("../useWalletStatus");
|
|
11
|
-
vi.mock("../utils/useFrakContext");
|
|
12
10
|
|
|
13
|
-
import
|
|
14
|
-
import { processReferral } from "@frak-labs/core-sdk/actions";
|
|
15
|
-
import { ClientNotFound } from "@frak-labs/frame-connector";
|
|
11
|
+
import { referralInteraction } from "@frak-labs/core-sdk/actions";
|
|
16
12
|
import { renderHook, waitFor } from "@testing-library/react";
|
|
17
13
|
import { describe, expect, test } from "../../../tests/vitest-fixtures";
|
|
18
14
|
import { useFrakClient } from "../useFrakClient";
|
|
19
|
-
import { useWalletStatus } from "../useWalletStatus";
|
|
20
|
-
import { useFrakContext } from "../utils/useFrakContext";
|
|
21
15
|
import { useReferralInteraction } from "./useReferralInteraction";
|
|
22
16
|
|
|
23
17
|
describe("useReferralInteraction", () => {
|
|
24
|
-
test("should return processing when
|
|
18
|
+
test("should return processing when client is not available", ({
|
|
25
19
|
queryWrapper,
|
|
26
|
-
mockFrakClient,
|
|
27
20
|
}) => {
|
|
28
|
-
vi.mocked(useFrakClient).mockReturnValue(
|
|
29
|
-
vi.mocked(useFrakContext).mockReturnValue({
|
|
30
|
-
frakContext: null,
|
|
31
|
-
updateContext: vi.fn(),
|
|
32
|
-
});
|
|
33
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
34
|
-
data: undefined,
|
|
35
|
-
isSuccess: false,
|
|
36
|
-
isPending: true,
|
|
37
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
21
|
+
vi.mocked(useFrakClient).mockReturnValue(undefined);
|
|
38
22
|
|
|
39
23
|
const { result } = renderHook(() => useReferralInteraction(), {
|
|
40
24
|
wrapper: queryWrapper.wrapper,
|
|
41
25
|
});
|
|
42
26
|
|
|
43
|
-
// Query is disabled when
|
|
27
|
+
// Query is disabled when client is not available, status remains pending
|
|
44
28
|
expect(result.current).toBe("processing");
|
|
45
29
|
});
|
|
46
30
|
|
|
@@ -48,40 +32,18 @@ describe("useReferralInteraction", () => {
|
|
|
48
32
|
queryWrapper,
|
|
49
33
|
mockFrakClient,
|
|
50
34
|
}) => {
|
|
51
|
-
const mockReferralState = "success";
|
|
52
|
-
|
|
53
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
54
|
-
key: "connected",
|
|
55
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const mockFrakContext: FrakContext = {
|
|
59
|
-
r: "0x1234567890123456789012345678901234567890",
|
|
60
|
-
};
|
|
61
|
-
|
|
62
35
|
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
63
|
-
vi.mocked(
|
|
64
|
-
frakContext: mockFrakContext,
|
|
65
|
-
updateContext: vi.fn(),
|
|
66
|
-
});
|
|
67
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
68
|
-
data: mockWalletStatus,
|
|
69
|
-
isSuccess: true,
|
|
70
|
-
isPending: false,
|
|
71
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
72
|
-
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
36
|
+
vi.mocked(referralInteraction).mockResolvedValue("success");
|
|
73
37
|
|
|
74
38
|
const { result } = renderHook(() => useReferralInteraction(), {
|
|
75
39
|
wrapper: queryWrapper.wrapper,
|
|
76
40
|
});
|
|
77
41
|
|
|
78
42
|
await waitFor(() => {
|
|
79
|
-
expect(result.current).toEqual(
|
|
43
|
+
expect(result.current).toEqual("success");
|
|
80
44
|
});
|
|
81
45
|
|
|
82
|
-
expect(
|
|
83
|
-
walletStatus: mockWalletStatus,
|
|
84
|
-
frakContext: mockFrakContext,
|
|
46
|
+
expect(referralInteraction).toHaveBeenCalledWith(mockFrakClient, {
|
|
85
47
|
options: undefined,
|
|
86
48
|
});
|
|
87
49
|
});
|
|
@@ -90,28 +52,12 @@ describe("useReferralInteraction", () => {
|
|
|
90
52
|
queryWrapper,
|
|
91
53
|
mockFrakClient,
|
|
92
54
|
}) => {
|
|
93
|
-
const mockReferralState = "success";
|
|
94
|
-
|
|
95
55
|
const options = {
|
|
96
56
|
alwaysAppendUrl: true,
|
|
97
57
|
};
|
|
98
58
|
|
|
99
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
100
|
-
key: "connected",
|
|
101
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
102
|
-
};
|
|
103
|
-
|
|
104
59
|
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
105
|
-
vi.mocked(
|
|
106
|
-
frakContext: { r: "0x7890123456789012345678901234567890123456" },
|
|
107
|
-
updateContext: vi.fn(),
|
|
108
|
-
});
|
|
109
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
110
|
-
data: mockWalletStatus,
|
|
111
|
-
isSuccess: true,
|
|
112
|
-
isPending: false,
|
|
113
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
114
|
-
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
60
|
+
vi.mocked(referralInteraction).mockResolvedValue("success");
|
|
115
61
|
|
|
116
62
|
const { result } = renderHook(
|
|
117
63
|
() => useReferralInteraction({ options }),
|
|
@@ -121,39 +67,22 @@ describe("useReferralInteraction", () => {
|
|
|
121
67
|
);
|
|
122
68
|
|
|
123
69
|
await waitFor(() => {
|
|
124
|
-
expect(result.current).toEqual(
|
|
70
|
+
expect(result.current).toEqual("success");
|
|
125
71
|
});
|
|
126
72
|
|
|
127
|
-
expect(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
options,
|
|
131
|
-
})
|
|
132
|
-
);
|
|
73
|
+
expect(referralInteraction).toHaveBeenCalledWith(mockFrakClient, {
|
|
74
|
+
options,
|
|
75
|
+
});
|
|
133
76
|
});
|
|
134
77
|
|
|
135
78
|
test("should handle processing state", ({
|
|
136
79
|
queryWrapper,
|
|
137
80
|
mockFrakClient,
|
|
138
81
|
}) => {
|
|
139
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
140
|
-
key: "connected",
|
|
141
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
142
|
-
};
|
|
143
|
-
|
|
144
82
|
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
145
|
-
vi.mocked(useFrakContext).mockReturnValue({
|
|
146
|
-
frakContext: { r: "0x9999999999999999999999999999999999999999" },
|
|
147
|
-
updateContext: vi.fn(),
|
|
148
|
-
});
|
|
149
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
150
|
-
data: mockWalletStatus,
|
|
151
|
-
isSuccess: true,
|
|
152
|
-
isPending: false,
|
|
153
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
154
83
|
|
|
155
|
-
// Mock
|
|
156
|
-
vi.mocked(
|
|
84
|
+
// Mock referralInteraction to never resolve (simulate pending)
|
|
85
|
+
vi.mocked(referralInteraction).mockImplementation(
|
|
157
86
|
() => new Promise(() => {})
|
|
158
87
|
);
|
|
159
88
|
|
|
@@ -167,22 +96,8 @@ describe("useReferralInteraction", () => {
|
|
|
167
96
|
test("should handle errors", async ({ queryWrapper, mockFrakClient }) => {
|
|
168
97
|
const error = new Error("Referral processing failed");
|
|
169
98
|
|
|
170
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
171
|
-
key: "connected",
|
|
172
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
173
|
-
};
|
|
174
|
-
|
|
175
99
|
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
176
|
-
vi.mocked(
|
|
177
|
-
frakContext: { r: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" },
|
|
178
|
-
updateContext: vi.fn(),
|
|
179
|
-
});
|
|
180
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
181
|
-
data: mockWalletStatus,
|
|
182
|
-
isSuccess: true,
|
|
183
|
-
isPending: false,
|
|
184
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
185
|
-
vi.mocked(processReferral).mockRejectedValue(error);
|
|
100
|
+
vi.mocked(referralInteraction).mockRejectedValue(error);
|
|
186
101
|
|
|
187
102
|
const { result } = renderHook(() => useReferralInteraction(), {
|
|
188
103
|
wrapper: queryWrapper.wrapper,
|
|
@@ -193,117 +108,33 @@ describe("useReferralInteraction", () => {
|
|
|
193
108
|
});
|
|
194
109
|
});
|
|
195
110
|
|
|
196
|
-
test("should throw ClientNotFound when client is not available", async ({
|
|
111
|
+
test("should throw ClientNotFound when client is not available but enabled", async ({
|
|
197
112
|
queryWrapper,
|
|
198
113
|
}) => {
|
|
199
|
-
|
|
200
|
-
key: "connected",
|
|
201
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
202
|
-
};
|
|
203
|
-
|
|
114
|
+
// Force the query to run despite no client (edge case)
|
|
204
115
|
vi.mocked(useFrakClient).mockReturnValue(undefined);
|
|
205
|
-
vi.mocked(useFrakContext).mockReturnValue({
|
|
206
|
-
frakContext: { r: "0xcccccccccccccccccccccccccccccccccccccccc" },
|
|
207
|
-
updateContext: vi.fn(),
|
|
208
|
-
});
|
|
209
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
210
|
-
data: mockWalletStatus,
|
|
211
|
-
isSuccess: true,
|
|
212
|
-
isPending: false,
|
|
213
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
214
116
|
|
|
215
117
|
const { result } = renderHook(() => useReferralInteraction(), {
|
|
216
118
|
wrapper: queryWrapper.wrapper,
|
|
217
119
|
});
|
|
218
120
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test("should update query key when referrer changes", async ({
|
|
225
|
-
queryWrapper,
|
|
226
|
-
mockFrakClient,
|
|
227
|
-
}) => {
|
|
228
|
-
const mockReferralState = "success";
|
|
229
|
-
|
|
230
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
231
|
-
key: "connected",
|
|
232
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
236
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
237
|
-
data: mockWalletStatus,
|
|
238
|
-
isSuccess: true,
|
|
239
|
-
isPending: false,
|
|
240
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
241
|
-
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
242
|
-
|
|
243
|
-
// Start with one referrer
|
|
244
|
-
vi.mocked(useFrakContext).mockReturnValue({
|
|
245
|
-
frakContext: { r: "0x1111111111111111111111111111111111111111" },
|
|
246
|
-
updateContext: vi.fn(),
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
const { rerender } = renderHook(() => useReferralInteraction(), {
|
|
250
|
-
wrapper: queryWrapper.wrapper,
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
await waitFor(() => {
|
|
254
|
-
expect(processReferral).toHaveBeenCalledTimes(1);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Change referrer
|
|
258
|
-
vi.mocked(useFrakContext).mockReturnValue({
|
|
259
|
-
frakContext: { r: "0x2222222222222222222222222222222222222222" },
|
|
260
|
-
updateContext: vi.fn(),
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
rerender();
|
|
264
|
-
|
|
265
|
-
// Query should re-run with new referrer
|
|
266
|
-
await waitFor(() => {
|
|
267
|
-
expect(processReferral).toHaveBeenCalledTimes(2);
|
|
268
|
-
});
|
|
121
|
+
// Query is disabled when client is null, so it stays pending
|
|
122
|
+
expect(result.current).toBe("processing");
|
|
269
123
|
});
|
|
270
124
|
|
|
271
|
-
test("should
|
|
125
|
+
test("should return idle for no-referrer state", async ({
|
|
272
126
|
queryWrapper,
|
|
273
127
|
mockFrakClient,
|
|
274
128
|
}) => {
|
|
275
|
-
const mockReferralState = "success";
|
|
276
|
-
|
|
277
|
-
const mockWalletStatus: WalletStatusReturnType = {
|
|
278
|
-
key: "connected",
|
|
279
|
-
wallet: "0x1234567890123456789012345678901234567890",
|
|
280
|
-
};
|
|
281
|
-
|
|
282
129
|
vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
|
|
283
|
-
vi.mocked(
|
|
284
|
-
frakContext: null, // No referrer
|
|
285
|
-
updateContext: vi.fn(),
|
|
286
|
-
});
|
|
287
|
-
vi.mocked(useWalletStatus).mockReturnValue({
|
|
288
|
-
data: mockWalletStatus,
|
|
289
|
-
isSuccess: true,
|
|
290
|
-
isPending: false,
|
|
291
|
-
} as ReturnType<typeof useWalletStatus>);
|
|
292
|
-
vi.mocked(processReferral).mockResolvedValue(mockReferralState);
|
|
130
|
+
vi.mocked(referralInteraction).mockResolvedValue(undefined);
|
|
293
131
|
|
|
294
132
|
const { result } = renderHook(() => useReferralInteraction(), {
|
|
295
133
|
wrapper: queryWrapper.wrapper,
|
|
296
134
|
});
|
|
297
135
|
|
|
298
136
|
await waitFor(() => {
|
|
299
|
-
expect(result.current).toEqual(
|
|
137
|
+
expect(result.current).toEqual("idle");
|
|
300
138
|
});
|
|
301
|
-
|
|
302
|
-
expect(processReferral).toHaveBeenCalledWith(
|
|
303
|
-
mockFrakClient,
|
|
304
|
-
expect.objectContaining({
|
|
305
|
-
frakContext: null,
|
|
306
|
-
})
|
|
307
|
-
);
|
|
308
139
|
});
|
|
309
140
|
});
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ProcessReferralOptions,
|
|
3
|
-
|
|
3
|
+
referralInteraction,
|
|
4
4
|
} from "@frak-labs/core-sdk/actions";
|
|
5
5
|
import { ClientNotFound } from "@frak-labs/frame-connector";
|
|
6
6
|
import { useQuery } from "@tanstack/react-query";
|
|
7
7
|
import { useMemo } from "react";
|
|
8
8
|
import { useFrakClient } from "../useFrakClient";
|
|
9
|
-
import { useWalletStatus } from "../useWalletStatus";
|
|
10
|
-
import { useFrakContext } from "../utils/useFrakContext";
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* Helper hook to automatically submit a referral interaction when detected
|
|
14
12
|
*
|
|
13
|
+
* Runs once when the Frak client becomes available.
|
|
14
|
+
*
|
|
15
15
|
* @group hooks
|
|
16
16
|
*
|
|
17
17
|
* @param args
|
|
@@ -21,48 +21,30 @@ import { useFrakContext } from "../utils/useFrakContext";
|
|
|
21
21
|
*
|
|
22
22
|
* @description This function will automatically handle the referral interaction process
|
|
23
23
|
*
|
|
24
|
-
* @see {@link @frak-labs/core-sdk!actions.
|
|
24
|
+
* @see {@link @frak-labs/core-sdk!actions.referralInteraction | `referralInteraction()`} for more details on the automatic referral handling process
|
|
25
25
|
*/
|
|
26
26
|
export function useReferralInteraction({
|
|
27
27
|
options,
|
|
28
28
|
}: {
|
|
29
29
|
options?: ProcessReferralOptions;
|
|
30
30
|
} = {}) {
|
|
31
|
-
// Get the frak client
|
|
32
31
|
const client = useFrakClient();
|
|
33
32
|
|
|
34
|
-
// Get the current frak context
|
|
35
|
-
const { frakContext } = useFrakContext();
|
|
36
|
-
|
|
37
|
-
// Get the wallet status
|
|
38
|
-
const { data: walletStatus } = useWalletStatus();
|
|
39
|
-
|
|
40
|
-
// Setup the query that will transmit the referral interaction
|
|
41
33
|
const {
|
|
42
34
|
data: referralState,
|
|
43
35
|
error,
|
|
44
36
|
status,
|
|
45
37
|
} = useQuery({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
queryKey: [
|
|
49
|
-
"frak-sdk",
|
|
50
|
-
"auto-referral-interaction",
|
|
51
|
-
frakContext?.r ?? "no-referrer",
|
|
52
|
-
walletStatus?.key ?? "no-wallet-status",
|
|
53
|
-
],
|
|
54
|
-
queryFn: () => {
|
|
38
|
+
queryKey: ["frak-sdk", "auto-referral-interaction"],
|
|
39
|
+
queryFn: async () => {
|
|
55
40
|
if (!client) {
|
|
56
41
|
throw new ClientNotFound();
|
|
57
42
|
}
|
|
58
43
|
|
|
59
|
-
return
|
|
60
|
-
walletStatus,
|
|
61
|
-
frakContext,
|
|
62
|
-
options,
|
|
63
|
-
});
|
|
44
|
+
return referralInteraction(client, { options });
|
|
64
45
|
},
|
|
65
|
-
enabled: !!
|
|
46
|
+
enabled: !!client,
|
|
47
|
+
staleTime: Number.POSITIVE_INFINITY,
|
|
66
48
|
});
|
|
67
49
|
|
|
68
50
|
return useMemo(() => {
|
package/src/hook/index.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export { useReferralInteraction } from "./helper/useReferralInteraction";
|
|
2
2
|
export { useDisplayModal } from "./useDisplayModal";
|
|
3
|
+
export { useDisplaySharingPage } from "./useDisplaySharingPage";
|
|
3
4
|
export { useFrakClient } from "./useFrakClient";
|
|
4
5
|
export { useFrakConfig } from "./useFrakConfig";
|
|
5
6
|
export { useGetMerchantInformation } from "./useGetMerchantInformation";
|
|
7
|
+
export { useGetMergeToken } from "./useGetMergeToken";
|
|
8
|
+
export { useGetUserReferralStatus } from "./useGetUserReferralStatus";
|
|
6
9
|
export { useOpenSso } from "./useOpenSso";
|
|
7
10
|
export { usePrepareSso } from "./usePrepareSso";
|
|
8
11
|
export { useSendTransactionAction } from "./useSendTransaction";
|
|
12
|
+
export { useSetupReferral } from "./useSetupReferral";
|
|
9
13
|
export { useSiweAuthenticate } from "./useSiweAuthenticate";
|
|
10
14
|
export { useWalletStatus } from "./useWalletStatus";
|
|
@@ -13,7 +13,7 @@ type MutationOptions<T extends ModalStepTypes[]> = Omit<
|
|
|
13
13
|
UseMutationOptions<
|
|
14
14
|
ModalRpcStepsResultType<T>,
|
|
15
15
|
FrakRpcError,
|
|
16
|
-
DisplayModalParamsType<T>
|
|
16
|
+
DisplayModalParamsType<T> & { placement?: string }
|
|
17
17
|
>,
|
|
18
18
|
"mutationFn" | "mutationKey"
|
|
19
19
|
>;
|
|
@@ -56,13 +56,15 @@ export function useDisplayModal<T extends ModalStepTypes[] = ModalStepTypes[]>({
|
|
|
56
56
|
return useMutation({
|
|
57
57
|
...mutations,
|
|
58
58
|
mutationKey: ["frak-sdk", "display-modal"],
|
|
59
|
-
mutationFn: async (
|
|
59
|
+
mutationFn: async ({
|
|
60
|
+
placement,
|
|
61
|
+
...params
|
|
62
|
+
}: DisplayModalParamsType<T> & { placement?: string }) => {
|
|
60
63
|
if (!client) {
|
|
61
64
|
throw new ClientNotFound();
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
return displayModal(client, args);
|
|
67
|
+
return displayModal(client, params, placement);
|
|
66
68
|
},
|
|
67
69
|
});
|
|
68
70
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DisplaySharingPageParamsType,
|
|
3
|
+
DisplaySharingPageResultType,
|
|
4
|
+
} from "@frak-labs/core-sdk";
|
|
5
|
+
import { displaySharingPage } from "@frak-labs/core-sdk/actions";
|
|
6
|
+
import { ClientNotFound, type FrakRpcError } from "@frak-labs/frame-connector";
|
|
7
|
+
import { type UseMutationOptions, useMutation } from "@tanstack/react-query";
|
|
8
|
+
import { useFrakClient } from "./useFrakClient";
|
|
9
|
+
|
|
10
|
+
/** @ignore */
|
|
11
|
+
type MutationOptions = Omit<
|
|
12
|
+
UseMutationOptions<
|
|
13
|
+
DisplaySharingPageResultType,
|
|
14
|
+
FrakRpcError,
|
|
15
|
+
DisplaySharingPageParamsType & { placement?: string }
|
|
16
|
+
>,
|
|
17
|
+
"mutationFn" | "mutationKey"
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
/** @inline */
|
|
21
|
+
interface UseDisplaySharingPageParams {
|
|
22
|
+
/**
|
|
23
|
+
* Optional mutation options, see {@link @tanstack/react-query!useMutation | `useMutation()`} for more infos
|
|
24
|
+
*/
|
|
25
|
+
mutations?: MutationOptions;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Hook that return a mutation helping to display a sharing page to the user
|
|
30
|
+
*
|
|
31
|
+
* It's a {@link @tanstack/react-query!home | `tanstack`} wrapper around the {@link @frak-labs/core-sdk!actions.displaySharingPage | `displaySharingPage()`} action
|
|
32
|
+
*
|
|
33
|
+
* @param args - Optional config object with `mutations` for customizing the underlying {@link @tanstack/react-query!useMutation | `useMutation()`}
|
|
34
|
+
*
|
|
35
|
+
* @group hooks
|
|
36
|
+
*
|
|
37
|
+
* @returns
|
|
38
|
+
* The mutation hook wrapping the `displaySharingPage()` action
|
|
39
|
+
* The `mutate` and `mutateAsync` argument is of type {@link @frak-labs/core-sdk!index.DisplaySharingPageParamsType | `DisplaySharingPageParamsType`} with optional `placement`
|
|
40
|
+
* The `data` result is a {@link @frak-labs/core-sdk!index.DisplaySharingPageResultType | `DisplaySharingPageResultType`}
|
|
41
|
+
*
|
|
42
|
+
* @see {@link @frak-labs/core-sdk!actions.displaySharingPage | `displaySharingPage()`} for more info about the underlying action
|
|
43
|
+
* @see {@link @tanstack/react-query!useMutation | `useMutation()`} for more info about the mutation options and response
|
|
44
|
+
*/
|
|
45
|
+
export function useDisplaySharingPage({
|
|
46
|
+
mutations,
|
|
47
|
+
}: UseDisplaySharingPageParams = {}) {
|
|
48
|
+
const client = useFrakClient();
|
|
49
|
+
|
|
50
|
+
return useMutation({
|
|
51
|
+
...mutations,
|
|
52
|
+
mutationKey: ["frak-sdk", "display-sharing-page"],
|
|
53
|
+
mutationFn: async ({
|
|
54
|
+
placement,
|
|
55
|
+
...params
|
|
56
|
+
}: DisplaySharingPageParamsType & { placement?: string }) => {
|
|
57
|
+
if (!client) {
|
|
58
|
+
throw new ClientNotFound();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return displaySharingPage(client, params, placement);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -20,6 +20,10 @@ interface UseGetMerchantInformationParams {
|
|
|
20
20
|
* Optional query options, see {@link @tanstack/react-query!useQuery | `useQuery()`} for more infos
|
|
21
21
|
*/
|
|
22
22
|
query?: QueryOptions;
|
|
23
|
+
/**
|
|
24
|
+
* Time in ms to cache the result at the core SDK level. Default: 30_000 (30s). Set to 0 to disable.
|
|
25
|
+
*/
|
|
26
|
+
cacheTime?: number;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -40,6 +44,7 @@ interface UseGetMerchantInformationParams {
|
|
|
40
44
|
*/
|
|
41
45
|
export function useGetMerchantInformation({
|
|
42
46
|
query,
|
|
47
|
+
cacheTime,
|
|
43
48
|
}: UseGetMerchantInformationParams = {}) {
|
|
44
49
|
const client = useFrakClient();
|
|
45
50
|
|
|
@@ -50,7 +55,7 @@ export function useGetMerchantInformation({
|
|
|
50
55
|
if (!client) {
|
|
51
56
|
throw new ClientNotFound();
|
|
52
57
|
}
|
|
53
|
-
return getMerchantInformation(client);
|
|
58
|
+
return getMerchantInformation(client, { cacheTime });
|
|
54
59
|
},
|
|
55
60
|
});
|
|
56
61
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getMergeToken } from "@frak-labs/core-sdk/actions";
|
|
2
|
+
import { ClientNotFound, type FrakRpcError } from "@frak-labs/frame-connector";
|
|
3
|
+
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
|
|
4
|
+
import { useFrakClient } from "./useFrakClient";
|
|
5
|
+
|
|
6
|
+
/** @ignore */
|
|
7
|
+
type QueryOptions = Omit<
|
|
8
|
+
UseQueryOptions<string | null, FrakRpcError, string | null>,
|
|
9
|
+
"queryKey" | "queryFn"
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
/** @inline */
|
|
13
|
+
interface UseGetMergeTokenParams {
|
|
14
|
+
/**
|
|
15
|
+
* Optional query options, see {@link @tanstack/react-query!useQuery | `useQuery()`} for more infos
|
|
16
|
+
*/
|
|
17
|
+
query?: QueryOptions;
|
|
18
|
+
/**
|
|
19
|
+
* Time in ms to cache the result at the core SDK level. Default: 30_000 (30s). Set to 0 to disable.
|
|
20
|
+
*/
|
|
21
|
+
cacheTime?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Hook that return a query to fetch a merge token for the current anonymous identity
|
|
26
|
+
*
|
|
27
|
+
* Used by in-app browser redirect flows to preserve identity
|
|
28
|
+
* when switching from a WebView to the system browser.
|
|
29
|
+
*
|
|
30
|
+
* It's a {@link @tanstack/react-query!home | `tanstack`} wrapper around the {@link @frak-labs/core-sdk!actions.getMergeToken | `getMergeToken()`} action
|
|
31
|
+
*
|
|
32
|
+
* @param args - Optional config object with `query` for customizing the underlying {@link @tanstack/react-query!useQuery | `useQuery()`}
|
|
33
|
+
*
|
|
34
|
+
* @group hooks
|
|
35
|
+
*
|
|
36
|
+
* @returns
|
|
37
|
+
* The query hook wrapping the `getMergeToken()` action
|
|
38
|
+
* The `data` result is a `string | null`
|
|
39
|
+
*
|
|
40
|
+
* @see {@link @frak-labs/core-sdk!actions.getMergeToken | `getMergeToken()`} for more info about the underlying action
|
|
41
|
+
* @see {@link @tanstack/react-query!useQuery | `useQuery()`} for more info about the useQuery options and response
|
|
42
|
+
*/
|
|
43
|
+
export function useGetMergeToken({
|
|
44
|
+
query,
|
|
45
|
+
cacheTime,
|
|
46
|
+
}: UseGetMergeTokenParams = {}) {
|
|
47
|
+
const client = useFrakClient();
|
|
48
|
+
|
|
49
|
+
return useQuery({
|
|
50
|
+
...query,
|
|
51
|
+
queryKey: ["frak-sdk", "get-merge-token"],
|
|
52
|
+
queryFn: async () => {
|
|
53
|
+
if (!client) {
|
|
54
|
+
throw new ClientNotFound();
|
|
55
|
+
}
|
|
56
|
+
return getMergeToken(client, { cacheTime });
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|