clients/js - initial injective commit (#1447)

* clients/js - initial injective commit

* clients/js - upgrading the ethers package

* clients/js: fix packages
This commit is contained in:
Paul Noel 2022-10-06 19:39:34 +00:00 committed by GitHub
parent 066a2a56aa
commit 66700359f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 2341 additions and 836 deletions

191
clients/js/injective.ts Normal file
View File

@ -0,0 +1,191 @@
import { getNetworkInfo, Network } from "@injectivelabs/networks";
import {
MsgExecuteContract,
DEFAULT_STD_FEE,
privateKeyToPublicKeyBase64,
ChainRestAuthApi,
} from "@injectivelabs/sdk-ts";
import { PrivateKey } from "@injectivelabs/sdk-ts/dist/local";
import { createTransaction, MsgArg, TxGrpcClient } from "@injectivelabs/tx-ts";
import { fromUint8Array } from "js-base64";
import { impossible, Payload } from "./vaa";
import { NETWORKS } from "./networks";
import { CONTRACTS } from "@certusone/wormhole-sdk";
export async function execute_injective(
payload: Payload,
vaa: Buffer,
environment: "MAINNET" | "TESTNET" | "DEVNET"
) {
if (environment === "DEVNET") {
throw new Error("Injective is not supported in DEVNET");
}
const chainName = "injective";
let n = NETWORKS[environment][chainName];
if (!n.key) {
throw Error(`No ${environment} key defined for Injective`);
}
let contracts = CONTRACTS[environment][chainName];
const endPoint =
environment === "MAINNET" ? Network.MainnetK8s : Network.TestnetK8s;
const network = getNetworkInfo(endPoint);
const walletPKHash = n.key;
const walletPK = PrivateKey.fromPrivateKey(walletPKHash);
const walletInjAddr = walletPK.toBech32();
const walletPublicKey = privateKeyToPublicKeyBase64(
Buffer.from(walletPKHash, "hex")
);
let target_contract: string;
let execute_msg: object;
switch (payload.module) {
case "Core":
target_contract = contracts.core;
execute_msg = {
submit_v_a_a: {
vaa: fromUint8Array(vaa),
},
};
switch (payload.type) {
case "GuardianSetUpgrade":
console.log("Submitting new guardian set");
break;
case "ContractUpgrade":
console.log("Upgrading core contract");
break;
default:
impossible(payload);
}
break;
case "NFTBridge":
if (contracts.nft_bridge === undefined) {
// NOTE: this code can safely be removed once the injective NFT bridge is
// released, but it's fine for it to stay, as the condition will just be
// skipped once 'contracts.nft_bridge' is defined
throw new Error("NFT bridge not supported yet for injective");
}
target_contract = contracts.nft_bridge;
execute_msg = {
submit_vaa: {
data: fromUint8Array(vaa),
},
};
switch (payload.type) {
case "ContractUpgrade":
console.log("Upgrading contract");
break;
case "RegisterChain":
console.log("Registering chain");
break;
case "Transfer":
console.log("Completing transfer");
break;
default:
impossible(payload);
}
break;
case "TokenBridge":
console.log("contracts:", contracts);
if (contracts.token_bridge === undefined) {
throw new Error("contracts.token_bridge is undefined");
}
target_contract = contracts.token_bridge;
execute_msg = {
submit_vaa: {
data: fromUint8Array(vaa),
},
};
switch (payload.type) {
case "ContractUpgrade":
console.log("Upgrading contract");
break;
case "RegisterChain":
console.log("Registering chain");
break;
case "Transfer":
console.log("Completing transfer");
break;
case "AttestMeta":
console.log("Creating wrapped token");
break;
case "TransferWithPayload":
throw Error("Can't complete payload 3 transfer from CLI");
default:
impossible(payload);
break;
}
break;
default:
target_contract = impossible(payload);
execute_msg = impossible(payload);
}
console.log("execute_msg", execute_msg);
const transaction = MsgExecuteContract.fromJSON({
sender: walletInjAddr,
contractAddress: target_contract,
msg: {
data: fromUint8Array(vaa),
},
action: "submit_vaa",
});
console.log("transaction:", transaction);
const accountDetails = await new ChainRestAuthApi(
network.sentryHttpApi
).fetchAccount(walletInjAddr);
const { signBytes, txRaw } = createTransaction({
message: transaction.toDirectSign(),
memo: "",
fee: DEFAULT_STD_FEE,
pubKey: walletPublicKey,
sequence: parseInt(accountDetails.account.base_account.sequence, 10),
accountNumber: parseInt(
accountDetails.account.base_account.account_number,
10
),
chainId: network.chainId,
});
console.log("txRaw", txRaw);
console.log("sign transaction...");
/** Sign transaction */
const sig = await walletPK.sign(Buffer.from(signBytes));
/** Append Signatures */
txRaw.setSignaturesList([sig]);
const txService = new TxGrpcClient({
txRaw,
endpoint: network.sentryGrpcApi,
});
console.log("simulate transaction...");
/** Simulate transaction */
try {
const simulationResponse = await txService.simulate();
console.log(
`Transaction simulation response: ${JSON.stringify(
simulationResponse.gasInfo
)}`
);
} catch (e) {
console.log("Failed to simulate:", e);
return;
}
console.log("broadcast transaction...");
/** Broadcast transaction */
const txResponse = await txService.broadcast();
console.log("txResponse", txResponse);
if (txResponse.code !== 0) {
console.log(`Transaction failed: ${txResponse.rawLog}`);
} else {
console.log(
`Broadcasted transaction hash: ${JSON.stringify(txResponse.txhash)}`
);
}
}

View File

@ -3,7 +3,7 @@ import yargs from "yargs";
import { hideBin } from "yargs/helpers"; import { hideBin } from "yargs/helpers";
import { Bech32, fromBech32, toHex } from "@cosmjs/encoding"; import { fromBech32, toHex } from "@cosmjs/encoding";
import { import {
isTerraChain, isTerraChain,
assertEVMChain, assertEVMChain,
@ -14,6 +14,7 @@ import {
getEmitterAddressTerra, getEmitterAddressTerra,
getEmitterAddressEth, getEmitterAddressEth,
getEmitterAddressAlgorand, getEmitterAddressAlgorand,
isCosmWasmChain,
} from "@certusone/wormhole-sdk"; } from "@certusone/wormhole-sdk";
import { execute_solana } from "./solana"; import { execute_solana } from "./solana";
import { import {
@ -40,6 +41,7 @@ import { ethers } from "ethers";
import { NETWORKS } from "./networks"; import { NETWORKS } from "./networks";
import base58 from "bs58"; import base58 from "bs58";
import { execute_algorand } from "./algorand"; import { execute_algorand } from "./algorand";
import { execute_injective } from "./injective";
setDefaultWasm("node"); setDefaultWasm("node");
@ -278,9 +280,9 @@ yargs(hideBin(process.argv))
) { ) {
throw Error(`Unknown network: ${network}`); throw Error(`Unknown network: ${network}`);
} }
let chain = argv["chain"] let chain = argv["chain"];
let module = argv["module"] as "Core" | "NFTBridge" | "TokenBridge"; let module = argv["module"] as "Core" | "NFTBridge" | "TokenBridge";
let addr = "" let addr = "";
switch (module) { switch (module) {
case "Core": case "Core":
addr = CONTRACTS[network][chain]["core"]; addr = CONTRACTS[network][chain]["core"];
@ -295,7 +297,8 @@ yargs(hideBin(process.argv))
impossible(module); impossible(module);
} }
if (argv["emitter"]) { if (argv["emitter"]) {
if (chain === "solana" || chain === "pythnet") { // TODO: Create an isSolanaChain() if (chain === "solana" || chain === "pythnet") {
// TODO: Create an isSolanaChain()
addr = await getEmitterAddressSolana(addr); addr = await getEmitterAddressSolana(addr);
} else if (isTerraChain(chain)) { } else if (isTerraChain(chain)) {
addr = await getEmitterAddressTerra(addr); addr = await getEmitterAddressTerra(addr);
@ -303,9 +306,12 @@ yargs(hideBin(process.argv))
addr = getEmitterAddressAlgorand(BigInt(addr)); addr = getEmitterAddressAlgorand(BigInt(addr));
} else if (chain === "near") { } else if (chain === "near") {
if (network !== "MAINNET") { if (network !== "MAINNET") {
throw Error(`unable to look up near emitter address for ${network}`); throw Error(
`unable to look up near emitter address for ${network}`
);
} }
addr = "148410499d3fcda4dcfd68a1ebfcdddda16ab28326448d4aae4d2f0465cdfcb7"; addr =
"148410499d3fcda4dcfd68a1ebfcdddda16ab28326448d4aae4d2f0465cdfcb7";
} else { } else {
addr = getEmitterAddressEth(addr); addr = getEmitterAddressEth(addr);
} }
@ -317,15 +323,14 @@ yargs(hideBin(process.argv))
"chain-id <chain>", "chain-id <chain>",
"Print the wormhole chain ID integer associated with the specified chain name", "Print the wormhole chain ID integer associated with the specified chain name",
(yargs) => { (yargs) => {
return yargs return yargs.positional("chain", {
.positional("chain", { describe: "Chain to query",
describe: "Chain to query", type: "string",
type: "string", choices: Object.keys(CHAINS),
choices: Object.keys(CHAINS), });
});
}, },
async (argv) => { async (argv) => {
assertChain(argv["chain"]); assertChain(argv["chain"]);
console.log(toChainId(argv["chain"])); console.log(toChainId(argv["chain"]));
} }
) )
@ -664,7 +669,7 @@ yargs(hideBin(process.argv))
} else if (chain === "near") { } else if (chain === "near") {
await execute_near(parsed_vaa.payload, vaa_hex, network); await execute_near(parsed_vaa.payload, vaa_hex, network);
} else if (chain === "injective") { } else if (chain === "injective") {
throw Error("INJECTIVE is not supported yet"); await execute_injective(parsed_vaa.payload, buf, network);
} else if (chain === "osmosis") { } else if (chain === "osmosis") {
throw Error("OSMOSIS is not supported yet"); throw Error("OSMOSIS is not supported yet");
} else if (chain === "sui") { } else if (chain === "sui") {
@ -694,7 +699,7 @@ function parseAddress(chain: ChainName, address: string): string {
throw Error("Chain unset"); throw Error("Chain unset");
} else if (isEVMChain(chain)) { } else if (isEVMChain(chain)) {
return "0x" + evm_address(address); return "0x" + evm_address(address);
} else if (isTerraChain(chain)) { } else if (isCosmWasmChain(chain)) {
return "0x" + toHex(fromBech32(address).data).padStart(64, "0"); return "0x" + toHex(fromBech32(address).data).padStart(64, "0");
} else if (chain === "solana" || chain === "pythnet") { } else if (chain === "solana" || chain === "pythnet") {
return "0x" + toHex(base58.decode(address)).padStart(64, "0"); return "0x" + toHex(base58.decode(address)).padStart(64, "0");
@ -702,9 +707,7 @@ function parseAddress(chain: ChainName, address: string): string {
// TODO: is there a better native format for algorand? // TODO: is there a better native format for algorand?
return "0x" + evm_address(address); return "0x" + evm_address(address);
} else if (chain === "near") { } else if (chain === "near") {
return "0x" + hex(address).substring(2).padStart(64, "0") return "0x" + hex(address).substring(2).padStart(64, "0");
} else if (chain === "injective") {
throw Error("INJECTIVE is not supported yet");
} else if (chain === "osmosis") { } else if (chain === "osmosis") {
throw Error("OSMOSIS is not supported yet"); throw Error("OSMOSIS is not supported yet");
} else if (chain === "sui") { } else if (chain === "sui") {

View File

@ -82,7 +82,8 @@ const MAINNET = {
rpc: "https://rpc.mainnet.near.org", rpc: "https://rpc.mainnet.near.org",
key: get_env_var("NEAR_KEY"), key: get_env_var("NEAR_KEY"),
networkId: "mainnet", networkId: "mainnet",
deployerAccount: "85957f38de1768d6db9eab29bee9dd2a01462aff9c8d83daefb9bcd2506c32d2", deployerAccount:
"85957f38de1768d6db9eab29bee9dd2a01462aff9c8d83daefb9bcd2506c32d2",
}, },
injective: { injective: {
rpc: undefined, rpc: undefined,
@ -210,12 +211,12 @@ const TESTNET = {
injective: { injective: {
rpc: "https://k8s.testnet.tm.injective.network:443", rpc: "https://k8s.testnet.tm.injective.network:443",
chain_id: "injective-888", chain_id: "injective-888",
key: get_env_var("ETH_KEY_TESTNET"), key: get_env_var("INJECTIVE_KEY_TESTNET"),
}, },
osmosis: { osmosis: {
rpc: undefined, rpc: undefined,
chain_id: "osmo-test-4", chain_id: "osmo-test-4",
key: get_env_var("ETH_KEY_TESTNET"), key: get_env_var("OSMOSIS_KEY_TESTNET"),
}, },
aptos: { aptos: {
rpc: undefined, rpc: undefined,

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,9 @@
"@celo-tools/celo-ethers-wrapper": "^0.1.0", "@celo-tools/celo-ethers-wrapper": "^0.1.0",
"@certusone/wormhole-sdk": "^0.7.0", "@certusone/wormhole-sdk": "^0.7.0",
"@cosmjs/encoding": "^0.26.2", "@cosmjs/encoding": "^0.26.2",
"@injectivelabs/networks": "^1.0.12",
"@injectivelabs/sdk-ts": "^1.0.75",
"@injectivelabs/tx-ts": "^1.0.22",
"@solana/web3.js": "^1.22.0", "@solana/web3.js": "^1.22.0",
"@terra-money/terra.js": "^3.1.3", "@terra-money/terra.js": "^3.1.3",
"algosdk": "^1.15.0", "algosdk": "^1.15.0",
@ -14,7 +17,7 @@
"bs58": "^4.0.1", "bs58": "^4.0.1",
"buffer-layout": "^1.2.2", "buffer-layout": "^1.2.2",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"ethers": "^5.4.1", "ethers": "^5.6.8",
"js-base64": "^3.6.1", "js-base64": "^3.6.1",
"near-api-js": "^0.45.1", "near-api-js": "^0.45.1",
"npm": "^7.20.0", "npm": "^7.20.0",