-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdeploy-campaign.ts
156 lines (134 loc) · 4.43 KB
/
deploy-campaign.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import {
ICampaignArgs,
ICampaignState,
TLogger,
IMissionInstances,
IContractV6, IDeployCampaignConfig, IContractState,
} from "./types";
import { HardhatDeployer } from "../deployer/hardhat-deployer";
import { ITenderlyContractData, TDeployMissionCtor } from "../missions/types";
import { BaseDeployMission } from "../missions/base-deploy-mission";
import { MongoDBAdapter } from "../db/mongo-adapter/mongo-adapter";
import { IHardhatBase, ISignerBase } from "../deployer/types";
import { makeCampaignProxy } from "./proxy";
export class DeployCampaign <
H extends IHardhatBase,
S extends ISignerBase,
C extends IDeployCampaignConfig<S>,
St extends IContractState,
> {
state : ICampaignState<H, S, C, St>;
deployer : HardhatDeployer<H, S>;
dbAdapter : MongoDBAdapter;
logger : TLogger;
config : C;
// TODO dep: improve typing here so that methods of each contract type are resolved in Mission classes!
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[name : string | symbol] : any;
constructor ({
missions,
deployer,
dbAdapter,
logger,
config,
} : ICampaignArgs<H, S, C, St>) {
this.state = {
missions,
instances: {},
contracts: {} as St,
};
this.deployer = deployer;
this.dbAdapter = dbAdapter;
this.logger = logger;
this.config = config;
const campaignProxy = makeCampaignProxy(this);
// instantiate all missions
this.state.instances = missions.reduce(
(acc : IMissionInstances<H, S, C, St>, mission : TDeployMissionCtor<H, S, C, St>) => {
const instance = new mission({
campaign: campaignProxy,
logger,
config,
});
acc[instance.instanceName] = instance;
return acc;
},
{}
);
this.logger.info("Deploy Campaign initialized.");
return campaignProxy;
}
async execute () {
const {
env,
srcChainName,
} = this.config;
await this.dbAdapter.configureVersioning();
this.logger.info(
"Deploy Campaign execution started. " +
// eslint-disable-next-line max-len
`ENV: ${env}. CHAIN: ${srcChainName}. DB NAME: ${this.dbAdapter.dbName}. DB V: ${this.dbAdapter.versioner.curDbVersion}.`
);
await Object.values(this.state.instances).reduce(
async (
acc : Promise<void>,
missionInstance : BaseDeployMission<H, S, C, St>,
) : Promise<void> => {
await acc;
return missionInstance.execute();
},
Promise.resolve()
);
if (this.config.postDeploy.verifyContracts) {
await this.verify();
}
if (this.config.postDeploy.monitorContracts) {
await this.monitor();
}
// eslint-disable-next-line max-len
this.logger.info(`Deploy Campaign execution finished successfully under DB Version: ${this.dbAdapter.versioner.curDbVersion}.`);
}
updateStateContract (instanceName : string, contractName : string, contract : IContractV6) {
// TODO: can we improve this?
(this.state.contracts as IContractState)[instanceName] = contract;
this.logger.debug(`Data of deployed contract '${contractName}' is added to Campaign state at '${instanceName}'.`);
}
async verify () {
return Object.values(this.state.instances).reduce(
async (
acc : Promise<void>,
missionInstance : BaseDeployMission<H, S, C, St>,
) => {
await acc;
return missionInstance.verify();
},
Promise.resolve()
);
}
async monitor () {
this.logger.info("Pushing contracts to Tenderly...");
const contracts = await Object.values(this.state.instances).reduce(
async (
acc : Promise<Array<ITenderlyContractData>>,
missionInstance : BaseDeployMission<H, S, C, St>,
) : Promise<Array<ITenderlyContractData>> => {
const newAcc = await acc;
const data = await missionInstance.getMonitoringData();
return [...newAcc, ...data];
},
Promise.resolve([])
);
try {
const response = await this.deployer.tenderlyPush(contracts);
this.logger.info(
`Tenderly push finished successfully for Project ${this.config.postDeploy.tenderlyProjectSlug}
with data: ${JSON.stringify(response, null, "\t")}`
);
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
} catch (e : any) {
this.logger.error("Tenderly push failed.");
this.logger.error(e.message);
this.logger.debug("Continuing...");
}
}
}