@layerzerolabs/lz-solana-sdk-v2 3.0.103 → 3.0.105-mpt.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the kinobi library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun kinobi to update it.
5
+ *
6
+ * @see https://github.com/kinobi-so/kinobi
7
+ */
8
+
9
+ import {
10
+ Context,
11
+ Pda,
12
+ PublicKey,
13
+ Signer,
14
+ TransactionBuilder,
15
+ publicKey,
16
+ transactionBuilder,
17
+ } from '@metaplex-foundation/umi';
18
+ import {
19
+ Serializer,
20
+ bytes,
21
+ mapSerializer,
22
+ struct,
23
+ u64,
24
+ u8,
25
+ } from '@metaplex-foundation/umi/serializers';
26
+ import {
27
+ ResolvedAccount,
28
+ ResolvedAccountsWithIndices,
29
+ getAccountMetasAndSigners,
30
+ } from '../shared';
31
+
32
+ // Accounts.
33
+ export type PreExecuteInstructionAccounts = {
34
+ executor: Signer;
35
+ /**
36
+ * Execution context account that stores state between pre and post execution.
37
+ * This account is versioned to support future protocol upgrades.
38
+ */
39
+
40
+ context: PublicKey | Pda;
41
+ systemProgram?: PublicKey | Pda;
42
+ /** Instruction sysvar account for introspection */
43
+ instructionSysvar?: PublicKey | Pda;
44
+ };
45
+
46
+ // Data.
47
+ export type PreExecuteInstructionData = {
48
+ discriminator: Uint8Array;
49
+ /** Version of the execution context to use */
50
+ contextVersion: number;
51
+ /** Maximum fee that can be charged for execution */
52
+ feeLimit: bigint;
53
+ };
54
+
55
+ export type PreExecuteInstructionDataArgs = {
56
+ /** Version of the execution context to use */
57
+ contextVersion: number;
58
+ /** Maximum fee that can be charged for execution */
59
+ feeLimit: number | bigint;
60
+ };
61
+
62
+ export function getPreExecuteInstructionDataSerializer(): Serializer<
63
+ PreExecuteInstructionDataArgs,
64
+ PreExecuteInstructionData
65
+ > {
66
+ return mapSerializer<
67
+ PreExecuteInstructionDataArgs,
68
+ any,
69
+ PreExecuteInstructionData
70
+ >(
71
+ struct<PreExecuteInstructionData>(
72
+ [
73
+ ['discriminator', bytes({ size: 8 })],
74
+ ['contextVersion', u8()],
75
+ ['feeLimit', u64()],
76
+ ],
77
+ { description: 'PreExecuteInstructionData' }
78
+ ),
79
+ (value) => ({
80
+ ...value,
81
+ discriminator: new Uint8Array([207, 125, 18, 148, 72, 192, 198, 83]),
82
+ })
83
+ ) as Serializer<PreExecuteInstructionDataArgs, PreExecuteInstructionData>;
84
+ }
85
+
86
+ // Args.
87
+ export type PreExecuteInstructionArgs = PreExecuteInstructionDataArgs;
88
+
89
+ // Instruction.
90
+ export function preExecute(
91
+ context: Pick<Context, 'programs'>,
92
+ input: PreExecuteInstructionAccounts & PreExecuteInstructionArgs
93
+ ): TransactionBuilder {
94
+ // Program ID.
95
+ const programId = context.programs.getPublicKey(
96
+ 'executor',
97
+ '6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn'
98
+ );
99
+
100
+ // Accounts.
101
+ const resolvedAccounts = {
102
+ executor: {
103
+ index: 0,
104
+ isWritable: true as boolean,
105
+ value: input.executor ?? null,
106
+ },
107
+ context: {
108
+ index: 1,
109
+ isWritable: true as boolean,
110
+ value: input.context ?? null,
111
+ },
112
+ systemProgram: {
113
+ index: 2,
114
+ isWritable: false as boolean,
115
+ value: input.systemProgram ?? null,
116
+ },
117
+ instructionSysvar: {
118
+ index: 3,
119
+ isWritable: false as boolean,
120
+ value: input.instructionSysvar ?? null,
121
+ },
122
+ } satisfies ResolvedAccountsWithIndices;
123
+
124
+ // Arguments.
125
+ const resolvedArgs: PreExecuteInstructionArgs = { ...input };
126
+
127
+ // Default values.
128
+ if (!resolvedAccounts.systemProgram.value) {
129
+ resolvedAccounts.systemProgram.value = context.programs.getPublicKey(
130
+ 'splSystem',
131
+ '11111111111111111111111111111111'
132
+ );
133
+ resolvedAccounts.systemProgram.isWritable = false;
134
+ }
135
+ if (!resolvedAccounts.instructionSysvar.value) {
136
+ resolvedAccounts.instructionSysvar.value = publicKey(
137
+ 'Sysvar1nstructions1111111111111111111111111'
138
+ );
139
+ }
140
+
141
+ // Accounts in order.
142
+ const orderedAccounts: ResolvedAccount[] = Object.values(
143
+ resolvedAccounts
144
+ ).sort((a, b) => a.index - b.index);
145
+
146
+ // Keys and Signers.
147
+ const [keys, signers] = getAccountMetasAndSigners(
148
+ orderedAccounts,
149
+ 'programId',
150
+ programId
151
+ );
152
+
153
+ // Data.
154
+ const data = getPreExecuteInstructionDataSerializer().serialize(
155
+ resolvedArgs as PreExecuteInstructionDataArgs
156
+ );
157
+
158
+ // Bytes Created On Chain.
159
+ const bytesCreatedOnChain = 0;
160
+
161
+ return transactionBuilder([
162
+ { instruction: { keys, programId, data }, signers, bytesCreatedOnChain },
163
+ ]);
164
+ }
@@ -12,6 +12,5 @@ export * from './dstConfig';
12
12
  export * from './executionState';
13
13
  export * from './lzComposeParams';
14
14
  export * from './lzOption';
15
- export * from './lzReceiveParams';
16
15
  export * from './nativeDropRequest';
17
16
  export * from './ownerSetConfigParams';
package/src/index.ts CHANGED
@@ -11,6 +11,8 @@ export * as DVNProgram from './dvn'
11
11
  export * from './utility'
12
12
  export * from './config'
13
13
  export * from './receive'
14
+ export * from './receive-types-v1'
15
+ export * from './receive-types-v2'
14
16
  export * from './types'
15
17
  export * from './deployment'
16
18
  export * from './next_nonce'
package/src/pda.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Pda, PublicKey, defaultPublicKey, publicKeyBytes } from '@metaplex-foundation/umi'
2
- import { Endian, u16, u32, u64 } from '@metaplex-foundation/umi/serializers'
2
+ import { Endian, u16, u32, u64, u8 } from '@metaplex-foundation/umi/serializers'
3
3
  import { createWeb3JsEddsa } from '@metaplex-foundation/umi-eddsa-web3js'
4
4
 
5
5
  export const PEER_SEED = 'Peer'
@@ -309,12 +309,21 @@ export class EventPDA {
309
309
 
310
310
  export class ExecutorPDA {
311
311
  static EXECUTOR_CONFIG_SEED = 'ExecutorConfig'
312
+ static EXECUTION_CONTEXT_SEED = 'ExecutionContext'
312
313
 
313
314
  constructor(public program: PublicKey) {}
314
315
 
315
316
  config(): Pda {
316
317
  return EDDSA.findPda(this.program, [Buffer.from(ExecutorPDA.EXECUTOR_CONFIG_SEED, 'utf8')])
317
318
  }
319
+
320
+ context(executor: PublicKey, version: number): Pda {
321
+ return EDDSA.findPda(this.program, [
322
+ Buffer.from(ExecutorPDA.EXECUTION_CONTEXT_SEED, 'utf8'),
323
+ publicKeyBytes(executor),
324
+ u8().serialize(version),
325
+ ])
326
+ }
318
327
  }
319
328
 
320
329
  export class PriceFeedPDA {
@@ -0,0 +1,85 @@
1
+ import {
2
+ AccountMeta,
3
+ Commitment,
4
+ Instruction,
5
+ PublicKey,
6
+ RpcInterface,
7
+ defaultPublicKey,
8
+ } from '@metaplex-foundation/umi'
9
+ import { array, publicKey as publicKeySerializer } from '@metaplex-foundation/umi/serializers'
10
+ import { toWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'
11
+
12
+ import { OmniAppPDA } from '.'
13
+ import { LzReceiveParams, getLzReceiveAccountSerializer, getLzReceiveParamsSerializer } from './types'
14
+ import { instructionDiscriminator, simulateWeb3JsTransaction } from './utility'
15
+
16
+ /**
17
+ * Get the accounts required for lz_receive by querying lz_receive_types_v1.
18
+ */
19
+ export async function getLzReceiveAccountsFromTypesV1(
20
+ rpc: RpcInterface,
21
+ payer: PublicKey,
22
+ receiver: PublicKey,
23
+ receiverProgram: PublicKey,
24
+ params: LzReceiveParams,
25
+ commitment: Commitment = 'confirmed'
26
+ ): Promise<AccountMeta[]> {
27
+ // Derive the PDA for the lz_receive_types_accounts
28
+ const oappPDA = new OmniAppPDA(receiverProgram)
29
+ const [lzReceiveTypesAccountsPDA] = oappPDA.lzReceiveTypesAccounts(receiver)
30
+ // Fetch the PDA account and parse the static account list
31
+ const info = await rpc.getAccount(lzReceiveTypesAccountsPDA, { commitment })
32
+ const accounts: AccountMeta[] = []
33
+ if (info.exists) {
34
+ const buffer = Buffer.from(info.data)
35
+ const len = buffer.length - 8
36
+ if (len % 32 !== 0) {
37
+ throw new Error(
38
+ `Invalid length of AccountInfo.data. The length must be a multiple of 32 plus 8.(n*32+8). Current length is ${buffer.length}`
39
+ )
40
+ }
41
+ for (let i = 8; i < len; i += 32) {
42
+ const [address] = publicKeySerializer().deserialize(buffer, i)
43
+ accounts.push({
44
+ pubkey: address,
45
+ isSigner: false,
46
+ isWritable: false,
47
+ })
48
+ }
49
+ }
50
+ // Simulate the lz_receive_types instruction to get the dynamic account metas
51
+ const data = getLzReceiveParamsSerializer().serialize(params)
52
+ const lzReceiveTypesIx: Instruction = {
53
+ programId: receiverProgram,
54
+ keys: accounts,
55
+ data: Buffer.concat([instructionDiscriminator('lz_receive_types'), data]),
56
+ }
57
+ const keys = await simulateWeb3JsTransaction(
58
+ rpc.getEndpoint(),
59
+ [toWeb3JsInstruction(lzReceiveTypesIx)],
60
+ toWeb3JsPublicKey(receiverProgram),
61
+ toWeb3JsPublicKey(payer),
62
+ array(getLzReceiveAccountSerializer()),
63
+ commitment
64
+ )
65
+ return updateAccountFromSimulatedResp(keys, payer)
66
+ }
67
+
68
+ function updateAccountFromSimulatedResp(accounts: AccountMeta[], payer?: PublicKey): AccountMeta[] {
69
+ return accounts.map((r) => {
70
+ if (r.pubkey == defaultPublicKey() && r.isSigner) {
71
+ if (!payer) throw new Error('payer is required')
72
+ return {
73
+ pubkey: payer,
74
+ isSigner: true,
75
+ isWritable: r.isWritable,
76
+ } satisfies AccountMeta
77
+ } else {
78
+ return {
79
+ pubkey: r.pubkey,
80
+ isSigner: r.isSigner,
81
+ isWritable: r.isWritable,
82
+ } satisfies AccountMeta
83
+ }
84
+ })
85
+ }
@@ -0,0 +1,217 @@
1
+ import { AddressLookupTable, fetchAllAddressLookupTable } from '@metaplex-foundation/mpl-toolbox'
2
+ import {
3
+ AccountMeta,
4
+ Commitment,
5
+ Context,
6
+ Instruction,
7
+ KeypairSigner,
8
+ PublicKey,
9
+ RpcInterface,
10
+ generateSigner,
11
+ } from '@metaplex-foundation/umi'
12
+ import { bytes as bytesSerializer } from '@metaplex-foundation/umi/serializers'
13
+ import { toWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'
14
+
15
+ import { EDDSA, ExecutorPDA, OmniAppPDA } from '.'
16
+ import {
17
+ AccountMetaRef,
18
+ AddressLocator,
19
+ LzReceiveParams,
20
+ LzReceiveTypesV2Accounts,
21
+ getLzReceiveParamsSerializer,
22
+ getLzReceiveTypesV2AccountsSerializer,
23
+ getLzReceiveTypesV2ResultSerializer,
24
+ } from './types'
25
+ import { instructionDiscriminator, simulateWeb3JsTransaction } from './utility'
26
+
27
+ /**
28
+ * Retrieves the instructions and signers required for the LzReceive instruction (V2).
29
+ * This is used for lz_receive_types version 2.
30
+ */
31
+ export async function buildLzReceiveExecutionPlan(
32
+ rpc: RpcInterface,
33
+ executorProgram: PublicKey,
34
+ payer: PublicKey,
35
+ receiver: PublicKey,
36
+ receiverProgram: PublicKey,
37
+ params: LzReceiveParams,
38
+ receiveTypesAccounts?: LzReceiveTypesV2Accounts,
39
+ commitment: Commitment = 'confirmed'
40
+ ): Promise<{ contextVersion: number; signers: KeypairSigner[]; instructions: Instruction[] }> {
41
+ receiveTypesAccounts =
42
+ receiveTypesAccounts ?? (await getLzReceiveTypesInfo(rpc, payer, receiver, receiverProgram, params, commitment))
43
+
44
+ const data = getLzReceiveParamsSerializer().serialize(params)
45
+ const lzReceiveTypesIx: Instruction = {
46
+ programId: receiverProgram,
47
+ keys: receiveTypesAccounts.accounts.map((pubkey) => {
48
+ return {
49
+ pubkey,
50
+ isSigner: false,
51
+ isWritable: false,
52
+ }
53
+ }),
54
+ data: Buffer.concat([instructionDiscriminator('lz_receive_types_v2'), data]),
55
+ }
56
+ // Simulate the V2 instruction to get the result (instructions, ALTs, etc)
57
+ const resp = await simulateWeb3JsTransaction(
58
+ rpc.getEndpoint(),
59
+ [toWeb3JsInstruction(lzReceiveTypesIx)],
60
+ toWeb3JsPublicKey(receiverProgram),
61
+ toWeb3JsPublicKey(payer),
62
+ getLzReceiveTypesV2ResultSerializer(),
63
+ commitment
64
+ )
65
+ const tables = await fetchAllAddressLookupTable({ rpc }, resp.alts)
66
+ const signers: { [key: number]: KeypairSigner | undefined } = {}
67
+
68
+ const lzReceiveDiscriminator = instructionDiscriminator('lz_receive').toString('hex')
69
+ const instructionTracker: { [key: string]: boolean } = {}
70
+
71
+ for (const ix of resp.instructions) {
72
+ let programId = receiverProgram
73
+ let instructionType = 'lz_receive'
74
+ if (ix.__kind === 'Standard') {
75
+ const { programId: stdProgramId, data } = ix
76
+ programId = stdProgramId
77
+ const discriminator = Buffer.from(data.slice(0, 8)).toString('hex')
78
+ instructionType = discriminator === lzReceiveDiscriminator ? 'lz_receive' : discriminator
79
+ }
80
+ const key = `${programId}-${instructionType}`
81
+ if (instructionTracker[key]) {
82
+ throw new Error(`Duplicate instruction found: ${instructionType} for program ${programId}`)
83
+ }
84
+ instructionTracker[key] = true
85
+ }
86
+ const { contextVersion } = resp
87
+ const instructions: Instruction[] = resp.instructions.map((ix) => {
88
+ if (ix.__kind === 'LzReceive') {
89
+ return {
90
+ programId: receiverProgram,
91
+ keys: ix.accounts.map((account) =>
92
+ accountMetaRefToAccountMeta(
93
+ { eddsa: EDDSA },
94
+ executorProgram,
95
+ tables,
96
+ signers,
97
+ account,
98
+ payer,
99
+ contextVersion
100
+ )
101
+ ),
102
+ data: Buffer.concat([instructionDiscriminator('lz_receive'), data]),
103
+ }
104
+ } else {
105
+ return {
106
+ programId: ix.programId,
107
+ keys: ix.accounts.map((account) =>
108
+ accountMetaRefToAccountMeta(
109
+ { eddsa: EDDSA },
110
+ executorProgram,
111
+ tables,
112
+ signers,
113
+ account,
114
+ payer,
115
+ contextVersion
116
+ )
117
+ ),
118
+ data: ix.data,
119
+ }
120
+ }
121
+ })
122
+ return {
123
+ contextVersion,
124
+ signers: Object.values(signers).filter((signer) => signer !== undefined) as KeypairSigner[],
125
+ instructions,
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Fetches the metadata for lz_receive_types (versioned, V2).
131
+ * This reads the PDA account and deserializes the version, alts, and accounts.
132
+ */
133
+ export async function getLzReceiveTypesInfo(
134
+ rpc: RpcInterface,
135
+ payer: PublicKey,
136
+ receiver: PublicKey,
137
+ receiverProgram: PublicKey,
138
+ params: LzReceiveParams,
139
+ commitment: Commitment = 'confirmed'
140
+ ): Promise<LzReceiveTypesV2Accounts> {
141
+ const oappPDA = new OmniAppPDA(receiverProgram)
142
+ const [lzReceiveTypesAccountsPDA] = oappPDA.lzReceiveTypesAccounts(receiver)
143
+ const lzReceiveTypesIx: Instruction = {
144
+ programId: receiverProgram,
145
+ keys: [
146
+ {
147
+ pubkey: receiver,
148
+ isSigner: false,
149
+ isWritable: false,
150
+ },
151
+ {
152
+ pubkey: lzReceiveTypesAccountsPDA,
153
+ isSigner: false,
154
+ isWritable: false,
155
+ },
156
+ ],
157
+ data: Buffer.concat([instructionDiscriminator('lz_receive_types_info')]),
158
+ }
159
+
160
+ const resp = await simulateWeb3JsTransaction(
161
+ rpc.getEndpoint(),
162
+ [toWeb3JsInstruction(lzReceiveTypesIx)],
163
+ toWeb3JsPublicKey(receiverProgram),
164
+ toWeb3JsPublicKey(payer),
165
+ bytesSerializer(),
166
+ commitment
167
+ )
168
+ const version = resp.at(0)
169
+ if (version !== 2) {
170
+ throw new Error(`Invalid version ${version}. Expected version 2.`)
171
+ }
172
+ return getLzReceiveTypesV2AccountsSerializer().deserialize(resp, 1)[0]
173
+ }
174
+
175
+ function accountMetaRefToAccountMeta(
176
+ umi: Pick<Context, 'eddsa'>,
177
+ executorProgram: PublicKey,
178
+ tables: AddressLookupTable[],
179
+ signers: { [key: number]: KeypairSigner | undefined },
180
+ accountMetaRef: AccountMetaRef,
181
+ payer: PublicKey,
182
+ contextVersion: number
183
+ ): AccountMeta {
184
+ const { isWritable, pubkey: locator } = accountMetaRef
185
+ const pubkey = addressLocatorToPublicKey(umi, executorProgram, tables, signers, locator, payer, contextVersion)
186
+ return { pubkey, isSigner: locator.__kind === 'Signer' || locator.__kind === 'Payer', isWritable }
187
+ }
188
+
189
+ function addressLocatorToPublicKey(
190
+ umi: Pick<Context, 'eddsa'>,
191
+ executorProgram: PublicKey,
192
+ tables: AddressLookupTable[],
193
+ signers: { [key: number]: KeypairSigner | undefined },
194
+ locator: AddressLocator,
195
+ payer: PublicKey,
196
+ contextVersion: number
197
+ ): PublicKey {
198
+ if (locator.__kind === 'Payer') {
199
+ return payer
200
+ } else if (locator.__kind === 'Signer') {
201
+ const index = locator.fields[0]
202
+ let signer = signers[index]
203
+ if (signer === undefined) {
204
+ signer = generateSigner(umi)
205
+ signers[index] = signer
206
+ }
207
+ return signer.publicKey
208
+ } else if (locator.__kind === 'Address') {
209
+ return locator.fields[0]
210
+ } else if (locator.__kind === 'Context') {
211
+ const pda = new ExecutorPDA(executorProgram)
212
+ return pda.context(payer, contextVersion)[0]
213
+ } else {
214
+ const table = tables[locator.fields[0]]
215
+ return table.addresses[locator.fields[1]]
216
+ }
217
+ }