Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples/oft-solana): introduce getSolanaDeploymentFunction #1306

Merged
merged 11 commits into from
Feb 21, 2025
5 changes: 5 additions & 0 deletions .changeset/brave-icons-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@layerzerolabs/oft-solana-example": patch
---

introduce getSolanaDeploymentFunction and simplify solana task params
10 changes: 5 additions & 5 deletions examples/oft-solana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,15 @@ Note: If you are on testnet, consider using `MyOFTMock` to allow test token mint
Run the following command to init the pathway config. This step is unique to pathways that involve Solana.

```bash
npx hardhat lz:oft:solana:init-config --oapp-config layerzero.config.ts --solana-program-id <PROGRAM_ID>
npx hardhat lz:oft:solana:init-config --oapp-config layerzero.config.ts --solana-eid <SOLANA_ENDPOINT_ID>
```

### Wire

Run the following to wire the pathways specified in your `layerzero.config.ts`

```bash
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts --solana-program-id <PROGRAM_ID>
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts --solana-secret-key --solana-eid <SOLANA_ENDPOINT_ID>
```

With a squads multisig, you can simply append the `--multisig-key` flag to the end of the above command.
Expand Down Expand Up @@ -309,7 +309,7 @@ For Solana -> Sepolia, you should pass in the options value into the script at [
#### Send SOL -> Sepolia

```bash
npx hardhat lz:oft:solana:send --amount <AMOUNT> --from-eid 40168 --to <TO> --to-eid 40161 --mint <MINT_ADDRESS> --program-id <PROGRAM_ID> --escrow <ESCROW>
npx hardhat lz:oft:solana:send --amount <AMOUNT> --from-eid 40168 --to <TO> --to-eid 40161
```

#### Send Sepolia -> SOL
Expand Down Expand Up @@ -344,7 +344,7 @@ How to set delegate: https://docs.layerzero.network/v2/developers/evm/create-lz-
Now run

```
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts --solana-program-id <PROGRAM_ID>
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts --solana-eid <SOLANA_ENDPOINT_ID>
```

and execute the transactions.
Expand All @@ -356,7 +356,7 @@ How to set owner: https://docs.layerzero.network/v2/developers/evm/create-lz-oap
Now, run

```
npx hardhat lz:ownable:transfer-ownership --oapp-config layerzero.config.ts --solana-program-id <PROGRAM_ID>
npx hardhat lz:ownable:transfer-ownership --oapp-config layerzero.config.ts --solana-eid <SOLANA_ENDPOINT_ID>
```

### Common Errors
Expand Down
23 changes: 11 additions & 12 deletions examples/oft-solana/tasks/common/wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { PublicKey } from '@solana/web3.js'
import { subtask, task } from 'hardhat/config'

import { firstFactory } from '@layerzerolabs/devtools'
import { SUBTASK_LZ_SIGN_AND_SEND, types } from '@layerzerolabs/devtools-evm-hardhat'
import { SUBTASK_LZ_SIGN_AND_SEND, types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat'
import { setTransactionSizeBuffer } from '@layerzerolabs/devtools-solana'
import { type LogLevel, createLogger } from '@layerzerolabs/io-devtools'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { type IOApp, type OAppConfigurator, type OAppOmniGraph, configureOwnable } from '@layerzerolabs/ua-devtools'
import {
SUBTASK_LZ_OAPP_WIRE_CONFIGURE,
Expand All @@ -13,7 +14,7 @@ import {
TASK_LZ_OWNABLE_TRANSFER_OWNERSHIP,
} from '@layerzerolabs/ua-devtools-evm-hardhat'

import { useWeb3Js } from '../solana'
import { getSolanaDeployment, useWeb3Js } from '../solana'

import { publicKey } from './types'
import { createSdkFactory, createSolanaConnectionFactory, createSolanaSignerFactory } from './utils'
Expand All @@ -25,7 +26,7 @@ import type { SignAndSendTaskArgs } from '@layerzerolabs/devtools-evm-hardhat/ta
*/
interface Args {
logLevel: LogLevel
solanaProgramId: PublicKey
solanaEid: EndpointId
multisigKey?: PublicKey
internalConfigurator?: OAppConfigurator
}
Expand All @@ -34,14 +35,14 @@ interface Args {
* We extend the default wiring task to add functionality required by Solana
*/
task(TASK_LZ_OAPP_WIRE)
.addParam('solanaProgramId', 'The OFT program ID to use', undefined, publicKey, true)
.addParam('solanaEid', 'Solana mainnet or testnet', undefined, devtoolsTypes.eid, true)
.addParam('multisigKey', 'The MultiSig key', undefined, publicKey, true)
// We use this argument to get around the fact that we want to both override the task action for the wiring task
// and wrap this task with custom configurators
//
// By default, this argument will be left empty and the default OApp configurator will be used.
// The tasks that are using custom configurators will override this argument with the configurator of their choice
.addParam('internalConfigurator', 'FOR INTERNAL USE ONLY', undefined, types.fn, true)
.addParam('internalConfigurator', 'FOR INTERNAL USE ONLY', undefined, devtoolsTypes.fn, true)
.setAction(async (args: Args, hre, runSuper) => {
const logger = createLogger(args.logLevel)

Expand All @@ -64,11 +65,13 @@ task(TASK_LZ_OAPP_WIRE)
const keypair = useWeb3Js().web3JsKeypair
const userAccount = keypair.publicKey

const solanaDeployment = getSolanaDeployment(args.solanaEid)

// Then we grab the programId from the args
const programId = args.solanaProgramId
const programId = new PublicKey(solanaDeployment.programId)

if (!programId) {
logger.error('Missing --solana-program-id CLI argument')
logger.error('Missing programId in solana deployment')
return
}

Expand Down Expand Up @@ -137,11 +140,7 @@ task(TASK_LZ_OAPP_WIRE)
// The two tasks are identical and the only drawback of this approach is the fact
// that the logs will say "Wiring OApp" instead of "Transferring ownership"
task(TASK_LZ_OWNABLE_TRANSFER_OWNERSHIP)
// The next (optional) parameter is the OFT program ID
//
// Only pass this if you deployed a new OFT program, if you are using the default
// LayerZero OFT program you can omit this
.addParam('solanaProgramId', 'The OFT program ID to use', undefined, publicKey, true)
.addParam('solanaEid', 'Solana mainnet or testnet', undefined, devtoolsTypes.eid, true)
.addParam('multisigKey', 'The MultiSig key', undefined, publicKey, true)
.setAction(async (args: Args, hre) => {
return hre.run(TASK_LZ_OAPP_WIRE, { ...args, internalConfigurator: configureOwnable })
Expand Down
11 changes: 9 additions & 2 deletions examples/oft-solana/tasks/solana/createOFT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
deriveConnection,
deriveKeys,
getExplorerTxLink,
output,
saveSolanaDeployment,
} from './index'

const DEFAULT_LOCAL_DECIMALS = 9
Expand Down Expand Up @@ -327,6 +327,13 @@ task('lz:oft:solana:create', 'Mints new SPL Token and creates new OFT Store acco
`Please note that for MABA mode, you must carry out the change of Mint Authority before making any cross-chain transfers. For more details: https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-solana#for-oft-mint-and-burn-adapter-maba`
)
}
output(eid, programIdStr, mint.publicKey, mintAuthorityPublicKey.toBase58(), escrowPK, oftStorePda)
saveSolanaDeployment(
eid,
programIdStr,
mint.publicKey,
mintAuthorityPublicKey.toBase58(),
escrowPK,
oftStorePda
)
}
)
11 changes: 9 additions & 2 deletions examples/oft-solana/tasks/solana/createOFTAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
deriveConnection,
deriveKeys,
getExplorerTxLink,
output,
saveSolanaDeployment,
} from './index'

interface CreateOFTAdapterTaskArgs {
Expand Down Expand Up @@ -94,6 +94,13 @@ task('lz:oft-adapter:solana:create', 'Creates new OFT Adapter (OFT Store PDA)')
const { signature } = await txBuilder.sendAndConfirm(umi)
console.log(`initOftTx: ${getExplorerTxLink(bs58.encode(signature), eid == EndpointId.SOLANA_V2_TESTNET)}`)

output(eid, programIdStr, mint, mintAuthority ? mintAuthority.toBase58() : '', escrowPK, oftStorePda)
saveSolanaDeployment(
eid,
programIdStr,
mint,
mintAuthority ? mintAuthority.toBase58() : '',
escrowPK,
oftStorePda
)
}
)
30 changes: 28 additions & 2 deletions examples/oft-solana/tasks/solana/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'assert'
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'

import {
fetchAddressLookupTable,
Expand Down Expand Up @@ -112,7 +112,7 @@ export const deriveKeys = (programIdStr: string) => {
* @param escrow {string}
* @param oftStore {string}
*/
export const output = (
export const saveSolanaDeployment = (
eid: EndpointId,
programId: string,
mint: string,
Expand Down Expand Up @@ -141,6 +141,32 @@ export const output = (
console.log(`Accounts have been saved to ${outputDir}/OFT.json`)
}

/**
* Reads the OFT deployment info from disk for the given endpoint ID.
* @param eid {EndpointId}
* @returns The contents of the OFT.json file as a JSON object.
*/
export const getSolanaDeployment = (
eid: EndpointId
): {
programId: string
mint: string
mintAuthority: string
escrow: string
oftStore: string
} => {
const outputDir = `./deployments/${endpointIdToNetwork(eid)}`
const filePath = `${outputDir}/OFT.json`

if (!existsSync(filePath)) {
throw new Error(`Could not find Solana deployment file for eid ${eid} at: ${filePath}`)
}

const fileContents = readFileSync(filePath, 'utf-8')
return JSON.parse(fileContents)
}

// TODO: move below outside of solana folder since it's generic
export const getLayerZeroScanLink = (hash: string, isTestnet = false) =>
isTestnet ? `https://testnet.layerzeroscan.com/tx/${hash}` : `https://layerzeroscan.com/tx/${hash}`

Expand Down
4 changes: 3 additions & 1 deletion examples/oft-solana/tasks/solana/initConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import { ConfigurableTaskDefinition } from 'hardhat/types'

import { inheritTask } from '@layerzerolabs/devtools-evm-hardhat'
import { type LogLevel } from '@layerzerolabs/io-devtools'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { type OAppConfigurator } from '@layerzerolabs/ua-devtools'
import { TASK_LZ_OAPP_WIRE } from '@layerzerolabs/ua-devtools-evm-hardhat'
import { initOFTAccounts } from '@layerzerolabs/ua-devtools-solana'

// We'll create clones of the wire task and only override the configurator argument
const wireLikeTask = inheritTask(TASK_LZ_OAPP_WIRE)

// TODO: export from wire.ts instead of re-declaring
/**
* Additional CLI arguments for our custom wire task
*/
interface Args {
logLevel: LogLevel
solanaProgramId: PublicKey
solanaEid: EndpointId
multisigKey?: PublicKey
internalConfigurator?: OAppConfigurator
}
Expand Down
Loading
Loading