Skip to content

Commit 6c95cd3

Browse files
authored
DEVREL-930 Oapp solana migrate lzrt v2 (#1850)
1 parent c1adc9c commit 6c95cd3

39 files changed

Lines changed: 817 additions & 297 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@layerzerolabs/oapp-solana-example": minor
3+
---
4+
5+
migrate oapp-solana to LzReceiveTypesV2

examples/oapp-solana/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,26 @@ npx hardhat --network arbitrum-sepolia lz:oapp:send --from-eid 40231 --dst-eid 4
299299

300300
Congratulations, you have now successfully set up an EVM <> Solana OApp.
301301

302+
### Viewing Sent Strings
303+
304+
After sending cross-chain messages you can inspect the stored string on either side directly from the terminal:
305+
306+
- Solana store account:
307+
308+
```bash
309+
npx hardhat lz:oapp:solana:debug --eid 40168 --action store
310+
```
311+
312+
Use the Solana endpoint ID that matches your environment (e.g., `40168` for Devnet, `30168` for Mainnet) and optionally pass `--store <STORE_PUBKEY>` if you need to override the derived PDA.
313+
314+
- EVM contract storage:
315+
316+
```bash
317+
npx hardhat lz:oapp:evm:debug --network arbitrum-sepolia --contract-name MyOApp
318+
```
319+
320+
Switch `--network` to the EVM chain you deployed to and supply a different `--contract-name` if your deployment artifact uses another name. The task performs a read-only call to the `data()` getter and prints the latest received message.
321+
302322
### Running tests
303323

304324
The `test` command will execute the hardhat and forge tests:

examples/oapp-solana/layerzero.config.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ const SOLANA_ENFORCED_OPTIONS: OAppEnforcedOption[] = [
3838
// Arbitrum <-> Solana
3939

4040
// With the config generator, pathways declared are automatically bidirectional
41-
// i.e. if you declare A,B there's no need to declare B,A
41+
// i.e. if you declare Arbitrum,Solana there's no need to declare Solana,Arbitrum
4242
const pathways: TwoWayConfig[] = [
4343
[
44-
arbitrumContract, // Chain A contract
45-
solanaContract, // Chain B contract
44+
arbitrumContract, // Arbitrum contract
45+
solanaContract, // Solana contract
4646
[['LayerZero Labs'], []], // [ requiredDVN[], [ optionalDVN[], threshold ] ]
47-
[1, 32], // [A to B confirmations, B to A confirmations]
48-
[SOLANA_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS], // Chain B enforcedOptions, Chain A enforcedOptions
47+
[20, 32], // [Arbitrum to Solana outbound confirmations, Solana to Arbitrum outbound confirmations]
48+
[SOLANA_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS], // Arbitrum to Solana enforcedOptions, Solana to Arbitrum enforcedOptions
4949
],
5050
]
5151

examples/oapp-solana/lib/client/generated/my_oapp/accounts/endpointSettings.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ export function getEndpointSettingsAccountDataSerializer(): Serializer<
6464
],
6565
{ description: 'EndpointSettingsAccountData' }
6666
),
67-
(value) => ({
68-
...value,
69-
discriminator: new Uint8Array([221, 232, 73, 56, 10, 66, 72, 14]),
70-
})
67+
(value) => ({ ...value, discriminator: new Uint8Array([221, 232, 73, 56, 10, 66, 72, 14]) })
7168
) as Serializer<EndpointSettingsAccountDataArgs, EndpointSettingsAccountData>
7269
}
7370

@@ -124,7 +121,7 @@ export async function safeFetchAllEndpointSettings(
124121
}
125122

126123
export function getEndpointSettingsGpaBuilder(context: Pick<Context, 'rpc' | 'programs'>) {
127-
const programId = context.programs.getPublicKey('myOapp', 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay')
124+
const programId = context.programs.getPublicKey('myOapp', '')
128125
return gpaBuilder(context, programId)
129126
.registerFields<{
130127
discriminator: Uint8Array

examples/oapp-solana/lib/client/generated/my_oapp/accounts/lzReceiveTypesAccounts.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ import {
2525
mapSerializer,
2626
publicKey as publicKeySerializer,
2727
struct,
28+
u8,
2829
} from '@metaplex-foundation/umi/serializers'
2930

30-
/** LzReceiveTypesAccounts includes accounts that are used in the LzReceiveTypes instruction. */
3131
export type LzReceiveTypesAccounts = Account<LzReceiveTypesAccountsAccountData>
3232

3333
export type LzReceiveTypesAccountsAccountData = {
3434
discriminator: Uint8Array
3535
store: PublicKey
36+
alt: PublicKey
37+
bump: number
3638
}
3739

38-
export type LzReceiveTypesAccountsAccountDataArgs = { store: PublicKey }
40+
export type LzReceiveTypesAccountsAccountDataArgs = { store: PublicKey; alt: PublicKey; bump: number }
3941

4042
export function getLzReceiveTypesAccountsAccountDataSerializer(): Serializer<
4143
LzReceiveTypesAccountsAccountDataArgs,
@@ -46,13 +48,12 @@ export function getLzReceiveTypesAccountsAccountDataSerializer(): Serializer<
4648
[
4749
['discriminator', bytes({ size: 8 })],
4850
['store', publicKeySerializer()],
51+
['alt', publicKeySerializer()],
52+
['bump', u8()],
4953
],
5054
{ description: 'LzReceiveTypesAccountsAccountData' }
5155
),
52-
(value) => ({
53-
...value,
54-
discriminator: new Uint8Array([248, 87, 167, 117, 5, 251, 21, 126]),
55-
})
56+
(value) => ({ ...value, discriminator: new Uint8Array([248, 87, 167, 117, 5, 251, 21, 126]) })
5657
) as Serializer<LzReceiveTypesAccountsAccountDataArgs, LzReceiveTypesAccountsAccountData>
5758
}
5859

@@ -109,16 +110,18 @@ export async function safeFetchAllLzReceiveTypesAccounts(
109110
}
110111

111112
export function getLzReceiveTypesAccountsGpaBuilder(context: Pick<Context, 'rpc' | 'programs'>) {
112-
const programId = context.programs.getPublicKey('myOapp', 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay')
113+
const programId = context.programs.getPublicKey('myOapp', '')
113114
return gpaBuilder(context, programId)
114-
.registerFields<{ discriminator: Uint8Array; store: PublicKey }>({
115+
.registerFields<{ discriminator: Uint8Array; store: PublicKey; alt: PublicKey; bump: number }>({
115116
discriminator: [0, bytes({ size: 8 })],
116117
store: [8, publicKeySerializer()],
118+
alt: [40, publicKeySerializer()],
119+
bump: [72, u8()],
117120
})
118121
.deserializeUsing<LzReceiveTypesAccounts>((account) => deserializeLzReceiveTypesAccounts(account))
119122
.whereField('discriminator', new Uint8Array([248, 87, 167, 117, 5, 251, 21, 126]))
120123
}
121124

122125
export function getLzReceiveTypesAccountsSize(): number {
123-
return 40
126+
return 73
124127
}

examples/oapp-solana/lib/client/generated/my_oapp/accounts/peerConfig.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ export type PeerConfigAccountData = {
3131
bump: number
3232
}
3333

34-
export type PeerConfigAccountDataArgs = {
35-
peerAddress: Uint8Array
36-
enforcedOptions: EnforcedOptionsArgs
37-
bump: number
38-
}
34+
export type PeerConfigAccountDataArgs = { peerAddress: Uint8Array; enforcedOptions: EnforcedOptionsArgs; bump: number }
3935

4036
export function getPeerConfigAccountDataSerializer(): Serializer<PeerConfigAccountDataArgs, PeerConfigAccountData> {
4137
return mapSerializer<PeerConfigAccountDataArgs, any, PeerConfigAccountData>(
@@ -48,10 +44,7 @@ export function getPeerConfigAccountDataSerializer(): Serializer<PeerConfigAccou
4844
],
4945
{ description: 'PeerConfigAccountData' }
5046
),
51-
(value) => ({
52-
...value,
53-
discriminator: new Uint8Array([181, 157, 86, 198, 33, 193, 94, 203]),
54-
})
47+
(value) => ({ ...value, discriminator: new Uint8Array([181, 157, 86, 198, 33, 193, 94, 203]) })
5548
) as Serializer<PeerConfigAccountDataArgs, PeerConfigAccountData>
5649
}
5750

@@ -108,7 +101,7 @@ export async function safeFetchAllPeerConfig(
108101
}
109102

110103
export function getPeerConfigGpaBuilder(context: Pick<Context, 'rpc' | 'programs'>) {
111-
const programId = context.programs.getPublicKey('myOapp', 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay')
104+
const programId = context.programs.getPublicKey('myOapp', '')
112105
return gpaBuilder(context, programId)
113106
.registerFields<{
114107
discriminator: Uint8Array

examples/oapp-solana/lib/client/generated/my_oapp/accounts/store.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,7 @@ export type StoreAccountData = {
3939
string: string
4040
}
4141

42-
export type StoreAccountDataArgs = {
43-
admin: PublicKey
44-
bump: number
45-
endpointProgram: PublicKey
46-
string: string
47-
}
42+
export type StoreAccountDataArgs = { admin: PublicKey; bump: number; endpointProgram: PublicKey; string: string }
4843

4944
export function getStoreAccountDataSerializer(): Serializer<StoreAccountDataArgs, StoreAccountData> {
5045
return mapSerializer<StoreAccountDataArgs, any, StoreAccountData>(
@@ -58,10 +53,7 @@ export function getStoreAccountDataSerializer(): Serializer<StoreAccountDataArgs
5853
],
5954
{ description: 'StoreAccountData' }
6055
),
61-
(value) => ({
62-
...value,
63-
discriminator: new Uint8Array([130, 48, 247, 244, 182, 191, 30, 26]),
64-
})
56+
(value) => ({ ...value, discriminator: new Uint8Array([130, 48, 247, 244, 182, 191, 30, 26]) })
6557
) as Serializer<StoreAccountDataArgs, StoreAccountData>
6658
}
6759

@@ -118,7 +110,7 @@ export async function safeFetchAllStore(
118110
}
119111

120112
export function getStoreGpaBuilder(context: Pick<Context, 'rpc' | 'programs'>) {
121-
const programId = context.programs.getPublicKey('myOapp', 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay')
113+
const programId = context.programs.getPublicKey('myOapp', '')
122114
return gpaBuilder(context, programId)
123115
.registerFields<{
124116
discriminator: Uint8Array

examples/oapp-solana/lib/client/generated/my_oapp/errors/myOapp.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,44 @@ type ProgramErrorConstructor = new (program: Program, cause?: Error) => ProgramE
1212
const codeToErrorMap: Map<number, ProgramErrorConstructor> = new Map()
1313
const nameToErrorMap: Map<string, ProgramErrorConstructor> = new Map()
1414

15-
/** InvalidMessageType */
16-
export class InvalidMessageTypeError extends ProgramError {
17-
override readonly name: string = 'InvalidMessageType'
15+
/** InvalidLength: */
16+
export class InvalidLengthError extends ProgramError {
17+
override readonly name: string = 'InvalidLength'
1818

1919
readonly code: number = 0x1770 // 6000
2020

2121
constructor(program: Program, cause?: Error) {
2222
super('', program, cause)
2323
}
2424
}
25-
codeToErrorMap.set(0x1770, InvalidMessageTypeError)
26-
nameToErrorMap.set('InvalidMessageType', InvalidMessageTypeError)
25+
codeToErrorMap.set(0x1770, InvalidLengthError)
26+
nameToErrorMap.set('InvalidLength', InvalidLengthError)
27+
28+
/** BodyTooShort: */
29+
export class BodyTooShortError extends ProgramError {
30+
override readonly name: string = 'BodyTooShort'
31+
32+
readonly code: number = 0x1771 // 6001
33+
34+
constructor(program: Program, cause?: Error) {
35+
super('', program, cause)
36+
}
37+
}
38+
codeToErrorMap.set(0x1771, BodyTooShortError)
39+
nameToErrorMap.set('BodyTooShort', BodyTooShortError)
40+
41+
/** InvalidUtf8: */
42+
export class InvalidUtf8Error extends ProgramError {
43+
override readonly name: string = 'InvalidUtf8'
44+
45+
readonly code: number = 0x1772 // 6002
46+
47+
constructor(program: Program, cause?: Error) {
48+
super('', program, cause)
49+
}
50+
}
51+
codeToErrorMap.set(0x1772, InvalidUtf8Error)
52+
nameToErrorMap.set('InvalidUtf8', InvalidUtf8Error)
2753

2854
/**
2955
* Attempts to resolve a custom program error from the provided error code.

examples/oapp-solana/lib/client/generated/my_oapp/instructions/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
export * from './initStore'
1010
export * from './lzReceive'
11-
export * from './lzReceiveTypes'
11+
export * from './lzReceiveTypesInfo'
12+
export * from './lzReceiveTypesV2'
1213
export * from './quoteSend'
1314
export * from './send'
1415
export * from './setPeerConfig'

examples/oapp-solana/lib/client/generated/my_oapp/instructions/initStore.ts

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,14 @@ export type InitStoreInstructionAccounts = {
2121
payer?: Signer
2222
store: PublicKey | Pda
2323
lzReceiveTypesAccounts: PublicKey | Pda
24+
alt?: PublicKey | Pda
2425
systemProgram?: PublicKey | Pda
2526
}
2627

2728
// Data.
28-
export type InitStoreInstructionData = {
29-
discriminator: Uint8Array
30-
admin: PublicKey
31-
endpoint: PublicKey
32-
}
29+
export type InitStoreInstructionData = { discriminator: Uint8Array; admin: PublicKey; endpoint: PublicKey }
3330

34-
export type InitStoreInstructionDataArgs = {
35-
admin: PublicKey
36-
endpoint: PublicKey
37-
}
31+
export type InitStoreInstructionDataArgs = { admin: PublicKey; endpoint: PublicKey }
3832

3933
export function getInitStoreInstructionDataSerializer(): Serializer<
4034
InitStoreInstructionDataArgs,
@@ -49,10 +43,7 @@ export function getInitStoreInstructionDataSerializer(): Serializer<
4943
],
5044
{ description: 'InitStoreInstructionData' }
5145
),
52-
(value) => ({
53-
...value,
54-
discriminator: new Uint8Array([250, 74, 6, 95, 163, 188, 19, 181]),
55-
})
46+
(value) => ({ ...value, discriminator: new Uint8Array([250, 74, 6, 95, 163, 188, 19, 181]) })
5647
) as Serializer<InitStoreInstructionDataArgs, InitStoreInstructionData>
5748
}
5849

@@ -65,30 +56,15 @@ export function initStore(
6556
input: InitStoreInstructionAccounts & InitStoreInstructionArgs
6657
): TransactionBuilder {
6758
// Program ID.
68-
const programId = context.programs.getPublicKey('myOapp', 'HFyiETGKEUS9tr87K1HXmVJHkqQRtw8wShRNTMkKKxay')
59+
const programId = context.programs.getPublicKey('myOapp', '')
6960

7061
// Accounts.
7162
const resolvedAccounts = {
72-
payer: {
73-
index: 0,
74-
isWritable: true as boolean,
75-
value: input.payer ?? null,
76-
},
77-
store: {
78-
index: 1,
79-
isWritable: true as boolean,
80-
value: input.store ?? null,
81-
},
82-
lzReceiveTypesAccounts: {
83-
index: 2,
84-
isWritable: true as boolean,
85-
value: input.lzReceiveTypesAccounts ?? null,
86-
},
87-
systemProgram: {
88-
index: 3,
89-
isWritable: false as boolean,
90-
value: input.systemProgram ?? null,
91-
},
63+
payer: { index: 0, isWritable: true as boolean, value: input.payer ?? null },
64+
store: { index: 1, isWritable: true as boolean, value: input.store ?? null },
65+
lzReceiveTypesAccounts: { index: 2, isWritable: true as boolean, value: input.lzReceiveTypesAccounts ?? null },
66+
alt: { index: 3, isWritable: false as boolean, value: input.alt ?? null },
67+
systemProgram: { index: 4, isWritable: false as boolean, value: input.systemProgram ?? null },
9268
} satisfies ResolvedAccountsWithIndices
9369

9470
// Arguments.

0 commit comments

Comments
 (0)