@frak-labs/react-sdk 0.2.1-beta.13642b4b → 0.2.1-beta.1a53f1d5

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.js CHANGED
@@ -1 +1 @@
1
- import{displayModal as e,getMerchantInformation as t,openSso as n,prepareSso as r,processReferral as i,sendTransaction as a,siweAuthenticate as o,watchWalletStatus as s}from"@frak-labs/core-sdk/actions";import{ClientNotFound as c,FrakRpcError as l,RpcErrorCodes as u}from"@frak-labs/frame-connector";import{useMutation as d,useQuery as f,useQueryClient as p}from"@tanstack/react-query";import{Fragment as m,createContext as h,createElement as g,useCallback as _,useContext as v,useEffect as y,useMemo as b,useState as x}from"react";import{FrakContextManager as S,baseIframeProps as C,createIFrameFrakClient as w}from"@frak-labs/core-sdk";const T=h(void 0);function E(e){let{children:t,config:n}=e;return g(T.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 D=h(void 0);function O({style:e,children:t}){let n=I(),[r,i]=x(void 0);return g(m,null,g(`iframe`,{...C,src:`${n.walletUrl}/listener`,style:e??C.style,ref:e=>{!e||r||i(w({iframe:e,config:n}))}}),g(D.Provider,{value:r},t))}function k(){return v(D)}function A(){let e=p(),t=k(),n=_(t=>{e.setQueryData([`frak-sdk`,`wallet-status-listener`],t)},[e]);return f({gcTime:0,staleTime:0,queryKey:[`frak-sdk`,`wallet-status-listener`],queryFn:async()=>{if(!t)throw new c;return s(t,n)},enabled:!!t})}function j(){let[e,t]=x(!1);return y(()=>{t(!0)},[]),e}function M(){let e=j(),[t,n]=x(e?window.location:void 0);return y(()=>{if(!e)return;function r(){n(window.location)}return t||r(),window.addEventListener(`popstate`,r),()=>{window.removeEventListener(`popstate`,r)}},[e,t]),{location:t,href:b(()=>t?.href,[t?.href])}}function N(){let{location:e}=M();return{frakContext:b(()=>e?.href?S.parse({url:e.href}):null,[e?.href]),updateContext:_(t=>{console.log(`Updating context`,{newContext:t}),S.replaceUrl({url:e?.href,context:t})},[e?.href])}}function P({options:e}={}){let t=k(),{frakContext:n}=N(),{data:r}=A(),{data:a,error:o,status:s}=f({gcTime:0,staleTime:0,queryKey:[`frak-sdk`,`auto-referral-interaction`,n?.r??`no-referrer`,r?.key??`no-wallet-status`],queryFn:()=>{if(!t)throw new c;return i(t,{walletStatus:r,frakContext:n,options:e})},enabled:!!r});return b(()=>s===`pending`?`processing`:s===`error`?o:a||`idle`,[a,s,o])}function F({mutations:t}={}){let n=k();return d({...t,mutationKey:[`frak-sdk`,`display-modal`],mutationFn:async t=>{if(!n)throw new c;return e(n,t)}})}function I(){let e=v(T);if(!e)throw new l(u.configError,`Frak config not found`);return e}function L({query:e}={}){let n=k();return f({...e,queryKey:[`frak-sdk`,`get-merchant-information`],queryFn:async()=>{if(!n)throw new c;return t(n)}})}function R({mutations:e}={}){let t=k();return d({...e,mutationKey:[`frak-sdk`,`open-sso`],mutationFn:async e=>{if(!t)throw new c;return n(t,e)}})}function z(e){let t=k();return f({queryKey:[`frak-sdk`,`prepare-sso`,e],queryFn:async()=>{if(!t)throw new c;return r(t,e)}})}function B({mutations:e}={}){let t=k();return d({...e,mutationKey:[`frak-sdk`,`send-transaction`],mutationFn:async e=>{if(!t)throw new c;return a(t,e)}})}function V({mutations:e}={}){let t=k();return d({...e,mutationKey:[`frak-sdk`,`siwe-authenticate`,t?.config.domain??`no-domain`],mutationFn:async e=>{if(!t)throw new c;return o(t,e)}})}export{T as FrakConfigContext,E as FrakConfigProvider,D as FrakIFrameClientContext,O as FrakIFrameClientProvider,F as useDisplayModal,k as useFrakClient,I as useFrakConfig,L as useGetMerchantInformation,R as useOpenSso,z as usePrepareSso,P as useReferralInteraction,B as useSendTransactionAction,V as useSiweAuthenticate,A as useWalletStatus};
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.2.1-beta.13642b4b",
14
+ "version": "0.2.1-beta.1a53f1d5",
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/core-sdk": "0.2.1-beta.13642b4b",
71
- "@frak-labs/frame-connector": "0.2.0-beta.13642b4b"
70
+ "@frak-labs/core-sdk": "0.2.1-beta.1a53f1d5",
71
+ "@frak-labs/frame-connector": "0.2.0-beta.1a53f1d5"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "viem": "^2.x",
@@ -77,7 +77,6 @@
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
81
  "@frak-labs/wallet-shared": "0.0.3",
83
82
  "@tanstack/react-query": "^5.90.20",
@@ -86,15 +85,15 @@
86
85
  "@testing-library/react-hooks": "^8.0.1",
87
86
  "@testing-library/user-event": "^14.6.1",
88
87
  "@types/jsdom": "^28.0.0",
89
- "@types/node": "^24.10.13",
88
+ "@types/node": "^25.6.0",
90
89
  "@types/react": "19.2.13",
91
90
  "@vitest/coverage-v8": "^4.1.0",
92
91
  "@vitest/ui": "^4.1.0",
93
92
  "jsdom": "^29.0.0",
94
93
  "react": "^19.2.4",
95
- "tsdown": "^0.20.3",
96
- "typescript": "^5.9.3",
97
- "viem": "^2.39.0",
98
- "vitest": "^4.1.0"
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,25 @@ 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 type { FrakContext, WalletStatusReturnType } from "@frak-labs/core-sdk";
14
- import { processReferral } from "@frak-labs/core-sdk/actions";
11
+ import { referralInteraction } from "@frak-labs/core-sdk/actions";
15
12
  import { ClientNotFound } from "@frak-labs/frame-connector";
16
13
  import { renderHook, waitFor } from "@testing-library/react";
17
14
  import { describe, expect, test } from "../../../tests/vitest-fixtures";
18
15
  import { useFrakClient } from "../useFrakClient";
19
- import { useWalletStatus } from "../useWalletStatus";
20
- import { useFrakContext } from "../utils/useFrakContext";
21
16
  import { useReferralInteraction } from "./useReferralInteraction";
22
17
 
23
18
  describe("useReferralInteraction", () => {
24
- test("should return processing when wallet status is not available", ({
19
+ test("should return processing when client is not available", ({
25
20
  queryWrapper,
26
- mockFrakClient,
27
21
  }) => {
28
- vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
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>);
22
+ vi.mocked(useFrakClient).mockReturnValue(undefined);
38
23
 
39
24
  const { result } = renderHook(() => useReferralInteraction(), {
40
25
  wrapper: queryWrapper.wrapper,
41
26
  });
42
27
 
43
- // Query is disabled when wallet status is not available, status remains pending
28
+ // Query is disabled when client is not available, status remains pending
44
29
  expect(result.current).toBe("processing");
45
30
  });
46
31
 
@@ -48,40 +33,18 @@ describe("useReferralInteraction", () => {
48
33
  queryWrapper,
49
34
  mockFrakClient,
50
35
  }) => {
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
36
  vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
63
- vi.mocked(useFrakContext).mockReturnValue({
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);
37
+ vi.mocked(referralInteraction).mockResolvedValue("success");
73
38
 
74
39
  const { result } = renderHook(() => useReferralInteraction(), {
75
40
  wrapper: queryWrapper.wrapper,
76
41
  });
77
42
 
78
43
  await waitFor(() => {
79
- expect(result.current).toEqual(mockReferralState);
44
+ expect(result.current).toEqual("success");
80
45
  });
81
46
 
82
- expect(processReferral).toHaveBeenCalledWith(mockFrakClient, {
83
- walletStatus: mockWalletStatus,
84
- frakContext: mockFrakContext,
47
+ expect(referralInteraction).toHaveBeenCalledWith(mockFrakClient, {
85
48
  options: undefined,
86
49
  });
87
50
  });
@@ -90,28 +53,12 @@ describe("useReferralInteraction", () => {
90
53
  queryWrapper,
91
54
  mockFrakClient,
92
55
  }) => {
93
- const mockReferralState = "success";
94
-
95
56
  const options = {
96
57
  alwaysAppendUrl: true,
97
58
  };
98
59
 
99
- const mockWalletStatus: WalletStatusReturnType = {
100
- key: "connected",
101
- wallet: "0x1234567890123456789012345678901234567890",
102
- };
103
-
104
60
  vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
105
- vi.mocked(useFrakContext).mockReturnValue({
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);
61
+ vi.mocked(referralInteraction).mockResolvedValue("success");
115
62
 
116
63
  const { result } = renderHook(
117
64
  () => useReferralInteraction({ options }),
@@ -121,39 +68,23 @@ describe("useReferralInteraction", () => {
121
68
  );
122
69
 
123
70
  await waitFor(() => {
124
- expect(result.current).toEqual(mockReferralState);
71
+ expect(result.current).toEqual("success");
125
72
  });
126
73
 
127
- expect(processReferral).toHaveBeenCalledWith(
128
- mockFrakClient,
129
- expect.objectContaining({
130
- options,
131
- })
132
- );
74
+ expect(referralInteraction).toHaveBeenCalledWith(mockFrakClient, {
75
+ options,
76
+ });
133
77
  });
134
78
 
79
+
135
80
  test("should handle processing state", ({
136
81
  queryWrapper,
137
82
  mockFrakClient,
138
83
  }) => {
139
- const mockWalletStatus: WalletStatusReturnType = {
140
- key: "connected",
141
- wallet: "0x1234567890123456789012345678901234567890",
142
- };
143
-
144
84
  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
85
 
155
- // Mock processReferral to never resolve (simulate pending)
156
- vi.mocked(processReferral).mockImplementation(
86
+ // Mock referralInteraction to never resolve (simulate pending)
87
+ vi.mocked(referralInteraction).mockImplementation(
157
88
  () => new Promise(() => {})
158
89
  );
159
90
 
@@ -167,22 +98,8 @@ describe("useReferralInteraction", () => {
167
98
  test("should handle errors", async ({ queryWrapper, mockFrakClient }) => {
168
99
  const error = new Error("Referral processing failed");
169
100
 
170
- const mockWalletStatus: WalletStatusReturnType = {
171
- key: "connected",
172
- wallet: "0x1234567890123456789012345678901234567890",
173
- };
174
-
175
101
  vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
176
- vi.mocked(useFrakContext).mockReturnValue({
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);
102
+ vi.mocked(referralInteraction).mockRejectedValue(error);
186
103
 
187
104
  const { result } = renderHook(() => useReferralInteraction(), {
188
105
  wrapper: queryWrapper.wrapper,
@@ -193,117 +110,33 @@ describe("useReferralInteraction", () => {
193
110
  });
194
111
  });
195
112
 
196
- test("should throw ClientNotFound when client is not available", async ({
113
+ test("should throw ClientNotFound when client is not available but enabled", async ({
197
114
  queryWrapper,
198
115
  }) => {
199
- const mockWalletStatus: WalletStatusReturnType = {
200
- key: "connected",
201
- wallet: "0x1234567890123456789012345678901234567890",
202
- };
203
-
116
+ // Force the query to run despite no client (edge case)
204
117
  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
118
 
215
119
  const { result } = renderHook(() => useReferralInteraction(), {
216
120
  wrapper: queryWrapper.wrapper,
217
121
  });
218
122
 
219
- await waitFor(() => {
220
- expect(result.current).toBeInstanceOf(ClientNotFound);
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
- });
123
+ // Query is disabled when client is null, so it stays pending
124
+ expect(result.current).toBe("processing");
269
125
  });
270
126
 
271
- test("should handle no referrer in context", async ({
127
+ test("should return idle for no-referrer state", async ({
272
128
  queryWrapper,
273
129
  mockFrakClient,
274
130
  }) => {
275
- const mockReferralState = "success";
276
-
277
- const mockWalletStatus: WalletStatusReturnType = {
278
- key: "connected",
279
- wallet: "0x1234567890123456789012345678901234567890",
280
- };
281
-
282
131
  vi.mocked(useFrakClient).mockReturnValue(mockFrakClient);
283
- vi.mocked(useFrakContext).mockReturnValue({
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);
132
+ vi.mocked(referralInteraction).mockResolvedValue(undefined);
293
133
 
294
134
  const { result } = renderHook(() => useReferralInteraction(), {
295
135
  wrapper: queryWrapper.wrapper,
296
136
  });
297
137
 
298
138
  await waitFor(() => {
299
- expect(result.current).toEqual(mockReferralState);
139
+ expect(result.current).toEqual("idle");
300
140
  });
301
-
302
- expect(processReferral).toHaveBeenCalledWith(
303
- mockFrakClient,
304
- expect.objectContaining({
305
- frakContext: null,
306
- })
307
- );
308
141
  });
309
142
  });
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  type ProcessReferralOptions,
3
- processReferral,
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.processReferral | `processReferral()`} for more details on the automatic referral handling process
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
- gcTime: 0,
47
- staleTime: 0,
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 processReferral(client, {
60
- walletStatus,
61
- frakContext,
62
- options,
63
- });
44
+ return referralInteraction(client, { options });
64
45
  },
65
- enabled: !!walletStatus,
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 (args: DisplayModalParamsType<T>) => {
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
- // Ask to display the modal
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
+ }