332 lines
8.6 KiB
TypeScript
332 lines
8.6 KiB
TypeScript
// npx pretty-quick
|
|
|
|
const nearAPI = require("near-api-js");
|
|
const BN = require("bn.js");
|
|
const fs = require("fs");
|
|
const fetch = require("node-fetch");
|
|
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
|
|
import { TestLib } from "./testlib";
|
|
const { createHash } = require("crypto");
|
|
|
|
import { ChainId, CHAIN_ID_NEAR } from "@certusone/wormhole-sdk/lib/cjs/utils";
|
|
|
|
function hash(string: any) {
|
|
return createHash("sha256").update(string).digest("hex");
|
|
}
|
|
|
|
function getConfig(env: any) {
|
|
switch (env) {
|
|
case "sandbox":
|
|
case "local":
|
|
return {
|
|
networkId: "sandbox",
|
|
nodeUrl: "http://localhost:3030",
|
|
masterAccount: "test.near",
|
|
wormholeAccount:
|
|
Math.floor(Math.random() * 10000).toString() + "wormhole.test.near",
|
|
tokenAccount:
|
|
Math.floor(Math.random() * 10000).toString() + "token.test.near",
|
|
};
|
|
case "testnet":
|
|
return {
|
|
networkId: "testnet",
|
|
nodeUrl: "https://rpc.testnet.near.org",
|
|
masterAccount: "wormhole.testnet",
|
|
wormholeAccount: "wormhole.wormhole.testnet",
|
|
tokenAccount: "token.wormhole.testnet",
|
|
};
|
|
case "mainnet":
|
|
return {
|
|
networkId: "mainnet",
|
|
nodeUrl: "https://rpc.mainnet.near.org",
|
|
wormholeMasterAccount: "wormhole_crypto.near",
|
|
wormholeAccount: "contract.wormhole_crypto.near",
|
|
portalMasterAccount: "portalbridge.near",
|
|
tokenAccount: "contract.portalbridge.near",
|
|
};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
async function initNear() {
|
|
let e = process.env.NEAR_ENV || "sandbox";
|
|
|
|
let config = getConfig(e);
|
|
let p = process.env.PROD_ENV || "mainnet";
|
|
let prod_config = getConfig(p);
|
|
|
|
let masterKey: any;
|
|
|
|
if (e === "sandbox") {
|
|
// Retrieve the validator key directly in the Tilt environment
|
|
const response = await fetch("http://localhost:3031/validator_key.json");
|
|
|
|
const keyFile = await response.json();
|
|
|
|
masterKey = nearAPI.utils.KeyPair.fromString(
|
|
keyFile.secret_key || keyFile.private_key
|
|
);
|
|
} else {
|
|
masterKey = nearAPI.utils.KeyPair.fromString(process.env.NEAR_PK);
|
|
}
|
|
let masterPubKey = masterKey.getPublicKey();
|
|
|
|
let keyStore = new nearAPI.keyStores.InMemoryKeyStore();
|
|
keyStore.setKey(config.networkId, config.masterAccount, masterKey);
|
|
keyStore.setKey(config.networkId, config.wormholeAccount, masterKey);
|
|
keyStore.setKey(config.networkId, config.tokenAccount, masterKey);
|
|
|
|
let near = await nearAPI.connect({
|
|
deps: {
|
|
keyStore,
|
|
},
|
|
networkId: config.networkId,
|
|
nodeUrl: config.nodeUrl,
|
|
});
|
|
|
|
let masterAccount = new nearAPI.Account(
|
|
near.connection,
|
|
config.masterAccount
|
|
);
|
|
|
|
let prod_near = await nearAPI.connect({
|
|
deps: {
|
|
keyStore,
|
|
},
|
|
networkId: prod_config.networkId,
|
|
nodeUrl: prod_config.nodeUrl,
|
|
});
|
|
|
|
console.log(
|
|
"Finish init NEAR masterAccount: " +
|
|
JSON.stringify(await masterAccount.getAccountBalance())
|
|
);
|
|
|
|
console.log("reading local wasms we want to upgrade to...");
|
|
|
|
const wormholeContract = await fs.readFileSync(
|
|
"artifacts/near_wormhole.wasm"
|
|
);
|
|
const tokenContract = await fs.readFileSync(
|
|
"artifacts/near_token_bridge.wasm"
|
|
);
|
|
|
|
console.log("reading current production code ("+p+") we want to upgrade from..");
|
|
|
|
let wormhole_prod_code;
|
|
if (process.env.WORMHOLE_CONTRACT) {
|
|
console.log("Reading " + process.env.WORMHOLE_CONTRACT);
|
|
wormhole_prod_code = await fs.readFileSync(process.env.WORMHOLE_CONTRACT);
|
|
} else {
|
|
wormhole_prod_code = Buffer.from(
|
|
(
|
|
await prod_near.connection.provider.query({
|
|
request_type: "view_code",
|
|
finality: "final",
|
|
account_id: prod_config.wormholeAccount,
|
|
})
|
|
).code_base64,
|
|
"base64"
|
|
);
|
|
}
|
|
|
|
let token_prod_code;
|
|
|
|
if (process.env.TOKEN_CONTRACT) {
|
|
console.log("Reading " + process.env.TOKEN_CONTRACT);
|
|
token_prod_code = await fs.readFileSync(process.env.TOKEN_CONTRACT);
|
|
} else {
|
|
token_prod_code = Buffer.from(
|
|
(
|
|
await prod_near.connection.provider.query({
|
|
request_type: "view_code",
|
|
finality: "final",
|
|
account_id: prod_config.tokenAccount,
|
|
})
|
|
).code_base64,
|
|
"base64"
|
|
);
|
|
}
|
|
|
|
console.log(
|
|
"Deploying production ("+p+") wormhole contract to " + config.wormholeAccount
|
|
);
|
|
let wormholeAccount = await masterAccount.createAndDeployContract(
|
|
config.wormholeAccount,
|
|
masterKey.getPublicKey(),
|
|
wormhole_prod_code,
|
|
new BN("20000000000000000000000000")
|
|
);
|
|
|
|
await wormholeAccount.functionCall({
|
|
contractId: config.wormholeAccount,
|
|
methodName: "register_emitter",
|
|
args: { emitter: config.tokenAccount },
|
|
attachedDeposit: new BN("30000000000000000000000"),
|
|
gas: new BN("100000000000000"),
|
|
});
|
|
|
|
let tokenAccount: any;
|
|
|
|
console.log("Deploying production ("+p+") token contract to " + config.tokenAccount);
|
|
tokenAccount = await masterAccount.createAndDeployContract(
|
|
config.tokenAccount,
|
|
masterKey.getPublicKey(),
|
|
token_prod_code,
|
|
new BN("20000000000000000000000000")
|
|
);
|
|
|
|
let signers: any[] = [];
|
|
|
|
let vaasToken: any[] = [];
|
|
let vaasNFT: any[] = [];
|
|
|
|
let lines = fs.readFileSync(".env", "utf-8").split("\n");
|
|
|
|
lines.forEach((line: any) => {
|
|
let f = line.split("=");
|
|
if (f[0] === "INIT_SIGNERS") {
|
|
signers = eval(f[1]);
|
|
}
|
|
if (f[0].startsWith("REGISTER_") && f[0].endsWith("TOKEN_BRIDGE_VAA")) {
|
|
vaasToken.push(f[1]);
|
|
} else if (f[0].endsWith("TOKEN_BRIDGE_VAA_REGISTER")) {
|
|
vaasToken.push(f[1]);
|
|
}
|
|
|
|
if (f[0].startsWith("REGISTER_") && f[0].endsWith("NFT_BRIDGE_VAA")) {
|
|
vaasNFT.push(f[1]);
|
|
} else if (
|
|
f[0].endsWith("NFT_BRIDGE_VAA") ||
|
|
f[0].endsWith("NFT_BRIDGE_VAA_REGISTER")
|
|
) {
|
|
vaasNFT.push(f[1]);
|
|
}
|
|
});
|
|
|
|
if (e === "sandbox") {
|
|
let result = await masterAccount.functionCall({
|
|
contractId: config.wormholeAccount,
|
|
methodName: "boot_wormhole",
|
|
args: {
|
|
gset: 0,
|
|
addresses: signers,
|
|
},
|
|
gas: 100000000000000,
|
|
});
|
|
|
|
console.log("Booting up the token bridge");
|
|
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.tokenAccount,
|
|
methodName: "boot_portal",
|
|
args: {
|
|
core: config.wormholeAccount,
|
|
},
|
|
gas: 100000000000000,
|
|
});
|
|
}
|
|
|
|
console.log("token bridge booted.. now the fun begins");
|
|
|
|
let ts = new TestLib();
|
|
let seq = 1;
|
|
let h = hash(wormholeContract);
|
|
console.log(h);
|
|
let vaa = ts.genCoreUpdate(
|
|
ts.singleGuardianPrivKey,
|
|
0,
|
|
0,
|
|
seq,
|
|
CHAIN_ID_NEAR,
|
|
h
|
|
);
|
|
|
|
console.log("submitting vaa to wormhole contract for upgrade");
|
|
|
|
let result;
|
|
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.wormholeAccount,
|
|
methodName: "submit_vaa",
|
|
args: { vaa: vaa },
|
|
attachedDeposit: "12500000000000000000000",
|
|
gas: new BN("150000000000000"),
|
|
});
|
|
|
|
console.log("calling upgradeContract");
|
|
|
|
// result = await wormholeAccount.deployContract(wormholeContract);
|
|
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.wormholeAccount,
|
|
methodName: "update_contract",
|
|
args: wormholeContract,
|
|
attachedDeposit: "5279790000000000000000000",
|
|
gas: 300000000000000,
|
|
});
|
|
|
|
console.log("---");
|
|
console.log("lets do a health check on the wormhole contract");
|
|
|
|
console.log(
|
|
"message_fee returned: " +
|
|
(await masterAccount.viewFunction(
|
|
config.wormholeAccount,
|
|
"message_fee",
|
|
{}
|
|
))
|
|
);
|
|
|
|
h = hash(tokenContract);
|
|
seq = seq + 1;
|
|
vaa = ts.genTokenUpdate(
|
|
ts.singleGuardianPrivKey,
|
|
0,
|
|
0,
|
|
seq,
|
|
CHAIN_ID_NEAR,
|
|
h
|
|
);
|
|
|
|
console.log("submitting vaa");
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.tokenAccount,
|
|
methodName: "submit_vaa",
|
|
args: { vaa: vaa },
|
|
attachedDeposit: "12500000000000000000000",
|
|
gas: new BN("150000000000000"),
|
|
});
|
|
|
|
console.log("submitting vaa again");
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.tokenAccount,
|
|
methodName: "submit_vaa",
|
|
args: { vaa: vaa },
|
|
attachedDeposit: "12500000000000000000000",
|
|
gas: new BN("150000000000000"),
|
|
});
|
|
|
|
console.log("calling upgradeContract on the token bridge");
|
|
|
|
// result = await tokenAccount.deployContract(tokenContract);
|
|
|
|
result = await masterAccount.functionCall({
|
|
contractId: config.tokenAccount,
|
|
methodName: "update_contract",
|
|
args: tokenContract,
|
|
attachedDeposit: "22797900000000000000000000",
|
|
gas: 300000000000000,
|
|
});
|
|
|
|
console.log("---");
|
|
console.log("lets do a health check on the token bridge contract");
|
|
|
|
console.log(
|
|
"emitter returned: " +
|
|
(await masterAccount.viewFunction(config.tokenAccount, "emitter", {}))
|
|
);
|
|
}
|
|
|
|
initNear();
|