@raac/rpc 1.1.0-beta.54 → 1.1.0-beta.56

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.
@@ -288,6 +288,8 @@ class RPCLibrary {
288
288
  decodeErrorName: errorDecoder_1.decodeErrorName,
289
289
  getErrorInfo: errorDecoder_1.getErrorInfo,
290
290
  attachDecodedError: errorDecoder_1.attachDecodedError,
291
+ decodeErrorMessage: errorDecoder_1.decodeErrorMessage,
292
+ attachDecodedErrorMessage: errorDecoder_1.attachDecodedErrorMessage,
291
293
  };
292
294
  }
293
295
  async getWallet(privateKey, provider) {
@@ -6,6 +6,7 @@ const _helpers_1 = require("./_helpers");
6
6
  async function getWithdrawRequestInfo(chainId, userAddress, provider) {
7
7
  try {
8
8
  const stabilityPoolContract = await (0, _helpers_1.getStabilityPoolContract)(chainId, provider);
9
+ const duration = await stabilityPoolContract.withdrawTimelockDuration();
9
10
  const request = await stabilityPoolContract.withdrawTimelock(userAddress);
10
11
  if (request[0] === 0n) {
11
12
  return null;
@@ -13,7 +14,8 @@ async function getWithdrawRequestInfo(chainId, userAddress, provider) {
13
14
  return {
14
15
  amount: ethers_1.ethers.formatEther(request[0]),
15
16
  readyAt: Number(request[1]),
16
- expiresAt: Number(request[2])
17
+ expiresAt: Number(request[2]),
18
+ duration: Number(duration)
17
19
  };
18
20
  }
19
21
  catch (error) {
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const path_1 = __importDefault(require("path"));
8
+ const ethers_1 = require("ethers");
9
+ // Custom error messages based on error names
10
+ const ERROR_MESSAGES = {
11
+ // Access Control
12
+ 'AccessControlBadConfirmation': 'Invalid access control confirmation',
13
+ 'AccessControlUnauthorizedAccount': 'Account does not have required permissions',
14
+ 'AccessDenied': 'Access denied - insufficient permissions',
15
+ // Adapter Errors
16
+ 'AdapterAlreadySupported': 'This adapter is already supported',
17
+ 'AdapterNotSupported': 'This adapter is not supported',
18
+ // Address Errors
19
+ 'AddressCannotBeZero': 'Address cannot be zero',
20
+ 'AddressEmptyCode': 'Target address has no code',
21
+ 'AddressInsufficientBalance': 'Insufficient balance for operation',
22
+ // Amount Errors
23
+ 'AmountDifferentThanRequested': 'Amount differs from requested amount',
24
+ 'ApprovalFailed': 'Token approval failed',
25
+ // Compliance
26
+ 'BlacklistedAddress': 'Address is blacklisted',
27
+ // Pool Errors
28
+ 'BorrowCapReached': 'Borrow cap has been reached',
29
+ 'BorrowThresholdTooHigh': 'Borrow threshold is too high',
30
+ 'CannotBorrowUnderLiquidation': 'Cannot borrow while under liquidation',
31
+ 'CannotDepositWhenUnderLiquidation': 'Cannot deposit while under liquidation',
32
+ 'CannotRepayUnderLiquidationWithoutInsurance': 'Cannot repay under liquidation without insurance',
33
+ 'CannotWithdrawInSameBlock': 'Cannot withdraw in the same block',
34
+ 'CannotWithdrawUnderLiquidation': 'Cannot withdraw while under liquidation',
35
+ 'CapExceedSupply': 'Cap exceeds available supply',
36
+ 'CapZero': 'Cap cannot be zero',
37
+ 'DebtNotZero': 'Debt must be zero for this operation',
38
+ 'SupplyCapReached': 'Supply cap has been reached',
39
+ // Pause Errors
40
+ 'EnforcedPause': 'Contract is paused',
41
+ 'ExpectedPause': 'Contract should be paused',
42
+ // General Errors
43
+ 'FailedInnerCall': 'Internal call failed',
44
+ 'GracePeriodExpired': 'Grace period has expired',
45
+ 'InsufficientAllowance': 'Insufficient allowance for operation',
46
+ 'InsufficientBalance': 'Insufficient balance for operation',
47
+ 'InvalidAmount': 'Invalid amount provided',
48
+ 'InvalidCollateralRatio': 'Invalid collateral ratio',
49
+ 'InvalidHealthFactor': 'Invalid health factor',
50
+ 'InvalidLiquidationThreshold': 'Invalid liquidation threshold',
51
+ 'InvalidParameter': 'Invalid parameter provided',
52
+ 'InvalidPrice': 'Invalid price provided',
53
+ 'InvalidToken': 'Invalid token address',
54
+ 'LiquidationNotAllowed': 'Liquidation is not allowed',
55
+ 'NoLiquidationAvailable': 'No liquidation available',
56
+ 'NotEnoughLiquidity': 'Not enough liquidity available',
57
+ 'OperationNotAllowed': 'Operation is not allowed',
58
+ 'Overflow': 'Arithmetic overflow occurred',
59
+ 'Paused': 'Contract is paused',
60
+ 'ReentrancyGuardReentrantCall': 'Reentrant call detected',
61
+ 'ReserveAlreadyInitialized': 'Reserve is already initialized',
62
+ 'ReserveNotActive': 'Reserve is not active',
63
+ 'ReserveNotInitialized': 'Reserve is not initialized',
64
+ 'SafeERC20FailedOperation': 'SafeERC20 operation failed',
65
+ 'TransferFailed': 'Token transfer failed',
66
+ 'Unauthorized': 'Unauthorized operation',
67
+ 'Underflow': 'Arithmetic underflow occurred',
68
+ 'VaultNotOpen': 'Vault is not open',
69
+ 'WithdrawalNotAllowed': 'Withdrawal is not allowed',
70
+ // Custom contract-specific errors
71
+ 'InvalidOraclePrice': 'Invalid oracle price received',
72
+ 'PriceStale': 'Oracle price is stale',
73
+ 'InvalidRandomSeed': 'Invalid random seed provided',
74
+ 'RandomSeedNotReady': 'Random seed is not ready',
75
+ 'NFTNotAvailable': 'NFT is not available',
76
+ 'InvalidNFTId': 'Invalid NFT ID provided',
77
+ 'NFTAlreadyDeposited': 'NFT is already deposited',
78
+ 'NFTNotDeposited': 'NFT is not deposited',
79
+ 'InvalidVaultPosition': 'Invalid vault position',
80
+ 'PositionNotOpen': 'Position is not open',
81
+ 'InvalidCollateral': 'Invalid collateral provided',
82
+ 'CollateralNotSupported': 'Collateral is not supported',
83
+ 'InvalidDebtToken': 'Invalid debt token',
84
+ 'DebtTokenNotSupported': 'Debt token is not supported',
85
+ 'InvalidLiquidationProxy': 'Invalid liquidation proxy',
86
+ 'InvalidVaultProxy': 'Invalid vault proxy',
87
+ 'InvalidComplianceRegistry': 'Invalid compliance registry',
88
+ 'InvalidPrimeRate': 'Invalid prime rate',
89
+ 'InvalidAdmin': 'Invalid admin address',
90
+ 'InvalidReserveAsset': 'Invalid reserve asset',
91
+ 'InvalidRToken': 'Invalid R token',
92
+ 'InvalidDebtTokenAddress': 'Invalid debt token address',
93
+ 'InvalidLiquidationProxyAddress': 'Invalid liquidation proxy address',
94
+ 'InvalidVaultProxyAddress': 'Invalid vault proxy address',
95
+ 'InvalidComplianceRegistryAddress': 'Invalid compliance registry address',
96
+ 'InvalidInitialPrimeRate': 'Invalid initial prime rate',
97
+ 'InvalidAdminAddress': 'Invalid admin address',
98
+ };
99
+ function walkDir(dir) {
100
+ const files = [];
101
+ const items = fs_1.default.readdirSync(dir, { withFileTypes: true });
102
+ for (const item of items) {
103
+ const fullPath = path_1.default.join(dir, item.name);
104
+ if (item.isDirectory()) {
105
+ files.push(...walkDir(fullPath));
106
+ }
107
+ else if (item.name.endsWith('.json')) {
108
+ files.push(fullPath);
109
+ }
110
+ }
111
+ return files;
112
+ }
113
+ function generateErrorMap() {
114
+ const errorMap = {};
115
+ const artifactsDir = path_1.default.join(process.cwd(), 'artifacts');
116
+ if (!fs_1.default.existsSync(artifactsDir)) {
117
+ console.error('Artifacts directory not found');
118
+ process.exit(1);
119
+ }
120
+ const jsonFiles = walkDir(artifactsDir);
121
+ for (const filePath of jsonFiles) {
122
+ try {
123
+ const content = fs_1.default.readFileSync(filePath, 'utf8');
124
+ const json = JSON.parse(content);
125
+ if (!json.abi || !Array.isArray(json.abi))
126
+ continue;
127
+ const contractName = json.contractName || path_1.default.basename(filePath, '.json');
128
+ for (const item of json.abi) {
129
+ if (item.type !== 'error')
130
+ continue;
131
+ const inputs = item.inputs || [];
132
+ const signature = `${item.name}(${inputs.map((input) => input.type).join(',')})`;
133
+ const selector = (0, ethers_1.id)(signature).slice(0, 10).toLowerCase();
134
+ // Skip if already processed (first occurrence wins)
135
+ if (errorMap[selector])
136
+ continue;
137
+ const customMessage = ERROR_MESSAGES[item.name] ||
138
+ `${item.name.replace(/([A-Z])/g, ' $1').trim()} error occurred`;
139
+ errorMap[selector] = {
140
+ name: item.name,
141
+ signature,
142
+ message: customMessage,
143
+ contract: contractName,
144
+ inputs: inputs.map((input) => ({
145
+ name: input.name || '',
146
+ type: input.type,
147
+ internalType: input.internalType || input.type,
148
+ })),
149
+ };
150
+ }
151
+ }
152
+ catch (error) {
153
+ console.warn(`Failed to process ${filePath}:`, error);
154
+ }
155
+ }
156
+ return errorMap;
157
+ }
158
+ function main() {
159
+ console.log('🔍 Scanning ABIs for error definitions...');
160
+ const errorMap = generateErrorMap();
161
+ const outputPath = path_1.default.join(process.cwd(), 'generated', 'errorMap.json');
162
+ // Ensure generated directory exists
163
+ const generatedDir = path_1.default.dirname(outputPath);
164
+ if (!fs_1.default.existsSync(generatedDir)) {
165
+ fs_1.default.mkdirSync(generatedDir, { recursive: true });
166
+ }
167
+ // Write the error map
168
+ fs_1.default.writeFileSync(outputPath, JSON.stringify(errorMap, null, 2));
169
+ console.log(`✅ Generated error map with ${Object.keys(errorMap).length} errors`);
170
+ console.log(`📁 Output: ${outputPath}`);
171
+ // Show some examples
172
+ const examples = Object.entries(errorMap).slice(0, 5);
173
+ console.log('\n📋 Examples:');
174
+ for (const [selector, info] of examples) {
175
+ console.log(` ${selector} → ${info.name}: ${info.message}`);
176
+ }
177
+ }
178
+ if (require.main === module) {
179
+ main();
180
+ }
@@ -10,7 +10,6 @@ const RPCLibrary_1 = __importDefault(require("../RPCLibrary"));
10
10
  const contracts_1 = require("../utils/contracts");
11
11
  const artifacts_1 = require("../utils/artifacts");
12
12
  const _helpers_1 = require("../pools/rwaVault/_helpers");
13
- const errorDecoder_1 = require("../utils/errorDecoder");
14
13
  const chainId = 8453;
15
14
  const config = chains_1.default[chainId];
16
15
  const TEST_MNEMONIC = process.env.TEST_MNEMONIC;
@@ -34,11 +33,10 @@ async function createWallet(mnemonic, provider) {
34
33
  }
35
34
  }
36
35
  async function setup() {
37
- console.log((0, errorDecoder_1.decodeErrorName)("Encoded error signature 0xa9b65aba not found on ABI."));
38
- return;
36
+ const rpc = new RPCLibrary_1.default();
39
37
  const provider = await getProvider();
40
38
  const signer = await createWallet(TEST_MNEMONIC, provider);
41
- const rpc = new RPCLibrary_1.default();
39
+ // const rpc = new RPCLibrary();
42
40
  rpc.address = signer.address;
43
41
  rpc.provider = provider;
44
42
  rpc.chainId = chainId;
@@ -83,10 +81,9 @@ async function setup() {
83
81
  // console.log("Liquidity in the Mock Liquidity Pool", liquidity);
84
82
  // mint the current user 5 million irAAC
85
83
  console.log("Minting 5 million irAAC");
86
- await rpc.wallet.assets.approveAsset(chainId, "crvusd", await rpc.pools.rwaVault.getAdapterAddress(chainId, "crvusdadapter").address, "5000000", signer);
87
- const data = new ethers_1.ethers.AbiCoder().encode(["uint256"], [ethers_1.ethers.parseEther("5000000")]);
88
- await rpc.pools.rwaVault.depositToRWAVault(chainId, "crvusdadapter", data, signer.address, signer);
89
- return;
84
+ // await rpc.wallet.assets.approveAsset(chainId, "crvusd", await rpc.pools.rwaVault.getAdapterAddress(chainId, "crvusdadapter").address, "5000000", signer);
85
+ // const data = new ethers.AbiCoder().encode(["uint256"], [ ethers.parseEther("5000000") ])
86
+ // await rpc.pools.rwaVault.depositToRWAVault(chainId, "crvusdadapter", data, signer.address, signer)
90
87
  /// END OF ADD FUNDS IN THE MOCK LIQUIDITY POOL
91
88
  // // // send myself some CRVUSD
92
89
  // await rpc.wallet.assets.mintAsset(
@@ -95,7 +95,7 @@ import vaultOpened from "./pools/lendingPool/vaultOpened";
95
95
  import { getWithdrawRequestInfo as getStabilityPoolWithdrawRequestInfo } from "./pools/stabilityPool/getWithdrawRequestInfo";
96
96
  import { requestWithdraw as requestStabilityPoolWithdraw } from "./pools/stabilityPool/requestWithdraw";
97
97
  import { getABI } from "./utils/artifacts";
98
- import { decodeErrorName, getErrorInfo, attachDecodedError } from "./utils/errorDecoder";
98
+ import { decodeErrorName, getErrorInfo, attachDecodedError, decodeErrorMessage, attachDecodedErrorMessage } from "./utils/errorDecoder";
99
99
  declare class RPCLibrary {
100
100
  signer: Signer | null;
101
101
  isConnected: boolean;
@@ -241,6 +241,8 @@ declare class RPCLibrary {
241
241
  decodeErrorName: typeof decodeErrorName;
242
242
  getErrorInfo: typeof getErrorInfo;
243
243
  attachDecodedError: typeof attachDecodedError;
244
+ decodeErrorMessage: typeof decodeErrorMessage;
245
+ attachDecodedErrorMessage: typeof attachDecodedErrorMessage;
244
246
  };
245
247
  constructor(privateKey?: string);
246
248
  getWallet(privateKey: string, provider: Provider): Promise<ethers.JsonRpcSigner | ethers.Wallet>;
@@ -4,6 +4,7 @@ interface WithdrawRequestInfo {
4
4
  amount: string;
5
5
  readyAt: number;
6
6
  expiresAt: number;
7
+ duration: number;
7
8
  }
8
9
  export declare function getWithdrawRequestInfo(chainId: ChainId, userAddress: string, provider: Provider): Promise<WithdrawRequestInfo | null>;
9
10
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,21 +1,37 @@
1
- interface ErrorInfo {
1
+ interface GeneratedErrorInfo {
2
2
  name: string;
3
3
  signature: string;
4
- abiItem: any;
4
+ message: string;
5
+ contract?: string;
6
+ inputs?: Array<{
7
+ name: string;
8
+ type: string;
9
+ internalType: string;
10
+ }>;
5
11
  }
6
12
  /**
7
13
  * Returns detailed information about the error encoded in the given data blob.
8
14
  * @param data The revert data returned by the EVM (e.g., error.data).
9
15
  */
10
- export declare function getErrorInfo(data?: string): ErrorInfo | null;
16
+ export declare function getErrorInfo(data?: string): GeneratedErrorInfo | null;
11
17
  /**
12
18
  * Returns only the error name, or null if it cannot be decoded.
13
19
  */
14
20
  export declare function decodeErrorName(data?: string): string | null;
21
+ /**
22
+ * Returns the custom error message, or null if it cannot be decoded.
23
+ */
24
+ export declare function decodeErrorMessage(data?: string): string | null;
15
25
  /**
16
26
  * Builds a user-friendly error prefix with decoded error name (if available).
17
27
  * Usage example:
18
28
  * const msg = attachDecodedError("Deposit failed", caughtError);
19
29
  */
20
30
  export declare function attachDecodedError(prefix: string, error: any): string;
31
+ /**
32
+ * Builds a user-friendly error message with custom error description (if available).
33
+ * Usage example:
34
+ * const msg = attachDecodedErrorMessage("Deposit failed", caughtError);
35
+ */
36
+ export declare function attachDecodedErrorMessage(prefix: string, error: any): string;
21
37
  export {};
@@ -2,33 +2,50 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getErrorInfo = getErrorInfo;
4
4
  exports.decodeErrorName = decodeErrorName;
5
+ exports.decodeErrorMessage = decodeErrorMessage;
5
6
  exports.attachDecodedError = attachDecodedError;
7
+ exports.attachDecodedErrorMessage = attachDecodedErrorMessage;
6
8
  const ethers_1 = require("ethers");
7
9
  const artifacts_1 = require("./artifacts");
8
- const ERROR_SIGNATURE_MAP = {};
9
- (function buildErrorSignatureMap() {
10
- for (const abiKey in artifacts_1.ABIS) {
11
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
12
- // @ts-ignore – ABIS may contain unknown items
13
- const abi = artifacts_1.ABIS[abiKey];
14
- if (!Array.isArray(abi))
15
- continue;
16
- for (const item of abi) {
17
- if (item.type !== "error")
10
+ // Try to load the generated error map, fallback to runtime scanning
11
+ let ERROR_SIGNATURE_MAP = {};
12
+ try {
13
+ const generatedMap = require('../generated/errorMap.json');
14
+ ERROR_SIGNATURE_MAP = generatedMap;
15
+ }
16
+ catch (error) {
17
+ console.warn('Generated error map not found, falling back to runtime scanning...');
18
+ // Fallback to runtime scanning (original implementation)
19
+ (function buildErrorSignatureMap() {
20
+ for (const abiKey in artifacts_1.ABIS) {
21
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
22
+ // @ts-ignore – ABIS may contain unknown items
23
+ const abi = artifacts_1.ABIS[abiKey];
24
+ if (!Array.isArray(abi))
18
25
  continue;
19
- const inputs = (item.inputs || []);
20
- const signature = `${item.name}(${inputs.map((input) => input.type).join(",")})`;
21
- const selector = (0, ethers_1.id)(signature).slice(0, 10).toLowerCase();
22
- if (!ERROR_SIGNATURE_MAP[selector]) {
23
- ERROR_SIGNATURE_MAP[selector] = {
24
- name: item.name,
25
- signature,
26
- abiItem: item,
27
- };
26
+ for (const item of abi) {
27
+ if (item.type !== "error")
28
+ continue;
29
+ const inputs = (item.inputs || []);
30
+ const signature = `${item.name}(${inputs.map((input) => input.type).join(",")})`;
31
+ const selector = (0, ethers_1.id)(signature).slice(0, 10).toLowerCase();
32
+ if (!ERROR_SIGNATURE_MAP[selector]) {
33
+ ERROR_SIGNATURE_MAP[selector] = {
34
+ name: item.name,
35
+ signature,
36
+ message: `${item.name.replace(/([A-Z])/g, ' $1').trim()} error occurred`,
37
+ contract: abiKey,
38
+ inputs: inputs.map((input) => ({
39
+ name: input.name || '',
40
+ type: input.type,
41
+ internalType: input.internalType || input.type,
42
+ })),
43
+ };
44
+ }
28
45
  }
29
46
  }
30
- }
31
- })();
47
+ })();
48
+ }
32
49
  /**
33
50
  * Returns detailed information about the error encoded in the given data blob.
34
51
  * @param data The revert data returned by the EVM (e.g., error.data).
@@ -57,6 +74,13 @@ function decodeErrorName(data) {
57
74
  const info = getErrorInfo(data);
58
75
  return info?.name ?? null;
59
76
  }
77
+ /**
78
+ * Returns the custom error message, or null if it cannot be decoded.
79
+ */
80
+ function decodeErrorMessage(data) {
81
+ const info = getErrorInfo(data);
82
+ return info?.message ?? null;
83
+ }
60
84
  /**
61
85
  * Builds a user-friendly error prefix with decoded error name (if available).
62
86
  * Usage example:
@@ -86,3 +110,28 @@ function attachDecodedError(prefix, error) {
86
110
  // console.debug("Decoded", selector, decodedName);
87
111
  return decodedName ? `${prefix} (${decodedName})` : prefix;
88
112
  }
113
+ /**
114
+ * Builds a user-friendly error message with custom error description (if available).
115
+ * Usage example:
116
+ * const msg = attachDecodedErrorMessage("Deposit failed", caughtError);
117
+ */
118
+ function attachDecodedErrorMessage(prefix, error) {
119
+ const data = (error && ((error.data ?? error.error?.data) ||
120
+ undefined));
121
+ let selector;
122
+ if (data && data.startsWith("0x")) {
123
+ selector = data.slice(0, 10).toLowerCase();
124
+ }
125
+ else if (typeof error?.message === "string") {
126
+ const SIGNATURE_REGEX = /Encoded error signature \"(0x[0-9a-fA-F]{8})\"/;
127
+ const match = error.message.match(SIGNATURE_REGEX);
128
+ if (match)
129
+ selector = match[1].toLowerCase();
130
+ }
131
+ if (!selector)
132
+ return prefix;
133
+ const errorInfo = ERROR_SIGNATURE_MAP[selector];
134
+ if (!errorInfo)
135
+ return prefix;
136
+ return `${prefix}: ${errorInfo.message}`;
137
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raac/rpc",
3
- "version": "1.1.0-beta.54",
3
+ "version": "1.1.0-beta.56",
4
4
  "description": "RPC Library for RAAC ",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -9,12 +9,13 @@
9
9
  ],
10
10
  "scripts": {
11
11
  "dev": "ts-node-dev --transpile-only --env-file=.env scripts/index.ts",
12
- "build": "tsc && cp -r typechain-types dist/types",
12
+ "build": "npm run generate:errors && tsc && cp -r typechain-types dist/types",
13
13
  "build:watch": "tsc --watch",
14
14
  "test": "echo \"Error: no test specified\" && exit 1",
15
15
  "sync": "bash setup.sh",
16
16
  "clean": "rm -rf dist",
17
- "prebuild": "npm run clean"
17
+ "prebuild": "npm run clean",
18
+ "generate:errors": "ts-node scripts/generateErrorMap.ts"
18
19
  },
19
20
  "keywords": [
20
21
  "RAAC",