@coin-voyage/crypto 2.4.3 → 2.4.5-beta.0

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.
@@ -0,0 +1,10 @@
1
+ declare const USER_REJECTED_ERROR = "User rejected the request.";
2
+ declare const INSUFFICIENT_FUNDS_ERROR = "Insufficient funds to cover the transaction amount and network fees.";
3
+ declare const SWITCH_CHAIN_ERROR = "Unable to switch networks. Please switch networks in your wallet and try again.";
4
+ declare const GAS_ESTIMATION_ERROR = "Unable to estimate network fees. Please try again.";
5
+ declare const TRANSACTION_SUBMISSION_ERROR = "Transaction could not be submitted. Please try again.";
6
+ declare function isUserRejectedError(error: unknown): boolean;
7
+ declare function isInsufficientFundsError(error: unknown): boolean;
8
+ declare function walletError(message: string, cause: unknown): Error;
9
+ declare function toTransactionError(error: unknown): Error;
10
+ export { toTransactionError, walletError, isUserRejectedError, isInsufficientFundsError, USER_REJECTED_ERROR, INSUFFICIENT_FUNDS_ERROR, SWITCH_CHAIN_ERROR, GAS_ESTIMATION_ERROR, TRANSACTION_SUBMISSION_ERROR };
@@ -0,0 +1,29 @@
1
+ const USER_REJECTED_ERROR = "User rejected the request.";
2
+ const INSUFFICIENT_FUNDS_ERROR = "Insufficient funds to cover the transaction amount and network fees.";
3
+ const SWITCH_CHAIN_ERROR = "Unable to switch networks. Please switch networks in your wallet and try again.";
4
+ const GAS_ESTIMATION_ERROR = "Unable to estimate network fees. Please try again.";
5
+ const TRANSACTION_SUBMISSION_ERROR = "Transaction could not be submitted. Please try again.";
6
+ function getErrorMessage(error) {
7
+ return error instanceof Error ? error.message : String(error);
8
+ }
9
+ function isUserRejectedError(error) {
10
+ const message = getErrorMessage(error).toLowerCase();
11
+ return message.includes("user rejected") || message.includes("user denied") || message.includes("rejected request");
12
+ }
13
+ function isInsufficientFundsError(error) {
14
+ const message = getErrorMessage(error).toLowerCase();
15
+ return message.includes("insufficient funds") || message.includes("insufficient balance");
16
+ }
17
+ function walletError(message, cause) {
18
+ return new Error(message, { cause });
19
+ }
20
+ function toTransactionError(error) {
21
+ if (isUserRejectedError(error)) {
22
+ return walletError(USER_REJECTED_ERROR, error);
23
+ }
24
+ if (isInsufficientFundsError(error)) {
25
+ return walletError(INSUFFICIENT_FUNDS_ERROR, error);
26
+ }
27
+ return walletError(TRANSACTION_SUBMISSION_ERROR, error);
28
+ }
29
+ export { toTransactionError, walletError, isUserRejectedError, isInsufficientFundsError, USER_REJECTED_ERROR, INSUFFICIENT_FUNDS_ERROR, SWITCH_CHAIN_ERROR, GAS_ESTIMATION_ERROR, TRANSACTION_SUBMISSION_ERROR };
@@ -1,5 +1,6 @@
1
1
  import { estimateFeesPerGas } from "viem/actions";
2
2
  import { useChainId, useConfig, useSendTransaction, useSwitchChain, useWriteContract } from "wagmi";
3
+ import { GAS_ESTIMATION_ERROR, isUserRejectedError, SWITCH_CHAIN_ERROR, toTransactionError, USER_REJECTED_ERROR, walletError, } from "./errors";
3
4
  export function useEVMTransaction() {
4
5
  const { writeContractAsync } = useWriteContract();
5
6
  const { sendTransactionAsync } = useSendTransaction();
@@ -15,12 +16,13 @@ export function useEVMTransaction() {
15
16
  switchedId = switched?.id;
16
17
  }
17
18
  catch (e) {
18
- console.error("Failed to switch chain", e);
19
- throw new Error("Failed to switch chain", { cause: e });
19
+ if (isUserRejectedError(e)) {
20
+ throw walletError(USER_REJECTED_ERROR, e);
21
+ }
22
+ throw walletError(SWITCH_CHAIN_ERROR, e);
20
23
  }
21
24
  if (switchedId !== sourceChainId) {
22
- console.error("Failed to switch chain", { expected: sourceChainId, actual: switchedId });
23
- throw new Error("Failed to switch chain");
25
+ throw walletError(SWITCH_CHAIN_ERROR, null);
24
26
  }
25
27
  };
26
28
  const feesPerGas = async (options) => {
@@ -29,8 +31,7 @@ export function useEVMTransaction() {
29
31
  return await estimateFeesPerGas(client, options);
30
32
  }
31
33
  catch (e) {
32
- console.error("Failed to estimate fees per gas", e);
33
- throw new Error("Failed to estimate fees per gas", { cause: e });
34
+ throw walletError(GAS_ESTIMATION_ERROR, e);
34
35
  }
35
36
  };
36
37
  const execute = async (params) => {
@@ -45,7 +46,7 @@ export function useEVMTransaction() {
45
46
  evmPaymentData.maxFeePerGas = gasEstimates.maxFeePerGas?.toString();
46
47
  evmPaymentData.maxPriorityFeePerGas = gasEstimates.maxPriorityFeePerGas?.toString();
47
48
  }
48
- const tx = await sendTransactionAsync({
49
+ const tx = await submitEVMTransaction(() => sendTransactionAsync({
49
50
  to: evmPaymentData.to,
50
51
  data: evmPaymentData.data,
51
52
  value: BigInt(evmPaymentData.value),
@@ -54,7 +55,7 @@ export function useEVMTransaction() {
54
55
  maxPriorityFeePerGas: evmPaymentData.maxPriorityFeePerGas
55
56
  ? BigInt(evmPaymentData.maxPriorityFeePerGas)
56
57
  : undefined,
57
- });
58
+ }));
58
59
  return tx;
59
60
  }
60
61
  const { chainId, to: toAddress, amount, token } = params;
@@ -75,17 +76,17 @@ export function useEVMTransaction() {
75
76
  ? BigInt(gasEstimates.maxPriorityFeePerGas)
76
77
  : undefined;
77
78
  if (!token) {
78
- const tx = await sendTransactionAsync({
79
+ const tx = await submitEVMTransaction(() => sendTransactionAsync({
79
80
  to,
80
81
  value,
81
82
  chainId,
82
83
  maxFeePerGas,
83
84
  maxPriorityFeePerGas,
84
- });
85
+ }));
85
86
  return tx;
86
87
  }
87
88
  // ERC20 -> same ABI (transfer)
88
- const tx = await writeContractAsync({
89
+ const tx = await submitEVMTransaction(() => writeContractAsync({
89
90
  abi: [
90
91
  {
91
92
  type: "function",
@@ -104,8 +105,16 @@ export function useEVMTransaction() {
104
105
  maxFeePerGas,
105
106
  maxPriorityFeePerGas,
106
107
  args: [to, value],
107
- });
108
+ }));
108
109
  return tx;
109
110
  };
110
111
  return { execute };
111
112
  }
113
+ async function submitEVMTransaction(submit) {
114
+ try {
115
+ return await submit();
116
+ }
117
+ catch (error) {
118
+ throw toTransactionError(error);
119
+ }
120
+ }
@@ -1,8 +1,8 @@
1
- import { randomStringForEntropy } from "@stablelib/random";
2
1
  import { useCallback, useMemo } from "react";
3
2
  import { useAccount, useConnect, useConnectors, useSignMessage } from "wagmi";
4
3
  import { isWalletInstalled } from "../utils/is-wallet-installed";
5
4
  import { toMessage } from "../utils/message";
5
+ import { generateNonce as generateDefaultNonce } from "../utils/nonce";
6
6
  import { toBaseConnector } from "./utils";
7
7
  export function useSignInWithEvm({ signIn, onError, generateNonce }) {
8
8
  const { address, connector, isConnected } = useAccount();
@@ -13,7 +13,7 @@ export function useSignInWithEvm({ signIn, onError, generateNonce }) {
13
13
  .filter((c) => isWalletInstalled(c.id))
14
14
  .map(toBaseConnector), [connectors]);
15
15
  const handleSignature = useCallback(async (address) => {
16
- const nonce = generateNonce ? await generateNonce() : randomStringForEntropy(96);
16
+ const nonce = generateNonce ? await generateNonce() : generateDefaultNonce();
17
17
  const msg = {
18
18
  domain: window.location.host,
19
19
  address,
@@ -1,13 +1,13 @@
1
1
  import { useConnectWallet, useCurrentWallet, useSignPersonalMessage, useWallets } from "@mysten/dapp-kit";
2
- import { randomStringForEntropy } from "@stablelib/random";
3
2
  import { toMessage } from "../utils/message";
3
+ import { generateNonce as generateDefaultNonce } from "../utils/nonce";
4
4
  export function useSignInWithSui({ signIn, onError, generateNonce }) {
5
5
  const { mutate: connect } = useConnectWallet();
6
6
  const { currentWallet, isConnected } = useCurrentWallet();
7
7
  const { mutate: signPersonalMessage } = useSignPersonalMessage();
8
8
  const wallets = useWallets();
9
9
  const handleSignature = async (address) => {
10
- const nonce = generateNonce ? await generateNonce() : randomStringForEntropy(96);
10
+ const nonce = generateNonce ? await generateNonce() : generateDefaultNonce();
11
11
  const msg = {
12
12
  domain: window.location.host,
13
13
  address,
@@ -4,3 +4,4 @@ export * from "./get-connector-icon";
4
4
  export * from "./get-wallet-priority";
5
5
  export * from "./is-wallet-installed";
6
6
  export * from "./message";
7
+ export * from "./nonce";
@@ -4,3 +4,4 @@ export * from "./get-connector-icon";
4
4
  export * from "./get-wallet-priority";
5
5
  export * from "./is-wallet-installed";
6
6
  export * from "./message";
7
+ export * from "./nonce";
@@ -0,0 +1 @@
1
+ export declare function generateNonce(entropyBits?: number): string;
@@ -0,0 +1,4 @@
1
+ import { randomStringForEntropy } from "@stablelib/random";
2
+ export function generateNonce(entropyBits = 96) {
3
+ return randomStringForEntropy(entropyBits);
4
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coin-voyage/crypto",
3
3
  "description": "Crypto utilities for Coin Voyage",
4
- "version": "2.4.3",
4
+ "version": "2.4.5-beta.0",
5
5
  "private": false,
6
6
  "sideEffects": false,
7
7
  "author": "Lars <lars@coinvoyage.io>",
@@ -39,6 +39,10 @@
39
39
  "types": "./dist/utils/index.d.ts",
40
40
  "default": "./dist/utils/index.js"
41
41
  },
42
+ "./utils/nonce": {
43
+ "types": "./dist/utils/nonce.d.ts",
44
+ "default": "./dist/utils/nonce.js"
45
+ },
42
46
  "./utxo": {
43
47
  "types": "./dist/utxo/index.d.ts",
44
48
  "default": "./dist/utxo/index.js"
@@ -77,6 +81,9 @@
77
81
  "utils": [
78
82
  "dist/utils/index.d.ts"
79
83
  ],
84
+ "utils/nonce": [
85
+ "dist/utils/nonce.d.ts"
86
+ ],
80
87
  "utxo": [
81
88
  "dist/utxo/index.d.ts"
82
89
  ],
@@ -106,7 +113,7 @@
106
113
  "@solana/wallet-adapter-walletconnect": "0.1.21",
107
114
  "@solana/wallet-adapter-base": "0.9.27",
108
115
  "@solana/wallet-adapter-coinbase": "0.1.23",
109
- "@coin-voyage/shared": "2.4.3"
116
+ "@coin-voyage/shared": "2.4.5-beta.0"
110
117
  },
111
118
  "devDependencies": {
112
119
  "@types/elliptic": "6.4.18"