@0xsequence/catapult 1.3.3 → 1.3.4

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.
Files changed (45) hide show
  1. package/README.md +16 -0
  2. package/dist/commands/run.d.ts.map +1 -1
  3. package/dist/commands/run.js +4 -2
  4. package/dist/commands/run.js.map +1 -1
  5. package/dist/lib/__tests__/deployer.spec.js +71 -1
  6. package/dist/lib/__tests__/deployer.spec.js.map +1 -1
  7. package/dist/lib/core/__tests__/engine.spec.js +270 -0
  8. package/dist/lib/core/__tests__/engine.spec.js.map +1 -1
  9. package/dist/lib/core/__tests__/resolver.spec.js +132 -0
  10. package/dist/lib/core/__tests__/resolver.spec.js.map +1 -1
  11. package/dist/lib/core/engine.d.ts +13 -0
  12. package/dist/lib/core/engine.d.ts.map +1 -1
  13. package/dist/lib/core/engine.js +59 -5
  14. package/dist/lib/core/engine.js.map +1 -1
  15. package/dist/lib/core/resolver.d.ts +1 -0
  16. package/dist/lib/core/resolver.d.ts.map +1 -1
  17. package/dist/lib/core/resolver.js +24 -7
  18. package/dist/lib/core/resolver.js.map +1 -1
  19. package/dist/lib/deployer.d.ts +2 -0
  20. package/dist/lib/deployer.d.ts.map +1 -1
  21. package/dist/lib/deployer.js +18 -1
  22. package/dist/lib/deployer.js.map +1 -1
  23. package/dist/lib/events/cli-adapter.d.ts.map +1 -1
  24. package/dist/lib/events/cli-adapter.js +20 -0
  25. package/dist/lib/events/cli-adapter.js.map +1 -1
  26. package/dist/lib/events/types.d.ts +25 -1
  27. package/dist/lib/events/types.d.ts.map +1 -1
  28. package/dist/lib/types/values.d.ts +8 -1
  29. package/dist/lib/types/values.d.ts.map +1 -1
  30. package/dist/lib/utils/assertion.d.ts +4 -0
  31. package/dist/lib/utils/assertion.d.ts.map +1 -0
  32. package/dist/lib/utils/assertion.js +27 -0
  33. package/dist/lib/utils/assertion.js.map +1 -0
  34. package/package.json +12 -13
  35. package/src/commands/run.ts +4 -1
  36. package/src/lib/__tests__/deployer.spec.ts +108 -1
  37. package/src/lib/core/__tests__/engine.spec.ts +321 -0
  38. package/src/lib/core/__tests__/resolver.spec.ts +150 -1
  39. package/src/lib/core/engine.ts +92 -6
  40. package/src/lib/core/resolver.ts +29 -8
  41. package/src/lib/deployer.ts +28 -1
  42. package/src/lib/events/cli-adapter.ts +24 -0
  43. package/src/lib/events/types.ts +29 -1
  44. package/src/lib/types/values.ts +10 -1
  45. package/src/lib/utils/assertion.ts +24 -0
@@ -5,16 +5,17 @@ import {
5
5
  AbiEncodeValue,
6
6
  AbiPackValue,
7
7
  ConstructorEncodeValue,
8
+ ComputeCreateValue,
8
9
  ComputeCreate2Value,
9
10
  ReadBalanceValue,
10
11
  BasicArithmeticValue,
11
12
  CallValue,
12
- ContractExistsCondition,
13
13
  ContractExistsValue,
14
14
  JobCompletedValue,
15
15
  ReadJsonValue,
16
16
  } from '../types'
17
17
  import { ExecutionContext } from './context'
18
+ import { isAddress, isBigNumberish, isBytesLike } from '../utils/assertion'
18
19
 
19
20
  /**
20
21
  * A scope for resolving local variables, such as template arguments.
@@ -154,6 +155,8 @@ export class ValueResolver {
154
155
  return this.resolveAbiPack(resolvedArgs as AbiPackValue['arguments'])
155
156
  case 'constructor-encode':
156
157
  return this.resolveConstructorEncode(resolvedArgs as ConstructorEncodeValue['arguments'])
158
+ case 'compute-create':
159
+ return this.resolveComputeCreate(resolvedArgs as ComputeCreateValue['arguments'])
157
160
  case 'compute-create2':
158
161
  return this.resolveComputeCreate2(resolvedArgs as ComputeCreate2Value['arguments'])
159
162
  case 'read-balance':
@@ -260,7 +263,7 @@ export class ValueResolver {
260
263
  }
261
264
 
262
265
  // Validate that creation code is valid bytecode
263
- if (!ethers.isBytesLike(creationCode)) {
266
+ if (!isBytesLike(creationCode)) {
264
267
  throw new Error(`Invalid creation code: ${creationCode}`)
265
268
  }
266
269
 
@@ -280,18 +283,36 @@ export class ValueResolver {
280
283
  return '0x' + cleanCreationCode + cleanEncodedArgs
281
284
  }
282
285
 
286
+ private resolveComputeCreate(args: ComputeCreateValue['arguments']): string {
287
+ const { deployerAddress, nonce } = args
288
+ // Check if the deployer address is a valid address
289
+ if (!isAddress(deployerAddress)) {
290
+ throw new Error(`Invalid deployer address: ${deployerAddress}`)
291
+ }
292
+ // Check if the nonce is a valid value
293
+ if (!isBigNumberish(nonce)) {
294
+ throw new Error(`Invalid nonce: ${nonce}`)
295
+ }
296
+ const bnNonce = ethers.toBigInt(nonce)
297
+ // Create the create address
298
+ return ethers.getCreateAddress({
299
+ from: deployerAddress,
300
+ nonce: bnNonce,
301
+ })
302
+ }
303
+
283
304
  private resolveComputeCreate2(args: ComputeCreate2Value['arguments']): string {
284
305
  const { deployerAddress, salt, initCode } = args
285
306
  // Check if the deployer address is a valid address
286
- if (!ethers.isAddress(deployerAddress)) {
307
+ if (!isAddress(deployerAddress)) {
287
308
  throw new Error(`Invalid deployer address: ${deployerAddress}`)
288
309
  }
289
310
  // Check if the salt is a valid bytes value
290
- if (!ethers.isBytesLike(salt)) {
311
+ if (!isBytesLike(salt)) {
291
312
  throw new Error(`Invalid salt: ${salt}`)
292
313
  }
293
314
  // Check if the init code is a valid bytes value
294
- if (!ethers.isBytesLike(initCode)) {
315
+ if (!isBytesLike(initCode)) {
295
316
  throw new Error(`Invalid init code: ${initCode}`)
296
317
  }
297
318
  // Hash the init code using Keccak256
@@ -304,7 +325,7 @@ export class ValueResolver {
304
325
  // Check if the address is a valid address
305
326
  const addressValue = args.address as any
306
327
 
307
- if (!ethers.isAddress(addressValue)) {
328
+ if (!isAddress(addressValue)) {
308
329
  throw new Error(`Invalid address: ${addressValue}`)
309
330
  }
310
331
 
@@ -349,7 +370,7 @@ export class ValueResolver {
349
370
  }
350
371
 
351
372
  // Validate that the target address is a valid Ethereum address
352
- if (!ethers.isAddress(to)) {
373
+ if (!isAddress(to)) {
353
374
  throw new Error(`call: invalid target address: ${to}`)
354
375
  }
355
376
 
@@ -407,7 +428,7 @@ export class ValueResolver {
407
428
  private async resolveContractExists(args: ContractExistsValue['arguments'], context: ExecutionContext): Promise<boolean> {
408
429
  const { address } = args
409
430
 
410
- if (!ethers.isAddress(address)) {
431
+ if (!isAddress(address)) {
411
432
  throw new Error(`contract-exists: invalid address: ${address}`)
412
433
  }
413
434
 
@@ -52,6 +52,9 @@ export interface DeployerOptions {
52
52
 
53
53
  /** Optional: Show end-of-run summary (default: true). */
54
54
  showSummary?: boolean
55
+
56
+ /** Optional: Convert verification errors to warnings instead of failing (default: false). */
57
+ ignoreVerifyErrors?: boolean
55
58
  }
56
59
 
57
60
  /**
@@ -157,7 +160,8 @@ export class Deployer {
157
160
  const engine = new ExecutionEngine(this.loader.templates, {
158
161
  eventEmitter: this.events,
159
162
  verificationRegistry,
160
- noPostCheckConditions: this.noPostCheckConditions
163
+ noPostCheckConditions: this.noPostCheckConditions,
164
+ ignoreVerifyErrors: this.options.ignoreVerifyErrors ?? false
161
165
  })
162
166
 
163
167
  // Track if any jobs have failed
@@ -312,6 +316,11 @@ export class Deployer {
312
316
  // 5. Write results to output files.
313
317
  await this.writeOutputFiles()
314
318
 
319
+ // Show verification warnings report if ignoreVerifyErrors is enabled
320
+ if (this.options.ignoreVerifyErrors) {
321
+ this.emitVerificationWarningsReport(engine)
322
+ }
323
+
315
324
  // Emit end-of-run summary before final status
316
325
  if (this.showSummary) {
317
326
  this.emitRunSummary(hasFailures)
@@ -423,6 +432,24 @@ export class Deployer {
423
432
  this.events.emitEvent(summaryEvent)
424
433
  }
425
434
 
435
+ /**
436
+ * Emit verification warnings report when ignoreVerifyErrors is enabled
437
+ */
438
+ private emitVerificationWarningsReport(engine: ExecutionEngine): void {
439
+ const warnings = engine.getVerificationWarnings()
440
+
441
+ if (warnings.length > 0) {
442
+ this.events.emitEvent({
443
+ type: 'verification_warnings_report',
444
+ level: 'warn',
445
+ data: {
446
+ totalWarnings: warnings.length,
447
+ warnings: warnings
448
+ }
449
+ })
450
+ }
451
+ }
452
+
426
453
  /**
427
454
  * Determines the final, ordered list of jobs to execute based on user input.
428
455
  * If a user requests specific jobs, this ensures all their dependencies are also included.
@@ -266,6 +266,30 @@ export class CLIEventAdapter {
266
266
  // Keep short to reduce noise
267
267
  console.log(chalk.gray(` Verification retry ${event.data.attempt}/${event.data.maxRetries}: ${event.data.error}`))
268
268
  break
269
+
270
+ case 'verification_skipped':
271
+ console.log(chalk.yellow(` ⚠️ ${event.data.reason}`))
272
+ break
273
+
274
+ case 'verification_warnings_report':
275
+ // Display detailed verification warnings report
276
+ console.log(chalk.yellow('\n📋 Verification Warnings Report'))
277
+ console.log(chalk.yellow(` Total warnings: ${event.data.totalWarnings}`))
278
+ console.log('')
279
+
280
+ if (event.data.warnings && event.data.warnings.length > 0) {
281
+ for (const warning of event.data.warnings) {
282
+ console.log(chalk.red(` ❌ ${warning.actionName} (${warning.contractName})`))
283
+ console.log(chalk.gray(` Address: ${warning.address}`))
284
+ console.log(chalk.gray(` Platform: ${warning.platform}`))
285
+ if (warning.networkName) {
286
+ console.log(chalk.gray(` Network: ${warning.networkName}`))
287
+ }
288
+ console.log(chalk.gray(` Error: ${warning.error}`))
289
+ console.log('')
290
+ }
291
+ }
292
+ break
269
293
  case 'contract_created':
270
294
  console.log(chalk.gray(` contract: ${event.data.contractAddress}`))
271
295
  break
@@ -429,6 +429,32 @@ export interface VerificationRetryEvent extends BaseEvent {
429
429
  }
430
430
  }
431
431
 
432
+ export interface VerificationSkippedEvent extends BaseEvent {
433
+ type: 'verification_skipped'
434
+ level: 'warn'
435
+ data: {
436
+ actionName: string
437
+ reason: string
438
+ }
439
+ }
440
+
441
+ export interface VerificationWarningsReportEvent extends BaseEvent {
442
+ type: 'verification_warnings_report'
443
+ level: 'warn'
444
+ data: {
445
+ totalWarnings: number
446
+ warnings: Array<{
447
+ actionName: string
448
+ address: string
449
+ contractName: string
450
+ platform: string
451
+ error: string
452
+ jobName?: string
453
+ networkName?: string
454
+ }>
455
+ }
456
+ }
457
+
432
458
  // End-of-run summary
433
459
  export interface RunSummaryEvent extends BaseEvent {
434
460
  type: 'run_summary'
@@ -488,5 +514,7 @@ export type DeploymentEvent =
488
514
  | VerificationSubmittedEvent
489
515
  | VerificationCompletedEvent
490
516
  | VerificationFailedEvent
491
- | VerificationRetryEvent
517
+ | VerificationRetryEvent
518
+ | VerificationSkippedEvent
519
+ | VerificationWarningsReportEvent
492
520
  | RunSummaryEvent
@@ -32,6 +32,14 @@ export interface ConstructorEncodeValue {
32
32
  };
33
33
  }
34
34
 
35
+ export interface ComputeCreateValue {
36
+ type: 'compute-create';
37
+ arguments: {
38
+ deployerAddress: AddressValue;
39
+ nonce: Uint256Value;
40
+ };
41
+ }
42
+
35
43
  export interface ComputeCreate2Value {
36
44
  type: 'compute-create2';
37
45
  arguments: {
@@ -94,6 +102,7 @@ export type ValueResolver =
94
102
  | AbiEncodeValue
95
103
  | AbiPackValue
96
104
  | ConstructorEncodeValue
105
+ | ComputeCreateValue
97
106
  | ComputeCreate2Value
98
107
  | ReadBalanceValue
99
108
  | BasicArithmeticValue
@@ -113,4 +122,4 @@ export type Value<T = string | number | boolean> = T | Reference | ValueResolver
113
122
  export type BytesValue = Value<string>;
114
123
  export type AddressValue = Value<string>;
115
124
  export type Uint256Value = Value<string | number>;
116
- export type BooleanValue = Value<boolean>;
125
+ export type BooleanValue = Value<boolean>;
@@ -0,0 +1,24 @@
1
+ import { ethers } from "ethers";
2
+
3
+ export function isAddress(value: unknown): value is string {
4
+ return ethers.isAddress(value)
5
+ }
6
+
7
+ export function isBytesLike(value: unknown): value is string {
8
+ return ethers.isBytesLike(value)
9
+ }
10
+
11
+ export function isBigNumberish(value: unknown): value is string | number | bigint {
12
+ try {
13
+ switch (typeof(value)) {
14
+ case "bigint":
15
+ case "number":
16
+ case "string":
17
+ ethers.toBigInt(value)
18
+ return true
19
+ }
20
+ } catch (error) {
21
+ // Fail out
22
+ }
23
+ return false
24
+ }