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