@@ -17,6 +17,8 @@ import {
17
17
isUnlockableUtxo ,
18
18
isStandardUnlockableUtxo ,
19
19
StandardUnlockableUtxo ,
20
+ VmResourceUsage ,
21
+ isContractUnlocker ,
20
22
} from './interfaces.js' ;
21
23
import { NetworkProvider } from './network/index.js' ;
22
24
import {
@@ -172,6 +174,44 @@ export class TransactionBuilder {
172
174
return debugLibauthTemplate ( this . getLibauthTemplate ( ) , this ) ;
173
175
}
174
176
177
+ getVmResourceUsage ( verbose : boolean = false ) : Array < VmResourceUsage > {
178
+ // Note that only StandardUnlockableUtxo inputs are supported for debugging, so any transaction with custom unlockers
179
+ // cannot be debugged (and therefore cannot return VM resource usage)
180
+ const results = this . debug ( ) ;
181
+ const vmResourceUsage : Array < VmResourceUsage > = [ ] ;
182
+ const tableData : Array < Record < string , any > > = [ ] ;
183
+
184
+ const formatMetric = ( value : number , total : number , withPercentage : boolean = false ) : string =>
185
+ `${ formatNumber ( value ) } / ${ formatNumber ( total ) } ${ withPercentage ? ` (${ ( value / total * 100 ) . toFixed ( 0 ) } %)` : '' } ` ;
186
+ const formatNumber = ( value : number ) : string => value . toLocaleString ( 'en' ) ;
187
+
188
+ const resultEntries = Object . entries ( results ) ;
189
+ for ( const [ index , input ] of this . inputs . entries ( ) ) {
190
+ const [ , result ] = resultEntries . find ( ( [ entryKey ] ) => entryKey . includes ( `input${ index } ` ) ) ?? [ ] ;
191
+ const metrics = result ?. at ( - 1 ) ?. metrics ;
192
+
193
+ // Should not happen
194
+ if ( ! metrics ) throw new Error ( 'VM resource could not be calculated' ) ;
195
+
196
+ vmResourceUsage . push ( metrics ) ;
197
+ tableData . push ( {
198
+ 'Contract - Function' : isContractUnlocker ( input . unlocker ) ? `${ input . unlocker . contract . name } - ${ input . unlocker . abiFunction . name } ` : 'P2PKH Input' ,
199
+ Ops : metrics . evaluatedInstructionCount ,
200
+ 'Op Cost Budget Usage' : formatMetric ( metrics . operationCost , metrics . maximumOperationCost , true ) ,
201
+ SigChecks : formatMetric ( metrics . signatureCheckCount , metrics . maximumSignatureCheckCount ) ,
202
+ Hashes : formatMetric ( metrics . hashDigestIterations , metrics . maximumHashDigestIterations ) ,
203
+ } ) ;
204
+ }
205
+
206
+ if ( verbose ) {
207
+ console . log ( 'VM Resource usage by inputs:' ) ;
208
+ console . table ( tableData ) ;
209
+ }
210
+
211
+ return vmResourceUsage ;
212
+ }
213
+
214
+ // TODO: rename to getBitauthUri()
175
215
bitauthUri ( ) : string {
176
216
console . warn ( 'WARNING: it is unsafe to use this Bitauth URI when using real private keys as they are included in the transaction template' ) ;
177
217
return getBitauthUri ( this . getLibauthTemplate ( ) ) ;
0 commit comments