ci: add github workflow with prettier checks for clients/js/src and sdk/js/src (#3176)

* github: add prettier check for clients/js

* github: update workflow to include sdk/js
This commit is contained in:
Paul Noel 2023-07-12 15:30:14 +00:00 committed by GitHub
parent f5987a334f
commit 6309b321e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1208 additions and 1070 deletions

View File

@ -394,3 +394,11 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- run: chmod 755 ./scripts/check-npm-package-scopes.sh - run: chmod 755 ./scripts/check-npm-package-scopes.sh
- run: ./scripts/check-npm-package-scopes.sh - run: ./scripts/check-npm-package-scopes.sh
prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- run: npx prettier --check ./clients/js/src ./sdk/js/src

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
sdk/js/src/ethers-contracts

View File

@ -115,7 +115,7 @@ export async function execute_algorand(
break; break;
} }
case "WormholeRelayer": case "WormholeRelayer":
throw Error("Wormhole Relayer not supported on Algorand"); throw Error("Wormhole Relayer not supported on Algorand");
default: default:
target_contract = impossible(payload); target_contract = impossible(payload);
} }

View File

@ -120,7 +120,7 @@ export const submit = async (
break; break;
} }
case "WormholeRelayer": case "WormholeRelayer":
throw Error("Wormhole Relayer not supported on Sei"); throw Error("Wormhole Relayer not supported on Sei");
default: default:
target_contract = impossible(payload); target_contract = impossible(payload);
execute_msg = impossible(payload); execute_msg = impossible(payload);

View File

@ -199,7 +199,7 @@ export const submit = async (
break; break;
} }
case "WormholeRelayer": case "WormholeRelayer":
throw Error("Wormhole Relayer not supported on Sui"); throw Error("Wormhole Relayer not supported on Sui");
default: default:
impossible(payload); impossible(payload);
} }

View File

@ -311,14 +311,14 @@ export const isSameType = (a: string, b: string) => {
export const isSuiCreateEvent = < export const isSuiCreateEvent = <
T extends NonNullable<SuiTransactionBlockResponse["objectChanges"]>[number], T extends NonNullable<SuiTransactionBlockResponse["objectChanges"]>[number],
K extends Extract<T, { type: "created" }> K extends Extract<T, { type: "created" }>,
>( >(
event: T event: T
): event is K => event?.type === "created"; ): event is K => event?.type === "created";
export const isSuiPublishEvent = < export const isSuiPublishEvent = <
T extends NonNullable<SuiTransactionBlockResponse["objectChanges"]>[number], T extends NonNullable<SuiTransactionBlockResponse["objectChanges"]>[number],
K extends Extract<T, { type: "published" }> K extends Extract<T, { type: "published" }>,
>( >(
event: T event: T
): event is K => event?.type === "published"; ): event is K => event?.type === "published";

View File

@ -82,8 +82,7 @@ export const builder = function (y: typeof yargs) {
describe: "Module to register", describe: "Module to register",
choices: ["NFTBridge", "TokenBridge", "WormholeRelayer"], choices: ["NFTBridge", "TokenBridge", "WormholeRelayer"],
demandOption: true, demandOption: true,
} as const) } as const),
,
(argv) => { (argv) => {
const module = argv["module"]; const module = argv["module"];
assertChain(argv.chain); assertChain(argv.chain);
@ -272,7 +271,7 @@ export const builder = function (y: typeof yargs) {
describe: "Address of the delivery provider contract", describe: "Address of the delivery provider contract",
type: "string", type: "string",
demandOption: true, demandOption: true,
}) });
}, },
(argv) => { (argv) => {
assertChain(argv.chain); assertChain(argv.chain);
@ -280,7 +279,10 @@ export const builder = function (y: typeof yargs) {
module: "WormholeRelayer", module: "WormholeRelayer",
type: "SetDefaultDeliveryProvider", type: "SetDefaultDeliveryProvider",
chain: toChainId(argv["chain"]), chain: toChainId(argv["chain"]),
relayProviderAddress: parseAddress(argv["chain"], argv["delivery-provider-address"]) relayProviderAddress: parseAddress(
argv["chain"],
argv["delivery-provider-address"]
),
}; };
let v = makeVAA( let v = makeVAA(
GOVERNANCE_CHAIN, GOVERNANCE_CHAIN,

View File

@ -2,12 +2,8 @@ import {
CHAINS, CHAINS,
ChainName, ChainName,
assertChain, assertChain,
} from "@certusone/wormhole-sdk/lib/esm/utils/consts"; } from "@certusone/wormhole-sdk/lib/esm/utils/consts";
import { import { relayer, Network } from "@certusone/wormhole-sdk";
relayer,
Network
} from "@certusone/wormhole-sdk"
import yargs from "yargs"; import yargs from "yargs";
import { CONTRACTS, NETWORKS } from "../consts"; import { CONTRACTS, NETWORKS } from "../consts";
import { assertNetwork } from "../utils"; import { assertNetwork } from "../utils";
@ -15,7 +11,8 @@ import { impossible } from "../vaa";
import { ethers } from "ethers"; import { ethers } from "ethers";
export const command = "status <network> <chain> <tx>"; export const command = "status <network> <chain> <tx>";
export const desc = "Prints information about the automatic delivery initiated on the specified network, chain, and tx"; export const desc =
"Prints information about the automatic delivery initiated on the specified network, chain, and tx";
export const builder = (y: typeof yargs) => export const builder = (y: typeof yargs) =>
y y
.positional("network", { .positional("network", {
@ -40,8 +37,9 @@ export const handler = async (
assertNetwork(network); assertNetwork(network);
const chain = argv.chain; const chain = argv.chain;
assertChain(chain); assertChain(chain);
const addr = relayer.RELAYER_CONTRACTS[network][chain]?.wormholeRelayerAddress; const addr =
relayer.RELAYER_CONTRACTS[network][chain]?.wormholeRelayerAddress;
if (!addr) { if (!addr) {
throw new Error(`Wormhole Relayer not deployed on ${chain} in ${network}`); throw new Error(`Wormhole Relayer not deployed on ${chain} in ${network}`);
} }
@ -49,11 +47,20 @@ export const handler = async (
const sourceRPC = NETWORKS[network as Network][chain as ChainName].rpc; const sourceRPC = NETWORKS[network as Network][chain as ChainName].rpc;
const sourceChainProvider = new ethers.providers.JsonRpcProvider(sourceRPC); const sourceChainProvider = new ethers.providers.JsonRpcProvider(sourceRPC);
const targetChainProviders = new Map<ChainName, ethers.providers.Provider>(); const targetChainProviders = new Map<ChainName, ethers.providers.Provider>();
for(const key in NETWORKS[network]) { for (const key in NETWORKS[network]) {
targetChainProviders.set(key as ChainName, new ethers.providers.JsonRpcProvider(NETWORKS[network][key as ChainName].rpc)); targetChainProviders.set(
key as ChainName,
new ethers.providers.JsonRpcProvider(
NETWORKS[network][key as ChainName].rpc
)
);
} }
const info = await relayer.getWormholeRelayerInfo(chain, argv.tx, {environment: network, sourceChainProvider, targetChainProviders}); const info = await relayer.getWormholeRelayerInfo(chain, argv.tx, {
environment: network,
sourceChainProvider,
targetChainProviders,
});
console.log(relayer.stringifyWormholeRelayerInfo(info)); console.log(relayer.stringifyWormholeRelayerInfo(info));
}; };

View File

@ -123,9 +123,8 @@ export const addSetupCommands: YargsAddCommandsFn = (y: typeof yargs) =>
// Get token bridge state object ID // Get token bridge state object ID
const tokenBridgeStateObjectId = getCreatedObjects( const tokenBridgeStateObjectId = getCreatedObjects(
tokenBridgeInitRes tokenBridgeInitRes
).find((e) => ).find((e) => isSameType(e.type, `${tokenBridgePackageId}::state::State`))
isSameType(e.type, `${tokenBridgePackageId}::state::State`) ?.objectId;
)?.objectId;
if (!tokenBridgeStateObjectId) { if (!tokenBridgeStateObjectId) {
throw new Error("Couldn't find token bridge state object ID."); throw new Error("Couldn't find token bridge state object ID.");
} }

View File

@ -18,12 +18,11 @@ import * as sui from "./cmds/sui";
import * as verifyVaa from "./cmds/verifyVaa"; import * as verifyVaa from "./cmds/verifyVaa";
import * as status from "./cmds/status"; import * as status from "./cmds/status";
const MD_TAG = "<!--CLI_USAGE-->"; const MD_TAG = "<!--CLI_USAGE-->";
async function getHelpText(cmd: any): Promise<string> { async function getHelpText(cmd: any): Promise<string> {
// Note that `yargs` is called as a function to produce a fresh copy. // Note that `yargs` is called as a function to produce a fresh copy.
// Otherwise the imported module is effectively a singleton where state from // Otherwise the imported module is effectively a singleton where state from
// other commands is accumulated from repeat calls. // other commands is accumulated from repeat calls.
return await cmd.builder(yargs()).scriptName(`worm ${cmd.command}`).getHelp(); return await cmd.builder(yargs()).scriptName(`worm ${cmd.command}`).getHelp();
} }
@ -41,14 +40,15 @@ async function getHelpText(cmd: any): Promise<string> {
submit, submit,
sui, sui,
verifyVaa, verifyVaa,
status status,
]; ];
const helpOutputs: Buffer[] = []; const helpOutputs: Buffer[] = [];
for (const cmd of cmds) { for (const cmd of cmds) {
const helpText = await getHelpText(cmd); const helpText = await getHelpText(cmd);
helpOutputs.push(Buffer.from(` helpOutputs.push(
Buffer.from(`
<details> <details>
<summary> ${cmd.command} </summary> <summary> ${cmd.command} </summary>
@ -56,11 +56,10 @@ async function getHelpText(cmd: any): Promise<string> {
${helpText} ${helpText}
\`\`\` \`\`\`
</details> </details>
`)) `)
);
} }
const f = fs.readFileSync("README.md"); const f = fs.readFileSync("README.md");
const startIdx = f.indexOf(MD_TAG, 0); const startIdx = f.indexOf(MD_TAG, 0);
const stopIdx = f.indexOf(MD_TAG, startIdx + 1); const stopIdx = f.indexOf(MD_TAG, startIdx + 1);
@ -68,7 +67,7 @@ ${helpText}
const head = f.subarray(0, startIdx + MD_TAG.length); const head = f.subarray(0, startIdx + MD_TAG.length);
const tail = f.subarray(stopIdx, f.length); const tail = f.subarray(stopIdx, f.length);
const content = Buffer.concat([head, ...helpOutputs, tail]) const content = Buffer.concat([head, ...helpOutputs, tail]);
fs.writeFileSync("README.md", content.toString()) fs.writeFileSync("README.md", content.toString());
})(); })();

View File

@ -9,7 +9,7 @@ import {
getEmitterAddressEth, getEmitterAddressEth,
getEmitterAddressNear, getEmitterAddressNear,
getEmitterAddressSolana, getEmitterAddressSolana,
getEmitterAddressTerra getEmitterAddressTerra,
} from "@certusone/wormhole-sdk/lib/esm/bridge/getEmitterAddress"; } from "@certusone/wormhole-sdk/lib/esm/bridge/getEmitterAddress";
export async function getEmitterAddress( export async function getEmitterAddress(

View File

@ -29,10 +29,10 @@ console.warn = function (x: string) {
// //
// eslint-disable-next-line @typescript-eslint/no-redeclare // eslint-disable-next-line @typescript-eslint/no-redeclare
interface BigInt { interface BigInt {
/** Convert to BigInt to string form in JSON.stringify */ /** Convert to BigInt to string form in JSON.stringify */
toJSON: () => string; toJSON: () => string;
} }
// Without this JSON.stringify() blows up // Without this JSON.stringify() blows up
(BigInt.prototype as any).toJSON = function () { (BigInt.prototype as any).toJSON = function () {
return this.toString(); return this.toString();
}; };

View File

@ -143,7 +143,7 @@ export async function execute_terra(
break; break;
} }
case "WormholeRelayer": case "WormholeRelayer":
throw Error("Wormhole Relayer not supported on Terra"); throw Error("Wormhole Relayer not supported on Terra");
default: default:
target_contract = impossible(payload); target_contract = impossible(payload);
execute_msg = impossible(payload); execute_msg = impossible(payload);

File diff suppressed because it is too large Load Diff

View File

@ -139,7 +139,7 @@ export async function execute_xpla(
break; break;
} }
case "WormholeRelayer": case "WormholeRelayer":
throw Error("Wormhole Relayer not supported on Xpla"); throw Error("Wormhole Relayer not supported on Xpla");
default: default:
target_contract = impossible(payload); target_contract = impossible(payload);
execute_msg = impossible(payload); execute_msg = impossible(payload);

View File

@ -5,7 +5,7 @@ import { ChainId } from "../../utils";
export const upgradeGuardianSet = ( export const upgradeGuardianSet = (
coreBridgeAddress: string, coreBridgeAddress: string,
vaa: Uint8Array, vaa: Uint8Array
): Types.EntryFunctionPayload => { ): Types.EntryFunctionPayload => {
if (!coreBridgeAddress) throw new Error("Need core bridge address."); if (!coreBridgeAddress) throw new Error("Need core bridge address.");
return { return {
@ -22,12 +22,17 @@ export const initWormhole = (
chainId: ChainId, chainId: ChainId,
governanceChainId: number, governanceChainId: number,
governanceContract: Uint8Array, governanceContract: Uint8Array,
initialGuardian: Uint8Array, initialGuardian: Uint8Array
): Types.EntryFunctionPayload => { ): Types.EntryFunctionPayload => {
if (!coreBridgeAddress) throw new Error("Need core bridge address."); if (!coreBridgeAddress) throw new Error("Need core bridge address.");
return { return {
function: `${coreBridgeAddress}::wormhole::init`, function: `${coreBridgeAddress}::wormhole::init`,
type_arguments: [], type_arguments: [],
arguments: [chainId, governanceChainId, governanceContract, initialGuardian], arguments: [
chainId,
governanceChainId,
governanceContract,
initialGuardian,
],
}; };
}; };

View File

@ -17,16 +17,16 @@ import {
export const attestToken = ( export const attestToken = (
tokenBridgeAddress: string, tokenBridgeAddress: string,
tokenChain: ChainId | ChainName, tokenChain: ChainId | ChainName,
tokenAddress: string, tokenAddress: string
): Types.EntryFunctionPayload => { ): Types.EntryFunctionPayload => {
if (!tokenBridgeAddress) throw new Error("Need token bridge address."); if (!tokenBridgeAddress) throw new Error("Need token bridge address.");
const assetType = getAssetFullyQualifiedType( const assetType = getAssetFullyQualifiedType(
tokenBridgeAddress, tokenBridgeAddress,
coalesceChainId(tokenChain), coalesceChainId(tokenChain),
tokenAddress, tokenAddress
); );
if (!assetType) throw new Error("Invalid asset address."); if (!assetType) throw new Error("Invalid asset address.");
return { return {
function: `${tokenBridgeAddress}::attest_token::attest_token_entry`, function: `${tokenBridgeAddress}::attest_token::attest_token_entry`,
type_arguments: [assetType], type_arguments: [assetType],
@ -40,7 +40,7 @@ export const completeTransfer = async (
client: AptosClient, client: AptosClient,
tokenBridgeAddress: string, tokenBridgeAddress: string,
transferVAA: Uint8Array, transferVAA: Uint8Array,
feeRecipient: string, feeRecipient: string
): Promise<Types.EntryFunctionPayload> => { ): Promise<Types.EntryFunctionPayload> => {
if (!tokenBridgeAddress) throw new Error("Need token bridge address."); if (!tokenBridgeAddress) throw new Error("Need token bridge address.");
@ -52,7 +52,7 @@ export const completeTransfer = async (
if (parsedVAA.ToChain !== CHAIN_ID_APTOS) { if (parsedVAA.ToChain !== CHAIN_ID_APTOS) {
throw new Error("Transfer is not destined for Aptos"); throw new Error("Transfer is not destined for Aptos");
} }
assertChain(parsedVAA.FromChain); assertChain(parsedVAA.FromChain);
const assetType = const assetType =
parsedVAA.FromChain === CHAIN_ID_APTOS parsedVAA.FromChain === CHAIN_ID_APTOS
@ -78,7 +78,7 @@ export const completeTransfer = async (
export const completeTransferAndRegister = async ( export const completeTransferAndRegister = async (
client: AptosClient, client: AptosClient,
tokenBridgeAddress: string, tokenBridgeAddress: string,
transferVAA: Uint8Array, transferVAA: Uint8Array
): Promise<Types.EntryFunctionPayload> => { ): Promise<Types.EntryFunctionPayload> => {
if (!tokenBridgeAddress) throw new Error("Need token bridge address."); if (!tokenBridgeAddress) throw new Error("Need token bridge address.");
@ -90,7 +90,7 @@ export const completeTransferAndRegister = async (
if (parsedVAA.ToChain !== CHAIN_ID_APTOS) { if (parsedVAA.ToChain !== CHAIN_ID_APTOS) {
throw new Error("Transfer is not destined for Aptos"); throw new Error("Transfer is not destined for Aptos");
} }
assertChain(parsedVAA.FromChain); assertChain(parsedVAA.FromChain);
const assetType = const assetType =
parsedVAA.FromChain === CHAIN_ID_APTOS parsedVAA.FromChain === CHAIN_ID_APTOS
@ -117,21 +117,23 @@ export const completeTransferWithPayload = (
_tokenBridgeAddress: string, _tokenBridgeAddress: string,
_tokenChain: ChainId | ChainName, _tokenChain: ChainId | ChainName,
_tokenAddress: string, _tokenAddress: string,
_vaa: Uint8Array, _vaa: Uint8Array
): Types.EntryFunctionPayload => { ): Types.EntryFunctionPayload => {
throw new Error("Completing transfers with payload is not yet supported in the sdk"); throw new Error(
"Completing transfers with payload is not yet supported in the sdk"
);
}; };
/** /**
* Construct a payload for a transaction that registers a coin defined by the given origin chain * Construct a payload for a transaction that registers a coin defined by the given origin chain
* ID and address to the sender's account. * ID and address to the sender's account.
* *
* The bytecode was compiled from the following Move code: * The bytecode was compiled from the following Move code:
* ```move * ```move
* script { * script {
* use aptos_framework::coin; * use aptos_framework::coin;
* use aptos_framework::signer; * use aptos_framework::signer;
* *
* fun main<CoinType>(user: &signer) { * fun main<CoinType>(user: &signer) {
* if (!coin::is_account_registered<CoinType>(signer::address_of(user))) { * if (!coin::is_account_registered<CoinType>(signer::address_of(user))) {
* coin::register<CoinType>(user); * coin::register<CoinType>(user);
@ -170,7 +172,9 @@ export const registerCoin = (
// Deploy coin // Deploy coin
// don't need `signer` and `&signer` in argument list because the Move VM will inject them // don't need `signer` and `&signer` in argument list because the Move VM will inject them
export const deployCoin = (tokenBridgeAddress: string): Types.EntryFunctionPayload => { export const deployCoin = (
tokenBridgeAddress: string
): Types.EntryFunctionPayload => {
if (!tokenBridgeAddress) throw new Error("Need token bridge address."); if (!tokenBridgeAddress) throw new Error("Need token bridge address.");
return { return {
function: `${tokenBridgeAddress}::deploy_coin::deploy_coin`, function: `${tokenBridgeAddress}::deploy_coin::deploy_coin`,
@ -183,7 +187,7 @@ export const deployCoin = (tokenBridgeAddress: string): Types.EntryFunctionPaylo
export const registerChain = ( export const registerChain = (
tokenBridgeAddress: string, tokenBridgeAddress: string,
vaa: Uint8Array, vaa: Uint8Array
): Types.EntryFunctionPayload => { ): Types.EntryFunctionPayload => {
if (!tokenBridgeAddress) throw new Error("Need token bridge address."); if (!tokenBridgeAddress) throw new Error("Need token bridge address.");
return { return {

View File

@ -1,4 +1,7 @@
import { TransactionResponse, VersionedTransactionResponse } from "@solana/web3.js"; import {
TransactionResponse,
VersionedTransactionResponse,
} from "@solana/web3.js";
import { TxInfo } from "@terra-money/terra.js"; import { TxInfo } from "@terra-money/terra.js";
import { TxInfo as XplaTxInfo } from "@xpla/xpla.js"; import { TxInfo as XplaTxInfo } from "@xpla/xpla.js";
import { AptosClient, Types } from "aptos"; import { AptosClient, Types } from "aptos";
@ -105,7 +108,9 @@ export function parseSequenceFromLogInjective(info: any): string {
} }
const SOLANA_SEQ_LOG = "Program log: Sequence: "; const SOLANA_SEQ_LOG = "Program log: Sequence: ";
export function parseSequenceFromLogSolana(info: TransactionResponse | VersionedTransactionResponse) { export function parseSequenceFromLogSolana(
info: TransactionResponse | VersionedTransactionResponse
) {
// TODO: better parsing, safer // TODO: better parsing, safer
const sequence = info.meta?.logMessages const sequence = info.meta?.logMessages
?.filter((msg) => msg.startsWith(SOLANA_SEQ_LOG))?.[0] ?.filter((msg) => msg.startsWith(SOLANA_SEQ_LOG))?.[0]

View File

@ -16,6 +16,6 @@ export * as token_bridge from "./token_bridge";
export * as nft_bridge from "./nft_bridge"; export * as nft_bridge from "./nft_bridge";
export * as algorand from "./algorand"; export * as algorand from "./algorand";
export * as sui from "./sui"; export * as sui from "./sui";
export * as relayer from "./relayer" export * as relayer from "./relayer";
export { postVaaSolana, postVaaSolanaWithRetry } from "./solana"; export { postVaaSolana, postVaaSolanaWithRetry } from "./solana";

View File

@ -265,6 +265,4 @@ export class GovernanceEmitter extends MockEmitter {
uptickSequence uptickSequence
); );
} }
} }

View File

@ -1,45 +1,52 @@
import { afterAll, beforeEach, describe, expect, jest, test} from "@jest/globals"; import {
afterAll,
beforeEach,
describe,
expect,
jest,
test,
} from "@jest/globals";
import { ethers } from "ethers"; import { ethers } from "ethers";
import { DeliveryProvider__factory } from "../../ethers-contracts" import { DeliveryProvider__factory } from "../../ethers-contracts";
import {getAddressInfo} from "../consts" import { getAddressInfo } from "../consts";
import {getDefaultProvider} from "../relayer/helpers" import { getDefaultProvider } from "../relayer/helpers";
import {CHAINS, ChainId, ChainName, Network} from "../../../" import { CHAINS, ChainId, ChainName, Network } from "../../../";
import {getNetwork, PRIVATE_KEY, isCI} from "./utils/utils"; import { getNetwork, PRIVATE_KEY, isCI } from "./utils/utils";
const network: Network = getNetwork(); const network: Network = getNetwork();
const ci: boolean = isCI(); const ci: boolean = isCI();
const sourceChain = network == 'DEVNET' ? "ethereum" : "avalanche"; const sourceChain = network == "DEVNET" ? "ethereum" : "avalanche";
const targetChain = network == 'DEVNET' ? "bsc" : "celo"; const targetChain = network == "DEVNET" ? "bsc" : "celo";
const sourceChainId = CHAINS[sourceChain]; const sourceChainId = CHAINS[sourceChain];
const targetChainId = CHAINS[targetChain]; const targetChainId = CHAINS[targetChain];
describe("Relay Provider Test", () => { describe("Relay Provider Test", () => {
const addressInfo = getAddressInfo(sourceChain, network); const addressInfo = getAddressInfo(sourceChain, network);
const provider = getDefaultProvider(network, sourceChain, ci); const provider = getDefaultProvider(network, sourceChain, ci);
// signers // signers
const oracleDeployer = new ethers.Wallet(PRIVATE_KEY, provider); const oracleDeployer = new ethers.Wallet(PRIVATE_KEY, provider);
const deliveryProviderAddress = addressInfo.mockDeliveryProviderAddress; const deliveryProviderAddress = addressInfo.mockDeliveryProviderAddress;
if(!deliveryProviderAddress) throw Error("No relay provider address"); if (!deliveryProviderAddress) throw Error("No relay provider address");
const deliveryProvider = DeliveryProvider__factory.connect(deliveryProviderAddress, oracleDeployer); const deliveryProvider = DeliveryProvider__factory.connect(
deliveryProviderAddress,
oracleDeployer
);
describe("Read Prices Correctly", () => { describe("Read Prices Correctly", () => {
test("readPrices", async () => { test("readPrices", async () => {
const tokenPrice = ethers.BigNumber.from("100000"); const tokenPrice = ethers.BigNumber.from("100000");
const gasPrice = ethers.utils.parseUnits("300", "gwei"); const gasPrice = ethers.utils.parseUnits("300", "gwei");
const tokenPriceReturned = await deliveryProvider.nativeCurrencyPrice(targetChainId); const tokenPriceReturned = await deliveryProvider.nativeCurrencyPrice(
targetChainId
);
const gasPriceReturned = await deliveryProvider.gasPrice(targetChainId); const gasPriceReturned = await deliveryProvider.gasPrice(targetChainId);
expect(tokenPriceReturned.toString()).toBe(tokenPrice.toString()); expect(tokenPriceReturned.toString()).toBe(tokenPrice.toString());
expect(gasPriceReturned.toString()).toBe(gasPrice.toString()); expect(gasPriceReturned.toString()).toBe(gasPrice.toString());
}); });
}); });
}); });

View File

@ -1,26 +1,32 @@
import { Network } from "../../../utils"; import { Network } from "../../../utils";
import { PublicKey } from "@solana/web3.js"; import { PublicKey } from "@solana/web3.js";
import { ethers } from "ethers"; import { ethers } from "ethers";
import {ETH_PRIVATE_KEY, Environment} from "../../../token_bridge/__tests__/utils/consts"; import {
ETH_PRIVATE_KEY,
Environment,
} from "../../../token_bridge/__tests__/utils/consts";
const SAFE_RELAY_DELAY = 10000; const SAFE_RELAY_DELAY = 10000;
const characters = const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
export const PRIVATE_KEY = process.env['WALLET_KEY'] || ETH_PRIVATE_KEY; export const PRIVATE_KEY = process.env["WALLET_KEY"] || ETH_PRIVATE_KEY;
export const networkOptions = ["MAINNET", "TESTNET", "DEVNET"]; export const networkOptions = ["MAINNET", "TESTNET", "DEVNET"];
export const isCI = (): boolean => { export const isCI = (): boolean => {
return !!process.env['CI']; return !!process.env["CI"];
} };
export const getNetwork = (): Network => { export const getNetwork = (): Network => {
const network = process.env['NETWORK'] || ""; const network = process.env["NETWORK"] || "";
if(!(networkOptions.includes(network))) throw Error(`Invalid Network: ${network}. Options ${networkOptions.join(", ")}`); if (!networkOptions.includes(network))
return network as Network; throw Error(
} `Invalid Network: ${network}. Options ${networkOptions.join(", ")}`
);
return network as Network;
};
export const generateRandomString = (length: number) => { export const generateRandomString = (length: number) => {
let randomString = ""; let randomString = "";
@ -36,7 +42,7 @@ export const getArbitraryBytes32 = (): string => {
return ethers.utils.hexlify( return ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32)) ethers.utils.toUtf8Bytes(generateRandomString(32))
); );
} };
export async function waitForRelay(quantity?: number) { export async function waitForRelay(quantity?: number) {
await new Promise((resolve) => await new Promise((resolve) =>
@ -45,36 +51,48 @@ export async function waitForRelay(quantity?: number) {
} }
export const getGuardianRPC = (network: Network, ci: boolean) => { export const getGuardianRPC = (network: Network, ci: boolean) => {
return process.env.GUARDIAN_RPC || (ci ? "http://guardian:7071" : network == "DEVNET" ? "http://localhost:7071" : network == "TESTNET" ? "https://wormhole-v2-testnet-api.certus.one" : "https://wormhole-v2-mainnet-api.certus.one"); return (
} process.env.GUARDIAN_RPC ||
(ci
? "http://guardian:7071"
: network == "DEVNET"
? "http://localhost:7071"
: network == "TESTNET"
? "https://wormhole-v2-testnet-api.certus.one"
: "https://wormhole-v2-mainnet-api.certus.one")
);
};
// These variables also live in testing/solana-test-validator/sdk-tests/helpers // These variables also live in testing/solana-test-validator/sdk-tests/helpers
// Ideally we find a better home for these (probably somewhere in the SDK) // Ideally we find a better home for these (probably somewhere in the SDK)
// These are used to mock a devnet/CI guardian // These are used to mock a devnet/CI guardian
export const GUARDIAN_KEYS = process.env.GUARDIAN_KEY ? [process.env.GUARDIAN_KEY] : [ export const GUARDIAN_KEYS = process.env.GUARDIAN_KEY
"cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0", ? [process.env.GUARDIAN_KEY]
"c3b2e45c422a1602333a64078aeb42637370b0f48fe385f9cfa6ad54a8e0c47e", : [
"9f790d3f08bc4b5cd910d4278f3deb406e57bb5e924906ccd52052bb078ccd47", "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0",
"b20cc49d6f2c82a5e6519015fc18aa3e562867f85f872c58f1277cfbd2a0c8e4", "c3b2e45c422a1602333a64078aeb42637370b0f48fe385f9cfa6ad54a8e0c47e",
"eded5a2fdcb5bbbfa5b07f2a91393813420e7ac30a72fc935b6df36f8294b855", "9f790d3f08bc4b5cd910d4278f3deb406e57bb5e924906ccd52052bb078ccd47",
"00d39587c3556f289677a837c7f3c0817cb7541ce6e38a243a4bdc761d534c5e", "b20cc49d6f2c82a5e6519015fc18aa3e562867f85f872c58f1277cfbd2a0c8e4",
"da534d61a8da77b232f3a2cee55c0125e2b3e33a5cd8247f3fe9e72379445c3b", "eded5a2fdcb5bbbfa5b07f2a91393813420e7ac30a72fc935b6df36f8294b855",
"cdbabfc2118eb00bc62c88845f3bbd03cb67a9e18a055101588ca9b36387006c", "00d39587c3556f289677a837c7f3c0817cb7541ce6e38a243a4bdc761d534c5e",
"c83d36423820e7350428dc4abe645cb2904459b7d7128adefe16472fdac397ba", "da534d61a8da77b232f3a2cee55c0125e2b3e33a5cd8247f3fe9e72379445c3b",
"1cbf4e1388b81c9020500fefc83a7a81f707091bb899074db1bfce4537428112", "cdbabfc2118eb00bc62c88845f3bbd03cb67a9e18a055101588ca9b36387006c",
"17646a6ba14a541957fc7112cc973c0b3f04fce59484a92c09bb45a0b57eb740", "c83d36423820e7350428dc4abe645cb2904459b7d7128adefe16472fdac397ba",
"eb94ff04accbfc8195d44b45e7c7da4c6993b2fbbfc4ef166a7675a905df9891", "1cbf4e1388b81c9020500fefc83a7a81f707091bb899074db1bfce4537428112",
"053a6527124b309d914a47f5257a995e9b0ad17f14659f90ed42af5e6e262b6a", "17646a6ba14a541957fc7112cc973c0b3f04fce59484a92c09bb45a0b57eb740",
"3fbf1e46f6da69e62aed5670f279e818889aa7d8f1beb7fd730770fd4f8ea3d7", "eb94ff04accbfc8195d44b45e7c7da4c6993b2fbbfc4ef166a7675a905df9891",
"53b05697596ba04067e40be8100c9194cbae59c90e7870997de57337497172e9", "053a6527124b309d914a47f5257a995e9b0ad17f14659f90ed42af5e6e262b6a",
"4e95cb2ff3f7d5e963631ad85c28b1b79cb370f21c67cbdd4c2ffb0bf664aa06", "3fbf1e46f6da69e62aed5670f279e818889aa7d8f1beb7fd730770fd4f8ea3d7",
"01b8c448ce2c1d43cfc5938d3a57086f88e3dc43bb8b08028ecb7a7924f4676f", "53b05697596ba04067e40be8100c9194cbae59c90e7870997de57337497172e9",
"1db31a6ba3bcd54d2e8a64f8a2415064265d291593450c6eb7e9a6a986bd9400", "4e95cb2ff3f7d5e963631ad85c28b1b79cb370f21c67cbdd4c2ffb0bf664aa06",
"70d8f1c9534a0ab61a020366b831a494057a289441c07be67e4288c44bc6cd5d", "01b8c448ce2c1d43cfc5938d3a57086f88e3dc43bb8b08028ecb7a7924f4676f",
]; "1db31a6ba3bcd54d2e8a64f8a2415064265d291593450c6eb7e9a6a986bd9400",
export const GUARDIAN_SET_INDEX = process.env.GUARDIAN_SET_INDEX ? parseInt(process.env.GUARDIAN_SET_INDEX) : 0; "70d8f1c9534a0ab61a020366b831a494057a289441c07be67e4288c44bc6cd5d",
export const GOVERNANCE_EMITTER_ADDRESS = process.env.GOVERNANCE_EMITTER_ADDRESS || new PublicKey( ];
"11111111111111111111111111111115" export const GUARDIAN_SET_INDEX = process.env.GUARDIAN_SET_INDEX
).toBuffer().toString("hex"); ? parseInt(process.env.GUARDIAN_SET_INDEX)
: 0;
export const GOVERNANCE_EMITTER_ADDRESS =
process.env.GOVERNANCE_EMITTER_ADDRESS ||
new PublicKey("11111111111111111111111111111115").toBuffer().toString("hex");

View File

@ -21,7 +21,7 @@ import {
VaaKey, VaaKey,
DeliveryOverrideArgs, DeliveryOverrideArgs,
parseForwardFailureError, parseForwardFailureError,
parseRefundStatus parseRefundStatus,
} from "../structs"; } from "../structs";
import { import {
DeliveryProvider, DeliveryProvider,

View File

@ -19,7 +19,7 @@ export type SendOptionalParams = {
chainId?: ChainId; chainId?: ChainId;
emitterAddress: string; emitterAddress: string;
sequenceNumber: ethers.BigNumberish; sequenceNumber: ethers.BigNumberish;
} },
]; ];
deliveryProviderAddress?: string; deliveryProviderAddress?: string;
wormholeRelayerAddress?: string; wormholeRelayerAddress?: string;

View File

@ -7,7 +7,7 @@ export enum RelayerPayloadId {
} }
export enum ExecutionInfoVersion { export enum ExecutionInfoVersion {
EVM_V1 = 0 EVM_V1 = 0,
} }
export enum DeliveryStatus { export enum DeliveryStatus {
@ -26,16 +26,21 @@ export enum RefundStatus {
RefundFail = "Refund Fail", RefundFail = "Refund Fail",
CrossChainRefundSent = "Cross Chain Refund Sent", CrossChainRefundSent = "Cross Chain Refund Sent",
CrossChainRefundFailProviderNotSupported = "Cross Chain Refund Fail - Provider does not support the refund chain", CrossChainRefundFailProviderNotSupported = "Cross Chain Refund Fail - Provider does not support the refund chain",
CrossChainRefundFailNotEnough = "Cross Chain Refund Fail - Refund too low for cross chain refund" CrossChainRefundFailNotEnough = "Cross Chain Refund Fail - Refund too low for cross chain refund",
} }
export function parseRefundStatus(index: number) { export function parseRefundStatus(index: number) {
return index === 0 ? RefundStatus.RefundSent return index === 0
: index === 1 ? RefundStatus.RefundFail ? RefundStatus.RefundSent
: index === 2 ? RefundStatus.CrossChainRefundSent : index === 1
: index === 3 ? RefundStatus.CrossChainRefundFailProviderNotSupported ? RefundStatus.RefundFail
: index === 4 ? RefundStatus.CrossChainRefundFailNotEnough : index === 2
: RefundStatus.CrossChainRefundFailProviderNotSupported; ? RefundStatus.CrossChainRefundSent
: index === 3
? RefundStatus.CrossChainRefundFailProviderNotSupported
: index === 4
? RefundStatus.CrossChainRefundFailNotEnough
: RefundStatus.CrossChainRefundFailProviderNotSupported;
} }
export interface VaaKey { export interface VaaKey {
@ -184,7 +189,7 @@ export function parseWormholeRelayerSend(bytes: Buffer): DeliveryInstruction {
refundDeliveryProvider, refundDeliveryProvider,
sourceDeliveryProvider, sourceDeliveryProvider,
senderAddress, senderAddress,
vaaKeys: messages vaaKeys: messages,
}; };
} }
@ -200,23 +205,22 @@ function parseVaaKey(bytes: Buffer, idx: number): [VaaKey, number] {
const version = bytes.readUInt8(idx); const version = bytes.readUInt8(idx);
idx += 1; idx += 1;
const chainId = bytes.readUInt16BE(idx); const chainId = bytes.readUInt16BE(idx);
idx += 2; idx += 2;
const emitterAddress = bytes.slice(idx, idx + 32); const emitterAddress = bytes.slice(idx, idx + 32);
idx += 32; idx += 32;
const sequence = ethers.BigNumber.from( const sequence = ethers.BigNumber.from(
Uint8Array.prototype.subarray.call(bytes, idx, idx + 8) Uint8Array.prototype.subarray.call(bytes, idx, idx + 8)
); );
idx += 8; idx += 8;
return [ return [
{ {
chainId, chainId,
emitterAddress, emitterAddress,
sequence, sequence,
}, },
idx, idx,
]; ];
} }
export function parseEVMExecutionInfoV1( export function parseEVMExecutionInfoV1(
@ -226,7 +230,7 @@ export function parseEVMExecutionInfoV1(
idx += 31; idx += 31;
const version = bytes.readUInt8(idx); const version = bytes.readUInt8(idx);
idx += 1; idx += 1;
if(version !== ExecutionInfoVersion.EVM_V1) { if (version !== ExecutionInfoVersion.EVM_V1) {
throw new Error("Unexpected Execution Info version"); throw new Error("Unexpected Execution Info version");
} }
const gasLimit = ethers.BigNumber.from( const gasLimit = ethers.BigNumber.from(
@ -267,11 +271,9 @@ export function parseWormholeRelayerResend(
let newEncodedExecutionInfo; let newEncodedExecutionInfo;
[newEncodedExecutionInfo, idx] = parsePayload(bytes, idx); [newEncodedExecutionInfo, idx] = parsePayload(bytes, idx);
const newSourceDeliveryProvider = bytes.slice(idx, idx + 32); const newSourceDeliveryProvider = bytes.slice(idx, idx + 32);
idx += 32; idx += 32;
const newSenderAddress = bytes.slice(idx, idx + 32); const newSenderAddress = bytes.slice(idx, idx + 32);
idx += 32; idx += 32;
return { return {
@ -280,14 +282,12 @@ export function parseWormholeRelayerResend(
newRequestedReceiverValue, newRequestedReceiverValue,
newEncodedExecutionInfo, newEncodedExecutionInfo,
newSourceDeliveryProvider, newSourceDeliveryProvider,
newSenderAddress newSenderAddress,
}; };
} }
export function executionInfoToString( export function executionInfoToString(encodedExecutionInfo: Buffer): string {
encodedExecutionInfo: Buffer const [parsed] = parseEVMExecutionInfoV1(encodedExecutionInfo, 0);
): string {
const [parsed,] = parseEVMExecutionInfoV1(encodedExecutionInfo, 0)
return `Gas limit: ${parsed.gasLimit}, Target chain refund per unit gas unused: ${parsed.targetChainRefundPerGasUnused}`; return `Gas limit: ${parsed.gasLimit}, Target chain refund per unit gas unused: ${parsed.targetChainRefundPerGasUnused}`;
} }
@ -311,11 +311,11 @@ export function deliveryInstructionsPrintable(
} }
export function vaaKeyPrintable(ix: VaaKey): StringLeaves<VaaKey> { export function vaaKeyPrintable(ix: VaaKey): StringLeaves<VaaKey> {
return { return {
chainId: ix.chainId?.toString(), chainId: ix.chainId?.toString(),
emitterAddress: ix.emitterAddress?.toString("hex"), emitterAddress: ix.emitterAddress?.toString("hex"),
sequence: ix.sequence?.toString(), sequence: ix.sequence?.toString(),
}; };
} }
export function redeliveryInstructionPrintable( export function redeliveryInstructionPrintable(
@ -327,7 +327,7 @@ export function redeliveryInstructionPrintable(
newRequestedReceiverValue: ix.newRequestedReceiverValue.toString(), newRequestedReceiverValue: ix.newRequestedReceiverValue.toString(),
newEncodedExecutionInfo: executionInfoToString(ix.newEncodedExecutionInfo), newEncodedExecutionInfo: executionInfoToString(ix.newEncodedExecutionInfo),
newSourceDeliveryProvider: ix.newSourceDeliveryProvider.toString("hex"), newSourceDeliveryProvider: ix.newSourceDeliveryProvider.toString("hex"),
newSenderAddress: ix.newSenderAddress.toString("hex") newSenderAddress: ix.newSenderAddress.toString("hex"),
}; };
} }
@ -353,13 +353,11 @@ export function packOverrides(overrides: DeliveryOverrideArgs): string {
return "0x" + packed; return "0x" + packed;
} }
export function parseForwardFailureError( export function parseForwardFailureError(bytes: Buffer): string {
bytes: Buffer
): string {
let idx = 4; let idx = 4;
idx += 32; idx += 32;
if(bytes.length <= idx) { if (bytes.length <= idx) {
return `Delivery Provider failed in performing forward` return `Delivery Provider failed in performing forward`;
} }
try { try {
const amountOfFunds = ethers.BigNumber.from( const amountOfFunds = ethers.BigNumber.from(
@ -369,12 +367,12 @@ export function parseForwardFailureError(
const amountOfFundsNeeded = ethers.BigNumber.from( const amountOfFundsNeeded = ethers.BigNumber.from(
Uint8Array.prototype.subarray.call(bytes, idx, idx + 32) Uint8Array.prototype.subarray.call(bytes, idx, idx + 32)
); );
return `Not enough funds leftover for forward: Had ${ethers.utils.formatEther(amountOfFunds)} and needed ${ethers.utils.formatEther(amountOfFundsNeeded)}.` return `Not enough funds leftover for forward: Had ${ethers.utils.formatEther(
amountOfFunds
)} and needed ${ethers.utils.formatEther(amountOfFundsNeeded)}.`;
} catch (err) { } catch (err) {
return `Delivery Provider unexpectedly failed in performing forward` return `Delivery Provider unexpectedly failed in performing forward`;
} }
} }
export function parseOverrideInfoFromDeliveryEvent( export function parseOverrideInfoFromDeliveryEvent(
@ -397,7 +395,7 @@ export function parseOverrideInfoFromDeliveryEvent(
return { return {
newReceiverValue, newReceiverValue,
newExecutionInfo, newExecutionInfo,
redeliveryHash redeliveryHash,
}; };
} }

View File

@ -4,7 +4,9 @@ import { IdlEvent } from "../../anchor";
export class WormholeEventsCoder implements EventCoder { export class WormholeEventsCoder implements EventCoder {
constructor(_idl: Idl) {} constructor(_idl: Idl) {}
decode<E extends IdlEvent = IdlEvent, T = Record<string, string>>(_log: string): Event<E, T> | null { decode<E extends IdlEvent = IdlEvent, T = Record<string, string>>(
_log: string
): Event<E, T> | null {
throw new Error("Wormhole program does not have events"); throw new Error("Wormhole program does not have events");
} }
} }

View File

@ -2,111 +2,111 @@
// //
// https://github.com/coral-xyz/anchor/blob/master/ts/packages/anchor/src/coder/borsh/idl.ts // https://github.com/coral-xyz/anchor/blob/master/ts/packages/anchor/src/coder/borsh/idl.ts
import * as borsh from "@coral-xyz/borsh" import * as borsh from "@coral-xyz/borsh";
import { Layout } from "buffer-layout"; import { Layout } from "buffer-layout";
import { IdlField, IdlTypeDef } from "../../anchor"; import { IdlField, IdlTypeDef } from "../../anchor";
import { camelCase } from "lodash"; import { camelCase } from "lodash";
export class IdlCoder { export class IdlCoder {
public static fieldLayout( public static fieldLayout(
field: { name?: string } & Pick<IdlField, "type">, field: { name?: string } & Pick<IdlField, "type">,
types?: IdlTypeDef[] types?: IdlTypeDef[]
): Layout { ): Layout {
const fieldName = const fieldName =
field.name !== undefined ? camelCase(field.name) : undefined; field.name !== undefined ? camelCase(field.name) : undefined;
switch (field.type) { switch (field.type) {
case "bool": { case "bool": {
return borsh.bool(fieldName); return borsh.bool(fieldName);
} }
case "u8": { case "u8": {
return borsh.u8(fieldName); return borsh.u8(fieldName);
} }
case "i8": { case "i8": {
return borsh.i8(fieldName); return borsh.i8(fieldName);
} }
case "u16": { case "u16": {
return borsh.u16(fieldName); return borsh.u16(fieldName);
} }
case "i16": { case "i16": {
return borsh.i16(fieldName); return borsh.i16(fieldName);
} }
case "u32": { case "u32": {
return borsh.u32(fieldName); return borsh.u32(fieldName);
} }
case "i32": { case "i32": {
return borsh.i32(fieldName); return borsh.i32(fieldName);
} }
case "f32": { case "f32": {
return borsh.f32(fieldName); return borsh.f32(fieldName);
} }
case "u64": { case "u64": {
return borsh.u64(fieldName); return borsh.u64(fieldName);
} }
case "i64": { case "i64": {
return borsh.i64(fieldName); return borsh.i64(fieldName);
} }
case "f64": { case "f64": {
return borsh.f64(fieldName); return borsh.f64(fieldName);
} }
case "u128": { case "u128": {
return borsh.u128(fieldName); return borsh.u128(fieldName);
} }
case "i128": { case "i128": {
return borsh.i128(fieldName); return borsh.i128(fieldName);
} }
case "u256": { case "u256": {
return borsh.u256(fieldName); return borsh.u256(fieldName);
} }
case "i256": { case "i256": {
return borsh.i256(fieldName); return borsh.i256(fieldName);
} }
case "bytes": { case "bytes": {
return borsh.vecU8(fieldName); return borsh.vecU8(fieldName);
} }
case "string": { case "string": {
return borsh.str(fieldName); return borsh.str(fieldName);
} }
case "publicKey": { case "publicKey": {
return borsh.publicKey(fieldName); return borsh.publicKey(fieldName);
} }
default: { default: {
if ("vec" in field.type) { if ("vec" in field.type) {
return borsh.vec( return borsh.vec(
IdlCoder.fieldLayout( IdlCoder.fieldLayout(
{
name: undefined,
type: field.type.vec,
},
types
),
fieldName
);
} else if ("option" in field.type) {
return borsh.option(
IdlCoder.fieldLayout(
{
name: undefined,
type: field.type.option,
},
types
),
fieldName
);
} else if ("array" in field.type) {
let arrayTy = field.type.array[0];
let arrayLen = field.type.array[1];
let innerLayout = IdlCoder.fieldLayout(
{ {
name: undefined, name: undefined,
type: arrayTy, type: field.type.vec,
}, },
types types
); ),
return borsh.array(innerLayout, arrayLen, fieldName); fieldName
} else { );
throw new Error(`Not yet implemented: ${field}`); } else if ("option" in field.type) {
} return borsh.option(
IdlCoder.fieldLayout(
{
name: undefined,
type: field.type.option,
},
types
),
fieldName
);
} else if ("array" in field.type) {
let arrayTy = field.type.array[0];
let arrayLen = field.type.array[1];
let innerLayout = IdlCoder.fieldLayout(
{
name: undefined,
type: arrayTy,
},
types
);
return borsh.array(innerLayout, arrayLen, fieldName);
} else {
throw new Error(`Not yet implemented: ${field}`);
} }
} }
} }
} }
}

View File

@ -9,4 +9,4 @@ export class WormholeStateCoder implements StateCoder {
decode<T = any>(_ix: Buffer): T { decode<T = any>(_ix: Buffer): T {
throw new Error("Wormhole program does not have state"); throw new Error("Wormhole program does not have state");
} }
} }

View File

@ -1,12 +1,12 @@
import { Idl, TypesCoder } from "@project-serum/anchor"; import { Idl, TypesCoder } from "@project-serum/anchor";
export class WormholeTypesCoder implements TypesCoder { export class WormholeTypesCoder implements TypesCoder {
constructor(_idl: Idl) {} constructor(_idl: Idl) {}
encode<T = any>(_name: string, _type: T): Buffer { encode<T = any>(_name: string, _type: T): Buffer {
throw new Error("Wormhole program does not have user-defined types"); throw new Error("Wormhole program does not have user-defined types");
} }
decode<T = any>(_name: string, _typeData: Buffer): T { decode<T = any>(_name: string, _typeData: Buffer): T {
throw new Error("Wormhole program does not have user-defined types"); throw new Error("Wormhole program does not have user-defined types");
} }
} }

View File

@ -23,11 +23,9 @@ export function createInitializeInstruction(
): TransactionInstruction { ): TransactionInstruction {
const methods = createReadOnlyWormholeProgramInterface( const methods = createReadOnlyWormholeProgramInterface(
wormholeProgramId wormholeProgramId
).methods.initialize( ).methods.initialize(guardianSetExpirationTime, new BN(fee.toString()), [
guardianSetExpirationTime, ...initialGuardians,
new BN(fee.toString()), ]);
[...initialGuardians]
);
// @ts-ignore // @ts-ignore
return methods._ixFn(...methods._args, { return methods._ixFn(...methods._args, {

View File

@ -70,7 +70,7 @@ export async function createVerifySignaturesInstructions(
for (let i = 0; i < Math.ceil(guardianSignatures.length / batchSize); ++i) { for (let i = 0; i < Math.ceil(guardianSignatures.length / batchSize); ++i) {
const start = i * batchSize; const start = i * batchSize;
const end = Math.min(guardianSignatures.length, (i + 1) * batchSize); const end = Math.min(guardianSignatures.length, (i + 1) * batchSize);
const signatureStatus = new Array(MAX_LEN_GUARDIAN_KEYS).fill(-1); const signatureStatus = new Array(MAX_LEN_GUARDIAN_KEYS).fill(-1);
const signatures: Buffer[] = []; const signatures: Buffer[] = [];
const keys: Buffer[] = []; const keys: Buffer[] = [];
@ -123,9 +123,10 @@ function createVerifySignaturesInstruction(
signatureSet: PublicKeyInitData, signatureSet: PublicKeyInitData,
signatureStatus: number[] signatureStatus: number[]
): TransactionInstruction { ): TransactionInstruction {
const methods = createReadOnlyWormholeProgramInterface( const methods =
wormholeProgramId createReadOnlyWormholeProgramInterface(
).methods.verifySignatures(signatureStatus); wormholeProgramId
).methods.verifySignatures(signatureStatus);
// @ts-ignore // @ts-ignore
return methods._ixFn(...methods._args, { return methods._ixFn(...methods._args, {

View File

@ -109,7 +109,7 @@ export const tryUint8ArrayToNative = (
} else if (chainId === CHAIN_ID_XPLA) { } else if (chainId === CHAIN_ID_XPLA) {
return humanAddress("xpla", a.slice(-20)); return humanAddress("xpla", a.slice(-20));
} else if (chainId === CHAIN_ID_SEI) { } else if (chainId === CHAIN_ID_SEI) {
return humanAddress("sei", a.slice(-20)); return humanAddress("sei", a.slice(-20));
} else if (chainId === CHAIN_ID_NEAR) { } else if (chainId === CHAIN_ID_NEAR) {
throw Error("uint8ArrayToNative: Use tryHexToNativeStringNear instead."); throw Error("uint8ArrayToNative: Use tryHexToNativeStringNear instead.");
} else if (chainId === CHAIN_ID_OSMOSIS) { } else if (chainId === CHAIN_ID_OSMOSIS) {

View File

@ -63,12 +63,14 @@ export const EVMChainNames: ReadonlyArray<ChainName> = [
] as const; ] as const;
export type EVMChainName = (typeof EVMChainNames)[number]; export type EVMChainName = (typeof EVMChainNames)[number];
/* /*
* *
* All the Solana-based chain names that Wormhole supports * All the Solana-based chain names that Wormhole supports
*/ */
export const SolanaChainNames: ReadonlyArray<ChainName> = ["solana", "pythnet"] as const; export const SolanaChainNames: ReadonlyArray<ChainName> = [
"solana",
"pythnet",
] as const;
export type SolanaChainName = (typeof SolanaChainNames)[number]; export type SolanaChainName = (typeof SolanaChainNames)[number];
export const CosmWasmChainNames: ReadonlyArray<ChainName> = [ export const CosmWasmChainNames: ReadonlyArray<ChainName> = [
@ -81,7 +83,10 @@ export const CosmWasmChainNames: ReadonlyArray<ChainName> = [
export type CosmWasmChainName = (typeof CosmWasmChainNames)[number]; export type CosmWasmChainName = (typeof CosmWasmChainNames)[number];
// TODO: why? these are dupe of entries in CosmWasm // TODO: why? these are dupe of entries in CosmWasm
export const TerraChainNames: ReadonlyArray<ChainName> = ["terra", "terra2"] as const; export const TerraChainNames: ReadonlyArray<ChainName> = [
"terra",
"terra2",
] as const;
export type TerraChainName = (typeof TerraChainNames)[number]; export type TerraChainName = (typeof TerraChainNames)[number];
export type Contracts = { export type Contracts = {
@ -810,7 +815,7 @@ export function isEVMChain(
chain: ChainId | ChainName chain: ChainId | ChainName
): chain is EVMChainId | EVMChainName { ): chain is EVMChainId | EVMChainName {
const chainName = coalesceChainName(chain); const chainName = coalesceChainName(chain);
return EVMChainNames.includes(chainName) return EVMChainNames.includes(chainName);
} }
export function isCosmWasmChain( export function isCosmWasmChain(

View File

@ -384,7 +384,7 @@ function serialiseCoreContractUpgrade(payload: CoreContractUpgrade): string {
} }
export interface PortalContractUpgrade< export interface PortalContractUpgrade<
Module extends "NFTBridge" | "TokenBridge" Module extends "NFTBridge" | "TokenBridge",
> { > {
module: Module; module: Module;
type: "ContractUpgrade"; type: "ContractUpgrade";
@ -394,7 +394,7 @@ export interface PortalContractUpgrade<
// Parse a portal contract upgrade payload // Parse a portal contract upgrade payload
function portalContractUpgradeParser< function portalContractUpgradeParser<
Module extends "NFTBridge" | "TokenBridge" Module extends "NFTBridge" | "TokenBridge",
>(module: Module): P<PortalContractUpgrade<Module>> { >(module: Module): P<PortalContractUpgrade<Module>> {
return new P( return new P(
new Parser() new Parser()
@ -423,7 +423,7 @@ function portalContractUpgradeParser<
} }
function serialisePortalContractUpgrade< function serialisePortalContractUpgrade<
Module extends "NFTBridge" | "TokenBridge" Module extends "NFTBridge" | "TokenBridge",
>(payload: PortalContractUpgrade<Module>): string { >(payload: PortalContractUpgrade<Module>): string {
const body = [ const body = [
encode("bytes32", encodeString(payload.module)), encode("bytes32", encodeString(payload.module)),
@ -438,7 +438,7 @@ function serialisePortalContractUpgrade<
// Registrations // Registrations
export interface PortalRegisterChain< export interface PortalRegisterChain<
Module extends "NFTBridge" | "TokenBridge" Module extends "NFTBridge" | "TokenBridge",
> { > {
module: Module; module: Module;
type: "RegisterChain"; type: "RegisterChain";
@ -479,7 +479,7 @@ function portalRegisterChainParser<Module extends "NFTBridge" | "TokenBridge">(
} }
function serialisePortalRegisterChain< function serialisePortalRegisterChain<
Module extends "NFTBridge" | "TokenBridge" Module extends "NFTBridge" | "TokenBridge",
>(payload: PortalRegisterChain<Module>): string { >(payload: PortalRegisterChain<Module>): string {
const body = [ const body = [
encode("bytes32", encodeString(payload.module)), encode("bytes32", encodeString(payload.module)),