@layerzerolabs/oft-v2-solana-sdk 3.0.47 → 3.0.49
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.
- package/CHANGELOG.md +20 -0
- package/deployments/solana-sandbox-local/{TokenOneOFT.json → 302/TokenOneOFT.json} +5 -4
- package/deployments/solana-sandbox-local/{TokenThreeOFT.json → 302/TokenThreeOFT.json} +5 -4
- package/deployments/solana-sandbox-local/{TokenTwoOFTAdapter.json → 302/TokenTwoOFTAdapter.json} +5 -4
- package/deployments/solana-testnet/202/TokenOneOFT.json +16 -0
- package/dist/index.cjs +2101 -266
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1349 -269
- package/dist/index.d.ts +1349 -269
- package/dist/index.mjs +2099 -260
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -9
- package/src/consts.ts +5 -0
- package/src/generated/{accounts → oft202/accounts}/lzReceiveTypesAccounts.ts +1 -2
- package/src/generated/{accounts → oft202/accounts}/oFTStore.ts +1 -2
- package/src/generated/oft202/accounts/peerConfig.ts +178 -0
- package/src/generated/oft202/instructions/index.ts +18 -0
- package/src/generated/{instructions → oft202/instructions}/initOft.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/lzReceive.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/lzReceiveTypes.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/quoteOft.ts +1 -2
- package/src/generated/oft202/instructions/quoteSend.ts +149 -0
- package/src/generated/oft202/instructions/send.ts +193 -0
- package/src/generated/{instructions → oft202/instructions}/setOftConfig.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/setPause.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/setPeerConfig.ts +1 -2
- package/src/generated/{instructions → oft202/instructions}/withdrawFee.ts +1 -2
- package/src/generated/{programs → oft202/programs}/oft.ts +2 -2
- package/src/generated/oft202/types/composeParams.ts +35 -0
- package/src/generated/oft202/types/index.ts +22 -0
- package/src/generated/oft202/types/peerConfigParam.ts +143 -0
- package/src/generated/oft302/accounts/index.ts +11 -0
- package/src/generated/oft302/accounts/lzReceiveTypesAccounts.ts +167 -0
- package/src/generated/oft302/accounts/oFTStore.ts +198 -0
- package/src/generated/{accounts → oft302/accounts}/peerConfig.ts +1 -2
- package/src/generated/oft302/errors/index.ts +9 -0
- package/src/generated/oft302/errors/oft.ts +159 -0
- package/src/generated/oft302/index.ts +14 -0
- package/src/generated/oft302/instructions/initOft.ts +179 -0
- package/src/generated/oft302/instructions/lzReceive.ts +203 -0
- package/src/generated/oft302/instructions/lzReceiveTypes.ts +124 -0
- package/src/generated/{instructions → oft302/instructions}/oftVersion.ts +1 -2
- package/src/generated/oft302/instructions/quoteOft.ts +144 -0
- package/src/generated/{instructions → oft302/instructions}/quoteSend.ts +1 -2
- package/src/generated/{instructions → oft302/instructions}/send.ts +1 -2
- package/src/generated/oft302/instructions/setOftConfig.ts +124 -0
- package/src/generated/oft302/instructions/setPause.ts +119 -0
- package/src/generated/oft302/instructions/setPeerConfig.ts +148 -0
- package/src/generated/oft302/instructions/withdrawFee.ts +151 -0
- package/src/generated/oft302/programs/index.ts +9 -0
- package/src/generated/oft302/programs/oft.ts +47 -0
- package/src/generated/oft302/shared/index.ts +117 -0
- package/src/generated/oft302/types/enforcedOptions.ts +31 -0
- package/src/generated/oft302/types/lzAccount.ts +35 -0
- package/src/generated/oft302/types/lzReceiveParams.ts +50 -0
- package/src/generated/oft302/types/messagingFee.ts +29 -0
- package/src/generated/oft302/types/oFTFeeDetail.ts +34 -0
- package/src/generated/oft302/types/oFTLimits.ts +26 -0
- package/src/generated/oft302/types/oFTReceipt.ts +29 -0
- package/src/generated/oft302/types/oFTType.ts +23 -0
- package/src/generated/oft302/types/quoteOFTResult.ts +50 -0
- package/src/generated/oft302/types/rateLimitParams.ts +38 -0
- package/src/generated/oft302/types/rateLimiter.ts +38 -0
- package/src/generated/oft302/types/setOFTConfigParams.ts +124 -0
- package/src/index.ts +5 -46
- package/src/oft202.ts +618 -0
- package/src/{oft.ts → oft302.ts} +54 -55
- package/src/pda.ts +34 -0
- package/src/types.ts +40 -0
- package/deployments/solana-sandbox-local/TokenFourOFTAdapter.json +0 -15
- /package/src/generated/{accounts → oft202/accounts}/index.ts +0 -0
- /package/src/generated/{errors → oft202/errors}/index.ts +0 -0
- /package/src/generated/{errors → oft202/errors}/oft.ts +0 -0
- /package/src/generated/{index.ts → oft202/index.ts} +0 -0
- /package/src/generated/{programs → oft202/programs}/index.ts +0 -0
- /package/src/generated/{shared → oft202/shared}/index.ts +0 -0
- /package/src/generated/{types → oft202/types}/enforcedOptions.ts +0 -0
- /package/src/generated/{types → oft202/types}/lzAccount.ts +0 -0
- /package/src/generated/{types → oft202/types}/lzReceiveParams.ts +0 -0
- /package/src/generated/{types → oft202/types}/messagingFee.ts +0 -0
- /package/src/generated/{types → oft202/types}/oFTFeeDetail.ts +0 -0
- /package/src/generated/{types → oft202/types}/oFTLimits.ts +0 -0
- /package/src/generated/{types → oft202/types}/oFTReceipt.ts +0 -0
- /package/src/generated/{types → oft202/types}/oFTType.ts +0 -0
- /package/src/generated/{types → oft202/types}/quoteOFTResult.ts +0 -0
- /package/src/generated/{types → oft202/types}/rateLimitParams.ts +0 -0
- /package/src/generated/{types → oft202/types}/rateLimiter.ts +0 -0
- /package/src/generated/{types → oft202/types}/setOFTConfigParams.ts +0 -0
- /package/src/generated/{instructions → oft302/instructions}/index.ts +0 -0
- /package/src/generated/{types → oft302/types}/index.ts +0 -0
- /package/src/generated/{types → oft302/types}/peerConfigParam.ts +0 -0
- /package/src/generated/{types → oft302/types}/version.ts +0 -0
package/src/oft202.ts
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
2
|
+
|
|
3
|
+
// 1. init native OFT from existing mint
|
|
4
|
+
// 2. init adapter OFT from existing mint, optionally an existing escrow
|
|
5
|
+
// 3. Wire a peer
|
|
6
|
+
// 4. Set the DVN etc. options
|
|
7
|
+
import { hexlify } from '@ethersproject/bytes'
|
|
8
|
+
import {
|
|
9
|
+
Cluster,
|
|
10
|
+
Program,
|
|
11
|
+
ProgramError,
|
|
12
|
+
ProgramRepositoryInterface,
|
|
13
|
+
PublicKey,
|
|
14
|
+
RpcInterface,
|
|
15
|
+
Signer,
|
|
16
|
+
WrappedInstruction,
|
|
17
|
+
createNullRpc,
|
|
18
|
+
none,
|
|
19
|
+
publicKeyBytes,
|
|
20
|
+
some,
|
|
21
|
+
} from '@metaplex-foundation/umi'
|
|
22
|
+
import { createDefaultProgramRepository } from '@metaplex-foundation/umi-program-repository'
|
|
23
|
+
import { fromWeb3JsPublicKey, toWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'
|
|
24
|
+
import { TOKEN_PROGRAM_ID } from '@solana/spl-token'
|
|
25
|
+
import { AccountMeta, ComputeBudgetProgram, Connection } from '@solana/web3.js'
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
EndpointPDADeriver,
|
|
29
|
+
EndpointProgram,
|
|
30
|
+
EventPDADeriver,
|
|
31
|
+
SimpleMessageLibProgram,
|
|
32
|
+
UlnProgram,
|
|
33
|
+
simulateTransaction,
|
|
34
|
+
} from '@layerzerolabs/lz-solana-sdk-v2'
|
|
35
|
+
import { PacketPath } from '@layerzerolabs/lz-v2-utilities'
|
|
36
|
+
|
|
37
|
+
import { OFT_DECIMALS } from './consts'
|
|
38
|
+
import * as OFTAccounts from './generated/oft202/accounts'
|
|
39
|
+
import * as errors from './generated/oft202/errors'
|
|
40
|
+
import * as instructions from './generated/oft202/instructions'
|
|
41
|
+
import * as types from './generated/oft202/types/index'
|
|
42
|
+
import { OftPDA } from './pda'
|
|
43
|
+
import {
|
|
44
|
+
SetOFTConfigParams,
|
|
45
|
+
SetPeerAddressParam,
|
|
46
|
+
SetPeerEnforcedOptionsParam,
|
|
47
|
+
SetPeerFeeBpsParam,
|
|
48
|
+
SetPeerIsEndpointV1Param,
|
|
49
|
+
SetPeerRateLimitParam,
|
|
50
|
+
} from './types'
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
initSendLibrary,
|
|
54
|
+
initReceiveLibrary,
|
|
55
|
+
setSendLibrary,
|
|
56
|
+
setReceiveLibrary,
|
|
57
|
+
initConfig,
|
|
58
|
+
setConfig,
|
|
59
|
+
initOAppNonce,
|
|
60
|
+
getEndpointConfig,
|
|
61
|
+
getPeerAddress,
|
|
62
|
+
getDelegate,
|
|
63
|
+
getEnforcedOptions,
|
|
64
|
+
} from './oft302'
|
|
65
|
+
|
|
66
|
+
export * as accounts from './generated/oft202/accounts'
|
|
67
|
+
export * as instructions from './generated/oft202/instructions'
|
|
68
|
+
export * as programs from './generated/oft202/programs'
|
|
69
|
+
export * as shared from './generated/oft202/shared'
|
|
70
|
+
export * as types from './generated/oft202/types/index'
|
|
71
|
+
export * as errors from './generated/oft202/errors'
|
|
72
|
+
|
|
73
|
+
const ENDPOINT_PROGRAM_ID = fromWeb3JsPublicKey(EndpointProgram.PROGRAM_ID)
|
|
74
|
+
const PROGRAM_NAME = 'oft'
|
|
75
|
+
|
|
76
|
+
export function createOFTProgramRepo(oftProgram: PublicKey, rpc?: RpcInterface): ProgramRepositoryInterface {
|
|
77
|
+
if (rpc === undefined) {
|
|
78
|
+
rpc = createNullRpc()
|
|
79
|
+
rpc.getCluster = (): Cluster => 'custom'
|
|
80
|
+
}
|
|
81
|
+
return createDefaultProgramRepository({ rpc: rpc }, [
|
|
82
|
+
{
|
|
83
|
+
name: PROGRAM_NAME,
|
|
84
|
+
publicKey: oftProgram,
|
|
85
|
+
getErrorFromCode(code: number, cause?: Error): ProgramError | null {
|
|
86
|
+
return errors.getOftErrorFromCode(code, this, cause)
|
|
87
|
+
},
|
|
88
|
+
getErrorFromName(name: string, cause?: Error): ProgramError | null {
|
|
89
|
+
return errors.getOftErrorFromName(name, this, cause)
|
|
90
|
+
},
|
|
91
|
+
isOnCluster(): boolean {
|
|
92
|
+
return true
|
|
93
|
+
},
|
|
94
|
+
} satisfies Program,
|
|
95
|
+
])
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function initOft(
|
|
99
|
+
accounts: { payer: Signer; admin: PublicKey; mint: PublicKey; escrow: Signer },
|
|
100
|
+
oftType: types.OFTType,
|
|
101
|
+
sharedDecimals = OFT_DECIMALS,
|
|
102
|
+
programs: { oft: PublicKey; endpoint?: PublicKey; token?: PublicKey }
|
|
103
|
+
): WrappedInstruction {
|
|
104
|
+
const programsRepo = createOFTProgramRepo(programs.oft)
|
|
105
|
+
const deriver = new OftPDA(programsRepo.getPublicKey(PROGRAM_NAME))
|
|
106
|
+
const endpoint = new EndpointProgram.Endpoint(toWeb3JsPublicKey(programs.endpoint ?? ENDPOINT_PROGRAM_ID))
|
|
107
|
+
const { payer, admin, mint, escrow } = accounts
|
|
108
|
+
const [oftStore] = deriver.oftStore(escrow.publicKey)
|
|
109
|
+
const [lzReceiveTypes] = deriver.lzReceiveTypesAccounts(oftStore)
|
|
110
|
+
|
|
111
|
+
const txBuilder = instructions.initOft(
|
|
112
|
+
{
|
|
113
|
+
payer: payer,
|
|
114
|
+
programs: programsRepo,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
// accounts
|
|
118
|
+
oftStore: oftStore,
|
|
119
|
+
lzReceiveTypesAccounts: lzReceiveTypes,
|
|
120
|
+
tokenMint: mint,
|
|
121
|
+
tokenEscrow: escrow,
|
|
122
|
+
tokenProgram: programs.token ?? fromWeb3JsPublicKey(TOKEN_PROGRAM_ID),
|
|
123
|
+
// params
|
|
124
|
+
oftType: oftType,
|
|
125
|
+
admin: admin,
|
|
126
|
+
sharedDecimals: sharedDecimals,
|
|
127
|
+
endpointProgram: fromWeb3JsPublicKey(endpoint.program),
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
const retval = txBuilder.addRemainingAccounts(
|
|
131
|
+
endpoint
|
|
132
|
+
.getRegisterOappIxAccountMetaForCPI(toWeb3JsPublicKey(payer.publicKey), toWeb3JsPublicKey(oftStore))
|
|
133
|
+
.map((acc) => {
|
|
134
|
+
return {
|
|
135
|
+
pubkey: fromWeb3JsPublicKey(acc.pubkey),
|
|
136
|
+
isSigner: acc.isSigner,
|
|
137
|
+
isWritable: acc.isWritable,
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
).items[0]
|
|
141
|
+
retval.signers = [payer, escrow]
|
|
142
|
+
return retval
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function setOFTConfig(
|
|
146
|
+
accounts: {
|
|
147
|
+
oftStore: PublicKey
|
|
148
|
+
admin: Signer
|
|
149
|
+
},
|
|
150
|
+
params: SetOFTConfigParams,
|
|
151
|
+
programs: {
|
|
152
|
+
oft: PublicKey
|
|
153
|
+
endpoint?: PublicKey
|
|
154
|
+
}
|
|
155
|
+
): WrappedInstruction {
|
|
156
|
+
let actualParams: types.SetOFTConfigParamsArgs
|
|
157
|
+
const { oftStore, admin } = accounts
|
|
158
|
+
const oftStoreWeb3Js = toWeb3JsPublicKey(oftStore)
|
|
159
|
+
const remainingAccounts: AccountMeta[] = []
|
|
160
|
+
if (params.__kind === 'Admin') {
|
|
161
|
+
if (params.admin === undefined) {
|
|
162
|
+
throw new Error('Admin is required')
|
|
163
|
+
}
|
|
164
|
+
actualParams = {
|
|
165
|
+
__kind: 'Admin',
|
|
166
|
+
fields: [params.admin],
|
|
167
|
+
}
|
|
168
|
+
} else if (params.__kind === 'Delegate') {
|
|
169
|
+
if (params.delegate === undefined) {
|
|
170
|
+
throw new Error('Delegate is required')
|
|
171
|
+
}
|
|
172
|
+
actualParams = {
|
|
173
|
+
__kind: 'Delegate',
|
|
174
|
+
fields: [params.delegate],
|
|
175
|
+
}
|
|
176
|
+
const endpointProgram = toWeb3JsPublicKey(programs.endpoint ?? ENDPOINT_PROGRAM_ID)
|
|
177
|
+
const [oAppRegistry] = new EndpointPDADeriver(endpointProgram).oappRegistry(oftStoreWeb3Js)
|
|
178
|
+
const [endpointEventAuthority] = new EventPDADeriver(endpointProgram).eventAuthority()
|
|
179
|
+
const keys = EndpointProgram.instructions.createSetDelegateInstructionAccounts(
|
|
180
|
+
{
|
|
181
|
+
oapp: oftStoreWeb3Js,
|
|
182
|
+
oappRegistry: oAppRegistry,
|
|
183
|
+
eventAuthority: endpointEventAuthority,
|
|
184
|
+
program: endpointProgram,
|
|
185
|
+
},
|
|
186
|
+
endpointProgram
|
|
187
|
+
)
|
|
188
|
+
for (const acc of keys) {
|
|
189
|
+
acc.isSigner = false
|
|
190
|
+
}
|
|
191
|
+
remainingAccounts.push(
|
|
192
|
+
{
|
|
193
|
+
pubkey: endpointProgram,
|
|
194
|
+
isSigner: false,
|
|
195
|
+
isWritable: false,
|
|
196
|
+
},
|
|
197
|
+
...keys
|
|
198
|
+
)
|
|
199
|
+
} else if (params.__kind === 'DefaultFee') {
|
|
200
|
+
if (params.defaultFee === undefined) {
|
|
201
|
+
throw new Error('DefaultFee is required')
|
|
202
|
+
}
|
|
203
|
+
actualParams = {
|
|
204
|
+
__kind: 'DefaultFee',
|
|
205
|
+
fields: [params.defaultFee],
|
|
206
|
+
}
|
|
207
|
+
} else if (params.__kind === 'Paused') {
|
|
208
|
+
if (params.paused === undefined) {
|
|
209
|
+
throw new Error('Paused is required')
|
|
210
|
+
}
|
|
211
|
+
actualParams = {
|
|
212
|
+
__kind: 'Paused',
|
|
213
|
+
fields: [params.paused],
|
|
214
|
+
}
|
|
215
|
+
} else if (params.__kind === 'Pauser') {
|
|
216
|
+
actualParams = {
|
|
217
|
+
__kind: 'Pauser',
|
|
218
|
+
fields: [params.pauser ? some(params.pauser) : none()],
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
actualParams = {
|
|
222
|
+
__kind: 'Unpauser',
|
|
223
|
+
fields: [params.unpauser ? some(params.unpauser) : none()],
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const txBuilder = instructions.setOftConfig(
|
|
228
|
+
{ programs: createOFTProgramRepo(programs.oft) },
|
|
229
|
+
{
|
|
230
|
+
admin: admin,
|
|
231
|
+
oftStore: oftStore,
|
|
232
|
+
params: actualParams,
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
return txBuilder.addRemainingAccounts(
|
|
236
|
+
remainingAccounts.map((acc) => {
|
|
237
|
+
return {
|
|
238
|
+
pubkey: fromWeb3JsPublicKey(acc.pubkey),
|
|
239
|
+
isSigner: acc.isSigner,
|
|
240
|
+
isWritable: acc.isWritable,
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
).items[0]
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function setPeerConfig(
|
|
247
|
+
accounts: {
|
|
248
|
+
admin: Signer
|
|
249
|
+
oftStore: PublicKey
|
|
250
|
+
},
|
|
251
|
+
param: (
|
|
252
|
+
| SetPeerAddressParam
|
|
253
|
+
| SetPeerFeeBpsParam
|
|
254
|
+
| SetPeerEnforcedOptionsParam
|
|
255
|
+
| SetPeerRateLimitParam
|
|
256
|
+
| SetPeerIsEndpointV1Param
|
|
257
|
+
) & {
|
|
258
|
+
remote: number
|
|
259
|
+
},
|
|
260
|
+
oftProgramId: PublicKey | ProgramRepositoryInterface
|
|
261
|
+
): WrappedInstruction {
|
|
262
|
+
const programsRepo = typeof oftProgramId === 'string' ? createOFTProgramRepo(oftProgramId) : oftProgramId
|
|
263
|
+
const { remote: remoteId } = param
|
|
264
|
+
if (remoteId % 30000 == 0) {
|
|
265
|
+
throw new Error('Invalid remote ID')
|
|
266
|
+
}
|
|
267
|
+
const { admin, oftStore } = accounts
|
|
268
|
+
const [peerPda] = new OftPDA(programsRepo.getPublicKey(PROGRAM_NAME)).peer(oftStore, remoteId)
|
|
269
|
+
let config: types.PeerConfigParamArgs
|
|
270
|
+
if (param.__kind === 'PeerAddress') {
|
|
271
|
+
if (param.peer.length !== 32) {
|
|
272
|
+
throw new Error('Peer must be 32 bytes (left-padded with zeroes)')
|
|
273
|
+
}
|
|
274
|
+
config = types.peerConfigParam('PeerAddress', [param.peer])
|
|
275
|
+
} else if (param.__kind === 'FeeBps') {
|
|
276
|
+
config = { __kind: 'FeeBps', fields: [some(param.feeBps)] }
|
|
277
|
+
} else if (param.__kind === 'EnforcedOptions') {
|
|
278
|
+
config = {
|
|
279
|
+
__kind: 'EnforcedOptions',
|
|
280
|
+
send: param.send,
|
|
281
|
+
sendAndCall: param.sendAndCall,
|
|
282
|
+
}
|
|
283
|
+
} else if (param.__kind === 'OutboundRateLimit' || param.__kind === 'InboundRateLimit') {
|
|
284
|
+
config = {
|
|
285
|
+
__kind: param.__kind,
|
|
286
|
+
fields: [
|
|
287
|
+
param.rateLimit
|
|
288
|
+
? some({
|
|
289
|
+
refillPerSecond: some(param.rateLimit.refillPerSecond),
|
|
290
|
+
capacity: some(param.rateLimit.capacity),
|
|
291
|
+
})
|
|
292
|
+
: null,
|
|
293
|
+
],
|
|
294
|
+
}
|
|
295
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
296
|
+
} else if (param.__kind === 'IsEndpointV1') {
|
|
297
|
+
config = { __kind: 'IsEndpointV1', fields: [param.isEndpointV1] }
|
|
298
|
+
} else {
|
|
299
|
+
throw new Error('Invalid peer config')
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return instructions.setPeerConfig(
|
|
303
|
+
{ programs: programsRepo },
|
|
304
|
+
{
|
|
305
|
+
admin: admin,
|
|
306
|
+
peer: peerPda,
|
|
307
|
+
oftStore: oftStore,
|
|
308
|
+
// params
|
|
309
|
+
remoteEid: remoteId,
|
|
310
|
+
config: config,
|
|
311
|
+
}
|
|
312
|
+
).items[0]
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// copied from oft302.ts withdrawFee
|
|
316
|
+
export function withdrawFee(
|
|
317
|
+
accounts: {
|
|
318
|
+
admin: Signer
|
|
319
|
+
mint: PublicKey
|
|
320
|
+
escrow: PublicKey
|
|
321
|
+
dest: PublicKey
|
|
322
|
+
},
|
|
323
|
+
amount: bigint,
|
|
324
|
+
programs: {
|
|
325
|
+
oft: PublicKey | ProgramRepositoryInterface
|
|
326
|
+
token?: PublicKey
|
|
327
|
+
}
|
|
328
|
+
): WrappedInstruction {
|
|
329
|
+
const { admin, mint, escrow, dest } = accounts
|
|
330
|
+
const programsRepo = typeof programs.oft === 'string' ? createOFTProgramRepo(programs.oft) : programs.oft
|
|
331
|
+
const [oftStore] = new OftPDA(programsRepo.getPublicKey('oft')).oftStore(escrow)
|
|
332
|
+
return instructions.withdrawFee(
|
|
333
|
+
{ programs: programsRepo },
|
|
334
|
+
{
|
|
335
|
+
admin: admin,
|
|
336
|
+
tokenEscrow: escrow,
|
|
337
|
+
tokenDest: dest,
|
|
338
|
+
tokenProgram: programs.token ?? fromWeb3JsPublicKey(TOKEN_PROGRAM_ID),
|
|
339
|
+
oftStore: oftStore,
|
|
340
|
+
tokenMint: mint,
|
|
341
|
+
// params
|
|
342
|
+
feeLd: amount,
|
|
343
|
+
}
|
|
344
|
+
).items[0]
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export async function send(
|
|
348
|
+
rpc: RpcInterface,
|
|
349
|
+
accounts: {
|
|
350
|
+
payer: Signer
|
|
351
|
+
tokenMint: PublicKey
|
|
352
|
+
tokenEscrow: PublicKey
|
|
353
|
+
tokenSource: PublicKey
|
|
354
|
+
peerAddr?: Uint8Array
|
|
355
|
+
},
|
|
356
|
+
sendParams: {
|
|
357
|
+
dstEid: number
|
|
358
|
+
to: Uint8Array
|
|
359
|
+
amountLd: bigint
|
|
360
|
+
minAmountLd: bigint
|
|
361
|
+
options?: Uint8Array
|
|
362
|
+
nativeFee: bigint
|
|
363
|
+
lzTokenFee?: bigint
|
|
364
|
+
composeParams?: {
|
|
365
|
+
composeGas: number | bigint
|
|
366
|
+
composeMsg: Uint8Array
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
programs: {
|
|
370
|
+
oft: PublicKey | ProgramRepositoryInterface
|
|
371
|
+
endpoint?: PublicKey // default is ENDPOINT_PROGRAM(76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6)
|
|
372
|
+
token?: PublicKey // default is TOKEN_PROGRAM_ID(TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA)
|
|
373
|
+
},
|
|
374
|
+
remainingAccounts?: AccountMeta[]
|
|
375
|
+
): Promise<WrappedInstruction> {
|
|
376
|
+
const { payer, tokenMint, tokenEscrow, tokenSource } = accounts
|
|
377
|
+
const { dstEid, to, amountLd, minAmountLd, options, composeParams, nativeFee, lzTokenFee } = sendParams
|
|
378
|
+
const programsRepo = typeof programs.oft === 'string' ? createOFTProgramRepo(programs.oft) : programs.oft
|
|
379
|
+
const oftProgramId = programsRepo.getPublicKey(PROGRAM_NAME)
|
|
380
|
+
const deriver = new OftPDA(oftProgramId)
|
|
381
|
+
const [oftStore] = deriver.oftStore(tokenEscrow)
|
|
382
|
+
const [peer] = deriver.peer(oftStore, dstEid)
|
|
383
|
+
|
|
384
|
+
const connection = new Connection(rpc.getEndpoint())
|
|
385
|
+
if (remainingAccounts === undefined || remainingAccounts.length === 0) {
|
|
386
|
+
const peerAddr: Uint8Array =
|
|
387
|
+
accounts.peerAddr ??
|
|
388
|
+
(await OFTAccounts.fetchPeerConfig({ rpc }, peer).then((peerInfo) => peerInfo.peerAddress))
|
|
389
|
+
|
|
390
|
+
const endpoint = new EndpointProgram.Endpoint(toWeb3JsPublicKey(programs.endpoint ?? ENDPOINT_PROGRAM_ID))
|
|
391
|
+
const msgLibProgram = await getSendLibraryProgram(connection, endpoint, payer.publicKey, oftStore, dstEid)
|
|
392
|
+
const packetPath: PacketPath = {
|
|
393
|
+
srcEid: 0,
|
|
394
|
+
dstEid,
|
|
395
|
+
sender: hexlify(publicKeyBytes(oftStore)),
|
|
396
|
+
receiver: hexlify(peerAddr),
|
|
397
|
+
}
|
|
398
|
+
remainingAccounts = await endpoint.getSendIXAccountMetaForCPI(
|
|
399
|
+
connection,
|
|
400
|
+
toWeb3JsPublicKey(payer.publicKey),
|
|
401
|
+
packetPath,
|
|
402
|
+
msgLibProgram
|
|
403
|
+
)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const [eventAuthorityPDA] = new EventPDADeriver(toWeb3JsPublicKey(oftProgramId)).eventAuthority()
|
|
407
|
+
const tokenProgram: PublicKey = programs.token ?? fromWeb3JsPublicKey(TOKEN_PROGRAM_ID)
|
|
408
|
+
const txBuilder = instructions.send(
|
|
409
|
+
{ programs: programsRepo },
|
|
410
|
+
{
|
|
411
|
+
signer: payer,
|
|
412
|
+
peer: peer,
|
|
413
|
+
oftStore: oftStore,
|
|
414
|
+
tokenSource: tokenSource,
|
|
415
|
+
tokenEscrow: tokenEscrow,
|
|
416
|
+
tokenMint: tokenMint,
|
|
417
|
+
tokenProgram: tokenProgram,
|
|
418
|
+
eventAuthority: fromWeb3JsPublicKey(eventAuthorityPDA),
|
|
419
|
+
program: oftProgramId,
|
|
420
|
+
// params
|
|
421
|
+
dstEid: dstEid,
|
|
422
|
+
to: to,
|
|
423
|
+
amountLd,
|
|
424
|
+
minAmountLd,
|
|
425
|
+
options: options ?? new Uint8Array(),
|
|
426
|
+
nativeFee,
|
|
427
|
+
lzTokenFee: lzTokenFee ?? 0,
|
|
428
|
+
composeParams: composeParams ?? null,
|
|
429
|
+
}
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
// Get remaining accounts from msgLib(simple_msgLib or uln)
|
|
433
|
+
return txBuilder.addRemainingAccounts(
|
|
434
|
+
remainingAccounts.map((acc) => {
|
|
435
|
+
return {
|
|
436
|
+
pubkey: fromWeb3JsPublicKey(acc.pubkey),
|
|
437
|
+
isSigner: acc.isSigner,
|
|
438
|
+
isWritable: acc.isWritable,
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
).items[0]
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export async function quote(
|
|
445
|
+
rpc: RpcInterface,
|
|
446
|
+
accounts: {
|
|
447
|
+
payer: PublicKey
|
|
448
|
+
tokenMint: PublicKey
|
|
449
|
+
tokenEscrow: PublicKey
|
|
450
|
+
peerAddr?: Uint8Array
|
|
451
|
+
},
|
|
452
|
+
quoteParams: {
|
|
453
|
+
dstEid: number
|
|
454
|
+
to: Uint8Array
|
|
455
|
+
amountLd: bigint
|
|
456
|
+
minAmountLd: bigint
|
|
457
|
+
options?: Uint8Array
|
|
458
|
+
payInLzToken?: boolean
|
|
459
|
+
composeParams?: {
|
|
460
|
+
composeGas: number | bigint
|
|
461
|
+
composeMsg: Uint8Array
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
programs: {
|
|
465
|
+
oft: PublicKey | ProgramRepositoryInterface
|
|
466
|
+
endpoint?: PublicKey
|
|
467
|
+
},
|
|
468
|
+
remainingAccounts?: AccountMeta[]
|
|
469
|
+
): Promise<{ nativeFee: bigint; lzTokenFee: bigint }> {
|
|
470
|
+
const { dstEid, to, amountLd, minAmountLd, options, payInLzToken, composeParams } = quoteParams
|
|
471
|
+
const { payer, tokenMint, tokenEscrow } = accounts
|
|
472
|
+
const programsRepo = typeof programs.oft === 'string' ? createOFTProgramRepo(programs.oft) : programs.oft
|
|
473
|
+
const deriver = new OftPDA(programsRepo.getPublicKey(PROGRAM_NAME))
|
|
474
|
+
const [oftStore] = deriver.oftStore(tokenEscrow)
|
|
475
|
+
const [peer] = deriver.peer(oftStore, dstEid)
|
|
476
|
+
|
|
477
|
+
const connection = new Connection(rpc.getEndpoint(), 'confirmed')
|
|
478
|
+
if (remainingAccounts === undefined || remainingAccounts.length === 0) {
|
|
479
|
+
const peerAddr: Uint8Array =
|
|
480
|
+
accounts.peerAddr ??
|
|
481
|
+
(await OFTAccounts.fetchPeerConfig({ rpc }, peer).then((peerInfo) => peerInfo.peerAddress))
|
|
482
|
+
|
|
483
|
+
const endpoint = new EndpointProgram.Endpoint(toWeb3JsPublicKey(programs.endpoint ?? ENDPOINT_PROGRAM_ID))
|
|
484
|
+
const messageLib = await getSendLibraryProgram(connection, endpoint, payer, oftStore, dstEid)
|
|
485
|
+
|
|
486
|
+
remainingAccounts = await endpoint.getQuoteIXAccountMetaForCPI(
|
|
487
|
+
connection,
|
|
488
|
+
toWeb3JsPublicKey(payer),
|
|
489
|
+
{
|
|
490
|
+
sender: hexlify(publicKeyBytes(oftStore)),
|
|
491
|
+
dstEid: dstEid,
|
|
492
|
+
receiver: hexlify(peerAddr),
|
|
493
|
+
},
|
|
494
|
+
messageLib
|
|
495
|
+
)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
let txBuilder = instructions.quoteSend(
|
|
499
|
+
{ programs: programsRepo },
|
|
500
|
+
{
|
|
501
|
+
oftStore: oftStore,
|
|
502
|
+
peer: peer,
|
|
503
|
+
tokenMint: tokenMint,
|
|
504
|
+
// params
|
|
505
|
+
dstEid: dstEid,
|
|
506
|
+
to: to,
|
|
507
|
+
amountLd: amountLd,
|
|
508
|
+
minAmountLd: minAmountLd,
|
|
509
|
+
options: options ?? new Uint8Array(),
|
|
510
|
+
payInLzToken: payInLzToken ?? false,
|
|
511
|
+
composeParams: composeParams ?? null,
|
|
512
|
+
}
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
txBuilder = txBuilder.addRemainingAccounts(
|
|
516
|
+
// Get remaining accounts from msgLib(simple_msgLib or uln)
|
|
517
|
+
remainingAccounts.map((acc) => {
|
|
518
|
+
return {
|
|
519
|
+
pubkey: fromWeb3JsPublicKey(acc.pubkey),
|
|
520
|
+
isSigner: acc.isSigner,
|
|
521
|
+
isWritable: acc.isWritable,
|
|
522
|
+
}
|
|
523
|
+
})
|
|
524
|
+
)
|
|
525
|
+
const web3Ix = toWeb3JsInstruction(txBuilder.getInstructions()[0])
|
|
526
|
+
const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
|
|
527
|
+
units: 1000000,
|
|
528
|
+
})
|
|
529
|
+
const buffer = await simulateTransaction(
|
|
530
|
+
connection,
|
|
531
|
+
[modifyComputeUnits, web3Ix],
|
|
532
|
+
web3Ix.programId,
|
|
533
|
+
toWeb3JsPublicKey(payer),
|
|
534
|
+
'confirmed'
|
|
535
|
+
)
|
|
536
|
+
const fee = EndpointProgram.types.messagingFeeBeet.read(buffer, 0)
|
|
537
|
+
return { nativeFee: BigInt(fee.nativeFee.toString()), lzTokenFee: BigInt(fee.lzTokenFee.toString()) }
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export async function quoteOft(
|
|
541
|
+
rpc: RpcInterface,
|
|
542
|
+
accounts: {
|
|
543
|
+
payer: PublicKey
|
|
544
|
+
tokenMint: PublicKey
|
|
545
|
+
tokenEscrow: PublicKey
|
|
546
|
+
},
|
|
547
|
+
quoteParams: {
|
|
548
|
+
dstEid: number
|
|
549
|
+
to: Uint8Array
|
|
550
|
+
amountLd: bigint
|
|
551
|
+
minAmountLd: bigint
|
|
552
|
+
options?: Uint8Array
|
|
553
|
+
payInLzToken?: boolean
|
|
554
|
+
composeMsg?: Uint8Array
|
|
555
|
+
},
|
|
556
|
+
oftProgram: PublicKey | ProgramRepositoryInterface
|
|
557
|
+
): Promise<types.QuoteOFTResult> {
|
|
558
|
+
const { payer, tokenMint, tokenEscrow } = accounts
|
|
559
|
+
const { dstEid, to, amountLd, minAmountLd, options, payInLzToken, composeMsg } = quoteParams
|
|
560
|
+
const programsRepo = typeof oftProgram === 'string' ? createOFTProgramRepo(oftProgram) : oftProgram
|
|
561
|
+
const deriver = new OftPDA(programsRepo.getPublicKey(PROGRAM_NAME))
|
|
562
|
+
const [oftStore] = deriver.oftStore(tokenEscrow)
|
|
563
|
+
const [peer] = deriver.peer(oftStore, dstEid)
|
|
564
|
+
const ix = instructions
|
|
565
|
+
.quoteOft(
|
|
566
|
+
{ programs: programsRepo },
|
|
567
|
+
{
|
|
568
|
+
oftStore: oftStore,
|
|
569
|
+
peer: peer,
|
|
570
|
+
tokenMint: tokenMint,
|
|
571
|
+
// params
|
|
572
|
+
dstEid: dstEid,
|
|
573
|
+
to: to,
|
|
574
|
+
amountLd: amountLd,
|
|
575
|
+
minAmountLd: minAmountLd,
|
|
576
|
+
options: options ?? new Uint8Array(),
|
|
577
|
+
payInLzToken: payInLzToken ?? false,
|
|
578
|
+
composeMsg: composeMsg ?? null,
|
|
579
|
+
}
|
|
580
|
+
)
|
|
581
|
+
.getInstructions()[0]
|
|
582
|
+
const web3Ix = toWeb3JsInstruction(ix)
|
|
583
|
+
const connection = new Connection(rpc.getEndpoint())
|
|
584
|
+
const returnedValues = await simulateTransaction(
|
|
585
|
+
connection,
|
|
586
|
+
[web3Ix],
|
|
587
|
+
web3Ix.programId,
|
|
588
|
+
toWeb3JsPublicKey(payer),
|
|
589
|
+
'confirmed'
|
|
590
|
+
)
|
|
591
|
+
const [result] = types.getQuoteOFTResultSerializer().deserialize(returnedValues, 0)
|
|
592
|
+
return result
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
async function getSendLibraryProgram(
|
|
596
|
+
connection: Connection,
|
|
597
|
+
endpoint: EndpointProgram.Endpoint,
|
|
598
|
+
payer: PublicKey,
|
|
599
|
+
oftStore: PublicKey,
|
|
600
|
+
remoteEid: number
|
|
601
|
+
): Promise<SimpleMessageLibProgram.SimpleMessageLib | UlnProgram.Uln> {
|
|
602
|
+
const sendLibInfo = await endpoint.getSendLibrary(connection, toWeb3JsPublicKey(oftStore), remoteEid)
|
|
603
|
+
if (!sendLibInfo?.programId) {
|
|
604
|
+
throw new Error('Send library not initialized or blocked message library')
|
|
605
|
+
}
|
|
606
|
+
const { programId: msgLibProgram } = sendLibInfo
|
|
607
|
+
const msgLibVersion = await endpoint.getMessageLibVersion(connection, toWeb3JsPublicKey(payer), msgLibProgram)
|
|
608
|
+
if (msgLibVersion?.major.toString() === '0' && msgLibVersion.minor == 0 && msgLibVersion.endpointVersion == 2) {
|
|
609
|
+
return new SimpleMessageLibProgram.SimpleMessageLib(msgLibProgram)
|
|
610
|
+
} else if (
|
|
611
|
+
msgLibVersion?.major.toString() === '3' &&
|
|
612
|
+
msgLibVersion.minor == 0 &&
|
|
613
|
+
msgLibVersion.endpointVersion == 2
|
|
614
|
+
) {
|
|
615
|
+
return new UlnProgram.Uln(msgLibProgram)
|
|
616
|
+
}
|
|
617
|
+
throw new Error(`Unsupported message library version: ${JSON.stringify(msgLibVersion, null, 2)}`)
|
|
618
|
+
}
|