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

View File

@ -82,7 +82,8 @@ const MAINNET = {
rpc: "https://rpc.mainnet.near.org",
key: get_env_var("NEAR_KEY"),
networkId: "mainnet",
deployerAccount: "85957f38de1768d6db9eab29bee9dd2a01462aff9c8d83daefb9bcd2506c32d2",
deployerAccount:
"85957f38de1768d6db9eab29bee9dd2a01462aff9c8d83daefb9bcd2506c32d2",
},
injective: {
rpc: undefined,
@ -210,12 +211,12 @@ const TESTNET = {
injective: {
rpc: "https://k8s.testnet.tm.injective.network:443",
chain_id: "injective-888",
key: get_env_var("ETH_KEY_TESTNET"),
key: get_env_var("INJECTIVE_KEY_TESTNET"),
},
osmosis: {
rpc: undefined,
chain_id: "osmo-test-4",
key: get_env_var("ETH_KEY_TESTNET"),
key: get_env_var("OSMOSIS_KEY_TESTNET"),
},
aptos: {
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",
"@certusone/wormhole-sdk": "^0.7.0",
"@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",
"@terra-money/terra.js": "^3.1.3",
"algosdk": "^1.15.0",
@ -14,7 +17,7 @@
"bs58": "^4.0.1",
"buffer-layout": "^1.2.2",
"dotenv": "^10.0.0",
"ethers": "^5.4.1",
"ethers": "^5.6.8",
"js-base64": "^3.6.1",
"near-api-js": "^0.45.1",
"npm": "^7.20.0",