@frak-labs/react-sdk 0.2.1-beta.1451c4b8 → 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.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 +8 -9
- package/src/hook/helper/useReferralInteraction.test.ts +23 -190
- 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.2.1-beta.
|
|
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.
|
|
71
|
-
"@frak-labs/frame-connector": "0.2.0-beta.
|
|
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": "^
|
|
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.
|
|
96
|
-
"typescript": "^
|
|
97
|
-
"viem": "^2.
|
|
98
|
-
"vitest": "^4.1.
|
|
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
|
|
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
|
|
19
|
+
test("should return processing when client is not available", ({
|
|
25
20
|
queryWrapper,
|
|
26
|
-
mockFrakClient,
|
|
27
21
|
}) => {
|
|
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>);
|
|
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
|
|
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(
|
|
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(
|
|
44
|
+
expect(result.current).toEqual("success");
|
|
80
45
|
});
|
|
81
46
|
|
|
82
|
-
expect(
|
|
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(
|
|
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(
|
|
71
|
+
expect(result.current).toEqual("success");
|
|
125
72
|
});
|
|
126
73
|
|
|
127
|
-
expect(
|
|
128
|
-
|
|
129
|
-
|
|
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
|
|
156
|
-
vi.mocked(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
});
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
+
}
|