Skip to content

Commit 51dc0b7

Browse files
committed
Handle verbose cast output in Anvil bootstrap scripts
1 parent 4f19e69 commit 51dc0b7

File tree

2 files changed

+108
-5
lines changed

2 files changed

+108
-5
lines changed

packages/contracts/script/anvil-base-node.ts

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,77 @@ console.log(chalk.blue('Running anvil base node'), {
1717
NEXT_PUBLIC_BASE_CHAIN_ID: $.env.NEXT_PUBLIC_BASE_CHAIN_ID,
1818
})
1919

20-
const baseBaseFee = await $`cast base-fee --rpc-url $ANVIL_BASE_FORK_URL`
21-
const baseGasPrice = await $`cast gas-price --rpc-url $ANVIL_BASE_FORK_URL`
20+
const parseCastBigInt = (stdout: string, label: string): bigint => {
21+
const tokens = stdout
22+
.split(/\s+/)
23+
.map((token) => token.replace(/[,;]+$/, ''))
24+
.filter(Boolean)
25+
26+
for (let i = tokens.length - 1; i >= 0; i--) {
27+
const candidate = tokens[i]
28+
if (/^-?(?:0x)?[0-9a-fA-F]+$/.test(candidate)) {
29+
try {
30+
return BigInt(candidate)
31+
} catch (error) {
32+
console.warn(chalk.yellow(`Failed to parse ${label} token "${candidate}" as BigInt`), error)
33+
}
34+
}
35+
}
36+
37+
throw new Error(
38+
`Unable to parse numeric output for ${label} from cast command. Raw stdout: ${stdout}`
39+
)
40+
}
41+
42+
const runCastBigInt = async (
43+
label: string,
44+
fn: () => ProcessPromise<ProcessOutput>
45+
): Promise<bigint> => {
46+
const maxAttempts = 3
47+
let lastError: unknown
48+
49+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
50+
try {
51+
const result = await fn()
52+
const stdout = result.stdout?.trim?.() ? result.stdout.trim() : `${result}`.trim()
53+
if (!stdout) {
54+
throw new Error(`cast returned empty stdout for ${label}`)
55+
}
56+
return parseCastBigInt(stdout, label)
57+
} catch (error) {
58+
lastError = error
59+
console.warn(
60+
chalk.yellow(`Attempt ${attempt}/${maxAttempts} to fetch ${label} failed. Retrying...`),
61+
error
62+
)
63+
await new Promise((resolve) => setTimeout(resolve, attempt * 1000))
64+
}
65+
}
66+
67+
throw new Error(`Failed to resolve ${label} after ${maxAttempts} attempts`, {
68+
cause: lastError,
69+
})
70+
}
71+
72+
const baseBaseFee = (
73+
await runCastBigInt(
74+
'base base fee',
75+
() => $`cast base-fee --rpc-url ${$.env.ANVIL_BASE_FORK_URL}`
76+
)
77+
).toString()
78+
const baseGasPrice = (
79+
await runCastBigInt(
80+
'base gas price',
81+
() => $`cast gas-price --rpc-url ${$.env.ANVIL_BASE_FORK_URL}`
82+
)
83+
).toString()
2284

2385
// do not fork from the absolute latest block
24-
const blockHeight = await $`cast bn --rpc-url $ANVIL_BASE_FORK_URL`.then(
25-
(r) => BigInt(r.stdout.trim()) - 30n
86+
const remoteBlockHeight = await runCastBigInt(
87+
'latest block',
88+
() => $`cast bn --rpc-url ${$.env.ANVIL_BASE_FORK_URL}`
2689
)
90+
const blockHeight = remoteBlockHeight > 30n ? remoteBlockHeight - 30n : remoteBlockHeight
2791

2892
await $`docker rm -f sendapp-anvil-base`
2993

packages/contracts/script/anvil-token-paymaster-deposit.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,52 @@ $.verbose = true
44
* This script is used to deposit into the Entrypoint for TokenPaymaster
55
*/
66

7+
const stripControlCharacters = (value: string): string => {
8+
let result = ''
9+
for (const char of value) {
10+
const code = char.charCodeAt(0)
11+
if (
12+
code === 0x0a || // \n
13+
code === 0x0d || // \r
14+
code === 0x09 || // \t
15+
code >= 0x20
16+
) {
17+
result += char
18+
}
19+
}
20+
return result
21+
}
22+
23+
const sanitizeCastBigInt = (stdout: string, label: string): string => {
24+
const cleanOutput = stripControlCharacters(stdout)
25+
const tokens = cleanOutput
26+
.split(/\s+/)
27+
.map((token) => token.replace(/[,;]+$/, ''))
28+
.filter(Boolean)
29+
30+
for (let i = tokens.length - 1; i >= 0; i--) {
31+
const candidate = tokens[i]
32+
if (/^-?(?:0x)?[0-9a-fA-F]+$/.test(candidate)) {
33+
try {
34+
return BigInt(candidate).toString()
35+
} catch (error) {
36+
console.warn(chalk.yellow(`Failed to parse ${label} token "${candidate}" as BigInt`), error)
37+
}
38+
}
39+
}
40+
41+
throw new Error(`Unable to parse numeric output for ${label}. Raw stdout: ${stdout}`)
42+
}
43+
744
void (async function main() {
845
console.log(chalk.blue('Enable auto-mining...'))
946
await $`cast rpc --rpc-url base-local evm_setAutomine true`
1047

1148
// base mainnet fork
1249
$.env.PAYMASTER = '0x592e1224D203Be4214B15e205F6081FbbaCFcD2D'
13-
$.env.DEPOSIT = await $`cast to-wei 100 ether`.then((r) => r.stdout.trim())
50+
$.env.DEPOSIT = await $`cast to-wei 100 ether`.then((r) =>
51+
sanitizeCastBigInt(r.stdout, 'deposit amount')
52+
)
1453

1554
console.log(chalk.blue('Adding deposit to paymaster...'), $.env.DEPOSIT)
1655
await $`forge script ./script/AddTokenPaymasterDeposit.s.sol:AddTokenPaymasterDepositScript \

0 commit comments

Comments
 (0)