Skip to content

Commit

Permalink
Client/js: Add Info Registrations (wormhole-foundation#3035)
Browse files Browse the repository at this point in the history
* Client/js: Add Info Registrations

Change-Id: Ib123dfe895d88c5574f575b16dfc3e6775d81f2a

* Fix build errors

Change-Id: Ifcacb564fc40f14337ab472ece617a2955b579c5
  • Loading branch information
bruce-riley authored Jun 9, 2023
1 parent 7f74b92 commit 1ae38c8
Show file tree
Hide file tree
Showing 13 changed files with 868 additions and 140 deletions.
282 changes: 179 additions & 103 deletions clients/js/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion clients/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
],
"dependencies": {
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
"@certusone/wormhole-sdk": "^0.9.16",
"@certusone/wormhole-sdk": "^0.9.18",
"@cosmjs/encoding": "^0.26.2",
"@injectivelabs/networks": "^1.10.7",
"@injectivelabs/sdk-ts": "^1.10.47",
Expand Down
64 changes: 64 additions & 0 deletions clients/js/src/aptos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { sha3_256 } from "js-sha3";
import { NETWORKS } from "./consts";
import { Network } from "./utils";
import { Payload, impossible } from "./vaa";
import { CHAINS, ensureHexPrefix } from "@certusone/wormhole-sdk";
import { TokenBridgeState } from "@certusone/wormhole-sdk/lib/esm/aptos/types";

export async function execute_aptos(
payload: Payload,
Expand Down Expand Up @@ -335,3 +337,65 @@ function hex(x: string): Buffer {
"hex"
);
}

export async function queryRegistrationsAptos(
network: Network,
module: "Core" | "NFTBridge" | "TokenBridge"
): Promise<Object> {
const n = NETWORKS[network]["aptos"];
const client = new AptosClient(n.rpc);
const contracts = CONTRACTS[network]["aptos"];
let stateObjectId: string | undefined;

switch (module) {
case "TokenBridge":
stateObjectId = contracts.token_bridge;
if (stateObjectId === undefined) {
throw Error(`Unknown token bridge contract on ${network} for Aptos`);
}
break;
default:
throw new Error(`Invalid module: ${module}`);
}

stateObjectId = ensureHexPrefix(stateObjectId);
const state = (
await client.getAccountResource(
stateObjectId,
`${stateObjectId}::state::State`
)
).data as TokenBridgeState;

const handle = state.registered_emitters.handle;

// Query the bridge registration for all the chains in parallel.
const registrations: string[][] = await Promise.all(
Object.entries(CHAINS)
.filter(([cname, _]) => cname !== "aptos" && cname !== "unset")
.map(async ([cname, cid]) => [
cname,
await (async () => {
let result = null;
try {
result = await client.getTableItem(handle, {
key_type: "u64",
value_type: "vector<u8>",
key: cid.toString(),
});
} catch {
// Not logging anything because a chain not registered returns an error.
}

return result;
})(),
])
);

const results: { [key: string]: string } = {};
for (let [cname, queryResponse] of registrations) {
if (queryResponse) {
results[cname] = queryResponse;
}
}
return results;
}
79 changes: 79 additions & 0 deletions clients/js/src/chains/sei/registrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { getCosmWasmClient } from "@sei-js/core";
import {
ChainName,
CHAINS,
CONTRACTS,
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
import { NETWORKS } from "../../consts/networks";
import { Network } from "../../utils";

export async function queryRegistrationsSei(
network: Network,
module: "Core" | "NFTBridge" | "TokenBridge"
): Promise<Object> {
const chain = "sei" as ChainName;
const n = NETWORKS[network][chain];
const contracts = CONTRACTS[network][chain];

let target_contract: string | undefined;

switch (module) {
case "TokenBridge":
target_contract = contracts.token_bridge;
break;
case "NFTBridge":
target_contract = contracts.nft_bridge;
break;
default:
throw new Error(`Invalid module: ${module}`);
}

if (!target_contract) {
throw new Error(`Contract for ${module} on ${network} does not exist`);
}

if (n.rpc === undefined) {
throw new Error(`RPC for ${module} on ${network} does not exist`);
}

// Create a CosmWasmClient
const client = await getCosmWasmClient(n.rpc);

// Query the bridge registration for all the chains in parallel.
const registrations = await Promise.all(
Object.entries(CHAINS)
.filter(([c_name, _]) => c_name !== chain && c_name !== "unset")
.map(async ([c_name, c_id]) => [
c_name,
await (async () => {
let query_msg = {
chain_registration: {
chain: c_id,
},
};

let result = null;
try {
result = await client.queryContractSmart(
target_contract as string,
query_msg
);
} catch {
// Not logging anything because a chain not registered returns an error.
}

return result;
})(),
])
);

const results: { [key: string]: string } = {};
for (let [c_name, queryResponse] of registrations) {
if (queryResponse) {
results[c_name] = Buffer.from(queryResponse.address, "base64").toString(
"hex"
);
}
}
return results;
}
57 changes: 57 additions & 0 deletions clients/js/src/chains/sui/registrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { getObjectFields } from "@certusone/wormhole-sdk/lib/esm/sui";
import {
CHAIN_ID_TO_NAME,
CONTRACTS,
} from "@certusone/wormhole-sdk/lib/esm/utils/consts";
import { NETWORKS } from "../../consts/networks";
import { Network } from "../../utils";
import { getProvider } from "./utils";
import { ChainId } from "@certusone/wormhole-sdk";

export async function queryRegistrationsSui(
network: Network,
module: "Core" | "NFTBridge" | "TokenBridge"
): Promise<Object> {
const n = NETWORKS[network]["sui"];
const provider = getProvider(network, n.rpc);
const contracts = CONTRACTS[network]["sui"];
let state_object_id: string;

switch (module) {
case "TokenBridge":
state_object_id = contracts.token_bridge;
if (state_object_id === undefined) {
throw Error(`Unknown token bridge contract on ${network} for Sui`);
}
break;
default:
throw new Error(`Invalid module: ${module}`);
}

const state = await getObjectFields(provider, state_object_id);
const emitterRegistryId = state!.emitter_registry.fields.id.id;

// TODO: handle pagination
// - recursive: https://github.com/wormhole-foundation/wormhole/blob/7608b2b740df5d4c2551daaf4d620eac81c07790/sdk/js/src/sui/utils.ts#L175
// - iterative: https://github.com/wormhole-foundation/wormhole/blob/7608b2b740df5d4c2551daaf4d620eac81c07790/sdk/js/src/sui/utils.ts#L199
const emitterRegistry = await provider.getDynamicFields({
parentId: emitterRegistryId,
});

const results: { [key: string]: string } = {};
for (let idx = 0; idx < emitterRegistry.data.length; idx++) {
const chainId = emitterRegistry.data[idx].name.value as ChainId;
for (const { objectId } of emitterRegistry.data.slice(idx, idx + 1)) {
const emitter = (await provider.getObject({
id: objectId,
options: { showContent: true },
})) as any;
const emitterAddress: Uint8Array =
emitter.data?.content?.fields.value.fields.value.fields.data;
const emitterAddrStr = Buffer.from(emitterAddress).toString("hex");
results[CHAIN_ID_TO_NAME[chainId]] = emitterAddrStr;
}
}

return results;
}
2 changes: 2 additions & 0 deletions clients/js/src/cmds/info/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as chainId from "./chainId";
import * as contract from "./contract";
import * as emitter from "./emitter";
import * as origin from "./origin";
import * as registrations from "./registrations";
import * as rpc from "./rpc";
import * as wrapped from "./wrapped";

Expand All @@ -15,6 +16,7 @@ export const builder = (y: typeof yargs) =>
.command(contract)
.command(emitter)
.command(origin)
.command(registrations)
.command(rpc)
.command(wrapped);
export const handler = () => {};
Loading

0 comments on commit 1ae38c8

Please sign in to comment.