Skip to content
This repository has been archived by the owner on May 28, 2022. It is now read-only.

Commit

Permalink
feat: governance utils
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-carroll committed Jan 26, 2022
1 parent 15006c8 commit 47baae6
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 67 deletions.
62 changes: 62 additions & 0 deletions typescript/nomad-deploy/src/governance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { NomadContext } from '@nomad-xyz/sdk';
import { CallBatch } from '@nomad-xyz/sdk/nomad';
import { getBatch, writeBatch } from './utils';
import { DeployEnvironment } from '../chain';

// execute a batch on the Governor Chain
export async function executeBatch(
batch: CallBatch,
environment: DeployEnvironment,
reason: string,
): Promise<void> {
// persist the call batch to a local file
await writeBatch(batch, environment, reason);
// send the batch transaction,
// either directly on-chain or to gnosis safe
if (environment === 'dev') {
// in dev, execute the batch directly
console.log('Sending governance transaction...');
const txResponse = await batch.execute();
const receipt = await txResponse.wait();
console.log('Governance tx mined!! ', receipt.transactionHash);
} else {
// TODO: send to gnosis safe directly
}
}

// execute the remote Call Batches on each non-Governor chain
export async function executeRemoteBatches(
sdk: NomadContext,
environment: string,
reason: string,
) {
const batch = await getBatch(sdk, environment, reason);
// ensure that all batch hashes have landed on each remote domain
await batch.waitAll();
console.log('All Batch Hashes Ready.');
// for each domain, execute the batch calls
for (const domain of batch.domains) {
const domainName = sdk.resolveDomainName(domain);
console.log(`Executing Batch on ${domainName}...`);
const tx = await batch.executeDomain(domain);
const receipt = await tx.wait();
console.log(`Executed Batch on ${domainName}:`, receipt.transactionHash);
}
}

// log the progress of batches on all domains
export async function waitBatches(
sdk: NomadContext,
environment: string,
reason: string,
): Promise<void[]> {
const batch = await getBatch(sdk, environment, reason);
return Promise.all(
batch.domains.map(async (domain: number) => {
const domainName = sdk.resolveDomainName(domain);
console.log(`Waiting for batch to be received on ${domainName}...`);
await batch.waitDomain(domain);
console.log(`Batch received on ${domainName}!`);
}),
);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,93 @@
import { NomadDomain } from '@nomad-xyz/sdk/nomad';
import { CallBatch, RemoteContents, NomadContext, NomadDomain } from '@nomad-xyz/sdk/nomad';
import { BridgeDeploy } from '../bridge/BridgeDeploy';
import { CoreDeploy } from '../core/CoreDeploy';
import {
isValidEnvironment,
parseFile,
VALID_ENVIRONMENTS,
} from '../verification/readDeployOutput';
import fs from 'fs';
import { DeployEnvironment } from "../chain";

// instantiate a stored call batch
export async function getBatch(sdk: NomadContext, environment: string, reason: string): Promise<CallBatch> {
const dir = getPathToBatchOutput(environment, reason);
const calls = parseFile(dir, "unbuilt.json");
return CallBatch.fromJSON(sdk, calls);
}

// write the batch to a local file
export async function writeBatch(batch: CallBatch, environment: DeployEnvironment, reason: string): Promise<void> {
console.log("Writing governance transaction to file.");
// construct unbuilt transaction contents
const remote: RemoteContents = {};
const domains = batch.domains;
domains.map((domain: number) => {
remote[domain.toString()] = batch.remote.get(domain)!;
})
const unbuiltStr = JSON.stringify(
{local: batch.local, remote},
null,
2,
);
// construct built transaction
const built = await batch.build();
const builtStr = JSON.stringify(built, null, 2);
// get the directory where the governance action will be written
const dir = getPathToBatchOutput(environment, reason);
// write to file to persist governance actions for posterity
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(`${dir}/built.json`, builtStr);
fs.writeFileSync(`${dir}/unbuilt.json`, unbuiltStr);
console.log("Done!");
}

// get the path for a call batch to be output
export function getPathToBatchOutput(environment: string, reason: string) {
if (!isValidEnvironment) {
throw new Error(
`${environment} is not a valid environment. Please choose from ${JSON.stringify(
VALID_ENVIRONMENTS,
null,
2,
)}`,
);
}
let folder;
if (environment == 'staging') {
folder = 'staging';
} else if (environment == 'prod') {
folder = 'mainnet';
} else {
folder = 'development';
}
return `../../governance/${folder}/${reason}`;
}

// TODO: everything below this is in question -- consider deleting or moving into local utils
export function deploysToSDK(
core: CoreDeploy,
bridge: BridgeDeploy,
safeService?: string,
): NomadDomain {
return {
id: core.chain.domain,
name: core.chain.name,
bridgeRouter: bridge.contracts.bridgeRouter!.proxy.address,
tokenRegistry: bridge.contracts.tokenRegistry!.proxy.address,
ethHelper: bridge.contracts.ethHelper?.address,
home: core.contracts.home!.proxy.address,
replicas: Object.entries(core.contracts.replicas).map(
([domain, replica]) => ({
domain: parseInt(domain),
address: replica.proxy.address,
}),
),
governanceRouter: core.contracts.governance!.proxy.address,
xAppConnectionManager: core.contracts.xAppConnectionManager!.address,
safeService,
};
}

/**
* Structure that allows to poll an async block
Expand Down Expand Up @@ -36,9 +118,9 @@ export class Waiter<T> {
* where `T` is callback's return and second item is a `success` boolean
*/
constructor(
callback: () => Promise<T | undefined>,
timeoutMs: number,
retryMs: number,
callback: () => Promise<T | undefined>,
timeoutMs: number,
retryMs: number,
) {
this.resolve = undefined;
this.reject = undefined;
Expand Down Expand Up @@ -90,63 +172,3 @@ export class Waiter<T> {
return await this.promise;
}
}

// TODO: bring it into good shape and move somewhere else. Also not sure if we should pass safe service as argument
export function deploysToSDK(
core: CoreDeploy,
bridge: BridgeDeploy,
safeService?: string,
): NomadDomain {
return {
id: core.chain.domain,
name: core.chain.name,
bridgeRouter: bridge.contracts.bridgeRouter!.proxy.address,
tokenRegistry: bridge.contracts.tokenRegistry!.proxy.address,
ethHelper: bridge.contracts.ethHelper?.address,
home: core.contracts.home!.proxy.address,
replicas: Object.entries(core.contracts.replicas).map(
([domain, replica]) => ({
domain: parseInt(domain),
address: replica.proxy.address,
}),
),
governanceRouter: core.contracts.governance!.proxy.address,
xAppConnectionManager: core.contracts.xAppConnectionManager!.address,
safeService,
};
}

export function writeBatchOutput(
builtStr: string,
unbuiltStr: string,
environment: string,
) {
let dir = getPathToBatchOutput(environment);

fs.mkdirSync(dir, { recursive: true });

fs.writeFileSync(`${dir}/built.json`, builtStr);

fs.writeFileSync(`${dir}/unbuilt.json`, unbuiltStr);
}

export function getPathToBatchOutput(environment: string) {
if (!isValidEnvironment) {
throw new Error(
`${environment} is not a valid environment. Please choose from ${JSON.stringify(
VALID_ENVIRONMENTS,
null,
2,
)}`,
);
}
let folder;
if (environment == 'staging') {
folder = 'staging';
} else if (environment == 'prod') {
folder = 'mainnet';
} else {
folder = 'development';
}
return `../../governance/${folder}`;
}
1 change: 1 addition & 0 deletions typescript/nomad-deploy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * as core from './core';
export * as bridge from './bridge';
export * as incremental from './incremental';

export * as governance from './governance';
export * as deploy from './deploy';
export * as chain from './chain';
export * as contracts from './contracts';
Expand Down
16 changes: 13 additions & 3 deletions typescript/nomad-deploy/src/verification/readDeployOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export function getVerificationInputFromDeploy(
* @param fileSuffix target file suffix to parse ("config", "contracts", "verification")
* */
export function parseFileFromDeploy(

path: string,
network: string,
fileSuffix: string,
Expand All @@ -121,10 +122,19 @@ export function parseFileFromDeploy(
`No ${fileSuffix} files found for ${network} at ${path}/${targetFileName}`,
);
}
return parseFile(path, targetFileName);
}

/*
* @notice Return the JSON-parsed file
* from the given file name
* and directory path
* @param path relative path to the file
* @param fileName the file name
* */
export function parseFile(path: string, fileName: string) {
const fileString: string = fs
.readFileSync(`${path}/${targetFileName}`)
.toString();

.readFileSync(`${path}/${fileName}`)
.toString();
return JSON.parse(fileString);
}
1 change: 1 addition & 0 deletions typescript/nomad-deploy/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
"./src/bridge/*.ts",
"./src/verification/*.ts",
"./src/incremental/*.ts",
"./src/governance/**/*.ts"
]
}

0 comments on commit 47baae6

Please sign in to comment.