@chipi-stack/chipi-react 11.22.0 → 12.1.0

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/hooks.js CHANGED
@@ -82,6 +82,367 @@ function useGetWallet(input) {
82
82
  fetchWallet
83
83
  };
84
84
  }
85
+ function useChipiWallet(config) {
86
+ const { chipiSDK } = useChipiContext();
87
+ const queryClient = reactQuery.useQueryClient();
88
+ const {
89
+ externalUserId,
90
+ getBearerToken,
91
+ defaultToken = "USDC",
92
+ enabled = true
93
+ } = config;
94
+ const isEnabled = Boolean(
95
+ enabled && externalUserId && externalUserId.trim() !== ""
96
+ );
97
+ const walletQuery = reactQuery.useQuery({
98
+ queryKey: ["chipi-wallet", externalUserId],
99
+ queryFn: async () => {
100
+ if (!externalUserId) return null;
101
+ const bearerToken = await getBearerToken();
102
+ if (!bearerToken) throw new Error("Bearer token is required");
103
+ return chipiSDK.getWallet({ externalUserId }, bearerToken);
104
+ },
105
+ enabled: isEnabled,
106
+ retry: (failureCount, error) => {
107
+ if (error instanceof shared.ChipiApiError || error?.status) {
108
+ return false;
109
+ }
110
+ return failureCount < 3;
111
+ }
112
+ });
113
+ const walletPublicKey = walletQuery.data?.wallet.publicKey;
114
+ const balanceQuery = reactQuery.useQuery({
115
+ queryKey: ["chipi-wallet-balance", walletPublicKey, defaultToken],
116
+ queryFn: async () => {
117
+ if (!walletPublicKey) throw new Error("No wallet");
118
+ const bearerToken = await getBearerToken();
119
+ if (!bearerToken) throw new Error("Bearer token is required");
120
+ return chipiSDK.getTokenBalance(
121
+ {
122
+ chain: "STARKNET",
123
+ chainToken: defaultToken,
124
+ walletPublicKey
125
+ },
126
+ bearerToken
127
+ );
128
+ },
129
+ enabled: Boolean(walletPublicKey),
130
+ retry: (failureCount, error) => {
131
+ if (error instanceof shared.ChipiApiError || error?.status) {
132
+ return false;
133
+ }
134
+ return failureCount < 3;
135
+ }
136
+ });
137
+ const createWalletMutation = reactQuery.useMutation({
138
+ mutationFn: async ({ encryptKey, walletType = "CHIPI" }) => {
139
+ if (!externalUserId) throw new Error("External user ID is required");
140
+ const bearerToken = await getBearerToken();
141
+ if (!bearerToken) throw new Error("Bearer token is required");
142
+ return chipiSDK.createWallet({
143
+ params: {
144
+ encryptKey,
145
+ externalUserId,
146
+ walletType
147
+ },
148
+ bearerToken
149
+ });
150
+ },
151
+ onSuccess: () => {
152
+ queryClient.invalidateQueries({
153
+ queryKey: ["chipi-wallet", externalUserId]
154
+ });
155
+ }
156
+ });
157
+ const wallet = react.useMemo(() => {
158
+ if (walletQuery.isLoading) return void 0;
159
+ if (!walletQuery.data) return null;
160
+ const data = walletQuery.data;
161
+ return {
162
+ ...data,
163
+ supportsSessionKeys: data.wallet.walletType === "CHIPI",
164
+ shortAddress: formatAddress(data.wallet.publicKey)
165
+ };
166
+ }, [walletQuery.data, walletQuery.isLoading]);
167
+ const formattedBalance = react.useMemo(() => {
168
+ if (!balanceQuery.data?.balance) return "0.00";
169
+ const num = Number(balanceQuery.data.balance);
170
+ return num.toLocaleString(void 0, {
171
+ minimumFractionDigits: 2,
172
+ maximumFractionDigits: defaultToken === "ETH" || defaultToken === "STRK" ? 6 : 2
173
+ });
174
+ }, [balanceQuery.data, defaultToken]);
175
+ const refetchWallet = react.useCallback(async () => {
176
+ await walletQuery.refetch();
177
+ }, [walletQuery]);
178
+ const refetchBalance = react.useCallback(async () => {
179
+ await balanceQuery.refetch();
180
+ }, [balanceQuery]);
181
+ const refetchAll = react.useCallback(async () => {
182
+ await Promise.all([walletQuery.refetch(), balanceQuery.refetch()]);
183
+ }, [walletQuery, balanceQuery]);
184
+ const createWallet = react.useCallback(
185
+ async (params) => {
186
+ return createWalletMutation.mutateAsync(params);
187
+ },
188
+ [createWalletMutation]
189
+ );
190
+ return {
191
+ // Wallet data
192
+ wallet,
193
+ hasWallet: wallet !== null && wallet !== void 0,
194
+ isLoadingWallet: walletQuery.isLoading,
195
+ walletError: walletQuery.error,
196
+ // Balance data
197
+ balance: balanceQuery.data,
198
+ formattedBalance,
199
+ isLoadingBalance: balanceQuery.isLoading,
200
+ // Create wallet
201
+ createWallet,
202
+ isCreating: createWalletMutation.isPending,
203
+ createdWallet: createWalletMutation.data,
204
+ // Actions
205
+ refetchWallet,
206
+ refetchBalance,
207
+ refetchAll
208
+ };
209
+ }
210
+ function formatAddress(address, chars = 6) {
211
+ if (!address || address.length < chars * 2) return address;
212
+ return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
213
+ }
214
+ function useChipiSession(config) {
215
+ const { chipiSDK } = useChipiContext();
216
+ const queryClient = reactQuery.useQueryClient();
217
+ const {
218
+ wallet,
219
+ encryptKey,
220
+ getBearerToken,
221
+ storedSession,
222
+ onSessionCreated,
223
+ defaultDurationSeconds = 21600,
224
+ // 6 hours
225
+ defaultMaxCalls = 1e3,
226
+ autoCheckStatus = true
227
+ } = config;
228
+ const [localSession, setLocalSession] = react.useState(
229
+ storedSession ?? null
230
+ );
231
+ const [error, setError] = react.useState(null);
232
+ react.useEffect(() => {
233
+ if (storedSession) {
234
+ setLocalSession(storedSession);
235
+ }
236
+ }, [storedSession]);
237
+ const supportsSession = react.useMemo(() => {
238
+ if (!wallet) return false;
239
+ return wallet.walletType === "CHIPI";
240
+ }, [wallet]);
241
+ const sessionStatusQuery = reactQuery.useQuery({
242
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey],
243
+ queryFn: async () => {
244
+ if (!wallet?.publicKey || !localSession?.publicKey) return null;
245
+ return chipiSDK.sessions.getSessionData({
246
+ walletAddress: wallet.publicKey,
247
+ sessionPublicKey: localSession.publicKey
248
+ });
249
+ },
250
+ enabled: Boolean(
251
+ autoCheckStatus && wallet?.publicKey && localSession?.publicKey && supportsSession
252
+ ),
253
+ staleTime: 3e4
254
+ // 30 seconds
255
+ });
256
+ const sessionState = react.useMemo(() => {
257
+ if (!localSession) return "none";
258
+ const status = sessionStatusQuery.data;
259
+ if (status) {
260
+ if (!status.isActive) return "revoked";
261
+ if (status.validUntil * 1e3 < Date.now()) return "expired";
262
+ if (status.remainingCalls <= 0) return "expired";
263
+ return "active";
264
+ }
265
+ if (localSession.validUntil * 1e3 < Date.now()) return "expired";
266
+ return "created";
267
+ }, [localSession, sessionStatusQuery.data]);
268
+ const hasActiveSession = sessionState === "active";
269
+ const isSessionExpired = sessionState === "expired";
270
+ const remainingCalls = sessionStatusQuery.data?.remainingCalls;
271
+ const createSessionMutation = reactQuery.useMutation({
272
+ mutationFn: async (params = {}) => {
273
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
274
+ if (!supportsSession) throw new Error("Wallet does not support sessions. Only CHIPI wallets support session keys.");
275
+ const sessionData = chipiSDK.sessions.createSessionKey({
276
+ encryptKey,
277
+ durationSeconds: params.durationSeconds ?? defaultDurationSeconds
278
+ });
279
+ return sessionData;
280
+ },
281
+ onSuccess: async (sessionData) => {
282
+ setLocalSession(sessionData);
283
+ setError(null);
284
+ if (onSessionCreated) {
285
+ await onSessionCreated(sessionData);
286
+ }
287
+ },
288
+ onError: (err) => {
289
+ setError(err);
290
+ }
291
+ });
292
+ const registerSessionMutation = reactQuery.useMutation({
293
+ mutationFn: async (sessionConfig = {}) => {
294
+ if (!wallet) throw new Error("Wallet is required");
295
+ if (!localSession) throw new Error("No session to register. Call createSession first.");
296
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
297
+ if (!supportsSession) throw new Error("Wallet does not support sessions");
298
+ const bearerToken = await getBearerToken();
299
+ if (!bearerToken) throw new Error("Bearer token is required");
300
+ const txHash = await chipiSDK.sessions.addSessionKeyToContract(
301
+ {
302
+ encryptKey,
303
+ wallet,
304
+ sessionConfig: {
305
+ sessionPublicKey: localSession.publicKey,
306
+ validUntil: sessionConfig.validUntil ?? localSession.validUntil,
307
+ maxCalls: sessionConfig.maxCalls ?? defaultMaxCalls,
308
+ allowedEntrypoints: sessionConfig.allowedEntrypoints ?? []
309
+ }
310
+ },
311
+ bearerToken
312
+ );
313
+ return txHash;
314
+ },
315
+ onSuccess: () => {
316
+ setError(null);
317
+ queryClient.invalidateQueries({
318
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
319
+ });
320
+ },
321
+ onError: (err) => {
322
+ setError(err);
323
+ }
324
+ });
325
+ const revokeSessionMutation = reactQuery.useMutation({
326
+ mutationFn: async () => {
327
+ if (!wallet) throw new Error("Wallet is required");
328
+ if (!localSession) throw new Error("No session to revoke");
329
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
330
+ if (!supportsSession) throw new Error("Wallet does not support sessions");
331
+ const bearerToken = await getBearerToken();
332
+ if (!bearerToken) throw new Error("Bearer token is required");
333
+ const txHash = await chipiSDK.sessions.revokeSessionKey(
334
+ {
335
+ encryptKey,
336
+ wallet,
337
+ sessionPublicKey: localSession.publicKey
338
+ },
339
+ bearerToken
340
+ );
341
+ return txHash;
342
+ },
343
+ onSuccess: () => {
344
+ setError(null);
345
+ queryClient.invalidateQueries({
346
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
347
+ });
348
+ },
349
+ onError: (err) => {
350
+ setError(err);
351
+ }
352
+ });
353
+ const executeWithSessionMutation = reactQuery.useMutation({
354
+ mutationFn: async (calls) => {
355
+ if (!wallet) throw new Error("Wallet is required");
356
+ if (!localSession) throw new Error("No active session");
357
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
358
+ if (!hasActiveSession) throw new Error("Session is not active. Register the session first.");
359
+ const bearerToken = await getBearerToken();
360
+ if (!bearerToken) throw new Error("Bearer token is required");
361
+ const txHash = await chipiSDK.executeTransactionWithSession({
362
+ params: {
363
+ encryptKey,
364
+ wallet,
365
+ session: localSession,
366
+ calls
367
+ },
368
+ bearerToken
369
+ });
370
+ return txHash;
371
+ },
372
+ onSuccess: () => {
373
+ setError(null);
374
+ queryClient.invalidateQueries({
375
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
376
+ });
377
+ },
378
+ onError: (err) => {
379
+ setError(err);
380
+ }
381
+ });
382
+ const createSession = react.useCallback(
383
+ async (params) => {
384
+ return createSessionMutation.mutateAsync(params ?? {});
385
+ },
386
+ [createSessionMutation]
387
+ );
388
+ const registerSession = react.useCallback(
389
+ async (sessionConfig) => {
390
+ return registerSessionMutation.mutateAsync(sessionConfig ?? {});
391
+ },
392
+ [registerSessionMutation]
393
+ );
394
+ const revokeSession = react.useCallback(async () => {
395
+ return revokeSessionMutation.mutateAsync();
396
+ }, [revokeSessionMutation]);
397
+ const executeWithSession = react.useCallback(
398
+ async (calls) => {
399
+ return executeWithSessionMutation.mutateAsync(calls);
400
+ },
401
+ [executeWithSessionMutation]
402
+ );
403
+ const clearSession = react.useCallback(() => {
404
+ setLocalSession(null);
405
+ setError(null);
406
+ }, []);
407
+ const refetchStatus = react.useCallback(async () => {
408
+ await sessionStatusQuery.refetch();
409
+ }, [sessionStatusQuery]);
410
+ const combinedError = react.useMemo(() => {
411
+ return error || createSessionMutation.error || registerSessionMutation.error || revokeSessionMutation.error || executeWithSessionMutation.error || sessionStatusQuery.error || null;
412
+ }, [
413
+ error,
414
+ createSessionMutation.error,
415
+ registerSessionMutation.error,
416
+ revokeSessionMutation.error,
417
+ executeWithSessionMutation.error,
418
+ sessionStatusQuery.error
419
+ ]);
420
+ return {
421
+ // Session data
422
+ session: localSession,
423
+ sessionStatus: sessionStatusQuery.data ?? void 0,
424
+ sessionState,
425
+ hasActiveSession,
426
+ isSessionExpired,
427
+ remainingCalls,
428
+ supportsSession,
429
+ // Actions
430
+ createSession,
431
+ registerSession,
432
+ revokeSession,
433
+ executeWithSession,
434
+ clearSession,
435
+ refetchStatus,
436
+ // Loading states
437
+ isCreating: createSessionMutation.isPending,
438
+ isRegistering: registerSessionMutation.isPending,
439
+ isRevoking: revokeSessionMutation.isPending,
440
+ isExecuting: executeWithSessionMutation.isPending,
441
+ isLoadingStatus: sessionStatusQuery.isLoading,
442
+ // Errors
443
+ error: combinedError
444
+ };
445
+ }
85
446
  function useTransfer() {
86
447
  const { chipiSDK } = useChipiContext();
87
448
  const mutation = reactQuery.useMutation(
@@ -409,8 +770,15 @@ function useRecordSendTransaction() {
409
770
  function useGetTokenBalance(input) {
410
771
  const { chipiSDK } = useChipiContext();
411
772
  const queryClient = reactQuery.useQueryClient();
773
+ const buildQueryKey = (params) => [
774
+ "chain-token-balance",
775
+ params?.chainToken ?? null,
776
+ params?.chain ?? null,
777
+ params?.walletPublicKey ?? null,
778
+ params?.externalUserId ?? null
779
+ ];
412
780
  const query = reactQuery.useQuery({
413
- queryKey: ["chain-token-balance", input?.params?.chainToken, input?.params?.chain, input?.params?.walletPublicKey, input?.params?.externalUserId],
781
+ queryKey: buildQueryKey(input?.params),
414
782
  queryFn: async () => {
415
783
  if (!input || !input.params || !input.getBearerToken) throw new Error("Input is required");
416
784
  const bearerToken = await input.getBearerToken();
@@ -418,17 +786,17 @@ function useGetTokenBalance(input) {
418
786
  return chipiSDK.getTokenBalance(input.params, bearerToken);
419
787
  },
420
788
  enabled: Boolean(input?.params && input?.getBearerToken),
421
- ...input?.queryOptions,
422
789
  retry: (failureCount, error) => {
423
790
  if (error instanceof shared.ChipiApiError || error?.status) {
424
791
  return false;
425
792
  }
426
793
  return failureCount < 3;
427
- }
794
+ },
795
+ ...input?.queryOptions
428
796
  });
429
797
  const fetchTokenBalance = async (newInput) => {
430
798
  return queryClient.fetchQuery({
431
- queryKey: ["chain-token-balance", newInput?.params?.chainToken, newInput?.params?.chain, newInput?.params?.walletPublicKey, newInput?.params?.externalUserId],
799
+ queryKey: buildQueryKey(newInput?.params),
432
800
  queryFn: async () => {
433
801
  if (!newInput || !newInput.getBearerToken || !newInput.params) throw new Error("Input is required");
434
802
  const bearerToken = await newInput.getBearerToken();
@@ -532,12 +900,113 @@ function useCreateUser() {
532
900
  reset: mutation.reset
533
901
  };
534
902
  }
903
+ function useCreateSessionKey() {
904
+ const { chipiSDK } = useChipiContext();
905
+ const mutation = reactQuery.useMutation({
906
+ mutationFn: async (params) => chipiSDK.sessions.createSessionKey(params)
907
+ });
908
+ return {
909
+ createSessionKey: mutation.mutate,
910
+ createSessionKeyAsync: mutation.mutateAsync,
911
+ data: mutation.data,
912
+ isLoading: mutation.isPending,
913
+ isError: mutation.isError,
914
+ error: mutation.error,
915
+ isSuccess: mutation.isSuccess,
916
+ reset: mutation.reset
917
+ };
918
+ }
919
+ function useAddSessionKeyToContract() {
920
+ const { chipiSDK } = useChipiContext();
921
+ const mutation = reactQuery.useMutation({
922
+ mutationFn: (input) => chipiSDK.sessions.addSessionKeyToContract(
923
+ input.params,
924
+ input.bearerToken
925
+ )
926
+ });
927
+ return {
928
+ addSessionKeyToContract: mutation.mutate,
929
+ addSessionKeyToContractAsync: mutation.mutateAsync,
930
+ data: mutation.data,
931
+ isLoading: mutation.isPending,
932
+ isError: mutation.isError,
933
+ error: mutation.error,
934
+ isSuccess: mutation.isSuccess,
935
+ reset: mutation.reset
936
+ };
937
+ }
938
+ function useRevokeSessionKey() {
939
+ const { chipiSDK } = useChipiContext();
940
+ const mutation = reactQuery.useMutation({
941
+ mutationFn: (input) => chipiSDK.sessions.revokeSessionKey(input.params, input.bearerToken)
942
+ });
943
+ return {
944
+ revokeSessionKey: mutation.mutate,
945
+ revokeSessionKeyAsync: mutation.mutateAsync,
946
+ data: mutation.data,
947
+ isLoading: mutation.isPending,
948
+ isError: mutation.isError,
949
+ error: mutation.error,
950
+ isSuccess: mutation.isSuccess,
951
+ reset: mutation.reset
952
+ };
953
+ }
954
+ function useGetSessionData(params, options) {
955
+ const { chipiSDK } = useChipiContext();
956
+ const query = reactQuery.useQuery({
957
+ queryKey: [
958
+ "sessionData",
959
+ params?.walletAddress,
960
+ params?.sessionPublicKey
961
+ ],
962
+ queryFn: () => {
963
+ if (!params) {
964
+ throw new Error("Session data params are required");
965
+ }
966
+ return chipiSDK.sessions.getSessionData(params);
967
+ },
968
+ enabled: options?.enabled !== false && params !== null
969
+ });
970
+ return {
971
+ data: query.data,
972
+ isLoading: query.isLoading,
973
+ isError: query.isError,
974
+ error: query.error,
975
+ isSuccess: query.isSuccess,
976
+ refetch: query.refetch
977
+ };
978
+ }
979
+ function useExecuteWithSession() {
980
+ const { chipiSDK } = useChipiContext();
981
+ const mutation = reactQuery.useMutation({
982
+ mutationFn: (input) => chipiSDK.executeTransactionWithSession({
983
+ params: input.params,
984
+ bearerToken: input.bearerToken
985
+ })
986
+ });
987
+ return {
988
+ executeWithSession: mutation.mutate,
989
+ executeWithSessionAsync: mutation.mutateAsync,
990
+ data: mutation.data,
991
+ isLoading: mutation.isPending,
992
+ isError: mutation.isError,
993
+ error: mutation.error,
994
+ isSuccess: mutation.isSuccess,
995
+ reset: mutation.reset
996
+ };
997
+ }
535
998
 
999
+ exports.useAddSessionKeyToContract = useAddSessionKeyToContract;
536
1000
  exports.useApprove = useApprove;
537
1001
  exports.useCallAnyContract = useCallAnyContract;
1002
+ exports.useChipiSession = useChipiSession;
1003
+ exports.useChipiWallet = useChipiWallet;
1004
+ exports.useCreateSessionKey = useCreateSessionKey;
538
1005
  exports.useCreateSkuTransaction = useCreateSkuTransaction;
539
1006
  exports.useCreateUser = useCreateUser;
540
1007
  exports.useCreateWallet = useCreateWallet;
1008
+ exports.useExecuteWithSession = useExecuteWithSession;
1009
+ exports.useGetSessionData = useGetSessionData;
541
1010
  exports.useGetSku = useGetSku;
542
1011
  exports.useGetSkuList = useGetSkuList;
543
1012
  exports.useGetSkuTransaction = useGetSkuTransaction;
@@ -546,6 +1015,7 @@ exports.useGetTransactionList = useGetTransactionList;
546
1015
  exports.useGetUser = useGetUser;
547
1016
  exports.useGetWallet = useGetWallet;
548
1017
  exports.useRecordSendTransaction = useRecordSendTransaction;
1018
+ exports.useRevokeSessionKey = useRevokeSessionKey;
549
1019
  exports.useStakeVesuUsdc = useStakeVesuUsdc;
550
1020
  exports.useTransfer = useTransfer;
551
1021
  exports.useWithdrawVesuUsdc = useWithdrawVesuUsdc;