@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 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
- - ✅ **FIXED**: All Turkish comments translated to English
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) => listener(event.url));
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) {
@@ -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
  /**
@@ -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
- response.appName &&
279
- response.version);
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
@@ -35,9 +35,9 @@ exports.SUPPORTED_WALLETS = [
35
35
  {
36
36
  name: 'Wallet in Telegram',
37
37
  appName: 'Wallet',
38
- universalLink: 'https://wallet.tonapi.io/ton-connect',
38
+ universalLink: 'https://wallet.tg/ton-connect',
39
39
  deepLink: 'tg://',
40
- iconUrl: 'https://wallet.tonapi.io/icon.png',
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 && react_native_1.Platform.OS !== 'web' ? (react_1.default.createElement(react_native_1.Image, { source: { uri: wallet.iconUrl }, style: styles.walletIcon, onError: () => {
104
- // Fallback to placeholder on error
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",
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) => listener(event.url));
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
 
@@ -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
- response.appName &&
351
- response.version
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
 
@@ -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.tonapi.io/ton-connect',
52
+ universalLink: 'https://wallet.tg/ton-connect',
53
53
  deepLink: 'tg://',
54
- iconUrl: 'https://wallet.tonapi.io/icon.png',
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 && Platform.OS !== 'web' ? (
164
+ {wallet.iconUrl && !imageError ? (
163
165
  <Image
164
166
  source={{ uri: wallet.iconUrl }}
165
167
  style={styles.walletIcon}
166
- onError={() => {
167
- // Fallback to placeholder on error
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
  />