Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit d266e7c

Browse files
committed
sdk cleanup
1 parent 7761ac6 commit d266e7c

File tree

5 files changed

+413
-385
lines changed

5 files changed

+413
-385
lines changed

sdk/src/consts.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ const DEVNET = [
1818

1919
const MAINNET: any[] = []
2020

21-
type ENV = "mainnet" | "testnet"
22-
23-
export function getCoreRelayerAddressNative(chainId: ChainId, env: Network): string {
21+
export function getWormholeRelayerAddress(chainId: ChainId, env: Network): string {
2422
if (env == "TESTNET") {
2523
const address = TESTNET.find((x) => x.chainId == chainId)?.coreRelayerAddress
2624
if (!address) {
@@ -44,12 +42,12 @@ export function getCoreRelayerAddressNative(chainId: ChainId, env: Network): str
4442
}
4543
}
4644

47-
export function getCoreRelayer(
45+
export function getWormholeRelayer(
4846
chainId: ChainId,
4947
env: Network,
5048
provider: ethers.providers.Provider
5149
): CoreRelayer {
52-
const thisChainsRelayer = getCoreRelayerAddressNative(chainId, env)
50+
const thisChainsRelayer = getWormholeRelayerAddress(chainId, env)
5351
const contract = CoreRelayer__factory.connect(thisChainsRelayer, provider)
5452
return contract
5553
}

sdk/src/main/helpers.ts

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import {
2+
ChainId,
3+
CHAIN_ID_TO_NAME,
4+
CHAINS,
5+
isChain,
6+
CONTRACTS,
7+
getSignedVAAWithRetry,
8+
Network,
9+
parseVaa,
10+
ParsedVaa,
11+
tryNativeToHexString,
12+
} from "@certusone/wormhole-sdk"
13+
import { GetSignedVAAResponse } from "@certusone/wormhole-sdk-proto-web/lib/cjs/publicrpc/v1/publicrpc"
14+
import { Implementation__factory } from "@certusone/wormhole-sdk/lib/cjs/ethers-contracts"
15+
import { BigNumber, ContractReceipt, ethers, providers } from "ethers"
16+
import {
17+
getWormholeRelayer,
18+
getWormholeRelayerAddress,
19+
RPCS_BY_CHAIN,
20+
GUARDIAN_RPC_HOSTS,
21+
} from "../consts"
22+
import {
23+
parseWormholeRelayerPayloadType,
24+
RelayerPayloadId,
25+
parseWormholeRelayerSend,
26+
parseWormholeRelayerResend,
27+
DeliveryInstruction,
28+
DeliveryInstructionsContainer,
29+
RedeliveryByTxHashInstruction,
30+
ExecutionParameters,
31+
MessageInfoType,
32+
DeliveryStatus
33+
} from "../structs"
34+
import { DeliveryEvent } from "../ethers-contracts/CoreRelayer"
35+
type DeliveryTargetInfo = {
36+
status: DeliveryStatus | string
37+
deliveryTxHash: string | null
38+
vaaHash: string | null
39+
sourceChain: number | null
40+
sourceVaaSequence: BigNumber | null
41+
}
42+
43+
44+
export function parseWormholeLog(log: ethers.providers.Log): {
45+
type: RelayerPayloadId
46+
parsed: DeliveryInstructionsContainer | RedeliveryByTxHashInstruction | string
47+
} {
48+
const abi = [
49+
"event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel);",
50+
]
51+
const iface = new ethers.utils.Interface(abi)
52+
const parsed = iface.parseLog(log)
53+
const payload = Buffer.from(parsed.args.payload.substring(2), "hex")
54+
const type = parseWormholeRelayerPayloadType(payload)
55+
if (type == RelayerPayloadId.Delivery) {
56+
return { type, parsed: parseWormholeRelayerSend(payload) }
57+
} else if (type == RelayerPayloadId.Redelivery) {
58+
return { type, parsed: parseWormholeRelayerResend(payload) }
59+
} else {
60+
throw Error("Invalid wormhole log");
61+
}
62+
}
63+
64+
export function printChain(chainId: number) {
65+
return `${CHAIN_ID_TO_NAME[chainId as ChainId]} (Chain ${chainId})`
66+
}
67+
68+
export function getDefaultProvider(network: Network, chainId: ChainId) {
69+
return new ethers.providers.StaticJsonRpcProvider(
70+
RPCS_BY_CHAIN[network][CHAIN_ID_TO_NAME[chainId]]
71+
)
72+
}
73+
74+
75+
export function getBlockRange(provider: ethers.providers.Provider, timestamp?: number): [ethers.providers.BlockTag, ethers.providers.BlockTag] {
76+
return [-2040, "latest"]
77+
}
78+
79+
export async function getWormholeRelayerDeliveryEventsBySourceSequence(
80+
environment: Network,
81+
targetChain: ChainId,
82+
targetChainProvider: ethers.providers.Provider,
83+
sourceChain: number,
84+
sourceVaaSequence: BigNumber,
85+
blockStartNumber: ethers.providers.BlockTag,
86+
blockEndNumber: ethers.providers.BlockTag
87+
): Promise<DeliveryTargetInfo[]> {
88+
const coreRelayer = getWormholeRelayer(targetChain, environment, targetChainProvider)
89+
90+
const deliveryEvents = coreRelayer.filters.Delivery(
91+
null,
92+
sourceChain,
93+
sourceVaaSequence
94+
)
95+
96+
// There is a max limit on RPCs sometimes for how many blocks to query
97+
return await transformDeliveryEvents(
98+
await coreRelayer.queryFilter(deliveryEvents, blockStartNumber, blockEndNumber),
99+
targetChainProvider
100+
)
101+
}
102+
103+
export function deliveryStatus(status: number) {
104+
switch (status) {
105+
case 0:
106+
return DeliveryStatus.DeliverySuccess
107+
case 1:
108+
return DeliveryStatus.ReceiverFailure
109+
case 2:
110+
return DeliveryStatus.ForwardRequestFailure
111+
case 3:
112+
return DeliveryStatus.ForwardRequestSuccess
113+
case 4:
114+
return DeliveryStatus.InvalidRedelivery
115+
default:
116+
return DeliveryStatus.ThisShouldNeverHappen
117+
}
118+
}
119+
120+
async function transformDeliveryEvents(
121+
events: DeliveryEvent[],
122+
targetProvider: ethers.providers.Provider
123+
): Promise<DeliveryTargetInfo[]> {
124+
return Promise.all(
125+
events.map(async (x) => {
126+
return {
127+
status: deliveryStatus(x.args[4]),
128+
deliveryTxHash: x.transactionHash,
129+
vaaHash: x.args[3],
130+
sourceVaaSequence: x.args[2],
131+
sourceChain: x.args[1],
132+
}
133+
})
134+
)
135+
}
136+
137+
export function getWormholeRelayerLog(
138+
receipt: ContractReceipt,
139+
bridgeAddress: string,
140+
emitterAddress: string,
141+
index: number,
142+
): { log: ethers.providers.Log; sequence: string } {
143+
const bridgeLogs = receipt.logs.filter((l) => {
144+
return l.address === bridgeAddress
145+
})
146+
147+
if (bridgeLogs.length == 0) {
148+
throw Error("No core contract interactions found for this transaction.")
149+
}
150+
151+
const parsed = bridgeLogs.map((bridgeLog) => {
152+
const log = Implementation__factory.createInterface().parseLog(bridgeLog)
153+
return {
154+
sequence: log.args[1].toString(),
155+
nonce: log.args[2].toString(),
156+
emitterAddress: tryNativeToHexString(log.args[0].toString(), "ethereum"),
157+
log: bridgeLog,
158+
}
159+
})
160+
161+
const filtered = parsed.filter(
162+
(x) =>
163+
x.emitterAddress == emitterAddress.toLowerCase()
164+
)
165+
166+
if (filtered.length == 0) {
167+
throw Error("No CoreRelayer contract interactions found for this transaction.")
168+
}
169+
170+
if (index >= filtered.length) {
171+
throw Error("Specified delivery index is out of range.")
172+
} else {
173+
return {
174+
log: filtered[index].log,
175+
sequence: filtered[index].sequence,
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)