Skip to content

Commit a566db0

Browse files
authored
🚀 feat(oft-solana): enhance debug task to print send and receive configs (#1437)
1 parent 8d51382 commit a566db0

1 file changed

Lines changed: 110 additions & 13 deletions

File tree

  • examples/oft-solana/tasks/solana

‎examples/oft-solana/tasks/solana/debug.ts‎

Lines changed: 110 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { fetchMint } from '@metaplex-foundation/mpl-toolbox' // Import fetchToken function
1+
import { fetchMint } from '@metaplex-foundation/mpl-toolbox'
22
import { publicKey, unwrapOption } from '@metaplex-foundation/umi'
33
import { toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'
4-
import { PublicKey } from '@solana/web3.js'
4+
import { Keypair, PublicKey } from '@solana/web3.js'
55
import { task } from 'hardhat/config'
66

7-
import { denormalizePeer } from '@layerzerolabs/devtools'
7+
import { OmniPoint, denormalizePeer } from '@layerzerolabs/devtools'
88
import { types } from '@layerzerolabs/devtools-evm-hardhat'
99
import { EndpointId, getNetworkForChainId } from '@layerzerolabs/lz-definitions'
1010
import { EndpointPDADeriver, EndpointProgram } from '@layerzerolabs/lz-solana-sdk-v2'
1111
import { OftPDA, oft } from '@layerzerolabs/oft-v2-solana-sdk'
12+
import { EndpointV2 } from '@layerzerolabs/protocol-devtools-solana'
1213

13-
import { DebugLogger, decodeLzReceiveOptions, uint8ArrayToHex } from '../common/utils'
14+
import { getSolanaReceiveConfig, getSolanaSendConfig } from '../common/taskHelper'
15+
import { DebugLogger, createSolanaConnectionFactory, decodeLzReceiveOptions, uint8ArrayToHex } from '../common/utils'
1416

1517
import { deriveConnection, getSolanaDeployment } from './index'
1618

@@ -61,19 +63,32 @@ task('lz:oft:solana:debug', 'Manages OFTStore and OAppRegistry information')
6163
types.string
6264
)
6365
.setAction(async (taskArgs: DebugTaskArgs) => {
64-
const { eid, oftStore, endpoint, dstEids, action } = taskArgs
66+
const { eid, oftStore: oftStoreArg, endpoint, dstEids, action } = taskArgs
6567
const { umi, connection } = await deriveConnection(eid, true)
66-
const store = getOftStore(eid, oftStore)
67-
const oftStoreInfo = await oft.accounts.fetchOFTStore(umi, store)
68+
const oftStore = getOftStore(eid, oftStoreArg)
69+
70+
let oftStoreInfo
71+
try {
72+
oftStoreInfo = await oft.accounts.fetchOFTStore(umi, oftStore)
73+
} catch (e) {
74+
console.error(`Failed to fetch OFTStore at ${oftStore.toString()}:`, e)
75+
return
76+
}
77+
6878
const mintAccount = await fetchMint(umi, publicKey(oftStoreInfo.tokenMint))
6979

7080
const epDeriver = new EndpointPDADeriver(new PublicKey(endpoint))
71-
const [oAppRegistry] = epDeriver.oappRegistry(toWeb3JsPublicKey(store))
81+
const [oAppRegistry] = epDeriver.oappRegistry(toWeb3JsPublicKey(oftStore))
7282
const oAppRegistryInfo = await EndpointProgram.accounts.OAppRegistry.fromAccountAddress(
7383
connection,
7484
oAppRegistry
7585
)
7686

87+
if (!oAppRegistryInfo) {
88+
console.warn('OAppRegistry info not found.')
89+
return
90+
}
91+
7792
const oftDeriver = new OftPDA(oftStoreInfo.header.owner)
7893

7994
const printOftStore = async () => {
@@ -114,23 +129,44 @@ task('lz:oft:solana:debug', 'Manages OFTStore and OAppRegistry information')
114129

115130
DebugLogger.header('Checks')
116131
DebugLogger.keyValue('Admin (Owner) same as Delegate', oftStoreInfo.admin === delegate)
117-
DebugLogger.keyValue('Token Mint Authority is OFT Store', unwrapOption(mintAccount.mintAuthority) === store)
132+
DebugLogger.keyValue(
133+
'Token Mint Authority is OFT Store',
134+
unwrapOption(mintAccount.mintAuthority) === oftStore
135+
)
118136
DebugLogger.separator()
119137
}
120138

121139
const printPeerConfigs = async () => {
122140
const peerConfigs = dstEids.map((dstEid) => {
123-
const peerConfig = oftDeriver.peer(store, dstEid)
141+
const peerConfig = oftDeriver.peer(oftStore, dstEid)
124142
return publicKey(peerConfig)
125143
})
144+
const mockKeypair = new Keypair()
145+
const point: OmniPoint = {
146+
eid,
147+
address: oftStore.toString(),
148+
}
149+
const endpointV2Sdk = new EndpointV2(
150+
await createSolanaConnectionFactory()(eid),
151+
point,
152+
mockKeypair.publicKey // doesn't matter as we are not sending transactions
153+
)
126154

127155
DebugLogger.header('Peer Configurations')
156+
128157
const peerConfigInfos = await oft.accounts.safeFetchAllPeerConfig(umi, peerConfigs)
129-
dstEids.forEach((dstEid, index) => {
158+
for (let index = 0; index < dstEids.length; index++) {
159+
const dstEid = dstEids[index]
130160
const info = peerConfigInfos[index]
131161
const network = getNetworkForChainId(dstEid)
162+
const oAppReceiveConfig = await getSolanaReceiveConfig(endpointV2Sdk, dstEid, oftStore)
163+
const oAppSendConfig = await getSolanaSendConfig(endpointV2Sdk, dstEid, oftStore)
164+
165+
// Show the chain info
132166
DebugLogger.header(`${dstEid} (${network.chainName})`)
167+
133168
if (info) {
169+
// Existing PeerConfig info
134170
DebugLogger.keyValue('PeerConfig Account', peerConfigs[index].toString())
135171
DebugLogger.keyValue('Peer Address', denormalizePeer(info.peerAddress, dstEid))
136172
DebugLogger.keyHeader('Enforced Options')
@@ -144,13 +180,17 @@ task('lz:oft:solana:debug', 'Manages OFTStore and OAppRegistry information')
144180
decodeLzReceiveOptions(uint8ArrayToHex(info.enforcedOptions.sendAndCall, true)),
145181
2
146182
)
183+
184+
printOAppReceiveConfigs(oAppReceiveConfig, network.chainName)
185+
printOAppSendConfigs(oAppSendConfig, network.chainName)
147186
} else {
187+
// No PeerConfig account
148188
console.log(`No PeerConfig account found for ${dstEid} (${network.chainName}).`)
149189
}
190+
150191
DebugLogger.separator()
151-
})
192+
}
152193
}
153-
154194
if (action) {
155195
switch (action) {
156196
case DEBUG_ACTIONS.OFT_STORE:
@@ -182,3 +222,60 @@ task('lz:oft:solana:debug', 'Manages OFTStore and OAppRegistry information')
182222
await printChecks()
183223
}
184224
})
225+
226+
function printOAppReceiveConfigs(
227+
oAppReceiveConfig: Awaited<ReturnType<typeof getSolanaReceiveConfig>>,
228+
peerChainName: string
229+
) {
230+
const oAppReceiveConfigIndexesToKeys: Record<number, string> = {
231+
0: 'receiveLibrary',
232+
1: 'receiveUlnConfig',
233+
2: 'receiveLibraryTimeoutConfig',
234+
}
235+
236+
if (!oAppReceiveConfig) {
237+
console.log('No receive configs found.')
238+
return
239+
}
240+
241+
DebugLogger.keyValue(`Receive Configs (${peerChainName} to solana)`, '')
242+
for (let i = 0; i < oAppReceiveConfig.length; i++) {
243+
const item = oAppReceiveConfig[i]
244+
if (typeof item === 'object' && item !== null) {
245+
// Print each property in the object
246+
DebugLogger.keyValue(`${oAppReceiveConfigIndexesToKeys[i]}`, '', 2)
247+
for (const [propKey, propVal] of Object.entries(item)) {
248+
DebugLogger.keyValue(`${propKey}`, String(propVal), 3)
249+
}
250+
} else {
251+
// Print a primitive (string, number, etc.)
252+
DebugLogger.keyValue(`${oAppReceiveConfigIndexesToKeys[i]}`, String(item), 2)
253+
}
254+
}
255+
}
256+
257+
function printOAppSendConfigs(oAppSendConfig: Awaited<ReturnType<typeof getSolanaSendConfig>>, peerChainName: string) {
258+
const sendOappConfigIndexesToKeys: Record<number, string> = {
259+
0: 'sendLibrary',
260+
1: 'sendUlnConfig',
261+
2: 'sendExecutorConfig',
262+
}
263+
264+
if (!oAppSendConfig) {
265+
console.log('No send configs found.')
266+
return
267+
}
268+
269+
DebugLogger.keyValue(`Send Configs (solana to ${peerChainName})`, '')
270+
for (let i = 0; i < oAppSendConfig.length; i++) {
271+
const item = oAppSendConfig[i]
272+
if (typeof item === 'object' && item !== null) {
273+
DebugLogger.keyValue(`${sendOappConfigIndexesToKeys[i]}`, '', 2)
274+
for (const [propKey, propVal] of Object.entries(item)) {
275+
DebugLogger.keyValue(`${propKey}`, String(propVal), 3)
276+
}
277+
} else {
278+
DebugLogger.keyValue(`${sendOappConfigIndexesToKeys[i]}`, String(item), 2)
279+
}
280+
}
281+
}

0 commit comments

Comments
 (0)