cruzo-web3 0.1.2 → 0.1.3

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
@@ -8,11 +8,6 @@ Web3 addon for [cruzo](https://github.com/MaratBektemirov/cruzo): wallet connect
8
8
  npm install cruzo cruzo-web3
9
9
  ```
10
10
 
11
- For mobile wallets, also install optional peer dependencies:
12
-
13
- ```bash
14
- npm install @tonconnect/sdk @tonconnect/ui @walletconnect/ethereum-provider
15
- ```
16
11
 
17
12
  ## Public API
18
13
 
@@ -16,6 +16,7 @@ import {
16
16
  import type { SignerState, SignerWallet } from "../../types/signer-state";
17
17
  import { buildSigningPageUrl } from "../../signing-url";
18
18
  import { pubKeyToText } from "../../utils/format-pub-key";
19
+ import { formatWalletError, isWalletUserCancellation } from "../../utils/wallet-error";
19
20
  import { web3Service } from "../../web3.service";
20
21
  import { isCustomWallet } from "../../web3-wallet";
21
22
 
@@ -309,7 +310,9 @@ export class Web3SignerComponent extends AbstractComponent<SignerConfig, any, Si
309
310
 
310
311
  action()
311
312
  .catch((error: unknown) => {
312
- this.error$.update(error instanceof Error ? error.message : String(error));
313
+ if (isWalletUserCancellation(error)) return;
314
+
315
+ this.error$.update(formatWalletError(error));
313
316
  })
314
317
  .finally(() => {
315
318
  this.busy$.update(false);
@@ -70,9 +70,12 @@ export class TonConnectProvider implements Web3Provider {
70
70
  });
71
71
  }
72
72
 
73
- return this.waitForAccount(() => {
74
- void this.ui.openModal();
75
- });
73
+ return this.waitForAccount(
74
+ () => {
75
+ void this.ui.openModal();
76
+ },
77
+ { watchModalClose: true },
78
+ );
76
79
  }
77
80
 
78
81
  async disconnect() {
@@ -115,28 +118,46 @@ export class TonConnectProvider implements Web3Provider {
115
118
  return account;
116
119
  }
117
120
 
118
- private waitForAccount(start: () => void) {
121
+ private waitForAccount(start: () => void, options?: { watchModalClose?: boolean }) {
119
122
  return new Promise<PubKey>((resolve, reject) => {
120
- const unsubscribe = this.ui.onStatusChange(
123
+ let settled = false;
124
+
125
+ const finish = (action: () => void) => {
126
+ if (settled) return;
127
+
128
+ settled = true;
129
+ unsubscribeStatus();
130
+ unsubscribeModal?.();
131
+ action();
132
+ };
133
+
134
+ const unsubscribeStatus = this.ui.onStatusChange(
121
135
  (wallet) => {
122
136
  if (!wallet?.account) return;
123
137
 
124
- unsubscribe();
125
138
  const pubKey = this.toPubKey(wallet.account);
126
139
  this.onAccountChange?.(pubKey);
127
- resolve(pubKey);
140
+ finish(() => resolve(pubKey));
128
141
  },
129
142
  (error) => {
130
- unsubscribe();
131
- reject(error);
143
+ finish(() => reject(error));
132
144
  },
133
145
  );
134
146
 
147
+ const unsubscribeModal = options?.watchModalClose
148
+ ? this.ui.onModalStateChange((state) => {
149
+ if (state.status === "opened" || this.ui.account) return;
150
+
151
+ if (state.closeReason === "action-cancelled") {
152
+ finish(() => reject(new Error("Connection cancelled")));
153
+ }
154
+ })
155
+ : null;
156
+
135
157
  try {
136
158
  start();
137
159
  } catch (error) {
138
- unsubscribe();
139
- reject(error);
160
+ finish(() => reject(error));
140
161
  }
141
162
  });
142
163
  }
@@ -0,0 +1,67 @@
1
+ function readMessage(error: unknown): string {
2
+ if (typeof error === "string") return error;
3
+
4
+ if (error instanceof Error) {
5
+ return error.message || error.name;
6
+ }
7
+
8
+ if (error && typeof error === "object") {
9
+ const record = error as Record<string, unknown>;
10
+ const message = record.message;
11
+
12
+ if (typeof message === "string" && message.length) return message;
13
+ if (message && typeof message === "object") {
14
+ const nested = message as Record<string, unknown>;
15
+
16
+ if (typeof nested.message === "string" && nested.message.length) {
17
+ return nested.message;
18
+ }
19
+ }
20
+
21
+ if (typeof record.reason === "string" && record.reason.length) {
22
+ return record.reason;
23
+ }
24
+ }
25
+
26
+ return "";
27
+ }
28
+
29
+ function isUserCancellationMessage(message: string) {
30
+ const text = message.toLowerCase();
31
+
32
+ return (
33
+ text.includes("user rejected") ||
34
+ text.includes("rejected the request") ||
35
+ text.includes("request rejected") ||
36
+ text.includes("action rejected") ||
37
+ text.includes("connection cancelled") ||
38
+ text.includes("connection canceled") ||
39
+ text.includes("wallet was not connected") ||
40
+ text.includes("was not sent") ||
41
+ text.includes("sign data canceled") ||
42
+ text.includes("sign data cancelled") ||
43
+ text.includes("sign message canceled") ||
44
+ text.includes("sign message cancelled") ||
45
+ text.includes("transaction canceled") ||
46
+ text.includes("transaction cancelled")
47
+ );
48
+ }
49
+
50
+ export function isWalletUserCancellation(error: unknown) {
51
+ if (error && typeof error === "object") {
52
+ const record = error as Record<string, unknown>;
53
+
54
+ if (record.code === 4001 || record.code === "4001") return true;
55
+ if (record.name === "UserRejectsError") return true;
56
+ }
57
+
58
+ const message = readMessage(error);
59
+
60
+ return message.length > 0 && isUserCancellationMessage(message);
61
+ }
62
+
63
+ export function formatWalletError(error: unknown) {
64
+ const message = readMessage(error);
65
+
66
+ return message || "Wallet request failed";
67
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cruzo-web3",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Web3 addon for cruzo: wallet providers, sign, verify",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,28 +31,16 @@
31
31
  "typecheck": "tsc -p tsconfig.json",
32
32
  "prepublishOnly": "npm run typecheck"
33
33
  },
34
+ "dependencies": {
35
+ "@tonconnect/sdk": "^3.4.1",
36
+ "@tonconnect/ui": "^3.0.0",
37
+ "@walletconnect/ethereum-provider": "^2.23.9"
38
+ },
34
39
  "peerDependencies": {
35
- "@tonconnect/sdk": ">=3.0.0",
36
- "@tonconnect/ui": ">=3.0.0",
37
- "@walletconnect/ethereum-provider": ">=2.0.0",
38
40
  "cruzo": "0.9.889"
39
41
  },
40
- "peerDependenciesMeta": {
41
- "@tonconnect/sdk": {
42
- "optional": true
43
- },
44
- "@tonconnect/ui": {
45
- "optional": true
46
- },
47
- "@walletconnect/ethereum-provider": {
48
- "optional": true
49
- }
50
- },
51
42
  "devDependencies": {
52
- "@tonconnect/sdk": "^3.4.1",
53
- "@tonconnect/ui": "^3.0.0",
54
43
  "@types/node": "20.0.0",
55
- "@walletconnect/ethereum-provider": "^2.23.9",
56
44
  "cruzo": "0.9.889",
57
45
  "typescript": "5.9.3"
58
46
  }