@iamgame/wallet-sdk 0.1.3 → 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 +171 -79
- package/dist/index.d.cts +66 -1
- package/dist/index.d.ts +66 -1
- package/dist/index.js +94 -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) {
|
|
@@ -249,6 +253,9 @@ function getTelegram() {
|
|
|
249
253
|
if (typeof window === "undefined") return void 0;
|
|
250
254
|
return window.Telegram;
|
|
251
255
|
}
|
|
256
|
+
function getTelegramWebApp() {
|
|
257
|
+
return getTelegram()?.WebApp ?? null;
|
|
258
|
+
}
|
|
252
259
|
function getTelegramInitData() {
|
|
253
260
|
const data = getTelegram()?.WebApp?.initData;
|
|
254
261
|
if (!data || typeof data !== "string" || data.length === 0) return null;
|
|
@@ -265,22 +272,48 @@ function notifyTelegramReady() {
|
|
|
265
272
|
} catch {
|
|
266
273
|
}
|
|
267
274
|
}
|
|
268
|
-
var SolvenContext =
|
|
275
|
+
var SolvenContext = React.createContext(null);
|
|
269
276
|
function useSolvenContext() {
|
|
270
|
-
const ctx =
|
|
277
|
+
const ctx = React.useContext(SolvenContext);
|
|
271
278
|
if (!ctx) throw new Error("useSolvenContext must be inside a <SolvenProvider />");
|
|
272
279
|
return ctx;
|
|
273
280
|
}
|
|
274
|
-
function
|
|
275
|
-
|
|
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), [
|
|
276
301
|
opts.publishableKey,
|
|
277
302
|
opts.baseUrl,
|
|
278
303
|
opts.storage,
|
|
279
304
|
opts.fetchImpl
|
|
280
305
|
]);
|
|
281
|
-
const [session, setSession] =
|
|
282
|
-
const [status, setStatus] =
|
|
283
|
-
|
|
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(() => {
|
|
284
317
|
let cancelled = false;
|
|
285
318
|
(async () => {
|
|
286
319
|
const stored = client.getSession();
|
|
@@ -312,8 +345,8 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
312
345
|
cancelled = true;
|
|
313
346
|
};
|
|
314
347
|
}, [client]);
|
|
315
|
-
const triedTelegram =
|
|
316
|
-
|
|
348
|
+
const triedTelegram = React.useRef(false);
|
|
349
|
+
React.useEffect(() => {
|
|
317
350
|
if (!autoTelegram || status !== "anonymous" || triedTelegram.current) return;
|
|
318
351
|
triedTelegram.current = true;
|
|
319
352
|
let cancelled = false;
|
|
@@ -345,15 +378,16 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
345
378
|
setSession: (s) => {
|
|
346
379
|
setSession(s);
|
|
347
380
|
setStatus(s ? "authenticated" : "anonymous");
|
|
348
|
-
}
|
|
381
|
+
},
|
|
382
|
+
reportError
|
|
349
383
|
};
|
|
350
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SolvenContext.Provider, { value, children });
|
|
384
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SolvenContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(SolvenErrorBoundary, { onError: reportError, children }) });
|
|
351
385
|
}
|
|
352
386
|
|
|
353
387
|
// ../../solven/sdk-client/src/hooks.ts
|
|
354
388
|
function useSolvenAuth() {
|
|
355
389
|
const { client, session, status, setSession } = useSolvenContext();
|
|
356
|
-
const connectExternal =
|
|
390
|
+
const connectExternal = React.useCallback(
|
|
357
391
|
async (adapter) => {
|
|
358
392
|
const { publicKey } = await adapter.connect();
|
|
359
393
|
const challenge = await client.requestSiwsChallenge(publicKey);
|
|
@@ -364,27 +398,27 @@ function useSolvenAuth() {
|
|
|
364
398
|
},
|
|
365
399
|
[client, setSession]
|
|
366
400
|
);
|
|
367
|
-
const connectTelegram =
|
|
401
|
+
const connectTelegram = React.useCallback(async () => {
|
|
368
402
|
const initData = getTelegramInitData();
|
|
369
403
|
if (!initData) throw new Error("Not running inside a Telegram Mini App.");
|
|
370
404
|
const session2 = await client.verifyTelegram({ initData });
|
|
371
405
|
setSession(session2);
|
|
372
406
|
}, [client, setSession]);
|
|
373
|
-
const requestEmailOtp =
|
|
407
|
+
const requestEmailOtp = React.useCallback(
|
|
374
408
|
async (email) => {
|
|
375
409
|
const { expiresAt } = await client.initiateEmail(email);
|
|
376
410
|
return { expiresAt };
|
|
377
411
|
},
|
|
378
412
|
[client]
|
|
379
413
|
);
|
|
380
|
-
const connectEmail =
|
|
414
|
+
const connectEmail = React.useCallback(
|
|
381
415
|
async (email, code) => {
|
|
382
416
|
const session2 = await client.verifyEmail(email, code);
|
|
383
417
|
setSession(session2);
|
|
384
418
|
},
|
|
385
419
|
[client, setSession]
|
|
386
420
|
);
|
|
387
|
-
const logout =
|
|
421
|
+
const logout = React.useCallback(async () => {
|
|
388
422
|
await client.logout();
|
|
389
423
|
setSession(null);
|
|
390
424
|
}, [client, setSession]);
|
|
@@ -400,25 +434,29 @@ function useSolvenAuth() {
|
|
|
400
434
|
};
|
|
401
435
|
}
|
|
402
436
|
function useSolvenWallet() {
|
|
403
|
-
const { client, status } = useSolvenContext();
|
|
404
|
-
const [wallet, setWallet] =
|
|
405
|
-
|
|
437
|
+
const { client, status, reportError } = useSolvenContext();
|
|
438
|
+
const [wallet, setWallet] = React.useState(null);
|
|
439
|
+
React.useEffect(() => {
|
|
406
440
|
if (status !== "authenticated") {
|
|
407
441
|
setWallet(null);
|
|
408
442
|
return;
|
|
409
443
|
}
|
|
410
444
|
let cancelled = false;
|
|
411
|
-
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
|
+
});
|
|
412
450
|
return () => {
|
|
413
451
|
cancelled = true;
|
|
414
452
|
};
|
|
415
|
-
}, [client, status]);
|
|
453
|
+
}, [client, status, reportError]);
|
|
416
454
|
return wallet;
|
|
417
455
|
}
|
|
418
456
|
function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
419
457
|
const { client, status } = useSolvenContext();
|
|
420
|
-
const [balance, setBalance] =
|
|
421
|
-
|
|
458
|
+
const [balance, setBalance] = React.useState(null);
|
|
459
|
+
React.useEffect(() => {
|
|
422
460
|
if (status !== "authenticated" || !walletId) {
|
|
423
461
|
setBalance(null);
|
|
424
462
|
return;
|
|
@@ -441,25 +479,32 @@ function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
|
441
479
|
return balance;
|
|
442
480
|
}
|
|
443
481
|
function useSolvenSign() {
|
|
444
|
-
const { client } = useSolvenContext();
|
|
445
|
-
const signAction =
|
|
446
|
-
({ walletId, txBase64, label, idempotencyKey }) =>
|
|
447
|
-
|
|
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]
|
|
448
493
|
);
|
|
449
494
|
return { signAction };
|
|
450
495
|
}
|
|
451
496
|
function useSolvenExport(walletId) {
|
|
452
497
|
const { client } = useSolvenContext();
|
|
453
|
-
const [preflight, setPreflight] =
|
|
454
|
-
const refreshPreflight =
|
|
498
|
+
const [preflight, setPreflight] = React.useState(null);
|
|
499
|
+
const refreshPreflight = React.useCallback(async () => {
|
|
455
500
|
if (!walletId) return;
|
|
456
501
|
const p = await client.exportPreflight(walletId);
|
|
457
502
|
setPreflight(p);
|
|
458
503
|
}, [client, walletId]);
|
|
459
|
-
|
|
504
|
+
React.useEffect(() => {
|
|
460
505
|
if (walletId) void refreshPreflight();
|
|
461
506
|
}, [walletId, refreshPreflight]);
|
|
462
|
-
const exportKey =
|
|
507
|
+
const exportKey = React.useCallback(
|
|
463
508
|
async (idempotencyKey) => {
|
|
464
509
|
if (!walletId) throw new Error("No wallet selected for export");
|
|
465
510
|
return client.exportWallet(walletId, idempotencyKey);
|
|
@@ -472,6 +517,13 @@ function useSolvenTransferIn() {
|
|
|
472
517
|
const wallet = useSolvenWallet();
|
|
473
518
|
return { destinationAddress: wallet?.address ?? null };
|
|
474
519
|
}
|
|
520
|
+
function useIsTelegram() {
|
|
521
|
+
const [inTelegram, setInTelegram] = React.useState(false);
|
|
522
|
+
React.useEffect(() => {
|
|
523
|
+
setInTelegram(isTelegramMiniApp());
|
|
524
|
+
}, []);
|
|
525
|
+
return inTelegram;
|
|
526
|
+
}
|
|
475
527
|
|
|
476
528
|
// ../../solven/sdk-client/src/wallet-adapter.ts
|
|
477
529
|
function phantomAdapter() {
|
|
@@ -588,20 +640,21 @@ var defaultTheme = {
|
|
|
588
640
|
};
|
|
589
641
|
function SolvenLoginContent(props) {
|
|
590
642
|
const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
|
|
591
|
-
const
|
|
592
|
-
const [
|
|
593
|
-
const [
|
|
594
|
-
const [
|
|
595
|
-
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);
|
|
596
649
|
const showEmail = props.showEmail ?? true;
|
|
597
|
-
const theme =
|
|
650
|
+
const theme = React.useMemo(
|
|
598
651
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
599
652
|
[props.theme]
|
|
600
653
|
);
|
|
601
|
-
const inTma =
|
|
654
|
+
const inTma = React.useMemo(() => isTelegramMiniApp(), []);
|
|
602
655
|
const autoTelegram = props.autoTelegram ?? true;
|
|
603
|
-
const wallets =
|
|
604
|
-
|
|
656
|
+
const wallets = React.useMemo(listSupportedWallets, []);
|
|
657
|
+
React.useEffect(() => {
|
|
605
658
|
notifyTelegramReady();
|
|
606
659
|
if (!inTma || !autoTelegram) return;
|
|
607
660
|
if (status === "authenticated") return;
|
|
@@ -616,6 +669,7 @@ function SolvenLoginContent(props) {
|
|
|
616
669
|
props.onCloseAfterSignIn?.();
|
|
617
670
|
} catch (e) {
|
|
618
671
|
if (!cancelled) {
|
|
672
|
+
reportError(e, { operation: "login:telegram" });
|
|
619
673
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
620
674
|
}
|
|
621
675
|
} finally {
|
|
@@ -642,6 +696,7 @@ function SolvenLoginContent(props) {
|
|
|
642
696
|
props.onSignIn?.();
|
|
643
697
|
props.onCloseAfterSignIn?.();
|
|
644
698
|
} catch (e) {
|
|
699
|
+
reportError(e, { operation: "login:wallet" });
|
|
645
700
|
setError(e instanceof Error ? e.message : "Wallet sign-in failed");
|
|
646
701
|
} finally {
|
|
647
702
|
setBusy(null);
|
|
@@ -655,6 +710,7 @@ function SolvenLoginContent(props) {
|
|
|
655
710
|
props.onSignIn?.();
|
|
656
711
|
props.onCloseAfterSignIn?.();
|
|
657
712
|
} catch (e) {
|
|
713
|
+
reportError(e, { operation: "login:telegram" });
|
|
658
714
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
659
715
|
} finally {
|
|
660
716
|
setBusy(null);
|
|
@@ -667,6 +723,7 @@ function SolvenLoginContent(props) {
|
|
|
667
723
|
await requestEmailOtp(email.trim());
|
|
668
724
|
setOtpSent(true);
|
|
669
725
|
} catch (e) {
|
|
726
|
+
reportError(e, { operation: "login:email" });
|
|
670
727
|
setError(e instanceof Error ? e.message : "Couldn't send the code");
|
|
671
728
|
} finally {
|
|
672
729
|
setBusy(null);
|
|
@@ -680,6 +737,7 @@ function SolvenLoginContent(props) {
|
|
|
680
737
|
props.onSignIn?.();
|
|
681
738
|
props.onCloseAfterSignIn?.();
|
|
682
739
|
} catch (e) {
|
|
740
|
+
reportError(e, { operation: "login:email" });
|
|
683
741
|
setError(e instanceof Error ? e.message : "Couldn't verify the code");
|
|
684
742
|
} finally {
|
|
685
743
|
setBusy(null);
|
|
@@ -917,7 +975,7 @@ function SolvenLoginContent(props) {
|
|
|
917
975
|
] });
|
|
918
976
|
}
|
|
919
977
|
function SolvenLogin(props) {
|
|
920
|
-
const theme =
|
|
978
|
+
const theme = React.useMemo(
|
|
921
979
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
922
980
|
[props.theme]
|
|
923
981
|
);
|
|
@@ -950,17 +1008,17 @@ function SolvenLoginModal(props) {
|
|
|
950
1008
|
closeOnEscape = true,
|
|
951
1009
|
...content
|
|
952
1010
|
} = props;
|
|
953
|
-
const theme =
|
|
1011
|
+
const theme = React.useMemo(
|
|
954
1012
|
() => ({ ...defaultTheme, ...props.theme ?? {} }),
|
|
955
1013
|
[props.theme]
|
|
956
1014
|
);
|
|
957
|
-
const dialogRef =
|
|
958
|
-
const previouslyFocused =
|
|
959
|
-
const [mounted, setMounted] =
|
|
960
|
-
|
|
1015
|
+
const dialogRef = React.useRef(null);
|
|
1016
|
+
const previouslyFocused = React.useRef(null);
|
|
1017
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1018
|
+
React.useEffect(() => {
|
|
961
1019
|
setMounted(true);
|
|
962
1020
|
}, []);
|
|
963
|
-
|
|
1021
|
+
React.useEffect(() => {
|
|
964
1022
|
if (!isOpen || !closeOnEscape) return;
|
|
965
1023
|
const onKey = (e) => {
|
|
966
1024
|
if (e.key === "Escape") {
|
|
@@ -971,7 +1029,7 @@ function SolvenLoginModal(props) {
|
|
|
971
1029
|
window.addEventListener("keydown", onKey);
|
|
972
1030
|
return () => window.removeEventListener("keydown", onKey);
|
|
973
1031
|
}, [isOpen, closeOnEscape, onClose]);
|
|
974
|
-
|
|
1032
|
+
React.useEffect(() => {
|
|
975
1033
|
if (!isOpen) return;
|
|
976
1034
|
previouslyFocused.current = document.activeElement ?? null;
|
|
977
1035
|
queueMicrotask(() => {
|
|
@@ -1007,7 +1065,7 @@ function SolvenLoginModal(props) {
|
|
|
1007
1065
|
previouslyFocused.current?.focus?.();
|
|
1008
1066
|
};
|
|
1009
1067
|
}, [isOpen]);
|
|
1010
|
-
const handleBackdropClick =
|
|
1068
|
+
const handleBackdropClick = React.useCallback(
|
|
1011
1069
|
(e) => {
|
|
1012
1070
|
if (!closeOnBackdrop) return;
|
|
1013
1071
|
if (e.target === e.currentTarget) onClose();
|
|
@@ -1109,12 +1167,12 @@ function truncateAddress(address, chars) {
|
|
|
1109
1167
|
}
|
|
1110
1168
|
function SolvenAddress(props) {
|
|
1111
1169
|
const wallet = useSolvenWallet();
|
|
1112
|
-
const theme =
|
|
1170
|
+
const theme = React.useMemo(() => ({ ...defaultTheme2, ...props.theme ?? {} }), [props.theme]);
|
|
1113
1171
|
const truncateChars = props.truncateChars ?? 6;
|
|
1114
1172
|
const showCopy = props.showCopy ?? true;
|
|
1115
1173
|
const label = props.label ?? "Wallet Address";
|
|
1116
|
-
const [copied, setCopied] =
|
|
1117
|
-
const handleCopy =
|
|
1174
|
+
const [copied, setCopied] = React.useState(false);
|
|
1175
|
+
const handleCopy = React.useCallback(async () => {
|
|
1118
1176
|
if (!wallet?.address) return;
|
|
1119
1177
|
try {
|
|
1120
1178
|
await navigator.clipboard.writeText(wallet.address);
|
|
@@ -1244,18 +1302,18 @@ function getTokenLabel(token) {
|
|
|
1244
1302
|
function SolvenBalance(props) {
|
|
1245
1303
|
const wallet = useSolvenWallet();
|
|
1246
1304
|
const balance = useSolvenBalance(wallet?.id ?? null, props.pollMs);
|
|
1247
|
-
const theme =
|
|
1305
|
+
const theme = React.useMemo(() => ({ ...defaultTheme3, ...props.theme ?? {} }), [props.theme]);
|
|
1248
1306
|
const showRefresh = props.showRefresh ?? true;
|
|
1249
1307
|
const label = props.label ?? "Balance";
|
|
1250
1308
|
const compact = props.compact ?? false;
|
|
1251
|
-
const [refreshing, setRefreshing] =
|
|
1252
|
-
const tokens =
|
|
1309
|
+
const [refreshing, setRefreshing] = React.useState(false);
|
|
1310
|
+
const tokens = React.useMemo(() => {
|
|
1253
1311
|
if (!balance?.tokens) return [];
|
|
1254
1312
|
if (!props.filterMints) return balance.tokens;
|
|
1255
1313
|
const set = new Set(props.filterMints);
|
|
1256
1314
|
return balance.tokens.filter((t) => set.has(t.mint));
|
|
1257
1315
|
}, [balance?.tokens, props.filterMints]);
|
|
1258
|
-
const handleRefresh =
|
|
1316
|
+
const handleRefresh = React.useCallback(() => {
|
|
1259
1317
|
setRefreshing(true);
|
|
1260
1318
|
setTimeout(() => setRefreshing(false), 1500);
|
|
1261
1319
|
}, []);
|
|
@@ -1455,26 +1513,26 @@ function isValidSolanaAddress(address) {
|
|
|
1455
1513
|
function SolvenWithdraw(props) {
|
|
1456
1514
|
const wallet = useSolvenWallet();
|
|
1457
1515
|
const balance = useSolvenBalance(wallet?.id ?? null);
|
|
1458
|
-
const { client } = useSolvenContext();
|
|
1459
|
-
const theme =
|
|
1516
|
+
const { client, reportError } = useSolvenContext();
|
|
1517
|
+
const theme = React.useMemo(() => ({ ...defaultTheme4, ...props.theme ?? {} }), [props.theme]);
|
|
1460
1518
|
const label = props.label ?? "Withdraw";
|
|
1461
|
-
const [toAddress, setToAddress] =
|
|
1462
|
-
const [amount, setAmount] =
|
|
1463
|
-
const [selectedMint, setSelectedMint] =
|
|
1464
|
-
const [busy, setBusy] =
|
|
1465
|
-
const [error, setError] =
|
|
1466
|
-
const [successSig, setSuccessSig] =
|
|
1467
|
-
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(() => {
|
|
1468
1526
|
if (!balance?.tokens) return [];
|
|
1469
1527
|
if (props.mint) return balance.tokens.filter((t) => t.mint === props.mint);
|
|
1470
1528
|
return balance.tokens;
|
|
1471
1529
|
}, [balance?.tokens, props.mint]);
|
|
1472
|
-
const selectedToken =
|
|
1530
|
+
const selectedToken = React.useMemo(
|
|
1473
1531
|
() => tokens.find((t) => t.mint === selectedMint) ?? null,
|
|
1474
1532
|
[tokens, selectedMint]
|
|
1475
1533
|
);
|
|
1476
1534
|
const availableFormatted = selectedToken ? formatTokenAmount2(selectedToken) : "0";
|
|
1477
|
-
const handleMax =
|
|
1535
|
+
const handleMax = React.useCallback(() => {
|
|
1478
1536
|
if (!selectedToken) return;
|
|
1479
1537
|
if (selectedToken.mint === "SOL") {
|
|
1480
1538
|
const raw = BigInt(selectedToken.amount);
|
|
@@ -1490,7 +1548,7 @@ function SolvenWithdraw(props) {
|
|
|
1490
1548
|
setAmount(formatTokenAmount2(selectedToken));
|
|
1491
1549
|
}
|
|
1492
1550
|
}, [selectedToken]);
|
|
1493
|
-
const handleSubmit =
|
|
1551
|
+
const handleSubmit = React.useCallback(async () => {
|
|
1494
1552
|
setError(null);
|
|
1495
1553
|
setSuccessSig(null);
|
|
1496
1554
|
if (!wallet) {
|
|
@@ -1533,6 +1591,7 @@ function SolvenWithdraw(props) {
|
|
|
1533
1591
|
props.onSuccess?.(result.signature);
|
|
1534
1592
|
} catch (e) {
|
|
1535
1593
|
const msg = e instanceof Error ? e.message : "Withdrawal failed";
|
|
1594
|
+
reportError(e, { operation: "withdraw" });
|
|
1536
1595
|
setError(msg);
|
|
1537
1596
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1538
1597
|
} finally {
|
|
@@ -1771,16 +1830,17 @@ function formatLamports(lamports) {
|
|
|
1771
1830
|
function SolvenExport(props) {
|
|
1772
1831
|
const wallet = useSolvenWallet();
|
|
1773
1832
|
const { preflight, refreshPreflight, exportKey } = useSolvenExport(wallet?.id ?? null);
|
|
1774
|
-
const
|
|
1833
|
+
const reportError = useSolvenReportError();
|
|
1834
|
+
const theme = React.useMemo(() => ({ ...defaultTheme5, ...props.theme ?? {} }), [props.theme]);
|
|
1775
1835
|
const label = props.label ?? "Export Wallet";
|
|
1776
|
-
const [step, setStep] =
|
|
1777
|
-
const [busy, setBusy] =
|
|
1778
|
-
const [error, setError] =
|
|
1779
|
-
const [exportedKey, setExportedKey] =
|
|
1780
|
-
const [newAddress, setNewAddress] =
|
|
1781
|
-
const [bootstrapSig, setBootstrapSig] =
|
|
1782
|
-
const [keyCopied, setKeyCopied] =
|
|
1783
|
-
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 () => {
|
|
1784
1844
|
setError(null);
|
|
1785
1845
|
setBusy(true);
|
|
1786
1846
|
try {
|
|
@@ -1792,13 +1852,14 @@ function SolvenExport(props) {
|
|
|
1792
1852
|
props.onSuccess?.(result.newWalletAddress);
|
|
1793
1853
|
} catch (e) {
|
|
1794
1854
|
const msg = e instanceof Error ? e.message : "Export failed";
|
|
1855
|
+
reportError(e, { operation: "export" });
|
|
1795
1856
|
setError(msg);
|
|
1796
1857
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1797
1858
|
} finally {
|
|
1798
1859
|
setBusy(false);
|
|
1799
1860
|
}
|
|
1800
1861
|
}, [wallet, exportKey, props]);
|
|
1801
|
-
const handleCopyKey =
|
|
1862
|
+
const handleCopyKey = React.useCallback(async () => {
|
|
1802
1863
|
if (!exportedKey) return;
|
|
1803
1864
|
try {
|
|
1804
1865
|
await navigator.clipboard.writeText(exportedKey);
|
|
@@ -2186,6 +2247,31 @@ async function buildSplTransferIn(deps, opts) {
|
|
|
2186
2247
|
tx.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
2187
2248
|
).toString("base64");
|
|
2188
2249
|
}
|
|
2250
|
+
var detectors = [
|
|
2251
|
+
{ platform: "telegram", detect: () => isTelegramMiniApp() }
|
|
2252
|
+
// Future hosts drop in here (or via registerPlatform), e.g.:
|
|
2253
|
+
// { platform: "mewe", detect: () => typeof window !== "undefined" && !!(window as { MeWe?: unknown }).MeWe },
|
|
2254
|
+
];
|
|
2255
|
+
function registerPlatform(detector) {
|
|
2256
|
+
detectors.unshift(detector);
|
|
2257
|
+
}
|
|
2258
|
+
function detectPlatform() {
|
|
2259
|
+
if (typeof window === "undefined") return "web";
|
|
2260
|
+
for (const d of detectors) {
|
|
2261
|
+
try {
|
|
2262
|
+
if (d.detect()) return d.platform;
|
|
2263
|
+
} catch {
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return "web";
|
|
2267
|
+
}
|
|
2268
|
+
function usePlatform() {
|
|
2269
|
+
const [platform, setPlatform] = React.useState("web");
|
|
2270
|
+
React.useEffect(() => {
|
|
2271
|
+
setPlatform(detectPlatform());
|
|
2272
|
+
}, []);
|
|
2273
|
+
return platform;
|
|
2274
|
+
}
|
|
2189
2275
|
|
|
2190
2276
|
// src/provider.tsx
|
|
2191
2277
|
var IAMGameWalletProvider = SolvenProvider;
|
|
@@ -2202,17 +2288,23 @@ exports.WalletWithdraw = SolvenWithdraw;
|
|
|
2202
2288
|
exports.backpackAdapter = backpackAdapter;
|
|
2203
2289
|
exports.buildSolTransferIn = buildSolTransferIn;
|
|
2204
2290
|
exports.buildSplTransferIn = buildSplTransferIn;
|
|
2291
|
+
exports.detectPlatform = detectPlatform;
|
|
2205
2292
|
exports.getTelegramInitData = getTelegramInitData;
|
|
2293
|
+
exports.getTelegramWebApp = getTelegramWebApp;
|
|
2206
2294
|
exports.inMemorySession = inMemorySession;
|
|
2207
2295
|
exports.isTelegramMiniApp = isTelegramMiniApp;
|
|
2208
2296
|
exports.listSupportedWallets = listSupportedWallets;
|
|
2209
2297
|
exports.localStorageSession = localStorageSession;
|
|
2210
2298
|
exports.notifyTelegramReady = notifyTelegramReady;
|
|
2211
2299
|
exports.phantomAdapter = phantomAdapter;
|
|
2300
|
+
exports.registerPlatform = registerPlatform;
|
|
2212
2301
|
exports.solflareAdapter = solflareAdapter;
|
|
2302
|
+
exports.useIsTelegram = useIsTelegram;
|
|
2303
|
+
exports.usePlatform = usePlatform;
|
|
2213
2304
|
exports.useWallet = useSolvenWallet;
|
|
2214
2305
|
exports.useWalletAuth = useSolvenAuth;
|
|
2215
2306
|
exports.useWalletBalance = useSolvenBalance;
|
|
2216
2307
|
exports.useWalletExport = useSolvenExport;
|
|
2308
|
+
exports.useWalletReportError = useSolvenReportError;
|
|
2217
2309
|
exports.useWalletSign = useSolvenSign;
|
|
2218
2310
|
exports.useWalletTransferIn = useSolvenTransferIn;
|
package/dist/index.d.cts
CHANGED
|
@@ -302,6 +302,22 @@ interface IUseIAMGameTransferIn {
|
|
|
302
302
|
destinationAddress: string | null;
|
|
303
303
|
}
|
|
304
304
|
declare function useIAMGameTransferIn(): IUseIAMGameTransferIn;
|
|
305
|
+
/**
|
|
306
|
+
* True when the app is running inside a Telegram Mini App. SSR-safe: returns false
|
|
307
|
+
* on the server and during the first client render, then the real value after mount —
|
|
308
|
+
* so it never causes a hydration mismatch. For imperative checks use isTelegramMiniApp();
|
|
309
|
+
* for the WebApp object (haptics etc.) use getTelegramWebApp().
|
|
310
|
+
*/
|
|
311
|
+
declare function useIsTelegram(): boolean;
|
|
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;
|
|
305
321
|
|
|
306
322
|
interface IAMGameLoginTheme {
|
|
307
323
|
primary?: string;
|
|
@@ -497,13 +513,62 @@ declare function buildSolTransferIn(deps: TransferInDeps, opts: BuildSolTransfer
|
|
|
497
513
|
*/
|
|
498
514
|
declare function buildSplTransferIn(deps: TransferInDeps, opts: BuildSplTransferOpts): Promise<string>;
|
|
499
515
|
|
|
516
|
+
/** Minimal shape of the Telegram WebApp object — enough for detection + common UI
|
|
517
|
+
* affordances (haptics, theme, buttons). It is the live Telegram object, so other
|
|
518
|
+
* fields exist at runtime; cast if you need them. */
|
|
519
|
+
interface TelegramWebApp {
|
|
520
|
+
initData?: string;
|
|
521
|
+
version?: string;
|
|
522
|
+
platform?: string;
|
|
523
|
+
colorScheme?: "light" | "dark";
|
|
524
|
+
ready?: () => void;
|
|
525
|
+
expand?: () => void;
|
|
526
|
+
close?: () => void;
|
|
527
|
+
HapticFeedback?: {
|
|
528
|
+
impactOccurred?: (style: "light" | "medium" | "heavy" | "rigid" | "soft") => void;
|
|
529
|
+
notificationOccurred?: (type: "error" | "success" | "warning") => void;
|
|
530
|
+
selectionChanged?: () => void;
|
|
531
|
+
};
|
|
532
|
+
[key: string]: unknown;
|
|
533
|
+
}
|
|
534
|
+
/** The live Telegram WebApp object when running inside Telegram, else null.
|
|
535
|
+
* Use it for haptics etc.: getTelegramWebApp()?.HapticFeedback?.impactOccurred("medium"). */
|
|
536
|
+
declare function getTelegramWebApp(): TelegramWebApp | null;
|
|
500
537
|
declare function getTelegramInitData(): string | null;
|
|
501
538
|
declare function isTelegramMiniApp(): boolean;
|
|
502
539
|
declare function notifyTelegramReady(): void;
|
|
503
540
|
|
|
541
|
+
/** Known hosts. Kept an open string so a new platform (e.g. "mewe") works before a
|
|
542
|
+
* release — register a detector for it and it just flows through everywhere. */
|
|
543
|
+
type Platform = "web" | "telegram" | "mewe" | (string & {});
|
|
544
|
+
interface PlatformDetector {
|
|
545
|
+
platform: Platform;
|
|
546
|
+
/** True when the app is running inside this host. Runs only in the browser. */
|
|
547
|
+
detect: () => boolean;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Register a host detector the SDK doesn't know yet (checked before the built-ins).
|
|
551
|
+
* Call once at app start. This is the seam for launching on a new platform — no SDK
|
|
552
|
+
* release required.
|
|
553
|
+
*/
|
|
554
|
+
declare function registerPlatform(detector: PlatformDetector): void;
|
|
555
|
+
/** The current host platform. "web" on the server and as the default. */
|
|
556
|
+
declare function detectPlatform(): Platform;
|
|
557
|
+
/** SSR-safe reactive platform: "web" on the server + first client render, then the
|
|
558
|
+
* real value after mount — so it never causes a hydration mismatch. */
|
|
559
|
+
declare function usePlatform(): Platform;
|
|
560
|
+
|
|
504
561
|
interface IAMGameWalletProviderProps extends IAMGameClientOptions {
|
|
505
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;
|
|
506
571
|
}
|
|
507
572
|
declare const IAMGameWalletProvider: React.FC<IAMGameWalletProviderProps>;
|
|
508
573
|
|
|
509
|
-
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 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, getTelegramInitData, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, solflareAdapter, 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
|
@@ -302,6 +302,22 @@ interface IUseIAMGameTransferIn {
|
|
|
302
302
|
destinationAddress: string | null;
|
|
303
303
|
}
|
|
304
304
|
declare function useIAMGameTransferIn(): IUseIAMGameTransferIn;
|
|
305
|
+
/**
|
|
306
|
+
* True when the app is running inside a Telegram Mini App. SSR-safe: returns false
|
|
307
|
+
* on the server and during the first client render, then the real value after mount —
|
|
308
|
+
* so it never causes a hydration mismatch. For imperative checks use isTelegramMiniApp();
|
|
309
|
+
* for the WebApp object (haptics etc.) use getTelegramWebApp().
|
|
310
|
+
*/
|
|
311
|
+
declare function useIsTelegram(): boolean;
|
|
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;
|
|
305
321
|
|
|
306
322
|
interface IAMGameLoginTheme {
|
|
307
323
|
primary?: string;
|
|
@@ -497,13 +513,62 @@ declare function buildSolTransferIn(deps: TransferInDeps, opts: BuildSolTransfer
|
|
|
497
513
|
*/
|
|
498
514
|
declare function buildSplTransferIn(deps: TransferInDeps, opts: BuildSplTransferOpts): Promise<string>;
|
|
499
515
|
|
|
516
|
+
/** Minimal shape of the Telegram WebApp object — enough for detection + common UI
|
|
517
|
+
* affordances (haptics, theme, buttons). It is the live Telegram object, so other
|
|
518
|
+
* fields exist at runtime; cast if you need them. */
|
|
519
|
+
interface TelegramWebApp {
|
|
520
|
+
initData?: string;
|
|
521
|
+
version?: string;
|
|
522
|
+
platform?: string;
|
|
523
|
+
colorScheme?: "light" | "dark";
|
|
524
|
+
ready?: () => void;
|
|
525
|
+
expand?: () => void;
|
|
526
|
+
close?: () => void;
|
|
527
|
+
HapticFeedback?: {
|
|
528
|
+
impactOccurred?: (style: "light" | "medium" | "heavy" | "rigid" | "soft") => void;
|
|
529
|
+
notificationOccurred?: (type: "error" | "success" | "warning") => void;
|
|
530
|
+
selectionChanged?: () => void;
|
|
531
|
+
};
|
|
532
|
+
[key: string]: unknown;
|
|
533
|
+
}
|
|
534
|
+
/** The live Telegram WebApp object when running inside Telegram, else null.
|
|
535
|
+
* Use it for haptics etc.: getTelegramWebApp()?.HapticFeedback?.impactOccurred("medium"). */
|
|
536
|
+
declare function getTelegramWebApp(): TelegramWebApp | null;
|
|
500
537
|
declare function getTelegramInitData(): string | null;
|
|
501
538
|
declare function isTelegramMiniApp(): boolean;
|
|
502
539
|
declare function notifyTelegramReady(): void;
|
|
503
540
|
|
|
541
|
+
/** Known hosts. Kept an open string so a new platform (e.g. "mewe") works before a
|
|
542
|
+
* release — register a detector for it and it just flows through everywhere. */
|
|
543
|
+
type Platform = "web" | "telegram" | "mewe" | (string & {});
|
|
544
|
+
interface PlatformDetector {
|
|
545
|
+
platform: Platform;
|
|
546
|
+
/** True when the app is running inside this host. Runs only in the browser. */
|
|
547
|
+
detect: () => boolean;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Register a host detector the SDK doesn't know yet (checked before the built-ins).
|
|
551
|
+
* Call once at app start. This is the seam for launching on a new platform — no SDK
|
|
552
|
+
* release required.
|
|
553
|
+
*/
|
|
554
|
+
declare function registerPlatform(detector: PlatformDetector): void;
|
|
555
|
+
/** The current host platform. "web" on the server and as the default. */
|
|
556
|
+
declare function detectPlatform(): Platform;
|
|
557
|
+
/** SSR-safe reactive platform: "web" on the server + first client render, then the
|
|
558
|
+
* real value after mount — so it never causes a hydration mismatch. */
|
|
559
|
+
declare function usePlatform(): Platform;
|
|
560
|
+
|
|
504
561
|
interface IAMGameWalletProviderProps extends IAMGameClientOptions {
|
|
505
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;
|
|
506
571
|
}
|
|
507
572
|
declare const IAMGameWalletProvider: React.FC<IAMGameWalletProviderProps>;
|
|
508
573
|
|
|
509
|
-
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 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, getTelegramInitData, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, solflareAdapter, 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
|
|
|
@@ -247,6 +247,9 @@ function getTelegram() {
|
|
|
247
247
|
if (typeof window === "undefined") return void 0;
|
|
248
248
|
return window.Telegram;
|
|
249
249
|
}
|
|
250
|
+
function getTelegramWebApp() {
|
|
251
|
+
return getTelegram()?.WebApp ?? null;
|
|
252
|
+
}
|
|
250
253
|
function getTelegramInitData() {
|
|
251
254
|
const data = getTelegram()?.WebApp?.initData;
|
|
252
255
|
if (!data || typeof data !== "string" || data.length === 0) return null;
|
|
@@ -269,7 +272,25 @@ function useSolvenContext() {
|
|
|
269
272
|
if (!ctx) throw new Error("useSolvenContext must be inside a <SolvenProvider />");
|
|
270
273
|
return ctx;
|
|
271
274
|
}
|
|
272
|
-
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 }) {
|
|
273
294
|
const client = useMemo(() => new SolvenClient(opts), [
|
|
274
295
|
opts.publishableKey,
|
|
275
296
|
opts.baseUrl,
|
|
@@ -278,6 +299,14 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
278
299
|
]);
|
|
279
300
|
const [session, setSession] = useState(client.getSession());
|
|
280
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
|
+
}, []);
|
|
281
310
|
useEffect(() => {
|
|
282
311
|
let cancelled = false;
|
|
283
312
|
(async () => {
|
|
@@ -343,9 +372,10 @@ function SolvenProvider({ children, autoTelegram = true, ...opts }) {
|
|
|
343
372
|
setSession: (s) => {
|
|
344
373
|
setSession(s);
|
|
345
374
|
setStatus(s ? "authenticated" : "anonymous");
|
|
346
|
-
}
|
|
375
|
+
},
|
|
376
|
+
reportError
|
|
347
377
|
};
|
|
348
|
-
return /* @__PURE__ */ jsx(SolvenContext.Provider, { value, children });
|
|
378
|
+
return /* @__PURE__ */ jsx(SolvenContext.Provider, { value, children: /* @__PURE__ */ jsx(SolvenErrorBoundary, { onError: reportError, children }) });
|
|
349
379
|
}
|
|
350
380
|
|
|
351
381
|
// ../../solven/sdk-client/src/hooks.ts
|
|
@@ -398,7 +428,7 @@ function useSolvenAuth() {
|
|
|
398
428
|
};
|
|
399
429
|
}
|
|
400
430
|
function useSolvenWallet() {
|
|
401
|
-
const { client, status } = useSolvenContext();
|
|
431
|
+
const { client, status, reportError } = useSolvenContext();
|
|
402
432
|
const [wallet, setWallet] = useState(null);
|
|
403
433
|
useEffect(() => {
|
|
404
434
|
if (status !== "authenticated") {
|
|
@@ -406,11 +436,15 @@ function useSolvenWallet() {
|
|
|
406
436
|
return;
|
|
407
437
|
}
|
|
408
438
|
let cancelled = false;
|
|
409
|
-
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
|
+
});
|
|
410
444
|
return () => {
|
|
411
445
|
cancelled = true;
|
|
412
446
|
};
|
|
413
|
-
}, [client, status]);
|
|
447
|
+
}, [client, status, reportError]);
|
|
414
448
|
return wallet;
|
|
415
449
|
}
|
|
416
450
|
function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
@@ -439,10 +473,17 @@ function useSolvenBalance(walletId, pollMs = 15e3) {
|
|
|
439
473
|
return balance;
|
|
440
474
|
}
|
|
441
475
|
function useSolvenSign() {
|
|
442
|
-
const { client } = useSolvenContext();
|
|
476
|
+
const { client, reportError } = useSolvenContext();
|
|
443
477
|
const signAction = useCallback(
|
|
444
|
-
({ walletId, txBase64, label, idempotencyKey }) =>
|
|
445
|
-
|
|
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]
|
|
446
487
|
);
|
|
447
488
|
return { signAction };
|
|
448
489
|
}
|
|
@@ -470,6 +511,13 @@ function useSolvenTransferIn() {
|
|
|
470
511
|
const wallet = useSolvenWallet();
|
|
471
512
|
return { destinationAddress: wallet?.address ?? null };
|
|
472
513
|
}
|
|
514
|
+
function useIsTelegram() {
|
|
515
|
+
const [inTelegram, setInTelegram] = useState(false);
|
|
516
|
+
useEffect(() => {
|
|
517
|
+
setInTelegram(isTelegramMiniApp());
|
|
518
|
+
}, []);
|
|
519
|
+
return inTelegram;
|
|
520
|
+
}
|
|
473
521
|
|
|
474
522
|
// ../../solven/sdk-client/src/wallet-adapter.ts
|
|
475
523
|
function phantomAdapter() {
|
|
@@ -586,6 +634,7 @@ var defaultTheme = {
|
|
|
586
634
|
};
|
|
587
635
|
function SolvenLoginContent(props) {
|
|
588
636
|
const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
|
|
637
|
+
const reportError = useSolvenReportError();
|
|
589
638
|
const [busy, setBusy] = useState(null);
|
|
590
639
|
const [error, setError] = useState(null);
|
|
591
640
|
const [email, setEmail] = useState("");
|
|
@@ -614,6 +663,7 @@ function SolvenLoginContent(props) {
|
|
|
614
663
|
props.onCloseAfterSignIn?.();
|
|
615
664
|
} catch (e) {
|
|
616
665
|
if (!cancelled) {
|
|
666
|
+
reportError(e, { operation: "login:telegram" });
|
|
617
667
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
618
668
|
}
|
|
619
669
|
} finally {
|
|
@@ -640,6 +690,7 @@ function SolvenLoginContent(props) {
|
|
|
640
690
|
props.onSignIn?.();
|
|
641
691
|
props.onCloseAfterSignIn?.();
|
|
642
692
|
} catch (e) {
|
|
693
|
+
reportError(e, { operation: "login:wallet" });
|
|
643
694
|
setError(e instanceof Error ? e.message : "Wallet sign-in failed");
|
|
644
695
|
} finally {
|
|
645
696
|
setBusy(null);
|
|
@@ -653,6 +704,7 @@ function SolvenLoginContent(props) {
|
|
|
653
704
|
props.onSignIn?.();
|
|
654
705
|
props.onCloseAfterSignIn?.();
|
|
655
706
|
} catch (e) {
|
|
707
|
+
reportError(e, { operation: "login:telegram" });
|
|
656
708
|
setError(e instanceof Error ? e.message : "Telegram sign-in failed");
|
|
657
709
|
} finally {
|
|
658
710
|
setBusy(null);
|
|
@@ -665,6 +717,7 @@ function SolvenLoginContent(props) {
|
|
|
665
717
|
await requestEmailOtp(email.trim());
|
|
666
718
|
setOtpSent(true);
|
|
667
719
|
} catch (e) {
|
|
720
|
+
reportError(e, { operation: "login:email" });
|
|
668
721
|
setError(e instanceof Error ? e.message : "Couldn't send the code");
|
|
669
722
|
} finally {
|
|
670
723
|
setBusy(null);
|
|
@@ -678,6 +731,7 @@ function SolvenLoginContent(props) {
|
|
|
678
731
|
props.onSignIn?.();
|
|
679
732
|
props.onCloseAfterSignIn?.();
|
|
680
733
|
} catch (e) {
|
|
734
|
+
reportError(e, { operation: "login:email" });
|
|
681
735
|
setError(e instanceof Error ? e.message : "Couldn't verify the code");
|
|
682
736
|
} finally {
|
|
683
737
|
setBusy(null);
|
|
@@ -1453,7 +1507,7 @@ function isValidSolanaAddress(address) {
|
|
|
1453
1507
|
function SolvenWithdraw(props) {
|
|
1454
1508
|
const wallet = useSolvenWallet();
|
|
1455
1509
|
const balance = useSolvenBalance(wallet?.id ?? null);
|
|
1456
|
-
const { client } = useSolvenContext();
|
|
1510
|
+
const { client, reportError } = useSolvenContext();
|
|
1457
1511
|
const theme = useMemo(() => ({ ...defaultTheme4, ...props.theme ?? {} }), [props.theme]);
|
|
1458
1512
|
const label = props.label ?? "Withdraw";
|
|
1459
1513
|
const [toAddress, setToAddress] = useState("");
|
|
@@ -1531,6 +1585,7 @@ function SolvenWithdraw(props) {
|
|
|
1531
1585
|
props.onSuccess?.(result.signature);
|
|
1532
1586
|
} catch (e) {
|
|
1533
1587
|
const msg = e instanceof Error ? e.message : "Withdrawal failed";
|
|
1588
|
+
reportError(e, { operation: "withdraw" });
|
|
1534
1589
|
setError(msg);
|
|
1535
1590
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1536
1591
|
} finally {
|
|
@@ -1769,6 +1824,7 @@ function formatLamports(lamports) {
|
|
|
1769
1824
|
function SolvenExport(props) {
|
|
1770
1825
|
const wallet = useSolvenWallet();
|
|
1771
1826
|
const { preflight, refreshPreflight, exportKey } = useSolvenExport(wallet?.id ?? null);
|
|
1827
|
+
const reportError = useSolvenReportError();
|
|
1772
1828
|
const theme = useMemo(() => ({ ...defaultTheme5, ...props.theme ?? {} }), [props.theme]);
|
|
1773
1829
|
const label = props.label ?? "Export Wallet";
|
|
1774
1830
|
const [step, setStep] = useState("preflight");
|
|
@@ -1790,6 +1846,7 @@ function SolvenExport(props) {
|
|
|
1790
1846
|
props.onSuccess?.(result.newWalletAddress);
|
|
1791
1847
|
} catch (e) {
|
|
1792
1848
|
const msg = e instanceof Error ? e.message : "Export failed";
|
|
1849
|
+
reportError(e, { operation: "export" });
|
|
1793
1850
|
setError(msg);
|
|
1794
1851
|
props.onError?.(e instanceof Error ? e : new Error(msg));
|
|
1795
1852
|
} finally {
|
|
@@ -2184,8 +2241,33 @@ async function buildSplTransferIn(deps, opts) {
|
|
|
2184
2241
|
tx.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
2185
2242
|
).toString("base64");
|
|
2186
2243
|
}
|
|
2244
|
+
var detectors = [
|
|
2245
|
+
{ platform: "telegram", detect: () => isTelegramMiniApp() }
|
|
2246
|
+
// Future hosts drop in here (or via registerPlatform), e.g.:
|
|
2247
|
+
// { platform: "mewe", detect: () => typeof window !== "undefined" && !!(window as { MeWe?: unknown }).MeWe },
|
|
2248
|
+
];
|
|
2249
|
+
function registerPlatform(detector) {
|
|
2250
|
+
detectors.unshift(detector);
|
|
2251
|
+
}
|
|
2252
|
+
function detectPlatform() {
|
|
2253
|
+
if (typeof window === "undefined") return "web";
|
|
2254
|
+
for (const d of detectors) {
|
|
2255
|
+
try {
|
|
2256
|
+
if (d.detect()) return d.platform;
|
|
2257
|
+
} catch {
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
return "web";
|
|
2261
|
+
}
|
|
2262
|
+
function usePlatform() {
|
|
2263
|
+
const [platform, setPlatform] = useState("web");
|
|
2264
|
+
useEffect(() => {
|
|
2265
|
+
setPlatform(detectPlatform());
|
|
2266
|
+
}, []);
|
|
2267
|
+
return platform;
|
|
2268
|
+
}
|
|
2187
2269
|
|
|
2188
2270
|
// src/provider.tsx
|
|
2189
2271
|
var IAMGameWalletProvider = SolvenProvider;
|
|
2190
2272
|
|
|
2191
|
-
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, getTelegramInitData, inMemorySession, isTelegramMiniApp, listSupportedWallets, localStorageSession, notifyTelegramReady, phantomAdapter, solflareAdapter, 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",
|