@blazium/ton-connect-mobile 1.2.3 → 1.2.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/README.md +6 -2
- package/dist/adapters/react-native.js +8 -1
- package/dist/core/protocol.d.ts +2 -0
- package/dist/core/protocol.js +6 -3
- package/dist/core/wallets.js +2 -2
- package/dist/react/WalletSelectionModal.js +7 -2
- package/package.json +1 -1
- package/src/adapters/react-native.ts +7 -1
- package/src/core/protocol.ts +5 -3
- package/src/core/wallets.ts +2 -2
- package/src/react/WalletSelectionModal.tsx +9 -3
package/README.md
CHANGED
|
@@ -284,7 +284,6 @@ const signed = await ton.signData('Hello, TON!', '1.0');
|
|
|
284
284
|
##### `disconnect(): Promise<void>`
|
|
285
285
|
|
|
286
286
|
Disconnect from wallet.
|
|
287
|
-
|
|
288
287
|
```typescript
|
|
289
288
|
await ton.disconnect();
|
|
290
289
|
```
|
|
@@ -830,6 +829,11 @@ try {
|
|
|
830
829
|
|
|
831
830
|
## Changelog
|
|
832
831
|
|
|
832
|
+
### v1.2.5
|
|
833
|
+
- ✅ **FIXED**: Connection response validation - `appName` and `version` fields are now optional, improving compatibility with wallets that don't send these fields
|
|
834
|
+
- ✅ **FIXED**: ReactNativeAdapter URL listener error handling - Added try-catch block to prevent app crashes if URL listeners throw errors
|
|
835
|
+
- ✅ **IMPROVED**: Enhanced error handling robustness across the SDK
|
|
836
|
+
|
|
833
837
|
### v1.2.3
|
|
834
838
|
- ✅ **NEW**: Network switching - Switch between mainnet and testnet dynamically
|
|
835
839
|
- ✅ **NEW**: Event emitters - Listen to connect, disconnect, transaction, and error events
|
|
@@ -845,7 +849,7 @@ try {
|
|
|
845
849
|
- ✅ **IMPROVED**: All wallets shown on web platform (with availability status)
|
|
846
850
|
- ✅ **IMPROVED**: Chain ID automatically updates when network changes
|
|
847
851
|
- ✅ **FIXED**: Tonkeeper now correctly shows as available on web
|
|
848
|
-
|
|
852
|
+
|
|
849
853
|
|
|
850
854
|
### v1.2.0
|
|
851
855
|
- ✅ **NEW**: Beautiful wallet selection modal component
|
|
@@ -34,7 +34,14 @@ class ReactNativeAdapter {
|
|
|
34
34
|
}
|
|
35
35
|
// Listen for deep links when app is already open
|
|
36
36
|
this.subscription = Linking.addEventListener('url', (event) => {
|
|
37
|
-
this.urlListeners.forEach((listener) =>
|
|
37
|
+
this.urlListeners.forEach((listener) => {
|
|
38
|
+
try {
|
|
39
|
+
listener(event.url);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error('[ReactNativeAdapter] Error in URL listener:', error);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
38
45
|
});
|
|
39
46
|
}
|
|
40
47
|
async openURL(url, skipCanOpenURLCheck = true) {
|
package/dist/core/protocol.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export declare function parseCallbackURL(url: string, scheme: string): {
|
|
|
40
40
|
export declare function extractWalletInfo(response: ConnectionResponsePayload): WalletInfo;
|
|
41
41
|
/**
|
|
42
42
|
* Validate connection response
|
|
43
|
+
* CRITICAL FIX: Only validate truly required fields (session, address, publicKey, name)
|
|
44
|
+
* appName and version are optional - extractWalletInfo has fallbacks for them
|
|
43
45
|
*/
|
|
44
46
|
export declare function validateConnectionResponse(response: ConnectionResponsePayload): boolean;
|
|
45
47
|
/**
|
package/dist/core/protocol.js
CHANGED
|
@@ -269,14 +269,17 @@ function extractWalletInfo(response) {
|
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* Validate connection response
|
|
272
|
+
* CRITICAL FIX: Only validate truly required fields (session, address, publicKey, name)
|
|
273
|
+
* appName and version are optional - extractWalletInfo has fallbacks for them
|
|
272
274
|
*/
|
|
273
275
|
function validateConnectionResponse(response) {
|
|
274
276
|
return !!(response.session &&
|
|
275
277
|
response.address &&
|
|
276
278
|
response.publicKey &&
|
|
277
|
-
response.name
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
response.name
|
|
280
|
+
// Note: appName and version are optional - extractWalletInfo handles fallbacks
|
|
281
|
+
// Some wallets may not send these fields, and that's OK
|
|
282
|
+
);
|
|
280
283
|
}
|
|
281
284
|
/**
|
|
282
285
|
* Validate transaction response
|
package/dist/core/wallets.js
CHANGED
|
@@ -35,9 +35,9 @@ exports.SUPPORTED_WALLETS = [
|
|
|
35
35
|
{
|
|
36
36
|
name: 'Wallet in Telegram',
|
|
37
37
|
appName: 'Wallet',
|
|
38
|
-
universalLink: 'https://wallet.
|
|
38
|
+
universalLink: 'https://wallet.tg/ton-connect',
|
|
39
39
|
deepLink: 'tg://',
|
|
40
|
-
iconUrl: 'https://wallet.
|
|
40
|
+
iconUrl: 'https://wallet.tg/images/logo-288.png',
|
|
41
41
|
platforms: ['ios', 'android'],
|
|
42
42
|
preferredReturnStrategy: 'post_redirect',
|
|
43
43
|
requiresReturnScheme: true, // Telegram Wallet requires explicit returnScheme
|
|
@@ -22,6 +22,7 @@ function WalletSelectionModal({ visible, onClose, wallets: customWallets, style,
|
|
|
22
22
|
const [wallets, setWallets] = react_1.default.useState([]);
|
|
23
23
|
const [connectingWallet, setConnectingWallet] = react_1.default.useState(null);
|
|
24
24
|
const [walletAvailability, setWalletAvailability] = react_1.default.useState({});
|
|
25
|
+
const [imageErrors, setImageErrors] = react_1.default.useState({});
|
|
25
26
|
// Load wallets and check availability
|
|
26
27
|
react_1.default.useEffect(() => {
|
|
27
28
|
const loadWallets = async () => {
|
|
@@ -95,13 +96,17 @@ function WalletSelectionModal({ visible, onClose, wallets: customWallets, style,
|
|
|
95
96
|
react_1.default.createElement(react_native_1.Text, { style: styles.emptyStateSubtext }, "Please install a TON wallet app to continue"))) : (wallets.map((wallet) => {
|
|
96
97
|
const isConnecting = connectingWallet === wallet.name;
|
|
97
98
|
const isAvailable = walletAvailability[wallet.name] !== false;
|
|
99
|
+
const imageError = imageErrors[wallet.name] || false;
|
|
98
100
|
return (react_1.default.createElement(react_native_1.TouchableOpacity, { key: wallet.name, style: [
|
|
99
101
|
styles.walletCard,
|
|
100
102
|
!isAvailable && styles.walletCardUnavailable,
|
|
101
103
|
isConnecting && styles.walletCardConnecting,
|
|
102
104
|
], onPress: () => isAvailable && !isConnecting && handleSelectWallet(wallet), disabled: !isAvailable || isConnecting },
|
|
103
|
-
react_1.default.createElement(react_native_1.View, { style: styles.walletIconContainer }, wallet.iconUrl &&
|
|
104
|
-
|
|
105
|
+
react_1.default.createElement(react_native_1.View, { style: styles.walletIconContainer }, wallet.iconUrl && !imageError ? (react_1.default.createElement(react_native_1.Image, { source: { uri: wallet.iconUrl }, style: styles.walletIcon, onError: (error) => {
|
|
106
|
+
console.log(`[WalletSelectionModal] Failed to load image for ${wallet.name}:`, wallet.iconUrl, error);
|
|
107
|
+
setImageErrors((prev) => ({ ...prev, [wallet.name]: true }));
|
|
108
|
+
}, onLoad: () => {
|
|
109
|
+
console.log(`[WalletSelectionModal] Successfully loaded image for ${wallet.name}:`, wallet.iconUrl);
|
|
105
110
|
}, resizeMode: "cover" })) : (react_1.default.createElement(react_native_1.View, { style: styles.walletIconPlaceholder },
|
|
106
111
|
react_1.default.createElement(react_native_1.Text, { style: styles.walletIconText }, wallet.name.charAt(0).toUpperCase())))),
|
|
107
112
|
react_1.default.createElement(react_native_1.Text, { style: styles.walletName, numberOfLines: 1 }, wallet.name),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blazium/ton-connect-mobile",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Production-ready TON Connect Mobile SDK for React Native and Expo. Implements the real TonConnect protocol for mobile applications using deep links and callbacks.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -42,7 +42,13 @@ export class ReactNativeAdapter implements PlatformAdapter {
|
|
|
42
42
|
}
|
|
43
43
|
// Listen for deep links when app is already open
|
|
44
44
|
this.subscription = Linking.addEventListener('url', (event: { url: string }) => {
|
|
45
|
-
this.urlListeners.forEach((listener) =>
|
|
45
|
+
this.urlListeners.forEach((listener) => {
|
|
46
|
+
try {
|
|
47
|
+
listener(event.url);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('[ReactNativeAdapter] Error in URL listener:', error);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
46
52
|
});
|
|
47
53
|
}
|
|
48
54
|
|
package/src/core/protocol.ts
CHANGED
|
@@ -338,6 +338,8 @@ export function extractWalletInfo(
|
|
|
338
338
|
|
|
339
339
|
/**
|
|
340
340
|
* Validate connection response
|
|
341
|
+
* CRITICAL FIX: Only validate truly required fields (session, address, publicKey, name)
|
|
342
|
+
* appName and version are optional - extractWalletInfo has fallbacks for them
|
|
341
343
|
*/
|
|
342
344
|
export function validateConnectionResponse(
|
|
343
345
|
response: ConnectionResponsePayload
|
|
@@ -346,9 +348,9 @@ export function validateConnectionResponse(
|
|
|
346
348
|
response.session &&
|
|
347
349
|
response.address &&
|
|
348
350
|
response.publicKey &&
|
|
349
|
-
response.name
|
|
350
|
-
|
|
351
|
-
|
|
351
|
+
response.name
|
|
352
|
+
// Note: appName and version are optional - extractWalletInfo handles fallbacks
|
|
353
|
+
// Some wallets may not send these fields, and that's OK
|
|
352
354
|
);
|
|
353
355
|
}
|
|
354
356
|
|
package/src/core/wallets.ts
CHANGED
|
@@ -49,9 +49,9 @@ export const SUPPORTED_WALLETS: WalletDefinition[] = [
|
|
|
49
49
|
{
|
|
50
50
|
name: 'Wallet in Telegram',
|
|
51
51
|
appName: 'Wallet',
|
|
52
|
-
universalLink: 'https://wallet.
|
|
52
|
+
universalLink: 'https://wallet.tg/ton-connect',
|
|
53
53
|
deepLink: 'tg://',
|
|
54
|
-
iconUrl: 'https://wallet.
|
|
54
|
+
iconUrl: 'https://wallet.tg/images/logo-288.png',
|
|
55
55
|
platforms: ['ios', 'android'],
|
|
56
56
|
preferredReturnStrategy: 'post_redirect',
|
|
57
57
|
requiresReturnScheme: true, // Telegram Wallet requires explicit returnScheme
|
|
@@ -45,6 +45,7 @@ export function WalletSelectionModal({
|
|
|
45
45
|
const [wallets, setWallets] = React.useState<WalletDefinition[]>([]);
|
|
46
46
|
const [connectingWallet, setConnectingWallet] = React.useState<string | null>(null);
|
|
47
47
|
const [walletAvailability, setWalletAvailability] = React.useState<Record<string, boolean>>({});
|
|
48
|
+
const [imageErrors, setImageErrors] = React.useState<Record<string, boolean>>({});
|
|
48
49
|
|
|
49
50
|
// Load wallets and check availability
|
|
50
51
|
React.useEffect(() => {
|
|
@@ -147,6 +148,7 @@ export function WalletSelectionModal({
|
|
|
147
148
|
wallets.map((wallet) => {
|
|
148
149
|
const isConnecting = connectingWallet === wallet.name;
|
|
149
150
|
const isAvailable = walletAvailability[wallet.name] !== false;
|
|
151
|
+
const imageError = imageErrors[wallet.name] || false;
|
|
150
152
|
return (
|
|
151
153
|
<TouchableOpacity
|
|
152
154
|
key={wallet.name}
|
|
@@ -159,12 +161,16 @@ export function WalletSelectionModal({
|
|
|
159
161
|
disabled={!isAvailable || isConnecting}
|
|
160
162
|
>
|
|
161
163
|
<View style={styles.walletIconContainer}>
|
|
162
|
-
{wallet.iconUrl &&
|
|
164
|
+
{wallet.iconUrl && !imageError ? (
|
|
163
165
|
<Image
|
|
164
166
|
source={{ uri: wallet.iconUrl }}
|
|
165
167
|
style={styles.walletIcon}
|
|
166
|
-
onError={() => {
|
|
167
|
-
|
|
168
|
+
onError={(error) => {
|
|
169
|
+
console.log(`[WalletSelectionModal] Failed to load image for ${wallet.name}:`, wallet.iconUrl, error);
|
|
170
|
+
setImageErrors((prev) => ({ ...prev, [wallet.name]: true }));
|
|
171
|
+
}}
|
|
172
|
+
onLoad={() => {
|
|
173
|
+
console.log(`[WalletSelectionModal] Successfully loaded image for ${wallet.name}:`, wallet.iconUrl);
|
|
168
174
|
}}
|
|
169
175
|
resizeMode="cover"
|
|
170
176
|
/>
|