Skip to content

Commit

Permalink
chore: add error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
stanleyyconsensys committed Oct 10, 2024
1 parent 2d897d4 commit cf120a3
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 3 deletions.
7 changes: 4 additions & 3 deletions packages/get-starknet/src/rpcs/switch-network.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RpcTypeToMessageMap } from 'get-starknet-core';

import { createStarkError } from '../utils/error';
import { StarknetWalletRpc } from '../utils/rpc';

export type WalletSwitchStarknetChainMethod = 'wallet_switchStarknetChain';
Expand All @@ -15,13 +16,13 @@ export class WalletSwitchStarknetChain extends StarknetWalletRpc {
return true;
}

await this.snap.switchNetwork(param.chainId);
const result = await this.snap.switchNetwork(param.chainId);

await this.wallet.init();

return true;
return result;
} catch (error) {
return false;
throw createStarkError(error?.data?.walletRpcError?.code);
}
}
}
29 changes: 29 additions & 0 deletions packages/get-starknet/src/utils/error.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createStarkError, CustomError, WalletRpcError, defaultErrorMessage, defaultErrorCode } from './error';

describe('createStarkError', () => {
it.each(
Object.entries(WalletRpcError).map(([code, message]) => ({
code: parseInt(code, 10),
message,
})),
)('returns corresponding error if the error code is $code', ({ code, message }) => {
const error = createStarkError(code);
expect(error).toBeInstanceOf(CustomError);
expect(error.message).toStrictEqual(message);
expect(error.code).toStrictEqual(code);
});

it('returns default error code and message if the error code is undefined', () => {
const error = createStarkError(undefined);
expect(error).toBeInstanceOf(CustomError);
expect(error.message).toStrictEqual(defaultErrorMessage);
expect(error.code).toStrictEqual(defaultErrorCode);
});

it('returns default error code and message if the error code is not exist in the mapping', () => {
const error = createStarkError(0);
expect(error).toBeInstanceOf(CustomError);
expect(error.message).toStrictEqual(defaultErrorMessage);
expect(error.code).toStrictEqual(defaultErrorCode);
});
});
51 changes: 51 additions & 0 deletions packages/get-starknet/src/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// The error code is following the Starknet Wallet RPC 0.7.2 specification.
export enum WalletRpcErrorCode {
InvalidErc20 = 111,
InvalidNetwork = 112,
UserDeny = 113,
InvalidRequest = 114,
AccountAlreadyDeployed = 115,
ApiVersionNotSupported = 162,
Unknown = 163,
}

// Here we define the error message for each error
export const WalletRpcError = {
[WalletRpcErrorCode.InvalidErc20]: 'An error occurred (NOT_ERC20)',
[WalletRpcErrorCode.InvalidNetwork]: 'An error occurred (UNLISTED_NETWORK)',
[WalletRpcErrorCode.UserDeny]: 'An error occurred (USER_REFUSED_OP)',
[WalletRpcErrorCode.InvalidRequest]: 'An error occurred (NOT_ERC20)',
[WalletRpcErrorCode.AccountAlreadyDeployed]: 'An error occurred (ACCOUNT_ALREADY_DEPLOYED)',
[WalletRpcErrorCode.ApiVersionNotSupported]: 'An error occurred (API_VERSION_NOT_SUPPORTED)',
[WalletRpcErrorCode.Unknown]: 'An error occurred (UNKNOWN_ERROR)',
};
export const defaultErrorCode = WalletRpcErrorCode.Unknown;
export const defaultErrorMessage = WalletRpcError[defaultErrorCode];

export class CustomError extends Error {
readonly code: number;

constructor(message: string, errorCode: number) {
super(message);
this.code = errorCode;
}
}

/**
* Create Custom Error base on the given error code to map with the Wallet API error.
*
* @param [errorCode] - Error code to map with the Wallet API error.
* @returns A CustomError Object that contains the corresponing Wallet API Error code and message.
*/
export function createStarkError(errorCode?: number) {
let code = errorCode ?? defaultErrorCode;
let message = defaultErrorMessage;

if (WalletRpcError[code]) {
message = WalletRpcError[code];
} else {
code = defaultErrorCode;
}

return new CustomError(message, code);
}
24 changes: 24 additions & 0 deletions packages/get-starknet/src/utils/object.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { isset } from './object';

describe('isset', () => {
const obj = {
p1: {
p2a: 1,
p2: {
p3: 4,
},
},
};

it.each(['p1.p2.p3'])('returns true if the property "%s" exist in the object', (property: string) => {
const result = isset(obj, property);

expect(result).toBe(true);
});

it('returns false if the property is not exist in the object', () => {
const result = isset(obj, 'p0');

expect(result).toBe(false);
});
});
20 changes: 20 additions & 0 deletions packages/get-starknet/src/utils/object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Verify if the given property is exist in the object or not.
*
* @param obj - The object to look up.
* @param property - The object property as the searching key, it allow nested search (e.g) "propertyLv1.propertyLv2".
* @returns boolean result to indicate the property exist in the object or not
*/
export function isset(obj: object, property: string): boolean {
let search = obj;
const properties = property.split('.');

for (const prop of properties) {
if (Object.prototype.hasOwnProperty.call(search, prop)) {
search = search[prop];
} else {
return false;
}
}
return true;
}

0 comments on commit cf120a3

Please sign in to comment.