Files
sashimono/examples/crawler/contract-instance-manager.js
2022-06-26 23:58:04 +05:30

117 lines
3.5 KiB
JavaScript

const fs = require('fs').promises;
const os = require('os');
const path = require('path');
const bson = require('bson');
const HotPocket = require('hotpocket-js-client');
const uploadTimeout = 30000;
class ContractInstanceManager {
#ownerPrivKeyHex;
#instancePubKeyHex;
#ip;
#userPort;
#contractId;
#contractBundle;
constructor(ownerPrivKeyHex, instancePubKeyHex, ip, userPort, contractId, contractBundle) {
this.#ownerPrivKeyHex = ownerPrivKeyHex;
this.#instancePubKeyHex = instancePubKeyHex;
this.#ip = ip;
this.#userPort = userPort;
this.#contractId = contractId;
this.#contractBundle = contractBundle;
}
async deployContract() {
const tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), 'evncrawler'));
try {
const hpc = await this.#getHotPocketConnection();
await this.#uploadBundle(hpc, this.#contractBundle);
await hpc.close();
}
catch (e) {
throw e;
}
finally {
await fs.rm(tmpdir, { recursive: true, force: true });
}
}
async #getHotPocketConnection() {
const server = `wss://${this.#ip}:${this.#userPort}`
const keys = await HotPocket.generateKeys(this.#ownerPrivKeyHex);
const hpc = await HotPocket.createClient([server], keys, {
contractId: this.#contractId,
trustedServerKeys: [this.#instancePubKeyHex],
protocol: HotPocket.protocols.bson
});
// Establish HotPocket connection.
if (!await hpc.connect()) {
throw `${server} connection failed.`
}
return hpc;
}
async #uploadBundle(hpc, bundleZipFile) {
return new Promise(async (resolve, reject) => {
const uploadTimer = setTimeout(() => reject("Upload timeout."), uploadTimeout);
const failure = (e) => {
clearTimeout(uploadTimer);
reject(e);
}
const success = () => {
console.log("Upload complete");
clearTimeout(uploadTimer);
resolve();
}
// This will get fired when contract sends an output.
hpc.on(HotPocket.events.contractOutput, (r) => {
r.outputs.forEach(output => {
let result;
try {
result = bson.deserialize(output);
}
catch (e) {
failure(e);
}
if (result.type == "uploadResult") {
if (result.status == "ok")
success();
else
failure(`Zip upload failed. reason: ${result.status}`);
}
else {
console.log("Unknown contract output.");
}
});
});
const fileContent = await fs.readFile(bundleZipFile);
console.log("Uploading");
const input = await hpc.submitContractInput(bson.serialize({
type: "upload",
content: fileContent
}));
const submission = await input.submissionStatus;
console.log(submission.status);
if (submission.status != "accepted")
failure("Upload submission failed. reason: " + submission.reason);
})
}
}
module.exports = {
ContractInstanceManager
}