@iamgame/wallet-sdk 0.1.4 → 0.1.5
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 +135 -83
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +59 -12
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var reactDom = require('react-dom');
|
|
6
6
|
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
|
+
|
|
7
11
|
// ../../solven/sdk-client/src/errors.ts
|
|
8
12
|
var SolvenSdkError = class _SolvenSdkError extends Error {
|
|
9
13
|
constructor(args) {
|
|
@@ -268,22 +272,48 @@ function notifyTelegramReady() {
|
|
|
268
272
|
} catch {
|
|
269
273
|
}
|
|
270
274
|
}
|
|
271
|
-
var SolvenContext =
|
|
275
|
+
var SolvenContext = React.createContext(null);
|
|
272
276
|
function useSolvenContext() {
|
|
273
|
-
const ctx =
|
|
277
|
+
const ctx = React.useContext(SolvenContext);
|
|
274
278
|
if (!ctx) throw new Error("useSolvenContext must be inside a <SolvenProvider />");
|
|
275
279
|
return ctx;
|
|
276
280
|
}
|
|
277
|
-
function
|
|
278
|
-
|
|
281
|
+
function useSolvenReportError() {
|
|
282
|
+
return useSolvenContext().reportError;
|
|
283
|
+
}
|
|
284
|
+
var SolvenErrorBoundary = class extends React__default.default.Component {
|
|
285
|
+
constructor() {
|
|
286
|
+
super(...arguments);
|
|
287
|
+
this.state = { hasError: false };
|
|
288
|
+
}
|
|
289
|
+
static getDerivedStateFromError() {
|
|
290
|
+
return { hasError: true };
|
|
291
|
+
}
|
|
292
|
+
componentDidCatch(error) {
|
|
293
|
+
this.props.onError(error, { operation: "render" });
|
|
294
|
+
}
|
|
295
|
+
render() {
|
|
296
|
+
return this.state.hasError ? null : this.props.children;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
function SolvenProvider({ children, autoTelegram = true, onError, ...opts }) {
|
|
300
|
+
const client = React.useMemo(() => new SolvenClient(opts), [
|
|
279
301
|
opts.publishableKey,
|
|
280
302
|
opts.baseUrl,
|
|
281
303
|
opts.storage,
|
|
282
304
|
opts.fetchImpl
|
|
283
305
|
]);
|
|
284
|
-
const [session, setSession] =
|
|
285
|
-
const [status, setStatus] =
|
|
286
|
-
|
|
306
|
+
const [session, setSession] = React.useState(client.getSession());
|
|
307
|
+
const [status, setStatus] = React.useState("loading");
|
|
308
|
+
const onErrorRef = React.useRef(onError);
|
|
309
|
+
onErrorRef.current = onError;
|
|
310
|
+
const reportError = React.useCallback((error, context) => {
|
|
311
|
+
try {
|
|
312
|
+
onErrorRef.current?.(error, context);
|
|
313
|
+
} catch {
|
|
314
|
+
}
|
|
315
|
+
}, []);
|
|
316
|
+
React.useEffect(() => {
|
|
287
317
|
let cancelled = false;
|
|
288
318
|
(async () => {
|
|
289
319
|
const stored = client.getSession();
|
|
@@ -315,8 +345,8 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
315
345
|
cancelled = true;
|
|
316
346
|
};
|
|
317
347
|
}, [client]);
|
|
318
|
-
const triedTelegram =
|
|
319
|
-
|
|
348
|
+
const triedTelegram = React.useRef(false);
|
|
349
|
+
React.useEffect(() => {
|
|
320
350
|
if (!autoTelegram || status !== "anonymous" || triedTelegram.current) return;
|
|
321
351
|
triedTelegram.current = true;
|
|
322
352
|
let cancelled = false;
|
|
@@ -348,15 +378,16 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
348
378
|
setSession: (s) => {
|
|
349
379
|
setSession(s);
|
|
350
380
|
setStatus(s ? "authenticated" : "anonymous");
|
|
351
|
-
}
|
|
381
|
+
},
|
|
382
|
+
reportError
|
|
352
383
|
};
|
|
353
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SolvenContext.Provider, { value, children });
|
|
384
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SolvenContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(SolvenErrorBoundary, { onError: reportError, children }) });
|
|
354
385
|
}
|
|
355
386
|
|
|
356
387
|
// ../../solven/sdk-client/src/hooks.ts
|
|
357
388
|
function useSolvenAuth() {
|
|
358
389
|
const { client, session, status, setSession } = useSolvenContext();
|
|
359
|
-
const connectExternal =
|
|
390
|
+
const connectExternal = React.useCallback(
|
|
360
391
|
async (adapter) => {
|
|
361
392
|
const { publicKey } = await adapter.connect();
|
|
362
393
|
const challenge = await client.requestSiwsChallenge(publicKey);
|
|
@@ -367,27 +398,27 @@ function useSolvenAuth() {
|
|
|
367
398
|
},
|
|
368
399
|
[client, setSession]
|
|
369
400
|
);
|
|
370
|
-
const connectTelegram =
|
|
401
|
+
const connectTelegram = React.useCallback(async () => {
|
|
371
402
|
const initData = getTelegramInitData();
|
|
372
403
|
if (!initData) throw new Error("Not running inside a Telegram Mini App.");
|
|
373
404
|
const session2 = await client.verifyTelegram({ initData });
|
|
374
405
|
setSession(session2);
|
|
375
406
|
}, [client, setSession]);
|
|
376
|
-
const requestEmailOtp =
|
|
407
|
+
const requestEmailOtp = React.useCallback(
|
|
377
408
|
async (email) => {
|
|
378
409
|
const { expiresAt } = await client.initiateEmail(email);
|
|
379
410
|
return { expiresAt };
|
|
380
411
|
},
|
|
381
412
|
[client]
|
|
382
413
|
);
|
|
383
|
-
const connectEmail =
|
|
414
|
+
const connectEmail = React.useCallback(
|
|
384
415
|
async (email, code) => {
|
|
385
416
|
const session2 = await client.verifyEmail(email, code);
|
|
386
417
|
setSession(session2);
|
|
387
418
|
},
|
|
388
419
|
[client, setSession]
|
|
389
420
|
);
|
|
390
|
-
const logout =
|
|
421
|
+
const logout = React.useCallback(async () => {
|
|
391
422
|
await client.logout();
|
|
392
423
|
setSession(null);
|
|
393
424
|
}, [client, setSession]);
|
|
@@ -403,25 +434,29 @@ function useSolvenAuth() {
|
|
|
403
434
|
};
|
|
404
435
|
}
|
|
405
436
|
function useSolvenWallet() {
|
|
406
|
-
const { client, status } = useSolvenContext();
|
|
407
|
-
const [wallet, setWallet] =
|
|
408
|
-
|
|
437
|
+
const { client, status, reportError } = useSolvenContext();
|
|
438
|
+
const [wallet, setWallet] = React.useState(null);
|
|
439
|
+
React.useEffect(() => {
|
|
409
440
|
if (status !== "authenticated") {
|
|
410
441
|
setWallet(null);
|
|
411
442
|
return;
|
|
412
443
|
}
|
|
413
444
|
let cancelled = false;
|
|
414
|
-
client.getMyWallet().then((w) => !cancelled && setWallet(w)).catch(() =>
|
|
445
|
+
client.getMyWallet().then((w) => !cancelled && setWallet(w)).catch((e) => {
|
|
446
|
+
if (cancelled) return;
|
|
447
|
+
reportError(e, { operation: "wallet:load" });
|
|
448
|
+
setWallet(null);
|
|
449
|
+
});
|
|
415
450
|
return () => {
|
|
416
451
|
cancelled = true;
|
|
417
452
|
};
|
|
418
|
-
}, [client, status]);
|
|
453
|
+
}, [client, status, reportError]);
|
|
419
454
|
return wallet;
|
|
420
455
|
}
|
|
421
456
|
function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
422
457
|
const { client, status } = useSolvenContext();
|
|
423
|
-
const [balance, setBalance] =
|
|
424
|
-
|
|
458
|
+
const [balance, setBalance] = React.useState(null);
|
|
459
|
+
React.useEffect(() => {
|
|
425
460
|
if (status !== "authenticated" || !walletId) {
|
|
426
461
|
setBalance(null);
|
|
427
462
|
return;
|
|
@@ -444,25 +479,32 @@ function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
|
444
479
|
return balance;
|
|
445
480
|
}
|
|
446
481
|
function useSolvenSign() {
|
|
447
|
-
const { client } = useSolvenContext();
|
|
448
|
-
const signAction =
|
|
449
|
-
({ walletId, txBase64, label, idempotencyKey }) =>
|
|
450
|
-
|
|
482
|
+
const { client, reportError } = useSolvenContext();
|
|
483
|
+
const signAction = React.useCallback(
|
|
484
|
+
async ({ walletId, txBase64, label, idempotencyKey }) => {
|
|
485
|
+
try {
|
|
486
|
+
return await client.signAction({ walletId, txBase64, label }, idempotencyKey);
|
|
487
|
+
} catch (e) {
|
|
488
|
+
reportError(e, { operation: "sign" });
|
|
489
|
+
throw e;
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
[client, reportError]
|
|
451
493
|
);
|
|
452
494
|
return { signAction };
|
|
453
495
|
}
|
|
454
496
|
function useSolvenExport(walletId) {
|
|
455
497
|
const { client } = useSolvenContext();
|
|
456
|
-
const [preflight, setPreflight] =
|
|
457
|
-
const refreshPreflight =
|
|
498
|
+
const [preflight, setPreflight] = React.useState(null);
|
|
499
|
+
const refreshPreflight = React.useCallback(async () => {
|
|
458
500
|
if (!walletId) return;
|
|
459
501
|
const p = await client.exportPreflight(walletId);
|
|
460
502
|
setPreflight(p);
|
|
461
503
|
}, [client, walletId]);
|
|
462
|
-
|
|
504
|
+
React.useEffect(() => {
|
|
463
505
|
if (walletId) void refreshPreflight();
|
|
464
506
|
}, [walletId, refreshPreflight]);
|
|
465
|
-
const exportKey =
|
|
507
|
+
const exportKey = React.useCallback(
|
|
466
508
|
async (idempotencyKey) => {
|
|
467
509
|
if (!walletId) throw new Error("No wallet selected for export");
|
|
468
510
|
return client.exportWallet(walletId, idempotencyKey);
|
|
@@ -476,8 +518,8 @@ function useSolvenTransferIn() {
|
|
|
476
518
|
return { destinationAddress: wallet?.address ?? null };
|
|
477
519
|
}
|
|
478
520
|
function useIsTelegram() {
|
|
479
|
-
const [inTelegram, setInTelegram] =
|
|
480
|
-
|
|
521
|
+
const [inTelegram, setInTelegram] = React.useState(false);
|
|
522
|
+
React.useEffect(() => {
|
|
481
523
|
setInTelegram(isTelegramMiniApp());
|
|
482
524
|
}, []);
|
|
483
525
|
return inTelegram;
|
|
@@ -598,20 +640,21 @@ var defaultTheme = {
|
|
|
598
640
|
};
|
|
599
641
|
function SolvenLoginContent(props) {
|
|
600
642
|
const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
|
|
601
|
-
const
|
|
602
|
-
const [
|
|
603
|
-
const [
|
|
604
|
-
const [
|
|
605
|
-
const [
|
|
643
|
+
const reportError = useSolvenReportError();
|
|
644
|
+
const [busy, setBusy] = React.useState(null);
|
|
645
|
+
const [error, setError] = React.useState(null);
|
|
646
|
+
const [email, setEmail] = React.useState("");
|
|
647
|
+
const [otp, setOtp] = React.useState("");
|
|
648
|
+
const [otpSent, setOtpSent] = React.useState(false);
|
|
606
649
|
const showEmail = props.showEmail ?? true;
|
|
607
|
-
const theme =
|
|
650
|
+
const theme = React.useMemo(
|
|
608
651
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
609
652
|
[props.theme]
|
|
610
653
|
);
|
|
611
|
-
const inTma =
|
|
654
|
+
const inTma = React.useMemo(() => isTelegramMiniApp(), []);
|
|
612
655
|
const autoTelegram = props.autoTelegram ?? true;
|
|
613
|
-
const wallets =
|
|
614
|
-
|
|
656
|
+
const wallets = React.useMemo(listSupportedWallets, []);
|
|
657
|
+
React.useEffect(() => {
|
|
615
658
|
notifyTelegramReady();
|
|
616
659
|
if (!inTma || !autoTelegram) return;
|
|
617
660
|
if (status === "authenticated") return;
|
|
@@ -626,6 +669,7 @@ function SolvenLoginContent(props) {
|
|
|
626
669
|
props.onCloseAfterSignIn?.();
|
|
627
670
|
} catch (e) {
|
|
628
671
|
if (!cancelled) {
|
|
672
|
+
reportError(e, { operation: "login:telegram" });
|
|
629
673
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
630
674
|
}
|
|
631
675
|
} finally {
|
|
@@ -652,6 +696,7 @@ function SolvenLoginContent(props) {
|
|
|
652
696
|
props.onSignIn?.();
|
|
653
697
|
props.onCloseAfterSignIn?.();
|
|
654
698
|
} catch (e) {
|
|
699
|
+
reportError(e, { operation: "login:wallet" });
|
|
655
700
|
setError(e instanceof Error ? e.message : "Wallet sign-in failed");
|
|
656
701
|
} finally {
|
|
657
702
|
setBusy(null);
|
|
@@ -665,6 +710,7 @@ function SolvenLoginContent(props) {
|
|
|
665
710
|
props.onSignIn?.();
|
|
666
711
|
props.onCloseAfterSignIn?.();
|
|
667
712
|
} catch (e) {
|
|
713
|
+
reportError(e, { operation: "login:telegram" });
|
|
668
714
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
669
715
|
} finally {
|
|
670
716
|
setBusy(null);
|
|
@@ -677,6 +723,7 @@ function SolvenLoginContent(props) {
|
|
|
677
723
|
await requestEmailOtp(email.trim());
|
|
678
724
|
setOtpSent(true);
|
|
679
725
|
} catch (e) {
|
|
726
|
+
reportError(e, { operation: "login:email" });
|
|
680
727
|
setError(e instanceof Error ? e.message : "Couldn't send the code");
|
|
681
728
|
} finally {
|
|
682
729
|
setBusy(null);
|
|
@@ -690,6 +737,7 @@ function SolvenLoginContent(props) {
|
|
|
690
737
|
props.onSignIn?.();
|
|
691
738
|
props.onCloseAfterSignIn?.();
|
|
692
739
|
} catch (e) {
|
|
740
|
+
reportError(e, { operation: "login:email" });
|
|
693
741
|
setError(e instanceof Error ? e.message : "Couldn't verify the code");
|
|
694
742
|
} finally {
|
|
695
743
|
setBusy(null);
|
|
@@ -927,7 +975,7 @@ function SolvenLoginContent(props) {
|
|
|
927
975
|
] });
|
|
928
976
|
}
|
|
929
977
|
function SolvenLogin(props) {
|
|
930
|
-
const theme =
|
|
978
|
+
const theme = React.useMemo(
|
|
931
979
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
932
980
|
[props.theme]
|
|
933
981
|
);
|
|
@@ -960,17 +1008,17 @@ function SolvenLoginModal(props) {
|
|
|
960
1008
|
closeOnEscape = true,
|
|
961
1009
|
...content
|
|
962
1010
|
} = props;
|
|
963
|
-
const theme =
|
|
1011
|
+
const theme = React.useMemo(
|
|
964
1012
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
965
1013
|
[props.theme]
|
|
966
1014
|
);
|
|
967
|
-
const dialogRef =
|
|
968
|
-
const previouslyFocused =
|
|
969
|
-
const [mounted, setMounted] =
|
|
970
|
-
|
|
1015
|
+
const dialogRef = React.useRef(null);
|
|
1016
|
+
const previouslyFocused = React.useRef(null);
|
|
1017
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1018
|
+
React.useEffect(() => {
|
|
971
1019
|
setMounted(true);
|
|
972
1020
|
}, []);
|
|
973
|
-
|
|
1021
|
+
React.useEffect(() => {
|
|
974
1022
|
if (!isOpen || !closeOnEscape) return;
|
|
975
1023
|
const onKey = (e) => {
|
|
976
1024
|
if (e.key === "Escape") {
|
|
@@ -981,7 +1029,7 @@ function SolvenLoginModal(props) {
|
|
|
981
1029
|
window.addEventListener("keydown", onKey);
|
|
982
1030
|
return () => window.removeEventListener("keydown", onKey);
|
|
983
1031
|
}, [isOpen, closeOnEscape, onClose]);
|
|
984
|
-
|
|
1032
|
+
React.useEffect(() => {
|
|
985
1033
|
if (!isOpen) return;
|
|
986
1034
|
previouslyFocused.current = document.activeElement ?? null;
|
|
987
1035
|
queueMicrotask(() => {
|
|
@@ -1017,7 +1065,7 @@ function SolvenLoginModal(props) {
|
|
|
1017
1065
|
previouslyFocused.current?.focus?.();
|
|
1018
1066
|
};
|
|
1019
1067
|
}, [isOpen]);
|
|
1020
|
-
const handleBackdropClick =
|
|
1068
|
+
const handleBackdropClick = React.useCallback(
|
|
1021
1069
|
(e) => {
|
|
1022
1070
|
if (!closeOnBackdrop) return;
|
|
1023
1071
|
if (e.target === e.currentTarget) onClose();
|
|
@@ -1119,12 +1167,12 @@ function truncateAddress(address, chars) {
|
|
|
1119
1167
|
}
|
|
1120
1168
|
function SolvenAddress(props) {
|
|
1121
1169
|
const wallet = useSolvenWallet();
|
|
1122
|
-
const theme =
|
|
1170
|
+
const theme = React.useMemo(() => ({ ...defaultTheme2, ...props.theme ?? {} }), [props.theme]);
|
|
1123
1171
|
const truncateChars = props.truncateChars ?? 6;
|
|
1124
1172
|
const showCopy = props.showCopy ?? true;
|
|
1125
1173
|
const label = props.label ?? "Wallet Address";
|
|
1126
|
-
const [copied, setCopied] =
|
|
1127
|
-
const handleCopy =
|
|
1174
|
+
const [copied, setCopied] = React.useState(false);
|
|
1175
|
+
const handleCopy = React.useCallback(async () => {
|
|
1128
1176
|
if (!wallet?.address) return;
|
|
1129
1177
|
try {
|
|
1130
1178
|
await navigator.clipboard.writeText(wallet.address);
|
|
@@ -1254,18 +1302,18 @@ function getTokenLabel(token) {
|
|
|
1254
1302
|
function SolvenBalance(props) {
|
|
1255
1303
|
const wallet = useSolvenWallet();
|
|
1256
1304
|
const balance = useSolvenBalance(wallet?.id ?? null, props.pollMs);
|
|
1257
|
-
const theme =
|
|
1305
|
+
const theme = React.useMemo(() => ({ ...defaultTheme3, ...props.theme ?? {} }), [props.theme]);
|
|
1258
1306
|
const showRefresh = props.showRefresh ?? true;
|
|
1259
1307
|
const label = props.label ?? "Balance";
|
|
1260
1308
|
const compact = props.compact ?? false;
|
|
1261
|
-
const [refreshing, setRefreshing] =
|
|
1262
|
-
const tokens =
|
|
1309
|
+
const [refreshing, setRefreshing] = React.useState(false);
|
|
1310
|
+
const tokens = React.useMemo(() => {
|
|
1263
1311
|
if (!balance?.tokens) return [];
|
|
1264
1312
|
if (!props.filterMints) return balance.tokens;
|
|
1265
1313
|
const set = new Set(props.filterMints);
|
|
1266
1314
|
return balance.tokens.filter((t) => set.has(t.mint));
|
|
1267
1315
|
}, [balance?.tokens, props.filterMints]);
|
|
1268
|
-
const handleRefresh =
|
|
1316
|
+
const handleRefresh = React.useCallback(() => {
|
|
1269
1317
|
setRefreshing(true);
|
|
1270
1318
|
setTimeout(() => setRefreshing(false), 1500);
|
|
1271
1319
|
}, []);
|
|
@@ -1465,26 +1513,26 @@ function isValidSolanaAddress(address) {
|
|
|
1465
1513
|
function SolvenWithdraw(props) {
|
|
1466
1514
|
const wallet = useSolvenWallet();
|
|
1467
1515
|
const balance = useSolvenBalance(wallet?.id ?? null);
|
|
1468
|
-
const { client } = useSolvenContext();
|
|
1469
|
-
const theme =
|
|
1516
|
+
const { client, reportError } = useSolvenContext();
|
|
1517
|
+
const theme = React.useMemo(() => ({ ...defaultTheme4, ...props.theme ?? {} }), [props.theme]);
|
|
1470
1518
|
const label = props.label ?? "Withdraw";
|
|
1471
|
-
const [toAddress, setToAddress] =
|
|
1472
|
-
const [amount, setAmount] =
|
|
1473
|
-
const [selectedMint, setSelectedMint] =
|
|
1474
|
-
const [busy, setBusy] =
|
|
1475
|
-
const [error, setError] =
|
|
1476
|
-
const [successSig, setSuccessSig] =
|
|
1477
|
-
const tokens =
|
|
1519
|
+
const [toAddress, setToAddress] = React.useState("");
|
|
1520
|
+
const [amount, setAmount] = React.useState("");
|
|
1521
|
+
const [selectedMint, setSelectedMint] = React.useState(props.mint ?? "SOL");
|
|
1522
|
+
const [busy, setBusy] = React.useState(false);
|
|
1523
|
+
const [error, setError] = React.useState(null);
|
|
1524
|
+
const [successSig, setSuccessSig] = React.useState(null);
|
|
1525
|
+
const tokens = React.useMemo(() => {
|
|
1478
1526
|
if (!balance?.tokens) return [];
|
|
1479
1527
|
if (props.mint) return balance.tokens.filter((t) => t.mint === props.mint);
|
|
1480
1528
|
return balance.tokens;
|
|
1481
1529
|
}, [balance?.tokens, props.mint]);
|
|
1482
|
-
const selectedToken =
|
|
1530
|
+
const selectedToken = React.useMemo(
|
|
1483
1531
|
() => tokens.find((t) => t.mint === selectedMint) ?? null,
|
|
1484
1532
|
[tokens, selectedMint]
|
|
1485
1533
|
);
|
|
1486
1534
|
const availableFormatted = selectedToken ? formatTokenAmount2(selectedToken) : "0";
|
|
1487
|
-
const handleMax =
|
|
1535
|
+
const handleMax = React.useCallback(() => {
|
|
1488
1536
|
if (!selectedToken) return;
|
|
1489
1537
|
if (selectedToken.mint === "SOL") {
|
|
1490
1538
|
const raw = BigInt(selectedToken.amount);
|
|
@@ -1500,7 +1548,7 @@ function SolvenWithdraw(props) {
|
|
|
1500
1548
|
setAmount(formatTokenAmount2(selectedToken));
|
|
1501
1549
|
}
|
|
1502
1550
|
}, [selectedToken]);
|
|
1503
|
-
const handleSubmit =
|
|
1551
|
+
const handleSubmit = React.useCallback(async () => {
|
|
1504
1552
|
setError(null);
|
|
1505
1553
|
setSuccessSig(null);
|
|
1506
1554
|
if (!wallet) {
|
|
@@ -1543,6 +1591,7 @@ function SolvenWithdraw(props) {
|
|
|
1543
1591
|
props.onSuccess?.(result.signature);
|
|
1544
1592
|
} catch (e) {
|
|
1545
1593
|
const msg = e instanceof Error ? e.message : "Withdrawal failed";
|
|
1594
|
+
reportError(e, { operation: "withdraw" });
|
|
1546
1595
|
setError(msg);
|
|
1547
1596
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1548
1597
|
} finally {
|
|
@@ -1781,16 +1830,17 @@ function formatLamports(lamports) {
|
|
|
1781
1830
|
function SolvenExport(props) {
|
|
1782
1831
|
const wallet = useSolvenWallet();
|
|
1783
1832
|
const { preflight, refreshPreflight, exportKey } = useSolvenExport(wallet?.id ?? null);
|
|
1784
|
-
const
|
|
1833
|
+
const reportError = useSolvenReportError();
|
|
1834
|
+
const theme = React.useMemo(() => ({ ...defaultTheme5, ...props.theme ?? {} }), [props.theme]);
|
|
1785
1835
|
const label = props.label ?? "Export Wallet";
|
|
1786
|
-
const [step, setStep] =
|
|
1787
|
-
const [busy, setBusy] =
|
|
1788
|
-
const [error, setError] =
|
|
1789
|
-
const [exportedKey, setExportedKey] =
|
|
1790
|
-
const [newAddress, setNewAddress] =
|
|
1791
|
-
const [bootstrapSig, setBootstrapSig] =
|
|
1792
|
-
const [keyCopied, setKeyCopied] =
|
|
1793
|
-
const handleExport =
|
|
1836
|
+
const [step, setStep] = React.useState("preflight");
|
|
1837
|
+
const [busy, setBusy] = React.useState(false);
|
|
1838
|
+
const [error, setError] = React.useState(null);
|
|
1839
|
+
const [exportedKey, setExportedKey] = React.useState(null);
|
|
1840
|
+
const [newAddress, setNewAddress] = React.useState(null);
|
|
1841
|
+
const [bootstrapSig, setBootstrapSig] = React.useState(null);
|
|
1842
|
+
const [keyCopied, setKeyCopied] = React.useState(false);
|
|
1843
|
+
const handleExport = React.useCallback(async () => {
|
|
1794
1844
|
setError(null);
|
|
1795
1845
|
setBusy(true);
|
|
1796
1846
|
try {
|
|
@@ -1802,13 +1852,14 @@ function SolvenExport(props) {
|
|
|
1802
1852
|
props.onSuccess?.(result.newWalletAddress);
|
|
1803
1853
|
} catch (e) {
|
|
1804
1854
|
const msg = e instanceof Error ? e.message : "Export failed";
|
|
1855
|
+
reportError(e, { operation: "export" });
|
|
1805
1856
|
setError(msg);
|
|
1806
1857
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1807
1858
|
} finally {
|
|
1808
1859
|
setBusy(false);
|
|
1809
1860
|
}
|
|
1810
1861
|
}, [wallet, exportKey, props]);
|
|
1811
|
-
const handleCopyKey =
|
|
1862
|
+
const handleCopyKey = React.useCallback(async () => {
|
|
1812
1863
|
if (!exportedKey) return;
|
|
1813
1864
|
try {
|
|
1814
1865
|
await navigator.clipboard.writeText(exportedKey);
|
|
@@ -2215,8 +2266,8 @@ function detectPlatform() {
|
|
|
2215
2266
|
return "web";
|
|
2216
2267
|
}
|
|
2217
2268
|
function usePlatform() {
|
|
2218
|
-
const [platform, setPlatform] =
|
|
2219
|
-
|
|
2269
|
+
const [platform, setPlatform] = React.useState("web");
|
|
2270
|
+
React.useEffect(() => {
|
|
2220
2271
|
setPlatform(detectPlatform());
|
|
2221
2272
|
}, []);
|
|
2222
2273
|
return platform;
|
|
@@ -2254,5 +2305,6 @@ exports.useWallet = useSolvenWallet;
|
|
|
2254
2305
|
exports.useWalletAuth = useSolvenAuth;
|
|
2255
2306
|
exports.useWalletBalance = useSolvenBalance;
|
|
2256
2307
|
exports.useWalletExport = useSolvenExport;
|
|
2308
|
+
exports.useWalletReportError = useSolvenReportError;
|
|
2257
2309
|
exports.useWalletSign = useSolvenSign;
|
|
2258
2310
|
exports.useWalletTransferIn = useSolvenTransferIn;
|
package/dist/index.d.cts
CHANGED
|
@@ -310,6 +310,15 @@ declare function useIAMGameTransferIn(): IUseIAMGameTransferIn;
|
|
|
310
310
|
*/
|
|
311
311
|
declare function useIsTelegram(): boolean;
|
|
312
312
|
|
|
313
|
+
/** Context passed to onError describing which wallet operation failed. */
|
|
314
|
+
interface IAMGameErrorContext {
|
|
315
|
+
/** e.g. "login:telegram" | "login:wallet" | "login:email" | "sign" | "withdraw" | "export" | "wallet:load" | "render". */
|
|
316
|
+
operation: string;
|
|
317
|
+
}
|
|
318
|
+
type IAMGameErrorReporter = (error: unknown, context: IAMGameErrorContext) => void;
|
|
319
|
+
/** Report a wallet failure from inside SDK components/hooks (wired to the provider's onError). */
|
|
320
|
+
declare function useIAMGameReportError(): IAMGameErrorReporter;
|
|
321
|
+
|
|
313
322
|
interface IAMGameLoginTheme {
|
|
314
323
|
primary?: string;
|
|
315
324
|
background?: string;
|
|
@@ -551,7 +560,15 @@ declare function usePlatform(): Platform;
|
|
|
551
560
|
|
|
552
561
|
interface IAMGameWalletProviderProps extends IAMGameClientOptions {
|
|
553
562
|
children: React.ReactNode;
|
|
563
|
+
/** Zero-tap Telegram login inside a Mini App. Defaults to true. */
|
|
564
|
+
autoTelegram?: boolean;
|
|
565
|
+
/**
|
|
566
|
+
* Called whenever a wallet operation fails in the UI — login, sign, withdraw,
|
|
567
|
+
* export, wallet load, or a render crash. Wire to your error tracker, e.g.
|
|
568
|
+
* `onError={(err, { operation }) => Sentry.captureException(err, { tags: { wallet_op: operation } })}`.
|
|
569
|
+
*/
|
|
570
|
+
onError?: IAMGameErrorReporter;
|
|
554
571
|
}
|
|
555
572
|
declare const IAMGameWalletProvider: React.FC<IAMGameWalletProviderProps>;
|
|
556
573
|
|
|
557
|
-
export { type AuthMethod, type BuildSolTransferOpts, type BuildSplTransferOpts, type ComplianceModuleType, type ComplianceStatus, IAMGameClient as IAMGameWalletClient, type IAMGameClientOptions as IAMGameWalletClientOptions, IAMGameWalletProvider, type IAMGameWalletProviderProps, type IComplianceState, type IExportInitiateRequest, type IExportInitiateResponse, type IExportPreflightResponse, type IExternalWalletAdapter, type ISession, type ISessionStorage, type ISignActionRequest, type ISignActionResponse, type ISiwsChallenge, type ISiwsVerifyRequest, type ITelegramVerifyRequest, type ITokenBalance, type IUseIAMGameAuth as IUseWalletAuth, type IUseIAMGameExport as IUseWalletExport, type IUseIAMGameSign as IUseWalletSign, type IUseIAMGameTransferIn as IUseWalletTransferIn, type IUser, type IUserIdentity, type IWallet, type IWalletBalance, type IIAMGameErrorEnvelope as IWalletErrorEnvelope, type IWebhookEnvelope, type IWebhookSignatureHeader, type IWithdrawRequest, type IWithdrawResponse, type Platform, type PlatformDetector, type TelegramWebApp, type TransferInDeps, IAMGameAddress as WalletAddress, type IAMGameAddressProps as WalletAddressProps, type IAMGameAddressTheme as WalletAddressTheme, IAMGameBalance as WalletBalance, type IAMGameBalanceProps as WalletBalanceProps, type IAMGameBalanceTheme as WalletBalanceTheme, type WalletCustody, type WalletDescriptor, type IAMGameErrorCode as WalletErrorCode, IAMGameExport as WalletExport, type IAMGameExportProps as WalletExportProps, type IAMGameExportTheme as WalletExportTheme, type WalletId, IAMGameLogin as WalletLogin, IAMGameLoginModal as WalletLoginModal, type IAMGameLoginModalProps as WalletLoginModalProps, type IAMGameLoginProps as WalletLoginProps, type IAMGameLoginTheme as WalletLoginTheme, IAMGameSdkError as WalletSdkError, type WalletStatus, IAMGameWithdraw as WalletWithdraw, type IAMGameWithdrawProps as WalletWithdrawProps, type IAMGameWithdrawTheme as WalletWithdrawTheme, type WebhookEventType, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useIAMGameWallet as useWallet, useIAMGameAuth as useWalletAuth, useIAMGameBalance as useWalletBalance, useIAMGameExport as useWalletExport, useIAMGameSign as useWalletSign, useIAMGameTransferIn as useWalletTransferIn };
|
|
574
|
+
export { type AuthMethod, type BuildSolTransferOpts, type BuildSplTransferOpts, type ComplianceModuleType, type ComplianceStatus, IAMGameClient as IAMGameWalletClient, type IAMGameClientOptions as IAMGameWalletClientOptions, IAMGameWalletProvider, type IAMGameWalletProviderProps, type IComplianceState, type IExportInitiateRequest, type IExportInitiateResponse, type IExportPreflightResponse, type IExternalWalletAdapter, type ISession, type ISessionStorage, type ISignActionRequest, type ISignActionResponse, type ISiwsChallenge, type ISiwsVerifyRequest, type ITelegramVerifyRequest, type ITokenBalance, type IUseIAMGameAuth as IUseWalletAuth, type IUseIAMGameExport as IUseWalletExport, type IUseIAMGameSign as IUseWalletSign, type IUseIAMGameTransferIn as IUseWalletTransferIn, type IUser, type IUserIdentity, type IWallet, type IWalletBalance, type IIAMGameErrorEnvelope as IWalletErrorEnvelope, type IWebhookEnvelope, type IWebhookSignatureHeader, type IWithdrawRequest, type IWithdrawResponse, type Platform, type PlatformDetector, type TelegramWebApp, type TransferInDeps, IAMGameAddress as WalletAddress, type IAMGameAddressProps as WalletAddressProps, type IAMGameAddressTheme as WalletAddressTheme, IAMGameBalance as WalletBalance, type IAMGameBalanceProps as WalletBalanceProps, type IAMGameBalanceTheme as WalletBalanceTheme, type WalletCustody, type WalletDescriptor, type IAMGameErrorCode as WalletErrorCode, type IAMGameErrorContext as WalletErrorContext, type IAMGameErrorReporter as WalletErrorReporter, IAMGameExport as WalletExport, type IAMGameExportProps as WalletExportProps, type IAMGameExportTheme as WalletExportTheme, type WalletId, IAMGameLogin as WalletLogin, IAMGameLoginModal as WalletLoginModal, type IAMGameLoginModalProps as WalletLoginModalProps, type IAMGameLoginProps as WalletLoginProps, type IAMGameLoginTheme as WalletLoginTheme, IAMGameSdkError as WalletSdkError, type WalletStatus, IAMGameWithdraw as WalletWithdraw, type IAMGameWithdrawProps as WalletWithdrawProps, type IAMGameWithdrawTheme as WalletWithdrawTheme, type WebhookEventType, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useIAMGameWallet as useWallet, useIAMGameAuth as useWalletAuth, useIAMGameBalance as useWalletBalance, useIAMGameExport as useWalletExport, useIAMGameReportError as useWalletReportError, useIAMGameSign as useWalletSign, useIAMGameTransferIn as useWalletTransferIn };
|
package/dist/index.d.ts
CHANGED
|
@@ -310,6 +310,15 @@ declare function useIAMGameTransferIn(): IUseIAMGameTransferIn;
|
|
|
310
310
|
*/
|
|
311
311
|
declare function useIsTelegram(): boolean;
|
|
312
312
|
|
|
313
|
+
/** Context passed to onError describing which wallet operation failed. */
|
|
314
|
+
interface IAMGameErrorContext {
|
|
315
|
+
/** e.g. "login:telegram" | "login:wallet" | "login:email" | "sign" | "withdraw" | "export" | "wallet:load" | "render". */
|
|
316
|
+
operation: string;
|
|
317
|
+
}
|
|
318
|
+
type IAMGameErrorReporter = (error: unknown, context: IAMGameErrorContext) => void;
|
|
319
|
+
/** Report a wallet failure from inside SDK components/hooks (wired to the provider's onError). */
|
|
320
|
+
declare function useIAMGameReportError(): IAMGameErrorReporter;
|
|
321
|
+
|
|
313
322
|
interface IAMGameLoginTheme {
|
|
314
323
|
primary?: string;
|
|
315
324
|
background?: string;
|
|
@@ -551,7 +560,15 @@ declare function usePlatform(): Platform;
|
|
|
551
560
|
|
|
552
561
|
interface IAMGameWalletProviderProps extends IAMGameClientOptions {
|
|
553
562
|
children: React.ReactNode;
|
|
563
|
+
/** Zero-tap Telegram login inside a Mini App. Defaults to true. */
|
|
564
|
+
autoTelegram?: boolean;
|
|
565
|
+
/**
|
|
566
|
+
* Called whenever a wallet operation fails in the UI — login, sign, withdraw,
|
|
567
|
+
* export, wallet load, or a render crash. Wire to your error tracker, e.g.
|
|
568
|
+
* `onError={(err, { operation }) => Sentry.captureException(err, { tags: { wallet_op: operation } })}`.
|
|
569
|
+
*/
|
|
570
|
+
onError?: IAMGameErrorReporter;
|
|
554
571
|
}
|
|
555
572
|
declare const IAMGameWalletProvider: React.FC<IAMGameWalletProviderProps>;
|
|
556
573
|
|
|
557
|
-
export { type AuthMethod, type BuildSolTransferOpts, type BuildSplTransferOpts, type ComplianceModuleType, type ComplianceStatus, IAMGameClient as IAMGameWalletClient, type IAMGameClientOptions as IAMGameWalletClientOptions, IAMGameWalletProvider, type IAMGameWalletProviderProps, type IComplianceState, type IExportInitiateRequest, type IExportInitiateResponse, type IExportPreflightResponse, type IExternalWalletAdapter, type ISession, type ISessionStorage, type ISignActionRequest, type ISignActionResponse, type ISiwsChallenge, type ISiwsVerifyRequest, type ITelegramVerifyRequest, type ITokenBalance, type IUseIAMGameAuth as IUseWalletAuth, type IUseIAMGameExport as IUseWalletExport, type IUseIAMGameSign as IUseWalletSign, type IUseIAMGameTransferIn as IUseWalletTransferIn, type IUser, type IUserIdentity, type IWallet, type IWalletBalance, type IIAMGameErrorEnvelope as IWalletErrorEnvelope, type IWebhookEnvelope, type IWebhookSignatureHeader, type IWithdrawRequest, type IWithdrawResponse, type Platform, type PlatformDetector, type TelegramWebApp, type TransferInDeps, IAMGameAddress as WalletAddress, type IAMGameAddressProps as WalletAddressProps, type IAMGameAddressTheme as WalletAddressTheme, IAMGameBalance as WalletBalance, type IAMGameBalanceProps as WalletBalanceProps, type IAMGameBalanceTheme as WalletBalanceTheme, type WalletCustody, type WalletDescriptor, type IAMGameErrorCode as WalletErrorCode, IAMGameExport as WalletExport, type IAMGameExportProps as WalletExportProps, type IAMGameExportTheme as WalletExportTheme, type WalletId, IAMGameLogin as WalletLogin, IAMGameLoginModal as WalletLoginModal, type IAMGameLoginModalProps as WalletLoginModalProps, type IAMGameLoginProps as WalletLoginProps, type IAMGameLoginTheme as WalletLoginTheme, IAMGameSdkError as WalletSdkError, type WalletStatus, IAMGameWithdraw as WalletWithdraw, type IAMGameWithdrawProps as WalletWithdrawProps, type IAMGameWithdrawTheme as WalletWithdrawTheme, type WebhookEventType, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useIAMGameWallet as useWallet, useIAMGameAuth as useWalletAuth, useIAMGameBalance as useWalletBalance, useIAMGameExport as useWalletExport, useIAMGameSign as useWalletSign, useIAMGameTransferIn as useWalletTransferIn };
|
|
574
|
+
export { type AuthMethod, type BuildSolTransferOpts, type BuildSplTransferOpts, type ComplianceModuleType, type ComplianceStatus, IAMGameClient as IAMGameWalletClient, type IAMGameClientOptions as IAMGameWalletClientOptions, IAMGameWalletProvider, type IAMGameWalletProviderProps, type IComplianceState, type IExportInitiateRequest, type IExportInitiateResponse, type IExportPreflightResponse, type IExternalWalletAdapter, type ISession, type ISessionStorage, type ISignActionRequest, type ISignActionResponse, type ISiwsChallenge, type ISiwsVerifyRequest, type ITelegramVerifyRequest, type ITokenBalance, type IUseIAMGameAuth as IUseWalletAuth, type IUseIAMGameExport as IUseWalletExport, type IUseIAMGameSign as IUseWalletSign, type IUseIAMGameTransferIn as IUseWalletTransferIn, type IUser, type IUserIdentity, type IWallet, type IWalletBalance, type IIAMGameErrorEnvelope as IWalletErrorEnvelope, type IWebhookEnvelope, type IWebhookSignatureHeader, type IWithdrawRequest, type IWithdrawResponse, type Platform, type PlatformDetector, type TelegramWebApp, type TransferInDeps, IAMGameAddress as WalletAddress, type IAMGameAddressProps as WalletAddressProps, type IAMGameAddressTheme as WalletAddressTheme, IAMGameBalance as WalletBalance, type IAMGameBalanceProps as WalletBalanceProps, type IAMGameBalanceTheme as WalletBalanceTheme, type WalletCustody, type WalletDescriptor, type IAMGameErrorCode as WalletErrorCode, type IAMGameErrorContext as WalletErrorContext, type IAMGameErrorReporter as WalletErrorReporter, IAMGameExport as WalletExport, type IAMGameExportProps as WalletExportProps, type IAMGameExportTheme as WalletExportTheme, type WalletId, IAMGameLogin as WalletLogin, IAMGameLoginModal as WalletLoginModal, type IAMGameLoginModalProps as WalletLoginModalProps, type IAMGameLoginProps as WalletLoginProps, type IAMGameLoginTheme as WalletLoginTheme, IAMGameSdkError as WalletSdkError, type WalletStatus, IAMGameWithdraw as WalletWithdraw, type IAMGameWithdrawProps as WalletWithdrawProps, type IAMGameWithdrawTheme as WalletWithdrawTheme, type WebhookEventType, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useIAMGameWallet as useWallet, useIAMGameAuth as useWalletAuth, useIAMGameBalance as useWalletBalance, useIAMGameExport as useWalletExport, useIAMGameReportError as useWalletReportError, useIAMGameSign as useWalletSign, useIAMGameTransferIn as useWalletTransferIn };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useMemo, useState,
|
|
1
|
+
import React, { createContext, useMemo, useState, useRef, useCallback, useEffect, useContext } from 'react';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
|
|
@@ -272,7 +272,25 @@ function useSolvenContext() {
|
|
|
272
272
|
if (!ctx) throw new Error("useSolvenContext must be inside a <SolvenProvider />");
|
|
273
273
|
return ctx;
|
|
274
274
|
}
|
|
275
|
-
function
|
|
275
|
+
function useSolvenReportError() {
|
|
276
|
+
return useSolvenContext().reportError;
|
|
277
|
+
}
|
|
278
|
+
var SolvenErrorBoundary = class extends React.Component {
|
|
279
|
+
constructor() {
|
|
280
|
+
super(...arguments);
|
|
281
|
+
this.state = { hasError: false };
|
|
282
|
+
}
|
|
283
|
+
static getDerivedStateFromError() {
|
|
284
|
+
return { hasError: true };
|
|
285
|
+
}
|
|
286
|
+
componentDidCatch(error) {
|
|
287
|
+
this.props.onError(error, { operation: "render" });
|
|
288
|
+
}
|
|
289
|
+
render() {
|
|
290
|
+
return this.state.hasError ? null : this.props.children;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
function SolvenProvider({ children, autoTelegram = true, onError, ...opts }) {
|
|
276
294
|
const client = useMemo(() => new SolvenClient(opts), [
|
|
277
295
|
opts.publishableKey,
|
|
278
296
|
opts.baseUrl,
|
|
@@ -281,6 +299,14 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
281
299
|
]);
|
|
282
300
|
const [session, setSession] = useState(client.getSession());
|
|
283
301
|
const [status, setStatus] = useState("loading");
|
|
302
|
+
const onErrorRef = useRef(onError);
|
|
303
|
+
onErrorRef.current = onError;
|
|
304
|
+
const reportError = useCallback((error, context) => {
|
|
305
|
+
try {
|
|
306
|
+
onErrorRef.current?.(error, context);
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
}, []);
|
|
284
310
|
useEffect(() => {
|
|
285
311
|
let cancelled = false;
|
|
286
312
|
(async () => {
|
|
@@ -346,9 +372,10 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
346
372
|
setSession: (s) => {
|
|
347
373
|
setSession(s);
|
|
348
374
|
setStatus(s ? "authenticated" : "anonymous");
|
|
349
|
-
}
|
|
375
|
+
},
|
|
376
|
+
reportError
|
|
350
377
|
};
|
|
351
|
-
return /* @__PURE__ */ jsx(SolvenContext.Provider, { value, children });
|
|
378
|
+
return /* @__PURE__ */ jsx(SolvenContext.Provider, { value, children: /* @__PURE__ */ jsx(SolvenErrorBoundary, { onError: reportError, children }) });
|
|
352
379
|
}
|
|
353
380
|
|
|
354
381
|
// ../../solven/sdk-client/src/hooks.ts
|
|
@@ -401,7 +428,7 @@ function useSolvenAuth() {
|
|
|
401
428
|
};
|
|
402
429
|
}
|
|
403
430
|
function useSolvenWallet() {
|
|
404
|
-
const { client, status } = useSolvenContext();
|
|
431
|
+
const { client, status, reportError } = useSolvenContext();
|
|
405
432
|
const [wallet, setWallet] = useState(null);
|
|
406
433
|
useEffect(() => {
|
|
407
434
|
if (status !== "authenticated") {
|
|
@@ -409,11 +436,15 @@ function useSolvenWallet() {
|
|
|
409
436
|
return;
|
|
410
437
|
}
|
|
411
438
|
let cancelled = false;
|
|
412
|
-
client.getMyWallet().then((w) => !cancelled && setWallet(w)).catch(() =>
|
|
439
|
+
client.getMyWallet().then((w) => !cancelled && setWallet(w)).catch((e) => {
|
|
440
|
+
if (cancelled) return;
|
|
441
|
+
reportError(e, { operation: "wallet:load" });
|
|
442
|
+
setWallet(null);
|
|
443
|
+
});
|
|
413
444
|
return () => {
|
|
414
445
|
cancelled = true;
|
|
415
446
|
};
|
|
416
|
-
}, [client, status]);
|
|
447
|
+
}, [client, status, reportError]);
|
|
417
448
|
return wallet;
|
|
418
449
|
}
|
|
419
450
|
function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
@@ -442,10 +473,17 @@ function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
|
442
473
|
return balance;
|
|
443
474
|
}
|
|
444
475
|
function useSolvenSign() {
|
|
445
|
-
const { client } = useSolvenContext();
|
|
476
|
+
const { client, reportError } = useSolvenContext();
|
|
446
477
|
const signAction = useCallback(
|
|
447
|
-
({ walletId, txBase64, label, idempotencyKey }) =>
|
|
448
|
-
|
|
478
|
+
async ({ walletId, txBase64, label, idempotencyKey }) => {
|
|
479
|
+
try {
|
|
480
|
+
return await client.signAction({ walletId, txBase64, label }, idempotencyKey);
|
|
481
|
+
} catch (e) {
|
|
482
|
+
reportError(e, { operation: "sign" });
|
|
483
|
+
throw e;
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
[client, reportError]
|
|
449
487
|
);
|
|
450
488
|
return { signAction };
|
|
451
489
|
}
|
|
@@ -596,6 +634,7 @@ var defaultTheme = {
|
|
|
596
634
|
};
|
|
597
635
|
function SolvenLoginContent(props) {
|
|
598
636
|
const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
|
|
637
|
+
const reportError = useSolvenReportError();
|
|
599
638
|
const [busy, setBusy] = useState(null);
|
|
600
639
|
const [error, setError] = useState(null);
|
|
601
640
|
const [email, setEmail] = useState("");
|
|
@@ -624,6 +663,7 @@ function SolvenLoginContent(props) {
|
|
|
624
663
|
props.onCloseAfterSignIn?.();
|
|
625
664
|
} catch (e) {
|
|
626
665
|
if (!cancelled) {
|
|
666
|
+
reportError(e, { operation: "login:telegram" });
|
|
627
667
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
628
668
|
}
|
|
629
669
|
} finally {
|
|
@@ -650,6 +690,7 @@ function SolvenLoginContent(props) {
|
|
|
650
690
|
props.onSignIn?.();
|
|
651
691
|
props.onCloseAfterSignIn?.();
|
|
652
692
|
} catch (e) {
|
|
693
|
+
reportError(e, { operation: "login:wallet" });
|
|
653
694
|
setError(e instanceof Error ? e.message : "Wallet sign-in failed");
|
|
654
695
|
} finally {
|
|
655
696
|
setBusy(null);
|
|
@@ -663,6 +704,7 @@ function SolvenLoginContent(props) {
|
|
|
663
704
|
props.onSignIn?.();
|
|
664
705
|
props.onCloseAfterSignIn?.();
|
|
665
706
|
} catch (e) {
|
|
707
|
+
reportError(e, { operation: "login:telegram" });
|
|
666
708
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
667
709
|
} finally {
|
|
668
710
|
setBusy(null);
|
|
@@ -675,6 +717,7 @@ function SolvenLoginContent(props) {
|
|
|
675
717
|
await requestEmailOtp(email.trim());
|
|
676
718
|
setOtpSent(true);
|
|
677
719
|
} catch (e) {
|
|
720
|
+
reportError(e, { operation: "login:email" });
|
|
678
721
|
setError(e instanceof Error ? e.message : "Couldn't send the code");
|
|
679
722
|
} finally {
|
|
680
723
|
setBusy(null);
|
|
@@ -688,6 +731,7 @@ function SolvenLoginContent(props) {
|
|
|
688
731
|
props.onSignIn?.();
|
|
689
732
|
props.onCloseAfterSignIn?.();
|
|
690
733
|
} catch (e) {
|
|
734
|
+
reportError(e, { operation: "login:email" });
|
|
691
735
|
setError(e instanceof Error ? e.message : "Couldn't verify the code");
|
|
692
736
|
} finally {
|
|
693
737
|
setBusy(null);
|
|
@@ -1463,7 +1507,7 @@ function isValidSolanaAddress(address) {
|
|
|
1463
1507
|
function SolvenWithdraw(props) {
|
|
1464
1508
|
const wallet = useSolvenWallet();
|
|
1465
1509
|
const balance = useSolvenBalance(wallet?.id ?? null);
|
|
1466
|
-
const { client } = useSolvenContext();
|
|
1510
|
+
const { client, reportError } = useSolvenContext();
|
|
1467
1511
|
const theme = useMemo(() => ({ ...defaultTheme4, ...props.theme ?? {} }), [props.theme]);
|
|
1468
1512
|
const label = props.label ?? "Withdraw";
|
|
1469
1513
|
const [toAddress, setToAddress] = useState("");
|
|
@@ -1541,6 +1585,7 @@ function SolvenWithdraw(props) {
|
|
|
1541
1585
|
props.onSuccess?.(result.signature);
|
|
1542
1586
|
} catch (e) {
|
|
1543
1587
|
const msg = e instanceof Error ? e.message : "Withdrawal failed";
|
|
1588
|
+
reportError(e, { operation: "withdraw" });
|
|
1544
1589
|
setError(msg);
|
|
1545
1590
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1546
1591
|
} finally {
|
|
@@ -1779,6 +1824,7 @@ function formatLamports(lamports) {
|
|
|
1779
1824
|
function SolvenExport(props) {
|
|
1780
1825
|
const wallet = useSolvenWallet();
|
|
1781
1826
|
const { preflight, refreshPreflight, exportKey } = useSolvenExport(wallet?.id ?? null);
|
|
1827
|
+
const reportError = useSolvenReportError();
|
|
1782
1828
|
const theme = useMemo(() => ({ ...defaultTheme5, ...props.theme ?? {} }), [props.theme]);
|
|
1783
1829
|
const label = props.label ?? "Export Wallet";
|
|
1784
1830
|
const [step, setStep] = useState("preflight");
|
|
@@ -1800,6 +1846,7 @@ function SolvenExport(props) {
|
|
|
1800
1846
|
props.onSuccess?.(result.newWalletAddress);
|
|
1801
1847
|
} catch (e) {
|
|
1802
1848
|
const msg = e instanceof Error ? e.message : "Export failed";
|
|
1849
|
+
reportError(e, { operation: "export" });
|
|
1803
1850
|
setError(msg);
|
|
1804
1851
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1805
1852
|
} finally {
|
|
@@ -2223,4 +2270,4 @@ function usePlatform() {
|
|
|
2223
2270
|
// src/provider.tsx
|
|
2224
2271
|
var IAMGameWalletProvider = SolvenProvider;
|
|
2225
2272
|
|
|
2226
|
-
export { SolvenClient as IAMGameWalletClient, IAMGameWalletProvider, SolvenAddress as WalletAddress, SolvenBalance as WalletBalance, SolvenExport as WalletExport, SolvenLogin as WalletLogin, SolvenLoginModal as WalletLoginModal, SolvenSdkError as WalletSdkError, SolvenWithdraw as WalletWithdraw, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useSolvenWallet as useWallet, useSolvenAuth as useWalletAuth, useSolvenBalance as useWalletBalance, useSolvenExport as useWalletExport, useSolvenSign as useWalletSign, useSolvenTransferIn as useWalletTransferIn };
|
|
2273
|
+
export { SolvenClient as IAMGameWalletClient, IAMGameWalletProvider, SolvenAddress as WalletAddress, SolvenBalance as WalletBalance, SolvenExport as WalletExport, SolvenLogin as WalletLogin, SolvenLoginModal as WalletLoginModal, SolvenSdkError as WalletSdkError, SolvenWithdraw as WalletWithdraw, backpackAdapter, buildSolTransferIn, buildSplTransferIn, detectPlatform, getTelegramInitData, getTelegramWebApp, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, registerPlatform, solflareAdapter, useIsTelegram, usePlatform, useSolvenWallet as useWallet, useSolvenAuth as useWalletAuth, useSolvenBalance as useWalletBalance, useSolvenExport as useWalletExport, useSolvenReportError as useWalletReportError, useSolvenSign as useWalletSign, useSolvenTransferIn as useWalletTransferIn };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iamgame/wallet-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "IAMGame Wallet browser SDK — Telegram & Solana wallet auth, balances, server-side signing, and key export. Drop-in React provider for game frontends.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://wallet.iamgame.com",
|