Skip to content

Commit b9dbd54

Browse files
authored
[contract-manager] General improvements (#1024)
* Better return types for transaction execution functions * Use new type for passing PrivateKey * Small typing improvements * Stricter liniting * Rename edge to beta for DeploymentType * Reduce any usage across the contract manager * Fix explicit any linting warnings
1 parent f316a51 commit b9dbd54

File tree

20 files changed

+318
-209
lines changed

20 files changed

+318
-209
lines changed

contract_manager/.eslintrc.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
root: true,
3+
parser: "@typescript-eslint/parser",
4+
plugins: ["@typescript-eslint"],
5+
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
6+
};

contract_manager/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
],
1111
"scripts": {
1212
"build": "tsc",
13-
"shell": "ts-node ./src/shell.ts"
13+
"shell": "ts-node ./src/shell.ts",
14+
"lint": "eslint src/"
1415
},
1516
"author": "",
1617
"license": "Apache-2.0",

contract_manager/scripts/update_pricefeed.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import yargs from "yargs";
22
import { hideBin } from "yargs/helpers";
3-
import { DefaultStore } from "../src";
3+
import { DefaultStore, toPrivateKey } from "../src";
44
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
55

66
const parser = yargs(hideBin(process.argv))
@@ -43,9 +43,12 @@ async function main() {
4343
argv.endpoint || defaultEndpoint
4444
);
4545
const vaas = await priceService.getLatestVaas(argv["feed-id"] as string[]);
46-
await contract.executeUpdatePriceFeed(
47-
argv["private-key"],
48-
vaas.map((vaa) => Buffer.from(vaa, "base64"))
46+
const privateKey = toPrivateKey(argv["private-key"]);
47+
console.log(
48+
await contract.executeUpdatePriceFeed(
49+
privateKey,
50+
vaas.map((vaa) => Buffer.from(vaa, "base64"))
51+
)
4952
);
5053
}
5154

contract_manager/src/base.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
import { DataSource } from "xc_admin_common";
22
import { Chain } from "./chains";
33

4+
export interface TxResult {
5+
id: string;
6+
info: unknown; // chain specific info
7+
}
8+
9+
export type DeploymentType = "stable" | "beta";
10+
export type PrivateKey = string & { __type: "PrivateKey" };
11+
function checkIsPrivateKey(key: string): asserts key is PrivateKey {
12+
if (Buffer.from(key, "hex").length !== 32)
13+
throw new Error("Invalid private key, must be 64 hex chars");
14+
}
15+
export function toPrivateKey(key: string): PrivateKey {
16+
checkIsPrivateKey(key);
17+
return key;
18+
}
19+
20+
export type KeyValueConfig = Record<string, string | number | boolean>;
21+
422
export abstract class Storable {
523
/**
624
* Returns the unique identifier for this object
@@ -17,7 +35,7 @@ export abstract class Storable {
1735
* Returns a JSON representation of this object. It should be possible to
1836
* reconstruct the object from the JSON using the fromJson method.
1937
*/
20-
abstract toJson(): any;
38+
abstract toJson(): KeyValueConfig;
2139
}
2240

2341
export interface Price {
@@ -75,31 +93,31 @@ export abstract class Contract extends Storable {
7593
* @param vaas an array of VAAs containing price update messages to execute
7694
*/
7795
abstract executeUpdatePriceFeed(
78-
senderPrivateKey: string,
96+
senderPrivateKey: PrivateKey,
7997
vaas: Buffer[]
80-
): Promise<any>;
98+
): Promise<TxResult>;
8199

82100
/**
83101
* Executes the governance instruction contained in the VAA using the sender credentials
84102
* @param senderPrivateKey private key of the sender in hex format without 0x prefix
85103
* @param vaa the VAA to execute
86104
*/
87105
abstract executeGovernanceInstruction(
88-
senderPrivateKey: string,
106+
senderPrivateKey: PrivateKey,
89107
vaa: Buffer
90-
): Promise<any>;
108+
): Promise<TxResult>;
91109

92110
/**
93111
* Returns the single data source that this contract accepts governance messages from
94112
*/
95113
abstract getGovernanceDataSource(): Promise<DataSource>;
96114
}
97115

98-
export function getDefaultDeploymentConfig(deploymentType: "stable" | "edge"): {
116+
export function getDefaultDeploymentConfig(deploymentType: DeploymentType): {
99117
dataSources: DataSource[];
100118
governanceDataSource: DataSource;
101119
wormholeConfig: {
102-
governanceChainId: Number;
120+
governanceChainId: number;
103121
governanceContract: string; // 32 byte address in 64 char hex format
104122
initialGuardianSet: string[]; // 20 byte addresses in 40 char hex format
105123
};
@@ -135,7 +153,7 @@ export function getDefaultDeploymentConfig(deploymentType: "stable" | "edge"): {
135153
initialGuardianSet: ["58cc3ae5c097b213ce3c81979e1b9f9570746aa5"],
136154
},
137155
};
138-
else if (deploymentType === "edge")
156+
else if (deploymentType === "beta")
139157
return {
140158
dataSources: [
141159
{

contract_manager/src/chains.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { Storable } from "./base";
1+
import { KeyValueConfig, PrivateKey, Storable } from "./base";
22
import {
33
ChainName,
4-
CHAINS,
54
SetFee,
65
CosmosUpgradeContract,
76
EvmUpgradeContract,
@@ -22,6 +21,10 @@ import {
2221
} from "@pythnetwork/cosmwasm-deploy-tools";
2322
import { Network } from "@injectivelabs/networks";
2423

24+
export type ChainConfig = Record<string, string> & {
25+
mainnet: boolean;
26+
id: string;
27+
};
2528
export abstract class Chain extends Storable {
2629
public wormholeChainName: ChainName;
2730

@@ -92,15 +95,15 @@ export abstract class Chain extends Storable {
9295
* Returns the payload for a governance contract upgrade instruction for contracts deployed on this chain
9396
* @param upgradeInfo based on the contract type, this can be a contract address, codeId, package digest, etc.
9497
*/
95-
abstract generateGovernanceUpgradePayload(upgradeInfo: any): Buffer;
98+
abstract generateGovernanceUpgradePayload(upgradeInfo: unknown): Buffer;
9699
}
97100

98101
export class GlobalChain extends Chain {
99-
static type: string = "GlobalChain";
102+
static type = "GlobalChain";
100103
constructor() {
101104
super("global", true, "unset");
102105
}
103-
generateGovernanceUpgradePayload(upgradeInfo: any): Buffer {
106+
generateGovernanceUpgradePayload(): Buffer {
104107
throw new Error(
105108
"Can not create a governance message for upgrading contracts on all chains!"
106109
);
@@ -110,7 +113,7 @@ export class GlobalChain extends Chain {
110113
return GlobalChain.type;
111114
}
112115

113-
toJson(): any {
116+
toJson(): KeyValueConfig {
114117
return {
115118
id: this.id,
116119
wormholeChainName: this.wormholeChainName,
@@ -121,7 +124,7 @@ export class GlobalChain extends Chain {
121124
}
122125

123126
export class CosmWasmChain extends Chain {
124-
static type: string = "CosmWasmChain";
127+
static type = "CosmWasmChain";
125128

126129
constructor(
127130
id: string,
@@ -135,7 +138,7 @@ export class CosmWasmChain extends Chain {
135138
super(id, mainnet, wormholeChainName);
136139
}
137140

138-
static fromJson(parsed: any): CosmWasmChain {
141+
static fromJson(parsed: ChainConfig): CosmWasmChain {
139142
if (parsed.type !== CosmWasmChain.type) throw new Error("Invalid type");
140143
return new CosmWasmChain(
141144
parsed.id,
@@ -148,7 +151,7 @@ export class CosmWasmChain extends Chain {
148151
);
149152
}
150153

151-
toJson(): any {
154+
toJson(): KeyValueConfig {
152155
return {
153156
endpoint: this.endpoint,
154157
id: this.id,
@@ -174,7 +177,7 @@ export class CosmWasmChain extends Chain {
174177
return new CosmosUpgradeContract(this.wormholeChainName, codeId).encode();
175178
}
176179

177-
async getExecutor(privateKey: string) {
180+
async getExecutor(privateKey: PrivateKey) {
178181
if (this.getId().indexOf("injective") > -1) {
179182
return InjectiveExecutor.fromPrivateKey(
180183
this.isMainnet() ? Network.Mainnet : Network.Testnet,
@@ -190,7 +193,7 @@ export class CosmWasmChain extends Chain {
190193
}
191194

192195
export class SuiChain extends Chain {
193-
static type: string = "SuiChain";
196+
static type = "SuiChain";
194197

195198
constructor(
196199
id: string,
@@ -201,7 +204,7 @@ export class SuiChain extends Chain {
201204
super(id, mainnet, wormholeChainName);
202205
}
203206

204-
static fromJson(parsed: any): SuiChain {
207+
static fromJson(parsed: ChainConfig): SuiChain {
205208
if (parsed.type !== SuiChain.type) throw new Error("Invalid type");
206209
return new SuiChain(
207210
parsed.id,
@@ -211,7 +214,7 @@ export class SuiChain extends Chain {
211214
);
212215
}
213216

214-
toJson(): any {
217+
toJson(): KeyValueConfig {
215218
return {
216219
id: this.id,
217220
wormholeChainName: this.wormholeChainName,
@@ -238,7 +241,7 @@ export class SuiChain extends Chain {
238241
}
239242

240243
export class EvmChain extends Chain {
241-
static type: string = "EvmChain";
244+
static type = "EvmChain";
242245

243246
constructor(
244247
id: string,
@@ -250,7 +253,7 @@ export class EvmChain extends Chain {
250253
super(id, mainnet, wormholeChainName);
251254
}
252255

253-
static fromJson(parsed: any): EvmChain {
256+
static fromJson(parsed: ChainConfig & { networkId: number }): EvmChain {
254257
if (parsed.type !== EvmChain.type) throw new Error("Invalid type");
255258
return new EvmChain(
256259
parsed.id,
@@ -277,7 +280,7 @@ export class EvmChain extends Chain {
277280
return new EvmSetWormholeAddress(this.wormholeChainName, address).encode();
278281
}
279282

280-
toJson(): any {
283+
toJson(): KeyValueConfig {
281284
return {
282285
id: this.id,
283286
wormholeChainName: this.wormholeChainName,
@@ -311,10 +314,10 @@ export class EvmChain extends Chain {
311314
* @returns the address of the deployed contract
312315
*/
313316
async deploy(
314-
privateKey: string,
315-
abi: any,
317+
privateKey: PrivateKey,
318+
abi: any, // eslint-disable-line @typescript-eslint/no-explicit-any
316319
bytecode: string,
317-
deployArgs: any[]
320+
deployArgs: any[] // eslint-disable-line @typescript-eslint/no-explicit-any
318321
): Promise<string> {
319322
const web3 = new Web3(this.getRpcUrl());
320323
const signer = web3.eth.accounts.privateKeyToAccount(privateKey);
@@ -375,7 +378,7 @@ export class AptosChain extends Chain {
375378
return AptosChain.type;
376379
}
377380

378-
toJson(): any {
381+
toJson(): KeyValueConfig {
379382
return {
380383
id: this.id,
381384
wormholeChainName: this.wormholeChainName,
@@ -385,7 +388,7 @@ export class AptosChain extends Chain {
385388
};
386389
}
387390

388-
static fromJson(parsed: any): AptosChain {
391+
static fromJson(parsed: ChainConfig): AptosChain {
389392
if (parsed.type !== AptosChain.type) throw new Error("Invalid type");
390393
return new AptosChain(
391394
parsed.id,

0 commit comments

Comments
 (0)