@@ -11,8 +11,8 @@ interface ImportMeta {
11
11
12
12
// Types based on events.rs
13
13
interface WebhookEvent {
14
- transactionId : string ;
15
- executorName : string ;
14
+ transactionId : string ;
15
+ executorName : string ;
16
16
stageName : string ; // "send" | "confirm"
17
17
eventType : string ; // "Success" | "Nack" | "Failure"
18
18
payload : any ;
@@ -37,9 +37,12 @@ interface BenchmarkConfig {
37
37
from : string ;
38
38
chainId : number ;
39
39
secretKey : string ;
40
- vaultAccessToken : string ;
40
+ vaultAccessToken ? : string ;
41
41
concurrentRequests : number ;
42
42
totalRequests : number ;
43
+ awsAccessKeyId ?: string ;
44
+ awsKmsArn ?: string ;
45
+ awsSecretAccessKey ?: string ;
43
46
}
44
47
45
48
interface AggregateResults {
@@ -98,14 +101,19 @@ const config: BenchmarkConfig = {
98
101
from : process . env . FROM ! ,
99
102
chainId : parseInt ( process . env . CHAIN_ID || "1337" ) ,
100
103
secretKey : process . env . SECRET_KEY ! ,
101
- vaultAccessToken : process . env . VAULT_ACCESS_TOKEN ! ,
104
+ vaultAccessToken : process . env . VAULT_ACCESS_TOKEN ,
105
+ awsAccessKeyId : process . env . AWS_ACCESS_KEY_ID ,
106
+ awsKmsArn : process . env . AWS_KMS_ARN ,
107
+ awsSecretAccessKey : process . env . AWS_SECRET_ACCESS_KEY ,
102
108
concurrentRequests : parseInt ( process . env . CONCURRENT_REQUESTS || "10" ) ,
103
109
totalRequests : parseInt ( process . env . TOTAL_REQUESTS || "100" ) ,
104
110
} ;
105
111
106
112
// Validate required env vars
107
- if ( ! config . from || ! config . secretKey || ! config . vaultAccessToken ) {
108
- console . error ( "❌ Missing required environment variables: FROM, SECRET_KEY, VAULT_ACCESS_TOKEN" ) ;
113
+ if ( ! config . from || ! config . secretKey ) {
114
+ console . error (
115
+ "❌ Missing required environment variables: FROM, SECRET_KEY"
116
+ ) ;
109
117
process . exit ( 1 ) ;
110
118
}
111
119
@@ -127,7 +135,9 @@ const webhookServer = Bun.serve({
127
135
} ,
128
136
} ) ;
129
137
130
- console . log ( `🎣 Webhook server listening on http://localhost:${ webhookServer . port } ` ) ;
138
+ console . log (
139
+ `🎣 Webhook server listening on http://localhost:${ webhookServer . port } `
140
+ ) ;
131
141
132
142
// Handle webhook events
133
143
function handleWebhookEvent ( event : WebhookEvent ) {
@@ -147,12 +157,20 @@ function handleWebhookEvent(event: WebhookEvent) {
147
157
metrics . submittedTime = now ;
148
158
metrics . sentToSubmittedMs = now - metrics . sentTime ;
149
159
metrics . status = "submitted" ;
150
- console . log ( `✅ Transaction ${ txId . slice ( 0 , 8 ) } ... submitted (${ metrics . sentToSubmittedMs } ms)` ) ;
160
+ console . log (
161
+ `✅ Transaction ${ txId . slice ( 0 , 8 ) } ... submitted (${
162
+ metrics . sentToSubmittedMs
163
+ } ms)`
164
+ ) ;
151
165
} else if ( event . eventType === "Failure" ) {
152
166
metrics . status = "failed" ;
153
167
metrics . error = JSON . stringify ( event . payload ) ;
154
168
pendingTransactions . delete ( txId ) ;
155
- console . log ( `❌ Transaction ${ txId . slice ( 0 , 8 ) } ... failed at send stage (pending: ${ pendingTransactions . size } )` ) ;
169
+ console . log (
170
+ `❌ Transaction ${ txId . slice ( 0 , 8 ) } ... failed at send stage (pending: ${
171
+ pendingTransactions . size
172
+ } )`
173
+ ) ;
156
174
}
157
175
} else if ( event . stageName === "confirm" ) {
158
176
if ( event . eventType === "SUCCESS" ) {
@@ -163,12 +181,23 @@ function handleWebhookEvent(event: WebhookEvent) {
163
181
metrics . totalTimeMs = now - metrics . sentTime ;
164
182
metrics . status = "confirmed" ;
165
183
pendingTransactions . delete ( txId ) ;
166
- console . log ( `🎉 Transaction ${ txId . slice ( 0 , 8 ) } ... confirmed (total: ${ metrics . totalTimeMs } ms, pending: ${ pendingTransactions . size } )` ) ;
167
- } else if ( event . eventType === "FAIL" || event . eventType === "NACK" ) {
184
+ console . log (
185
+ `🎉 Transaction ${ txId . slice ( 0 , 8 ) } ... confirmed (total: ${
186
+ metrics . totalTimeMs
187
+ } ms, pending: ${ pendingTransactions . size } )`
188
+ ) ;
189
+ } else if ( event . eventType === "FAIL" ) {
168
190
metrics . status = "failed" ;
169
191
metrics . error = JSON . stringify ( event . payload ) ;
170
192
pendingTransactions . delete ( txId ) ;
171
- console . log ( `❌ Transaction ${ txId . slice ( 0 , 8 ) } ... failed at confirmation stage (pending: ${ pendingTransactions . size } )` ) ;
193
+ console . log (
194
+ `❌ Transaction ${ txId . slice (
195
+ 0 ,
196
+ 8
197
+ ) } ... failed at confirmation stage (pending: ${
198
+ pendingTransactions . size
199
+ } )`
200
+ ) ;
172
201
}
173
202
}
174
203
}
@@ -183,7 +212,20 @@ async function sendTransaction(): Promise<TransactionMetrics> {
183
212
headers : {
184
213
"Content-Type" : "application/json" ,
185
214
"x-thirdweb-secret-key" : config . secretKey ,
186
- "x-vault-access-token" : config . vaultAccessToken ,
215
+ ...( config . vaultAccessToken
216
+ ? {
217
+ "x-vault-access-token" : config . vaultAccessToken ,
218
+ }
219
+ : { } ) ,
220
+ ...( config . awsAccessKeyId &&
221
+ config . awsKmsArn &&
222
+ config . awsSecretAccessKey
223
+ ? {
224
+ "x-aws-access-key-id" : config . awsAccessKeyId ,
225
+ "x-aws-kms-arn" : config . awsKmsArn ,
226
+ "x-aws-secret-access-key" : config . awsSecretAccessKey ,
227
+ }
228
+ : { } ) ,
187
229
} ,
188
230
body : JSON . stringify ( {
189
231
executionOptions : {
@@ -214,17 +256,20 @@ async function sendTransaction(): Promise<TransactionMetrics> {
214
256
throw new Error ( `HTTP ${ response . status } : ${ errorText } ` ) ;
215
257
}
216
258
217
- const res = await response . json ( ) as {
218
- result : {
219
- transactions : {
220
- id : string ;
221
- } [ ]
222
- }
259
+ const res = ( await response . json ( ) ) as {
260
+ result : {
261
+ transactions : {
262
+ id : string ;
263
+ } [ ] ;
264
+ } ;
223
265
} ;
224
266
const transactionId = res . result . transactions [ 0 ] ?. id ;
225
267
226
268
if ( ! transactionId ) {
227
- console . error ( "❌ No transaction ID in response:" , JSON . stringify ( response , null , 2 ) ) ;
269
+ console . error (
270
+ "❌ No transaction ID in response:" ,
271
+ JSON . stringify ( response , null , 2 )
272
+ ) ;
228
273
throw new Error ( "No transaction ID in response" ) ;
229
274
}
230
275
@@ -241,8 +286,13 @@ async function sendTransaction(): Promise<TransactionMetrics> {
241
286
242
287
transactions . set ( transactionId , metrics ) ;
243
288
pendingTransactions . add ( transactionId ) ;
244
-
245
- console . log ( `📝 Added transaction ${ transactionId . slice ( 0 , 8 ) } ... to pending (total: ${ pendingTransactions . size } )` ) ;
289
+
290
+ console . log (
291
+ `📝 Added transaction ${ transactionId . slice (
292
+ 0 ,
293
+ 8
294
+ ) } ... to pending (total: ${ pendingTransactions . size } )`
295
+ ) ;
246
296
247
297
return metrics ;
248
298
} catch ( error ) {
@@ -256,7 +306,11 @@ async function sendTransaction(): Promise<TransactionMetrics> {
256
306
error : error instanceof Error ? error . message : String ( error ) ,
257
307
} ;
258
308
transactions . set ( errorMetrics . transactionId , errorMetrics ) ;
259
- console . error ( `❌ Transaction request failed: ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
309
+ console . error (
310
+ `❌ Transaction request failed: ${
311
+ error instanceof Error ? error . message : String ( error )
312
+ } `
313
+ ) ;
260
314
return errorMetrics ;
261
315
}
262
316
}
@@ -293,7 +347,11 @@ async function runBenchmark() {
293
347
294
348
// Progress indicator
295
349
if ( ( i + 1 ) % 10 === 0 ) {
296
- console . log ( `📤 Sent ${ i + 1 } /${ config . totalRequests } requests... (in-flight: ${ inFlight . size } )` ) ;
350
+ console . log (
351
+ `📤 Sent ${ i + 1 } /${ config . totalRequests } requests... (in-flight: ${
352
+ inFlight . size
353
+ } )`
354
+ ) ;
297
355
}
298
356
}
299
357
@@ -313,15 +371,19 @@ async function runBenchmark() {
313
371
waited += pollInterval ;
314
372
315
373
if ( waited % 5000 === 0 ) {
316
- console . log ( ` Still waiting for ${ pendingTransactions . size } transactions...` ) ;
374
+ console . log (
375
+ ` Still waiting for ${ pendingTransactions . size } transactions...`
376
+ ) ;
317
377
}
318
378
}
319
379
320
380
const endTime = Date . now ( ) ;
321
381
const duration = endTime - startTime ;
322
382
323
383
if ( pendingTransactions . size > 0 ) {
324
- console . warn ( `\n⚠️ Timeout: ${ pendingTransactions . size } transactions still pending` ) ;
384
+ console . warn (
385
+ `\n⚠️ Timeout: ${ pendingTransactions . size } transactions still pending`
386
+ ) ;
325
387
} else {
326
388
console . log ( `\n🎉 All transactions completed!` ) ;
327
389
}
@@ -411,14 +473,21 @@ async function writeCSV(outputDir: string, timestamp: string) {
411
473
m . error || "" ,
412
474
] ) ;
413
475
414
- const csvContent = [ headers . join ( "," ) , ...rows . map ( ( row ) => row . join ( "," ) ) ] . join ( "\n" ) ;
476
+ const csvContent = [
477
+ headers . join ( "," ) ,
478
+ ...rows . map ( ( row ) => row . join ( "," ) ) ,
479
+ ] . join ( "\n" ) ;
415
480
416
481
await Bun . write ( csvPath , csvContent ) ;
417
482
console . log ( `📄 CSV written to: ${ csvPath } ` ) ;
418
483
}
419
484
420
485
// Write JSON results
421
- async function writeJSON ( outputDir : string , timestamp : string , results : AggregateResults ) {
486
+ async function writeJSON (
487
+ outputDir : string ,
488
+ timestamp : string ,
489
+ results : AggregateResults
490
+ ) {
422
491
const jsonPath = `${ outputDir } /result-${ timestamp } .json` ;
423
492
await Bun . write ( jsonPath , JSON . stringify ( results , null , 2 ) ) ;
424
493
console . log ( `📊 Results written to: ${ jsonPath } ` ) ;
@@ -435,7 +504,9 @@ function printResults(results: AggregateResults) {
435
504
console . log ( ` Successful: ${ results . successfulRequests } ` ) ;
436
505
console . log ( ` Failed: ${ results . failedRequests } ` ) ;
437
506
console . log ( ` Error Rate: ${ results . errorRate . toFixed ( 2 ) } %` ) ;
438
- console . log ( ` Duration: ${ ( results . duration / 1000 ) . toFixed ( 2 ) } s` ) ;
507
+ console . log (
508
+ ` Duration: ${ ( results . duration / 1000 ) . toFixed ( 2 ) } s`
509
+ ) ;
439
510
console . log ( ` Throughput: ${ results . throughput . toFixed ( 2 ) } req/s` ) ;
440
511
441
512
console . log ( "\n⏱️ HTTP Response Times (ms):" ) ;
@@ -458,7 +529,9 @@ function printResults(results: AggregateResults) {
458
529
459
530
console . log ( "\n✅ Submitted to Confirmed Times (ms):" ) ;
460
531
console . log ( ` Min: ${ results . submittedToConfirmedTimes . min . toFixed ( 2 ) } ` ) ;
461
- console . log ( ` Mean: ${ results . submittedToConfirmedTimes . mean . toFixed ( 2 ) } ` ) ;
532
+ console . log (
533
+ ` Mean: ${ results . submittedToConfirmedTimes . mean . toFixed ( 2 ) } `
534
+ ) ;
462
535
console . log ( ` P50: ${ results . submittedToConfirmedTimes . p50 . toFixed ( 2 ) } ` ) ;
463
536
console . log ( ` P90: ${ results . submittedToConfirmedTimes . p90 . toFixed ( 2 ) } ` ) ;
464
537
console . log ( ` P95: ${ results . submittedToConfirmedTimes . p95 . toFixed ( 2 ) } ` ) ;
@@ -513,4 +586,3 @@ async function main() {
513
586
514
587
// Run the benchmark
515
588
main ( ) ;
516
-
0 commit comments