@@ -181,41 +181,19 @@ export function formatViemError(error: any, abi: Abi = ErrorsAbi): FormattedViem
181181 return new FormattedViemError ( error . message , ( error as any ) ?. metaMessages ) ;
182182 }
183183
184- // Extract the actual error message and highlight it for clarity
185- let formattedRes = extractAndFormatRequestBody ( error ?. message || String ( error ) ) ;
186-
187- let errorDetail = '' ;
188- // Look for specific details in known locations
189- if ( error ) {
190- // Check for details property which often has the most specific error message
191- if ( typeof error . details === 'string' && error . details ) {
192- errorDetail = error . details ;
193- }
194- // Check for shortMessage which is often available in Viem errors
195- else if ( typeof error . shortMessage === 'string' && error . shortMessage ) {
196- errorDetail = error . shortMessage ;
197- }
198- }
199-
200- // If we found a specific error detail, format it clearly
201- if ( errorDetail ) {
202- // Look for key sections of the formatted result to replace with highlighted error
203- let replaced = false ;
204-
205- // Try to find the Details: section
206- const detailsMatch = formattedRes . match ( / D e t a i l s : ( [ ^ \n ] + ) / ) ;
207- if ( detailsMatch ) {
208- formattedRes = formattedRes . replace ( detailsMatch [ 0 ] , `Details: *${ errorDetail } *` ) ;
209- replaced = true ;
210- }
211-
212- // If we didn't find a Details section, add the error at the beginning
213- if ( ! replaced ) {
214- formattedRes = `Error: *${ errorDetail } *\n\n${ formattedRes } ` ;
215- }
216- }
217-
218- return new FormattedViemError ( formattedRes . replace ( / \\ n / g, '\n' ) , error ?. metaMessages ) ;
184+ const body = String ( error ) ;
185+ const length = body . length ;
186+ // LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
187+ // Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
188+ if ( length > 2000 ) {
189+ const chunk = 950 ;
190+ const truncated = length - 2 * chunk ;
191+ return new FormattedViemError (
192+ body . slice ( 0 , chunk ) + `...${ truncated } characters truncated...` + body . slice ( - 1 * chunk ) ,
193+ ) ;
194+ }
195+
196+ return new FormattedViemError ( body ) ;
219197}
220198
221199function stripAbis ( obj : any ) {
@@ -241,156 +219,6 @@ function stripAbis(obj: any) {
241219 } ) ;
242220}
243221
244- function extractAndFormatRequestBody ( message : string ) : string {
245- // First check if message is extremely large and contains very large hex strings
246- if ( message . length > 50000 ) {
247- message = replaceHexStrings ( message , { minLength : 10000 , truncateLength : 200 } ) ;
248- }
249-
250- // Add a specific check for RPC calls with large params
251- if ( message . includes ( '"method":"eth_sendRawTransaction"' ) ) {
252- message = replaceHexStrings ( message , {
253- pattern : / " p a r a m s " : \s * \[ \s * " ( 0 x [ a - f A - F 0 - 9 ] { 1000 , } ) " \s * \] / g,
254- transform : hex => `"params":["${ truncateHex ( hex , 200 ) } "]` ,
255- } ) ;
256- }
257-
258- // First handle Request body JSON
259- const requestBodyRegex = / R e q u e s t b o d y : ( { [ \s \S ] * ?} ) \n / g;
260- let result = message . replace ( requestBodyRegex , ( match , body ) => {
261- return `Request body: ${ formatRequestBody ( body ) } \n` ;
262- } ) ;
263-
264- // Then handle Arguments section
265- const argsRegex = / ( (?: R e q u e s t | E s t i m a t e G a s ) ? A r g u m e n t s : [ \s \S ] * ?(? = \n \n | $ ) ) / g;
266- result = result . replace ( argsRegex , section => {
267- const lines = section . split ( '\n' ) ;
268- const processedLines = lines . map ( line => {
269- // Check if line contains a colon followed by content
270- const colonIndex = line . indexOf ( ':' ) ;
271- if ( colonIndex !== - 1 ) {
272- const [ prefix , content ] = [ line . slice ( 0 , colonIndex + 1 ) , line . slice ( colonIndex + 1 ) . trim ( ) ] ;
273- // If content contains a hex string, truncate it
274- if ( content . includes ( '0x' ) ) {
275- const processedContent = replaceHexStrings ( content ) ;
276- return `${ prefix } ${ processedContent } ` ;
277- }
278- }
279- return line ;
280- } ) ;
281- return processedLines . join ( '\n' ) ;
282- } ) ;
283-
284- // Finally, catch any remaining hex strings in the message
285- result = replaceHexStrings ( result ) ;
286-
287- return result ;
288- }
289-
290- function truncateHex ( hex : string , length = 100 ) {
291- if ( ! hex || typeof hex !== 'string' ) {
292- return hex ;
293- }
294- if ( ! hex . startsWith ( '0x' ) ) {
295- return hex ;
296- }
297- if ( hex . length <= length * 2 ) {
298- return hex ;
299- }
300- // For extremely large hex strings, use more aggressive truncation
301- if ( hex . length > 10000 ) {
302- return `${ hex . slice ( 0 , length ) } ...<${ hex . length - length * 2 } chars omitted>...${ hex . slice ( - length ) } ` ;
303- }
304- return `${ hex . slice ( 0 , length ) } ...${ hex . slice ( - length ) } ` ;
305- }
306-
307- function replaceHexStrings (
308- text : string ,
309- options : {
310- minLength ?: number ;
311- maxLength ?: number ;
312- truncateLength ?: number ;
313- pattern ?: RegExp ;
314- transform ?: ( hex : string ) => string ;
315- } = { } ,
316- ) : string {
317- const {
318- minLength = 10 ,
319- maxLength = Infinity ,
320- truncateLength = 100 ,
321- pattern,
322- transform = hex => truncateHex ( hex , truncateLength ) ,
323- } = options ;
324-
325- const hexRegex = pattern ?? new RegExp ( `(0x[a-fA-F0-9]{${ minLength } ,${ maxLength } })` , 'g' ) ;
326- return text . replace ( hexRegex , match => transform ( match ) ) ;
327- }
328-
329- function formatRequestBody ( body : string ) {
330- try {
331- // Special handling for eth_sendRawTransaction
332- if ( body . includes ( '"method":"eth_sendRawTransaction"' ) ) {
333- try {
334- const parsed = JSON . parse ( body ) ;
335- if ( parsed . params && Array . isArray ( parsed . params ) && parsed . params . length > 0 ) {
336- // These are likely large transaction hex strings
337- parsed . params = parsed . params . map ( ( param : any ) => {
338- if ( typeof param === 'string' && param . startsWith ( '0x' ) && param . length > 1000 ) {
339- return truncateHex ( param , 200 ) ;
340- }
341- return param ;
342- } ) ;
343- }
344- return JSON . stringify ( parsed , null , 2 ) ;
345- } catch {
346- // If specific parsing fails, fall back to regex-based truncation
347- return replaceHexStrings ( body , {
348- pattern : / " p a r a m s " : \s * \[ \s * " ( 0 x [ a - f A - F 0 - 9 ] { 1000 , } ) " \s * \] / g,
349- transform : hex => `"params":["${ truncateHex ( hex , 200 ) } "]` ,
350- } ) ;
351- }
352- }
353-
354- // For extremely large request bodies, use simple truncation instead of parsing
355- if ( body . length > 50000 ) {
356- const jsonStart = body . indexOf ( '{' ) ;
357- const jsonEnd = body . lastIndexOf ( '}' ) ;
358- if ( jsonStart >= 0 && jsonEnd > jsonStart ) {
359- return replaceHexStrings ( body , { minLength : 10000 , truncateLength : 200 } ) ;
360- }
361- }
362-
363- const parsed = JSON . parse ( body ) ;
364-
365- // Process the entire request body
366- const processed = processParams ( parsed ) ;
367- return JSON . stringify ( processed , null , 2 ) ;
368- } catch {
369- // If JSON parsing fails, do a simple truncation of any large hex strings
370- return replaceHexStrings ( body , { minLength : 1000 , truncateLength : 150 } ) ;
371- }
372- }
373-
374- // Recursively process all parameters that might contain hex strings
375- function processParams ( obj : any ) : any {
376- if ( Array . isArray ( obj ) ) {
377- return obj . map ( item => processParams ( item ) ) ;
378- }
379- if ( typeof obj === 'object' && obj !== null ) {
380- const result : any = { } ;
381- for ( const [ key , value ] of Object . entries ( obj ) ) {
382- result [ key ] = processParams ( value ) ;
383- }
384- return result ;
385- }
386- if ( typeof obj === 'string' ) {
387- if ( obj . startsWith ( '0x' ) ) {
388- return truncateHex ( obj ) ;
389- }
390- }
391- return obj ;
392- }
393-
394222export function tryGetCustomErrorName ( err : any ) {
395223 try {
396224 // See https://viem.sh/docs/contract/simulateContract#handling-custom-errors
0 commit comments