Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): Provide error cause to errors #10

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/contract/deploy-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ export async function deployContract <CONTRACT extends CompiledContract>(
} catch (error) {
console.error('err', error);
// TODO: add more error handlers for different scenarios
return returnError('UserRejectedTransactionError');
return returnError('UserRejectedTransactionError', error as Error);
}
}
6 changes: 3 additions & 3 deletions packages/core/src/contract/read-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ export async function readContract<CONTRACT extends CompiledContract, GETTER ext
// TODO: handle the read with more details
if (res.error) {
if (res.response.status === 429) {
return returnError('TonRateLimitError');
return returnError('TonRateLimitError', res.error);
}
return returnError('TonReadError');
return returnError('TonReadError', res.error);
}

try {
return returnData(
parseReadReturn(fullContract.abi, options.getter, res.data) as ContractGetterReturn<CONTRACT, GETTER>
);
} catch (error) {
return returnError('TonReadError');
return returnError('TonReadError', error);
}
}
2 changes: 1 addition & 1 deletion packages/core/src/contract/write-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export async function writeContract <CONTRACT extends CompiledContract, METHOD e
return returnData(bocToHash(res.boc));
} catch (error) {
// TODO: add more error handlers for different scenarios
return returnError('UserRejectedTransactionError');
return returnError('UserRejectedTransactionError', error);
}
}

4 changes: 3 additions & 1 deletion packages/core/src/shared/errors/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export type SupportedErrors = {
TonRateLimitError: TonRateLimitError,
};

export type SupportedErrorsKeys = keyof typeof supportedErrors;

export const supportedErrors = {
// Syntax errors
ConnectFunctionUnavailableError: ConnectFunctionUnavailableError,
Expand All @@ -60,4 +62,4 @@ export const supportedErrors = {
TonWalletDisconnectError: TonWalletDisconnectError,
TonReadError: TonReadError,
TonRateLimitError: TonRateLimitError,
}
} as const;
21 changes: 18 additions & 3 deletions packages/core/src/shared/errors/return-error.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import type { DataOrError } from './types.js';
import { SupportedErrors, supportedErrors } from './errors.js';
import {
SupportedErrors,
supportedErrors,
SupportedErrorsKeys,
} from './errors.js';

/**
* A helper function to return a typed error in a form of `DataOrError`.
*/
export const returnError = <TYPE extends keyof typeof supportedErrors>(
export const returnError = <TYPE extends SupportedErrorsKeys>(
type: TYPE,
cause?: unknown
): DataOrError<any, SupportedErrors[TYPE]> => {
const error = new supportedErrors[type]();
const nativeTonErrors: SupportedErrorsKeys[] = ['TonConnectError', 'TonConnectUIError'] as const;

const errorClass = supportedErrors[type]

if (nativeTonErrors.includes(type)) {
const error = new errorClass();

return { data: undefined, error: error as SupportedErrors[TYPE] };
}

const error = new errorClass(cause as any);

return { data: undefined, error: error as SupportedErrors[TYPE] };
};
18 changes: 12 additions & 6 deletions packages/core/src/shared/errors/syntax-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,50 @@ export class SyntaxError extends Error {
}

export class ConnectFunctionUnavailableError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('This function is not available for UI-based wallet connections. Use `createWalletClientUI` instead');
this.name = 'ConnectFunctionUnavailableError';
this.cause = cause;
}
}

export class ConnectUIFunctionUnavailableError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('This function is only available for UI-based wallet connections');
this.name = 'ConnectUIFunctionUnavailableError';
this.cause = cause;
}
}


export class ConnectUIFunctionUnavailableInNodeError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('This function is not available in the server environment. Please you `createWalletClient` instead or, if you use Next.js, call `createWalletClientUI` in `useEffect` hook or in the event handler, so it creates a wallet client when the `window` is available.');
this.name = 'ConnectUIFunctionUnavailableInNodeError';
this.cause = cause;
}
}

export class ReconnectFunctionUnavailableError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('The reconnect is not available for UI-based wallet connections. Pass `restoreConnection: true` to the `createWalletClientUI` function to enable it');
this.name = 'ReconnectFunctionUnavailableError';
this.cause = cause;
}
}

export class IncorrectContractError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('The contract is incorrect. Provide the contract class compiled from your Tact or Func files');
this.name = 'IncorrectContractError';
this.cause = cause;
}
}

export class MissingContractAddressError extends SyntaxError {
constructor() {
constructor(cause?: unknown) {
super('The contract address is not provided to the walletClient. Call `setAddress` first');
this.name = 'MissingContractAddressError';
this.cause = cause;
}
}
12 changes: 8 additions & 4 deletions packages/core/src/shared/errors/ton-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,34 @@ export class TonError extends Error {
}

export class TonWalletConnectionError extends TonError {
constructor() {
constructor(cause?: unknown) {
super('Wallet connection failed');
this.name = 'TonWalletConnectionError';
this.cause = cause;
}
}

export class TonWalletDisconnectError extends TonError {
constructor() {
constructor(cause?: unknown) {
super('Could not disconnect from the wallet');
this.name = 'TonWalletDisconnectError';
this.cause = cause;
}
}

export class TonReadError extends TonError {
constructor() {
constructor(cause?: unknown) {
super('Cannot process the read request. Either the request returned a non-zero exit code or the data could not be parsed');
this.name = 'TonReadError';
this.cause = cause;
}
}

export class TonRateLimitError extends TonError {
constructor() {
constructor(cause?: unknown) {
super('Rate limit is exceeded. Provide the `authKey` to the public client with a better Ton Center plan to get more requests per second');
this.name = 'TonRateLimitError';
this.cause = cause;
}
}

Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/shared/errors/user-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ export class UserError extends Error {
}

export class UserUnauthorizedError extends UserError {
constructor() {
constructor(cause?: unknown) {
super('Not authorized. Please, connect the wallet first');
this.name = 'UserUnauthorizedError';
this.cause = cause;
}
}

export class UserRejectedConnectionError extends UserError {
constructor() {
constructor(cause?: unknown) {
super('User rejected the connection to their wallet');
this.name = 'UserRejectedConnectionError';
this.cause = cause;
}
}

export class UserRejectedTransactionError extends UserError {
constructor() {
constructor(cause?: unknown) {
super('User rejected the transaction request from their wallet');
this.name = 'UserRejectedTransactionError';
this.cause = cause;
}
}
2 changes: 1 addition & 1 deletion packages/core/src/wallet/send-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ export async function sendTransaction (
const hash = bocToHash(res.boc);
return returnData(hash);
} catch (error) {
return returnError('UserRejectedTransactionError');
return returnError('UserRejectedTransactionError', error);
}
}