Skip to content

Commit

Permalink
chore: Add LzApp SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista committed Feb 12, 2024
1 parent 3fb1788 commit 6146af1
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/ua-devtools-evm/src/lzapp/factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pMemoize from 'p-memoize'
import type { LzAppFactory } from '@layerzerolabs/ua-devtools'
import type { OmniContractFactory } from '@layerzerolabs/devtools-evm'
import { LzApp } from './sdk'

/**
* Syntactic sugar that creates an instance of EVM `LZApp` SDK
* based on an `OmniPoint` with help of an `OmniContractFactory`
*
* @param {OmniContractFactory} contractFactory
* @returns {LzAppFactory<LZApp>}
*/
export const createLzAppFactory = (contractFactory: OmniContractFactory): LzAppFactory<LzApp> =>
pMemoize(async (point) => new LzApp(await contractFactory(point)))
2 changes: 2 additions & 0 deletions packages/ua-devtools-evm/src/lzapp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './factory'
export * from './sdk'
57 changes: 57 additions & 0 deletions packages/ua-devtools-evm/src/lzapp/sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { ILzApp } from '@layerzerolabs/ua-devtools'
import {
type OmniAddress,
type OmniTransaction,
formatEid,
areBytes32Equal,
ignoreZero,
makeBytes32,
} from '@layerzerolabs/devtools'
import { type OmniContract, parseGenericError } from '@layerzerolabs/devtools-evm'
import type { EndpointId } from '@layerzerolabs/lz-definitions'
import { OmniSDK } from '@layerzerolabs/devtools-evm'

export class LzApp extends OmniSDK implements ILzApp {
constructor(contract: OmniContract) {
super(contract)
}

async getTrustedRemote(eid: EndpointId): Promise<OmniAddress | undefined> {
this.logger.debug(`Getting trusted remote for eid ${eid} (${formatEid(eid)})`)

try {
return ignoreZero(await this.contract.contract.getTrustedRemoteAddress(eid))
} catch (error: unknown) {
const parsedError = parseGenericError(error)

// The method will revert if there is no trusted remote set for this path
// in which case we want to return undefined instead of throwing
if (parsedError?.reason === 'LzApp: no trusted path record') return undefined

this.logger.debug(`Got an error getting trusted remote for eid ${eid} (${formatEid(eid)}): ${error}`)

throw error
}
}

async hasTrustedRemote(eid: EndpointId, address: OmniAddress | null | undefined): Promise<boolean> {
this.logger.debug(`Checking trusted remote for eid ${eid} (${formatEid(eid)})`)

return areBytes32Equal(address, await this.getTrustedRemote(eid))
}

async setTrustedRemote(eid: EndpointId, address: OmniAddress | null | undefined): Promise<OmniTransaction> {
const description = `Setting trusted remote for eid ${eid} (${formatEid(eid)}) to address ${makeBytes32(address)}`
this.logger.debug(description)

const data = this.contract.contract.interface.encodeFunctionData('setTrustedRemoteAddress', [
eid,
makeBytes32(address),
])

return {
...this.createTransaction(data),
description,
}
}
}
1 change: 1 addition & 0 deletions packages/ua-devtools/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './lzapp'
export * from './oapp'
29 changes: 29 additions & 0 deletions packages/ua-devtools/src/lzapp/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { flattenTransactions, formatOmniVector, type OmniTransaction } from '@layerzerolabs/devtools'
import { LzAppFactory, LzAppOmniGraph } from './types'
import { createModuleLogger, printBoolean } from '@layerzerolabs/io-devtools'

export type LzAppConfigurator = (graph: LzAppOmniGraph, createSdk: LzAppFactory) => Promise<OmniTransaction[]>

export const configureLzApp: LzAppConfigurator = async (graph: LzAppOmniGraph, createSdk: LzAppFactory) =>
flattenTransactions([await configureLzAppPeers(graph, createSdk)])

export const configureLzAppPeers: LzAppConfigurator = async (graph, createSdk) => {
const logger = createModuleLogger('LzApp')

return flattenTransactions(
await Promise.all(
graph.connections.map(async ({ vector: { from, to } }): Promise<OmniTransaction[]> => {
logger.verbose(`Checking connection ${formatOmniVector({ from, to })}`)

const sdk = await createSdk(from)
const hasPeer = await sdk.hasTrustedRemote(to.eid, to.address)

logger.verbose(`Checked connection ${formatOmniVector({ from, to })}: ${printBoolean(hasPeer)}`)
if (hasPeer) return []

logger.verbose(`Creating a connection ${formatOmniVector({ from, to })}`)
return [await sdk.setTrustedRemote(to.eid, to.address)]
})
)
)
}
2 changes: 2 additions & 0 deletions packages/ua-devtools/src/lzapp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './config'
export * from './types'
12 changes: 12 additions & 0 deletions packages/ua-devtools/src/lzapp/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Factory, IOmniSDK, OmniAddress, OmniGraph, OmniPoint, OmniTransaction } from '@layerzerolabs/devtools'
import type { EndpointId } from '@layerzerolabs/lz-definitions'

export interface ILzApp extends IOmniSDK {
getTrustedRemote(eid: EndpointId): Promise<OmniAddress | undefined>
hasTrustedRemote(eid: EndpointId, trustedRemote: OmniAddress | null | undefined): Promise<boolean>
setTrustedRemote(eid: EndpointId, trustedRemote: OmniAddress | null | undefined): Promise<OmniTransaction>
}

export type LzAppOmniGraph = OmniGraph<unknown, unknown>

export type LzAppFactory<TLzApp extends ILzApp = ILzApp, TOmniPoint = OmniPoint> = Factory<[TOmniPoint], TLzApp>

0 comments on commit 6146af1

Please sign in to comment.