explorer/wormhole (#15948)

* feat: add lending instruction names

* chore: capitalize words

* feat: add wormhole card

* feat: add asset contract

* chore: format
This commit is contained in:
B 2021-03-17 10:53:50 -05:00 committed by GitHub
parent 40997d0aef
commit 9b26c45be6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 129 additions and 13 deletions

View File

@ -18,6 +18,19 @@ import { useTokenRegistry } from "providers/mints/token-registry";
import { BigNumber } from "bignumber.js";
import { Copyable } from "components/common/Copyable";
const getEthAddress = (link?: string) => {
let address = "";
if (link) {
const extractEth = link.match(/0x[a-fA-F0-9]{40,64}/);
if (extractEth) {
address = extractEth[0];
}
}
return address;
};
export function TokenAccountSection({
account,
tokenAccount,
@ -62,16 +75,12 @@ function MintAccountCard({
const tokenInfo = tokenRegistry.get(mintAddress);
let bridgeContractAddress = tokenInfo?.extensions?.address;
if (tokenInfo?.extensions?.bridgeContract && !bridgeContractAddress) {
const extractEth = tokenInfo.extensions.bridgeContract.match(
/0x[a-fA-F0-9]{40,64}/
);
if (extractEth) {
bridgeContractAddress = extractEth[0];
}
}
const bridgeContractAddress = getEthAddress(
tokenInfo?.extensions?.bridgeContract
);
const assetContractAddress = getEthAddress(
tokenInfo?.extensions?.assetContract
);
return (
<div className="card">
@ -145,7 +154,7 @@ function MintAccountCard({
)}
{tokenInfo?.extensions?.bridgeContract && bridgeContractAddress && (
<tr>
<td>Wormhole Bridge Contract</td>
<td>Bridge Contract</td>
<td className="text-lg-right">
<Copyable text={bridgeContractAddress}>
<a
@ -159,6 +168,22 @@ function MintAccountCard({
</td>
</tr>
)}
{tokenInfo?.extensions?.assetContract && assetContractAddress && (
<tr>
<td>Bridged Asset Contract</td>
<td className="text-lg-right">
<Copyable text={assetContractAddress}>
<a
href={tokenInfo.extensions.bridgeContract}
target="_blank"
rel="noreferrer"
>
{assetContractAddress}
</a>
</Copyable>
</td>
</tr>
)}
</TableCardBody>
</div>
);

View File

@ -0,0 +1,46 @@
import React from "react";
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
import { InstructionCard } from "./InstructionCard";
import { useCluster } from "providers/cluster";
import { reportError } from "utils/sentry";
import { parsWormholeInstructionTitle } from "./wormhole/types";
export function WormholeDetailsCard({
ix,
index,
result,
signature,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
signature: string;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { url } = useCluster();
let title;
try {
title = parsWormholeInstructionTitle(ix);
} catch (error) {
reportError(error, {
url: url,
signature: signature,
});
}
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title={`Wormhole: ${title || "Unknown"}`}
innerCards={innerCards}
childIndex={childIndex}
defaultRaw
/>
);
}

View File

@ -28,7 +28,7 @@ export function parseTokenLendingInstructionTitle(
const code = instruction.data[0];
if (!(code in INSTRUCTION_LOOKUP)) {
throw new Error(`Unrecognized Token Swap instruction code: ${code}`);
throw new Error(`Unrecognized Token Lending instruction code: ${code}`);
}
return INSTRUCTION_LOOKUP[code];

View File

@ -0,0 +1,34 @@
import { TransactionInstruction } from "@solana/web3.js";
export const PROGRAM_IDS: string[] = [
"WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC", // mainnet / testnet / devnet
];
const INSTRUCTION_LOOKUP: { [key: number]: string } = {
0: "Initialize Bridge",
1: "Transfer Assets Out",
2: "Post VAA",
3: "Evict Transfer Proposal",
4: "Evict Claimed VAA",
5: "Poke Proposal",
6: "Verify Signatures",
7: "Create Wrapped Asset",
};
export function isWormholeInstruction(
instruction: TransactionInstruction
): boolean {
return PROGRAM_IDS.includes(instruction.programId.toBase58());
}
export function parsWormholeInstructionTitle(
instruction: TransactionInstruction
): string {
const code = instruction.data[0];
if (!(code in INSTRUCTION_LOOKUP)) {
throw new Error(`Unrecognized Wormhole instruction code: ${code}`);
}
return INSTRUCTION_LOOKUP[code];
}

View File

@ -18,6 +18,7 @@ import { SystemDetailsCard } from "components/instruction/system/SystemDetailsCa
import { TokenDetailsCard } from "components/instruction/token/TokenDetailsCard";
import { TokenLendingDetailsCard } from "components/instruction/TokenLendingDetailsCard";
import { TokenSwapDetailsCard } from "components/instruction/TokenSwapDetailsCard";
import { WormholeDetailsCard } from "components/instruction/WormholeDetailsCard";
import { UnknownDetailsCard } from "components/instruction/UnknownDetailsCard";
import {
SignatureProps,
@ -35,6 +36,7 @@ import {
import { Cluster, useCluster } from "providers/cluster";
import { BpfUpgradeableLoaderDetailsCard } from "components/instruction/bpf-upgradeable-loader/BpfUpgradeableLoaderDetailsCard";
import { VoteDetailsCard } from "components/instruction/vote/VoteDetailsCard";
import { isWormholeInstruction } from "components/instruction/wormhole/types";
export type InstructionDetailsProps = {
tx: ParsedTransaction;
@ -212,6 +214,8 @@ function renderInstructionCard({
return <TokenSwapDetailsCard key={key} {...props} />;
} else if (isTokenLendingInstruction(transactionIx)) {
return <TokenLendingDetailsCard key={key} {...props} />;
} else if (isWormholeInstruction(transactionIx)) {
return <WormholeDetailsCard key={key} {...props} />;
} else {
return <UnknownDetailsCard key={key} {...props} />;
}

View File

@ -14,6 +14,7 @@ import {
Transaction,
PartiallyDecodedInstruction,
ParsedInstruction,
Secp256k1Program,
} from "@solana/web3.js";
import { Cluster } from "providers/cluster";
import { SerumMarketRegistry } from "serumMarketRegistry";
@ -27,6 +28,7 @@ export enum PROGRAM_NAMES {
STAKE = "Stake Program",
SYSTEM = "System Program",
VOTE = "Vote Program",
SECP256K1 = "Secp256k1 Program",
// spl
ASSOCIATED_TOKEN = "Associated Token Program",
@ -38,6 +40,7 @@ export enum PROGRAM_NAMES {
TOKEN = "Token Program",
// other
WORMHOLE = "Wormhole",
BONFIDA_POOL = "Bonfida Pool Program",
BREAK_SOLANA = "Break Solana Program",
RAYDIUM_LIQUIDITY_1 = "Raydium Liquidity Pool Program v1",
@ -65,6 +68,7 @@ export const PROGRAM_DEPLOYMENTS = {
[PROGRAM_NAMES.STAKE]: ALL_CLUSTERS,
[PROGRAM_NAMES.SYSTEM]: ALL_CLUSTERS,
[PROGRAM_NAMES.VOTE]: ALL_CLUSTERS,
[PROGRAM_NAMES.SECP256K1]: ALL_CLUSTERS,
// spl
[PROGRAM_NAMES.ASSOCIATED_TOKEN]: ALL_CLUSTERS,
@ -76,6 +80,7 @@ export const PROGRAM_DEPLOYMENTS = {
[PROGRAM_NAMES.TOKEN]: ALL_CLUSTERS,
// other
[PROGRAM_NAMES.WORMHOLE]: MAINNET_ONLY,
[PROGRAM_NAMES.BONFIDA_POOL]: MAINNET_ONLY,
[PROGRAM_NAMES.BREAK_SOLANA]: LIVE_CLUSTERS,
[PROGRAM_NAMES.RAYDIUM_LIQUIDITY_1]: MAINNET_ONLY,
@ -92,6 +97,7 @@ export const PROGRAM_NAME_BY_ID = {
[StakeProgram.programId.toBase58()]: PROGRAM_NAMES.STAKE,
[SystemProgram.programId.toBase58()]: PROGRAM_NAMES.SYSTEM,
[VOTE_PROGRAM_ID.toBase58()]: PROGRAM_NAMES.VOTE,
[Secp256k1Program.programId.toBase58()]: PROGRAM_NAMES.SECP256K1,
// spl
ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL: PROGRAM_NAMES.ASSOCIATED_TOKEN,
@ -103,6 +109,7 @@ export const PROGRAM_NAME_BY_ID = {
LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi: PROGRAM_NAMES.LENDING,
// other
WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC: PROGRAM_NAMES.WORMHOLE,
WvmTNLpGMVbwJVYztYL4Hnsy82cJhQorxjnnXcRm3b6: PROGRAM_NAMES.BONFIDA_POOL,
BrEAK7zGZ6dM71zUDACDqJnekihmwF15noTddWTsknjC: PROGRAM_NAMES.BREAK_SOLANA,
RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr:
@ -161,7 +168,7 @@ export function tokenLabel(
if (tokenInfo.name === tokenInfo.symbol) {
return tokenInfo.name;
}
return `${tokenInfo.name} (${tokenInfo.symbol})`;
return `${tokenInfo.symbol} - ${tokenInfo.name}`;
}
export function addressLabel(