@@ -6,6 +6,8 @@ const istanbul = require('sc-istanbul');
66const assert = require ( 'assert' ) ;
77const detect = require ( 'detect-port' ) ;
88const _ = require ( 'lodash/lang' ) ;
9+ const ethersABI = require ( "@ethersproject/abi" ) ;
10+ const difflib = require ( 'difflib' ) ;
911
1012const ConfigValidator = require ( './validator' ) ;
1113const Instrumenter = require ( './instrumenter' ) ;
@@ -342,6 +344,104 @@ class API {
342344 }
343345 }
344346
347+ // =========
348+ // Abi Diff
349+ // =========
350+ diffAbis ( orig = { } , cur = { } ) {
351+ let origHR ;
352+ let curHR ;
353+ let plus = 0 ;
354+ let minus = 0 ;
355+
356+ const origFunctions = new ethersABI . Interface ( orig . abi ) . functions ;
357+ const curFunctions = new ethersABI . Interface ( cur . abi ) . functions ;
358+
359+ origHR = this . toHumanReadable ( origFunctions )
360+ curHR = this . toHumanReadable ( curFunctions )
361+
362+ const fns = difflib . unifiedDiff (
363+ origHR ,
364+ curHR ,
365+ {
366+ fromfile : orig . contractName ,
367+ tofile : cur . contractName ,
368+ fromfiledate : `sha: ${ orig . sha } ` ,
369+ tofiledate : `sha: ${ cur . sha } ` ,
370+ lineterm : ''
371+ }
372+ ) ;
373+
374+ const origEvents = new ethersABI . Interface ( orig . abi ) . events ;
375+ const curEvents = new ethersABI . Interface ( cur . abi ) . events ;
376+
377+ origHR = this . toHumanReadable ( origEvents )
378+ curHR = this . toHumanReadable ( curEvents )
379+
380+ let events = difflib . unifiedDiff (
381+ origHR ,
382+ curHR ,
383+ {
384+ fromfile : orig . contractName ,
385+ tofile : cur . contractName ,
386+ fromfiledate : `sha: ${ orig . sha } ` ,
387+ tofiledate : `sha: ${ cur . sha } ` ,
388+ lineterm : ''
389+ }
390+ ) ;
391+
392+ if ( events . length && fns . length ) {
393+ events = events . slice ( 3 ) ;
394+ }
395+
396+ const diff = fns . concat ( events ) ;
397+
398+ // Count changes (unified diff always has a plus & minus in header);
399+ if ( diff . length ) {
400+ plus = - 1 ;
401+ minus = - 1 ;
402+ }
403+
404+ diff . forEach ( line => {
405+ if ( line [ 0 ] === `+` ) plus ++ ;
406+ if ( line [ 0 ] === `-` ) minus ++ ;
407+ } )
408+
409+ return {
410+ plus,
411+ minus,
412+ diff
413+ }
414+ }
415+
416+ toHumanReadable ( ethersOutput ) {
417+ const human = [ ] ;
418+ const signatures = Object . keys ( ethersOutput ) ;
419+
420+ for ( const sig of signatures ) {
421+ const method = ethersOutput [ sig ] ;
422+
423+ let returns = '' ;
424+ if ( method . outputs ) {
425+ method . outputs . forEach ( output => {
426+ ( returns . length )
427+ ? returns += `, ${ output . type } `
428+ : returns += output . type ;
429+ } ) ;
430+ } ;
431+
432+ const mutability = method . stateMutability || '' ;
433+ let readable = `${ method . type } ${ sig } ${ mutability } ` ;
434+
435+ if ( returns . length ) {
436+ readable += ` returns (${ returns } )`
437+ }
438+
439+ human . push ( readable ) ;
440+ }
441+
442+ return human ;
443+ }
444+
345445 // ========
346446 // File I/O
347447 // ========
0 commit comments