Skip to content

Commit f162b81

Browse files
authored
feat: misc infra tweaks (#7168)
1 parent 651af9b commit f162b81

9 files changed

Lines changed: 119 additions & 30 deletions

File tree

typescript/infra/scripts/agent-utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,13 @@ export function withWrite<T>(args: Argv<T>) {
173173
.default('write', false);
174174
}
175175

176+
export function withAppend<T>(args: Argv<T>) {
177+
return args
178+
.describe('append', 'Write only new keys to file (preserves existing keys)')
179+
.boolean('append')
180+
.default('append', false);
181+
}
182+
176183
export function withChains<T>(args: Argv<T>, chainOptions?: ChainName[]) {
177184
return (
178185
args

typescript/infra/scripts/funding/calculate-relayer-daily-burn.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import {
2727
portForwardPrometheusServer,
2828
} from '../../src/infrastructure/monitoring/prometheus.js';
2929
import { fetchLatestGCPSecret } from '../../src/utils/gcloud.js';
30-
import { writeAndFormatJsonAtPath } from '../../src/utils/utils.js';
31-
import { withSkipReview } from '../agent-utils.js';
30+
import { writeJsonWithAppendMode } from '../../src/utils/utils.js';
31+
import { withAppend, withSkipReview } from '../agent-utils.js';
3232

3333
const tokenPrices: ChainMap<string> = rawTokenPrices;
3434
const currentDailyRelayerBurn: ChainMap<number> = rawDailyRelayerBurn;
@@ -44,8 +44,9 @@ const MIN_BURN_INCREASE_FACTOR = 0.05; // burn should be at least 5% higher than
4444
const LOW_PROPOSED_BURN_FACTOR = 0.5; // proposed burn should be at least 50% lower than current to initiate user review
4545

4646
async function main() {
47-
const { skipReview } = await withSkipReview(yargs(process.argv.slice(2)))
48-
.argv;
47+
const { skipReview, append } = await withAppend(
48+
withSkipReview(yargs(process.argv.slice(2))),
49+
).argv;
4950

5051
validateTokenPrices();
5152

@@ -61,7 +62,7 @@ async function main() {
6162

6263
burnData = sortThresholds(burnData);
6364

64-
writeBurnDataToFile(burnData);
65+
writeBurnDataToFile(burnData, append);
6566
}
6667

6768
function validateTokenPrices() {
@@ -326,10 +327,10 @@ async function getSealevelDomainIds(): Promise<ChainMap<string>> {
326327
return sealevelDomainIds;
327328
}
328329

329-
function writeBurnDataToFile(burnData: ChainMap<number>) {
330+
function writeBurnDataToFile(burnData: ChainMap<number>, append: boolean) {
330331
try {
331332
rootLogger.info('Writing daily burn data to file..');
332-
writeAndFormatJsonAtPath(DAILY_BURN_PATH, burnData);
333+
writeJsonWithAppendMode(DAILY_BURN_PATH, burnData, append);
333334
rootLogger.info('Daily burn data written to file.');
334335
} catch (err) {
335336
rootLogger.error('Error writing daily burn data to file:', err);

typescript/infra/scripts/helloworld/kathy.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,11 @@ async function sendMessage(
407407

408408
const sendAndConfirmMsg = async () => {
409409
const originProtocol = app.metadata(origin).protocol;
410-
const sender = keys[origin].addressForProtocol(originProtocol);
410+
const bech32Prefix = app.metadata(origin).bech32Prefix;
411+
const sender = keys[origin].addressForProtocol(
412+
originProtocol,
413+
bech32Prefix,
414+
);
411415
if (!sender) {
412416
throw new Error(
413417
`No sender address found for chain ${origin} and protocol ${originProtocol}`,

typescript/infra/scripts/keys/get-key-addresses.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,61 @@
1+
import prompts from 'prompts';
2+
3+
import { ProtocolType } from '../../../utils/dist/types.js';
4+
import { getChain } from '../../config/registry.js';
15
import { getAllCloudAgentKeys } from '../../src/agents/key-utils.js';
26
import { getArgs, withContext, withProtocol } from '../agent-utils.js';
37
import { getConfigsBasedOnArgs } from '../core-utils.js';
48

9+
function getKeyArgs() {
10+
return withProtocol(withContext(getArgs()))
11+
.alias('p', 'protocol')
12+
.option('bech32Prefix', {
13+
type: 'string',
14+
description: 'The bech32 prefix for the Cosmos address',
15+
})
16+
.alias('b', 'bech32Prefix');
17+
}
18+
519
async function main() {
6-
const argv = await withProtocol(withContext(getArgs())).argv;
20+
const argv = await getKeyArgs().argv;
21+
const { agentConfig, envConfig } = await getConfigsBasedOnArgs(argv);
722

8-
const { agentConfig } = await getConfigsBasedOnArgs(argv);
23+
if (argv.protocol === 'cosmos' || argv.protocol === 'cosmosnative') {
24+
if (!argv.bech32Prefix) {
25+
const bech32PrefixMap = envConfig.supportedChainNames.reduce<
26+
Record<string, string>
27+
>((acc, chainName) => {
28+
const chain = getChain(chainName);
29+
if (
30+
chain &&
31+
(chain.protocol === ProtocolType.Cosmos ||
32+
chain.protocol === ProtocolType.CosmosNative) &&
33+
chain.bech32Prefix
34+
) {
35+
acc[chainName] = chain.bech32Prefix;
36+
}
37+
return acc;
38+
}, {});
39+
40+
const response = await prompts({
41+
type: 'select',
42+
name: 'bech32Prefix',
43+
message: 'Select the bech32 prefix for Cosmos address:',
44+
choices: Object.entries(bech32PrefixMap).map(([chainName, prefix]) => ({
45+
title: chainName,
46+
value: prefix,
47+
})),
48+
});
49+
argv.bech32Prefix = response.bech32Prefix;
50+
}
51+
}
952

1053
const keys = getAllCloudAgentKeys(agentConfig);
1154
const keyInfoPromises = keys.map(async (key) => {
1255
let address = undefined;
1356
try {
1457
await key.fetch();
15-
address = key.addressForProtocol(argv.protocol);
58+
address = key.addressForProtocol(argv.protocol, argv.bech32Prefix);
1659
} catch (e) {
1760
// Swallow error
1861
console.error('Error getting address', { key: key.identifier, e });

typescript/infra/scripts/print-gas-prices.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Provider } from '@ethersproject/providers';
22
import { ethers } from 'ethers';
3+
import path from 'path';
34

45
import {
56
ChainMap,
@@ -22,12 +23,15 @@ import {
2223
getSafeNumericValue,
2324
updatePriceIfNeeded,
2425
} from '../src/config/gas-oracle.js';
25-
import { writeAndFormatJsonAtPath } from '../src/utils/utils.js';
26+
import { getInfraPath, writeJsonWithAppendMode } from '../src/utils/utils.js';
2627

27-
import { getArgs, withWrite } from './agent-utils.js';
28+
import { getArgs, withAppend, withWrite } from './agent-utils.js';
2829

2930
const gasPricesFilePath = (environment: DeployEnvironment) => {
30-
return `config/environments/${environment}/gasPrices.json`;
31+
return path.join(
32+
getInfraPath(),
33+
`config/environments/${environment}/gasPrices.json`,
34+
);
3135
};
3236

3337
// Helper function to extract numeric amount from GasPriceConfig
@@ -45,7 +49,8 @@ const createDefaultGasPrice = (
4549
});
4650

4751
async function main() {
48-
const { environment, write } = await withWrite(getArgs()).argv;
52+
const { environment, write, append } = await withAppend(withWrite(getArgs()))
53+
.argv;
4954
const { registry, supportedChainNames, gasPrices } =
5055
environment === 'mainnet3'
5156
? {
@@ -94,10 +99,9 @@ async function main() {
9499
),
95100
);
96101

97-
if (write) {
102+
if (write || append) {
98103
const outFile = gasPricesFilePath(environment);
99-
console.log(`Writing gas prices to ${outFile}`);
100-
writeAndFormatJsonAtPath(outFile, prices);
104+
await writeJsonWithAppendMode(outFile, prices, append);
101105
} else {
102106
console.log(JSON.stringify(prices, null, 2));
103107
}

typescript/infra/scripts/print-token-prices.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import chalk from 'chalk';
2+
import path from 'path';
23

34
import { ChainMap, ChainMetadata } from '@hyperlane-xyz/sdk';
45
import { objMap, pick } from '@hyperlane-xyz/utils';
@@ -16,9 +17,9 @@ import {
1617
getSafeNumericValue,
1718
shouldUpdatePrice,
1819
} from '../src/config/gas-oracle.js';
19-
import { writeAndFormatJsonAtPath } from '../src/utils/utils.js';
20+
import { getInfraPath, writeJsonWithAppendMode } from '../src/utils/utils.js';
2021

21-
import { getArgs, withWrite } from './agent-utils.js';
22+
import { getArgs, withAppend, withWrite } from './agent-utils.js';
2223

2324
const CURRENCY = 'usd';
2425

@@ -29,7 +30,10 @@ const DEFAULT_PRICE = {
2930
};
3031

3132
const tokenPricesFilePath = (environment: DeployEnvironment) => {
32-
return `config/environments/${environment}/tokenPrices.json`;
33+
return path.join(
34+
getInfraPath(),
35+
`config/environments/${environment}/tokenPrices.json`,
36+
);
3337
};
3438

3539
// Helper function to get new price with proper fallback logic
@@ -50,7 +54,8 @@ const getNewTokenPrice = (
5054
};
5155

5256
async function main() {
53-
const { environment, write } = await withWrite(getArgs()).argv;
57+
const { environment, write, append } = await withAppend(withWrite(getArgs()))
58+
.argv;
5459

5560
const { registry, supportedChainNames } =
5661
environment === 'mainnet3'
@@ -103,10 +108,9 @@ async function main() {
103108
: prevPrice.toString();
104109
});
105110

106-
if (write) {
111+
if (write || append) {
107112
const outFile = tokenPricesFilePath(environment);
108-
console.log(`Writing token prices to ${outFile}`);
109-
writeAndFormatJsonAtPath(outFile, prices);
113+
await writeJsonWithAppendMode(outFile, prices, append);
110114
} else {
111115
console.log(JSON.stringify(prices, null, 2));
112116
}

typescript/infra/src/agents/gcp.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ export class AgentGCPKey extends CloudAgentKey {
144144
return this.remoteKey.address;
145145
}
146146

147-
addressForProtocol(protocol: ProtocolType): string | undefined {
147+
addressForProtocol(
148+
protocol: ProtocolType,
149+
bech32Prefix?: string,
150+
): string | undefined {
148151
this.requireFetched();
149152
this.logger.debug(`Getting address for protocol: ${protocol}`);
150153

@@ -167,9 +170,10 @@ export class AgentGCPKey extends CloudAgentKey {
167170
const encodedPubkey = encodeSecp256k1Pubkey(
168171
new Uint8Array(Buffer.from(strip0x(compressedPubkey), 'hex')),
169172
);
170-
// TODO support other prefixes?
171-
// https://cosmosdrops.io/en/tools/bech32-converter is useful for converting to other prefixes.
172-
return pubkeyToAddress(encodedPubkey, 'celestia');
173+
if (!bech32Prefix) {
174+
throw new Error('Bech32 prefix is required for Cosmos address');
175+
}
176+
return pubkeyToAddress(encodedPubkey, bech32Prefix);
173177
}
174178
default:
175179
this.logger.debug(`Unsupported protocol: ${protocol}`);

typescript/infra/src/agents/keys.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ export abstract class BaseAgentKey {
2323

2424
// By default, only Ethereum keys are supported. Subclasses may override
2525
// this to support other protocols.
26-
addressForProtocol(protocol: ProtocolType): string | undefined {
26+
addressForProtocol(
27+
protocol: ProtocolType,
28+
_bech32Prefix?: string,
29+
): string | undefined {
2730
if (protocol === ProtocolType.Ethereum) {
2831
return this.address;
2932
}

typescript/infra/src/utils/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@ export async function writeAndFormatJsonAtPath(filepath: string, obj: any) {
173173
await formatFileWithPrettier(filepath);
174174
}
175175

176+
/**
177+
* Write JSON to file, optionally preserving existing values for keys.
178+
* If appendMode is true, keeps values from existingData for existing keys, adds new keys from newData.
179+
*/
180+
export async function writeJsonWithAppendMode(
181+
filepath: string,
182+
newData: Record<string, any>,
183+
appendMode: boolean,
184+
) {
185+
let data = newData;
186+
if (appendMode && fs.existsSync(filepath)) {
187+
const existing = readJSONAtPath(filepath);
188+
data = Object.fromEntries(
189+
Object.keys(newData).map((key) => [key, existing[key] ?? newData[key]]),
190+
);
191+
}
192+
await writeAndFormatJsonAtPath(filepath, data);
193+
}
194+
176195
/**
177196
* Gets the monorepo root directory
178197
*/

0 commit comments

Comments
 (0)