@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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import React, { createContext, useContext } from 'react';
1
+ import React, { createContext, useContext, useMemo, useCallback, useState, useEffect } from 'react';
2
2
  import { QueryClient, QueryClientProvider, useMutation, useQueryClient, useQuery } from '@tanstack/react-query';
3
3
  import { ChipiSDK } from '@chipi-stack/backend';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -109,6 +109,367 @@ function useGetWallet(input) {
109
109
  fetchWallet
110
110
  };
111
111
  }
112
+ function useChipiWallet(config) {
113
+ const { chipiSDK } = useChipiContext();
114
+ const queryClient = useQueryClient();
115
+ const {
116
+ externalUserId,
117
+ getBearerToken,
118
+ defaultToken = "USDC",
119
+ enabled = true
120
+ } = config;
121
+ const isEnabled = Boolean(
122
+ enabled && externalUserId && externalUserId.trim() !== ""
123
+ );
124
+ const walletQuery = useQuery({
125
+ queryKey: ["chipi-wallet", externalUserId],
126
+ queryFn: async () => {
127
+ if (!externalUserId) return null;
128
+ const bearerToken = await getBearerToken();
129
+ if (!bearerToken) throw new Error("Bearer token is required");
130
+ return chipiSDK.getWallet({ externalUserId }, bearerToken);
131
+ },
132
+ enabled: isEnabled,
133
+ retry: (failureCount, error) => {
134
+ if (error instanceof ChipiApiError || error?.status) {
135
+ return false;
136
+ }
137
+ return failureCount < 3;
138
+ }
139
+ });
140
+ const walletPublicKey = walletQuery.data?.wallet.publicKey;
141
+ const balanceQuery = useQuery({
142
+ queryKey: ["chipi-wallet-balance", walletPublicKey, defaultToken],
143
+ queryFn: async () => {
144
+ if (!walletPublicKey) throw new Error("No wallet");
145
+ const bearerToken = await getBearerToken();
146
+ if (!bearerToken) throw new Error("Bearer token is required");
147
+ return chipiSDK.getTokenBalance(
148
+ {
149
+ chain: "STARKNET",
150
+ chainToken: defaultToken,
151
+ walletPublicKey
152
+ },
153
+ bearerToken
154
+ );
155
+ },
156
+ enabled: Boolean(walletPublicKey),
157
+ retry: (failureCount, error) => {
158
+ if (error instanceof ChipiApiError || error?.status) {
159
+ return false;
160
+ }
161
+ return failureCount < 3;
162
+ }
163
+ });
164
+ const createWalletMutation = useMutation({
165
+ mutationFn: async ({ encryptKey, walletType = "CHIPI" }) => {
166
+ if (!externalUserId) throw new Error("External user ID is required");
167
+ const bearerToken = await getBearerToken();
168
+ if (!bearerToken) throw new Error("Bearer token is required");
169
+ return chipiSDK.createWallet({
170
+ params: {
171
+ encryptKey,
172
+ externalUserId,
173
+ walletType
174
+ },
175
+ bearerToken
176
+ });
177
+ },
178
+ onSuccess: () => {
179
+ queryClient.invalidateQueries({
180
+ queryKey: ["chipi-wallet", externalUserId]
181
+ });
182
+ }
183
+ });
184
+ const wallet = useMemo(() => {
185
+ if (walletQuery.isLoading) return void 0;
186
+ if (!walletQuery.data) return null;
187
+ const data = walletQuery.data;
188
+ return {
189
+ ...data,
190
+ supportsSessionKeys: data.wallet.walletType === "CHIPI",
191
+ shortAddress: formatAddress(data.wallet.publicKey)
192
+ };
193
+ }, [walletQuery.data, walletQuery.isLoading]);
194
+ const formattedBalance = useMemo(() => {
195
+ if (!balanceQuery.data?.balance) return "0.00";
196
+ const num = Number(balanceQuery.data.balance);
197
+ return num.toLocaleString(void 0, {
198
+ minimumFractionDigits: 2,
199
+ maximumFractionDigits: defaultToken === "ETH" || defaultToken === "STRK" ? 6 : 2
200
+ });
201
+ }, [balanceQuery.data, defaultToken]);
202
+ const refetchWallet = useCallback(async () => {
203
+ await walletQuery.refetch();
204
+ }, [walletQuery]);
205
+ const refetchBalance = useCallback(async () => {
206
+ await balanceQuery.refetch();
207
+ }, [balanceQuery]);
208
+ const refetchAll = useCallback(async () => {
209
+ await Promise.all([walletQuery.refetch(), balanceQuery.refetch()]);
210
+ }, [walletQuery, balanceQuery]);
211
+ const createWallet = useCallback(
212
+ async (params) => {
213
+ return createWalletMutation.mutateAsync(params);
214
+ },
215
+ [createWalletMutation]
216
+ );
217
+ return {
218
+ // Wallet data
219
+ wallet,
220
+ hasWallet: wallet !== null && wallet !== void 0,
221
+ isLoadingWallet: walletQuery.isLoading,
222
+ walletError: walletQuery.error,
223
+ // Balance data
224
+ balance: balanceQuery.data,
225
+ formattedBalance,
226
+ isLoadingBalance: balanceQuery.isLoading,
227
+ // Create wallet
228
+ createWallet,
229
+ isCreating: createWalletMutation.isPending,
230
+ createdWallet: createWalletMutation.data,
231
+ // Actions
232
+ refetchWallet,
233
+ refetchBalance,
234
+ refetchAll
235
+ };
236
+ }
237
+ function formatAddress(address, chars = 6) {
238
+ if (!address || address.length < chars * 2) return address;
239
+ return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
240
+ }
241
+ function useChipiSession(config) {
242
+ const { chipiSDK } = useChipiContext();
243
+ const queryClient = useQueryClient();
244
+ const {
245
+ wallet,
246
+ encryptKey,
247
+ getBearerToken,
248
+ storedSession,
249
+ onSessionCreated,
250
+ defaultDurationSeconds = 21600,
251
+ // 6 hours
252
+ defaultMaxCalls = 1e3,
253
+ autoCheckStatus = true
254
+ } = config;
255
+ const [localSession, setLocalSession] = useState(
256
+ storedSession ?? null
257
+ );
258
+ const [error, setError] = useState(null);
259
+ useEffect(() => {
260
+ if (storedSession) {
261
+ setLocalSession(storedSession);
262
+ }
263
+ }, [storedSession]);
264
+ const supportsSession = useMemo(() => {
265
+ if (!wallet) return false;
266
+ return wallet.walletType === "CHIPI";
267
+ }, [wallet]);
268
+ const sessionStatusQuery = useQuery({
269
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey],
270
+ queryFn: async () => {
271
+ if (!wallet?.publicKey || !localSession?.publicKey) return null;
272
+ return chipiSDK.sessions.getSessionData({
273
+ walletAddress: wallet.publicKey,
274
+ sessionPublicKey: localSession.publicKey
275
+ });
276
+ },
277
+ enabled: Boolean(
278
+ autoCheckStatus && wallet?.publicKey && localSession?.publicKey && supportsSession
279
+ ),
280
+ staleTime: 3e4
281
+ // 30 seconds
282
+ });
283
+ const sessionState = useMemo(() => {
284
+ if (!localSession) return "none";
285
+ const status = sessionStatusQuery.data;
286
+ if (status) {
287
+ if (!status.isActive) return "revoked";
288
+ if (status.validUntil * 1e3 < Date.now()) return "expired";
289
+ if (status.remainingCalls <= 0) return "expired";
290
+ return "active";
291
+ }
292
+ if (localSession.validUntil * 1e3 < Date.now()) return "expired";
293
+ return "created";
294
+ }, [localSession, sessionStatusQuery.data]);
295
+ const hasActiveSession = sessionState === "active";
296
+ const isSessionExpired = sessionState === "expired";
297
+ const remainingCalls = sessionStatusQuery.data?.remainingCalls;
298
+ const createSessionMutation = useMutation({
299
+ mutationFn: async (params = {}) => {
300
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
301
+ if (!supportsSession) throw new Error("Wallet does not support sessions. Only CHIPI wallets support session keys.");
302
+ const sessionData = chipiSDK.sessions.createSessionKey({
303
+ encryptKey,
304
+ durationSeconds: params.durationSeconds ?? defaultDurationSeconds
305
+ });
306
+ return sessionData;
307
+ },
308
+ onSuccess: async (sessionData) => {
309
+ setLocalSession(sessionData);
310
+ setError(null);
311
+ if (onSessionCreated) {
312
+ await onSessionCreated(sessionData);
313
+ }
314
+ },
315
+ onError: (err) => {
316
+ setError(err);
317
+ }
318
+ });
319
+ const registerSessionMutation = useMutation({
320
+ mutationFn: async (sessionConfig = {}) => {
321
+ if (!wallet) throw new Error("Wallet is required");
322
+ if (!localSession) throw new Error("No session to register. Call createSession first.");
323
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
324
+ if (!supportsSession) throw new Error("Wallet does not support sessions");
325
+ const bearerToken = await getBearerToken();
326
+ if (!bearerToken) throw new Error("Bearer token is required");
327
+ const txHash = await chipiSDK.sessions.addSessionKeyToContract(
328
+ {
329
+ encryptKey,
330
+ wallet,
331
+ sessionConfig: {
332
+ sessionPublicKey: localSession.publicKey,
333
+ validUntil: sessionConfig.validUntil ?? localSession.validUntil,
334
+ maxCalls: sessionConfig.maxCalls ?? defaultMaxCalls,
335
+ allowedEntrypoints: sessionConfig.allowedEntrypoints ?? []
336
+ }
337
+ },
338
+ bearerToken
339
+ );
340
+ return txHash;
341
+ },
342
+ onSuccess: () => {
343
+ setError(null);
344
+ queryClient.invalidateQueries({
345
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
346
+ });
347
+ },
348
+ onError: (err) => {
349
+ setError(err);
350
+ }
351
+ });
352
+ const revokeSessionMutation = useMutation({
353
+ mutationFn: async () => {
354
+ if (!wallet) throw new Error("Wallet is required");
355
+ if (!localSession) throw new Error("No session to revoke");
356
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
357
+ if (!supportsSession) throw new Error("Wallet does not support sessions");
358
+ const bearerToken = await getBearerToken();
359
+ if (!bearerToken) throw new Error("Bearer token is required");
360
+ const txHash = await chipiSDK.sessions.revokeSessionKey(
361
+ {
362
+ encryptKey,
363
+ wallet,
364
+ sessionPublicKey: localSession.publicKey
365
+ },
366
+ bearerToken
367
+ );
368
+ return txHash;
369
+ },
370
+ onSuccess: () => {
371
+ setError(null);
372
+ queryClient.invalidateQueries({
373
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
374
+ });
375
+ },
376
+ onError: (err) => {
377
+ setError(err);
378
+ }
379
+ });
380
+ const executeWithSessionMutation = useMutation({
381
+ mutationFn: async (calls) => {
382
+ if (!wallet) throw new Error("Wallet is required");
383
+ if (!localSession) throw new Error("No active session");
384
+ if (!encryptKey) throw new Error("Encryption key (PIN) is required");
385
+ if (!hasActiveSession) throw new Error("Session is not active. Register the session first.");
386
+ const bearerToken = await getBearerToken();
387
+ if (!bearerToken) throw new Error("Bearer token is required");
388
+ const txHash = await chipiSDK.executeTransactionWithSession({
389
+ params: {
390
+ encryptKey,
391
+ wallet,
392
+ session: localSession,
393
+ calls
394
+ },
395
+ bearerToken
396
+ });
397
+ return txHash;
398
+ },
399
+ onSuccess: () => {
400
+ setError(null);
401
+ queryClient.invalidateQueries({
402
+ queryKey: ["chipi-session-status", wallet?.publicKey, localSession?.publicKey]
403
+ });
404
+ },
405
+ onError: (err) => {
406
+ setError(err);
407
+ }
408
+ });
409
+ const createSession = useCallback(
410
+ async (params) => {
411
+ return createSessionMutation.mutateAsync(params ?? {});
412
+ },
413
+ [createSessionMutation]
414
+ );
415
+ const registerSession = useCallback(
416
+ async (sessionConfig) => {
417
+ return registerSessionMutation.mutateAsync(sessionConfig ?? {});
418
+ },
419
+ [registerSessionMutation]
420
+ );
421
+ const revokeSession = useCallback(async () => {
422
+ return revokeSessionMutation.mutateAsync();
423
+ }, [revokeSessionMutation]);
424
+ const executeWithSession = useCallback(
425
+ async (calls) => {
426
+ return executeWithSessionMutation.mutateAsync(calls);
427
+ },
428
+ [executeWithSessionMutation]
429
+ );
430
+ const clearSession = useCallback(() => {
431
+ setLocalSession(null);
432
+ setError(null);
433
+ }, []);
434
+ const refetchStatus = useCallback(async () => {
435
+ await sessionStatusQuery.refetch();
436
+ }, [sessionStatusQuery]);
437
+ const combinedError = useMemo(() => {
438
+ return error || createSessionMutation.error || registerSessionMutation.error || revokeSessionMutation.error || executeWithSessionMutation.error || sessionStatusQuery.error || null;
439
+ }, [
440
+ error,
441
+ createSessionMutation.error,
442
+ registerSessionMutation.error,
443
+ revokeSessionMutation.error,
444
+ executeWithSessionMutation.error,
445
+ sessionStatusQuery.error
446
+ ]);
447
+ return {
448
+ // Session data
449
+ session: localSession,
450
+ sessionStatus: sessionStatusQuery.data ?? void 0,
451
+ sessionState,
452
+ hasActiveSession,
453
+ isSessionExpired,
454
+ remainingCalls,
455
+ supportsSession,
456
+ // Actions
457
+ createSession,
458
+ registerSession,
459
+ revokeSession,
460
+ executeWithSession,
461
+ clearSession,
462
+ refetchStatus,
463
+ // Loading states
464
+ isCreating: createSessionMutation.isPending,
465
+ isRegistering: registerSessionMutation.isPending,
466
+ isRevoking: revokeSessionMutation.isPending,
467
+ isExecuting: executeWithSessionMutation.isPending,
468
+ isLoadingStatus: sessionStatusQuery.isLoading,
469
+ // Errors
470
+ error: combinedError
471
+ };
472
+ }
112
473
  function useTransfer() {
113
474
  const { chipiSDK } = useChipiContext();
114
475
  const mutation = useMutation(
@@ -436,8 +797,15 @@ function useRecordSendTransaction() {
436
797
  function useGetTokenBalance(input) {
437
798
  const { chipiSDK } = useChipiContext();
438
799
  const queryClient = useQueryClient();
800
+ const buildQueryKey = (params) => [
801
+ "chain-token-balance",
802
+ params?.chainToken ?? null,
803
+ params?.chain ?? null,
804
+ params?.walletPublicKey ?? null,
805
+ params?.externalUserId ?? null
806
+ ];
439
807
  const query = useQuery({
440
- queryKey: ["chain-token-balance", input?.params?.chainToken, input?.params?.chain, input?.params?.walletPublicKey, input?.params?.externalUserId],
808
+ queryKey: buildQueryKey(input?.params),
441
809
  queryFn: async () => {
442
810
  if (!input || !input.params || !input.getBearerToken) throw new Error("Input is required");
443
811
  const bearerToken = await input.getBearerToken();
@@ -445,17 +813,17 @@ function useGetTokenBalance(input) {
445
813
  return chipiSDK.getTokenBalance(input.params, bearerToken);
446
814
  },
447
815
  enabled: Boolean(input?.params && input?.getBearerToken),
448
- ...input?.queryOptions,
449
816
  retry: (failureCount, error) => {
450
817
  if (error instanceof ChipiApiError || error?.status) {
451
818
  return false;
452
819
  }
453
820
  return failureCount < 3;
454
- }
821
+ },
822
+ ...input?.queryOptions
455
823
  });
456
824
  const fetchTokenBalance = async (newInput) => {
457
825
  return queryClient.fetchQuery({
458
- queryKey: ["chain-token-balance", newInput?.params?.chainToken, newInput?.params?.chain, newInput?.params?.walletPublicKey, newInput?.params?.externalUserId],
826
+ queryKey: buildQueryKey(newInput?.params),
459
827
  queryFn: async () => {
460
828
  if (!newInput || !newInput.getBearerToken || !newInput.params) throw new Error("Input is required");
461
829
  const bearerToken = await newInput.getBearerToken();
@@ -559,7 +927,102 @@ function useCreateUser() {
559
927
  reset: mutation.reset
560
928
  };
561
929
  }
930
+ function useCreateSessionKey() {
931
+ const { chipiSDK } = useChipiContext();
932
+ const mutation = useMutation({
933
+ mutationFn: async (params) => chipiSDK.sessions.createSessionKey(params)
934
+ });
935
+ return {
936
+ createSessionKey: mutation.mutate,
937
+ createSessionKeyAsync: mutation.mutateAsync,
938
+ data: mutation.data,
939
+ isLoading: mutation.isPending,
940
+ isError: mutation.isError,
941
+ error: mutation.error,
942
+ isSuccess: mutation.isSuccess,
943
+ reset: mutation.reset
944
+ };
945
+ }
946
+ function useAddSessionKeyToContract() {
947
+ const { chipiSDK } = useChipiContext();
948
+ const mutation = useMutation({
949
+ mutationFn: (input) => chipiSDK.sessions.addSessionKeyToContract(
950
+ input.params,
951
+ input.bearerToken
952
+ )
953
+ });
954
+ return {
955
+ addSessionKeyToContract: mutation.mutate,
956
+ addSessionKeyToContractAsync: mutation.mutateAsync,
957
+ data: mutation.data,
958
+ isLoading: mutation.isPending,
959
+ isError: mutation.isError,
960
+ error: mutation.error,
961
+ isSuccess: mutation.isSuccess,
962
+ reset: mutation.reset
963
+ };
964
+ }
965
+ function useRevokeSessionKey() {
966
+ const { chipiSDK } = useChipiContext();
967
+ const mutation = useMutation({
968
+ mutationFn: (input) => chipiSDK.sessions.revokeSessionKey(input.params, input.bearerToken)
969
+ });
970
+ return {
971
+ revokeSessionKey: mutation.mutate,
972
+ revokeSessionKeyAsync: mutation.mutateAsync,
973
+ data: mutation.data,
974
+ isLoading: mutation.isPending,
975
+ isError: mutation.isError,
976
+ error: mutation.error,
977
+ isSuccess: mutation.isSuccess,
978
+ reset: mutation.reset
979
+ };
980
+ }
981
+ function useGetSessionData(params, options) {
982
+ const { chipiSDK } = useChipiContext();
983
+ const query = useQuery({
984
+ queryKey: [
985
+ "sessionData",
986
+ params?.walletAddress,
987
+ params?.sessionPublicKey
988
+ ],
989
+ queryFn: () => {
990
+ if (!params) {
991
+ throw new Error("Session data params are required");
992
+ }
993
+ return chipiSDK.sessions.getSessionData(params);
994
+ },
995
+ enabled: options?.enabled !== false && params !== null
996
+ });
997
+ return {
998
+ data: query.data,
999
+ isLoading: query.isLoading,
1000
+ isError: query.isError,
1001
+ error: query.error,
1002
+ isSuccess: query.isSuccess,
1003
+ refetch: query.refetch
1004
+ };
1005
+ }
1006
+ function useExecuteWithSession() {
1007
+ const { chipiSDK } = useChipiContext();
1008
+ const mutation = useMutation({
1009
+ mutationFn: (input) => chipiSDK.executeTransactionWithSession({
1010
+ params: input.params,
1011
+ bearerToken: input.bearerToken
1012
+ })
1013
+ });
1014
+ return {
1015
+ executeWithSession: mutation.mutate,
1016
+ executeWithSessionAsync: mutation.mutateAsync,
1017
+ data: mutation.data,
1018
+ isLoading: mutation.isPending,
1019
+ isError: mutation.isError,
1020
+ error: mutation.error,
1021
+ isSuccess: mutation.isSuccess,
1022
+ reset: mutation.reset
1023
+ };
1024
+ }
562
1025
 
563
- export { ChipiProvider, useApprove, useCallAnyContract, useChipiContext, useCreateSkuTransaction, useCreateUser, useCreateWallet, useGetSku, useGetSkuList, useGetSkuTransaction, useGetTokenBalance, useGetTransactionList, useGetUser, useGetWallet, useRecordSendTransaction, useStakeVesuUsdc, useTransfer, useWithdrawVesuUsdc };
1026
+ export { ChipiProvider, useAddSessionKeyToContract, useApprove, useCallAnyContract, useChipiContext, useChipiSession, useChipiWallet, useCreateSessionKey, useCreateSkuTransaction, useCreateUser, useCreateWallet, useExecuteWithSession, useGetSessionData, useGetSku, useGetSkuList, useGetSkuTransaction, useGetTokenBalance, useGetTransactionList, useGetUser, useGetWallet, useRecordSendTransaction, useRevokeSessionKey, useStakeVesuUsdc, useTransfer, useWithdrawVesuUsdc };
564
1027
  //# sourceMappingURL=index.mjs.map
565
1028
  //# sourceMappingURL=index.mjs.map