@layerzerolabs/lz-sui-oft-sdk-v2 3.0.136 → 3.0.137

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.
@@ -19,8 +19,8 @@ import {
19
19
  } from '@layerzerolabs/lz-sui-sdk-v2'
20
20
  import type { IPTBValidator, MessagingFee, ObjectOptions } from '@layerzerolabs/lz-sui-sdk-v2'
21
21
 
22
- import { parseOFTFeeDetails, parseOFTLimit, parseOFTReceipt } from '../bcs/oft'
23
- import { OFTFeeDetail, OFTLimit, OFTReceipt, SendParam } from '../types'
22
+ import { parseOFTFeeDetails, parseOFTInfoV1, parseOFTLimit, parseOFTReceipt } from '../bcs/oft'
23
+ import { OFTFeeDetail, OFTInfoV1, OFTLimit, OFTReceipt, SendParam } from '../types'
24
24
 
25
25
  const MODULE_NAME = 'oft'
26
26
  const OFT_SENDER_MODULE_NAME = 'oft_sender'
@@ -56,12 +56,12 @@ export const OFTErrorCode = {
56
56
  * @example
57
57
  * ```typescript
58
58
  * // Initialize OFT instance
59
- * const oft = new OFT(protocolSDK, oftPackageId, oftObjectId, coinType, oappObjectId, adminCapId);
59
+ * const oft = new OFT(protocolSDK, oftCallCapId);
60
60
  *
61
61
  * // Send tokens cross-chain
62
62
  * const tx = new Transaction();
63
63
  * const coin = await oft.splitCoinMoveCall(tx, sender, amount);
64
- * await oft.sendMoveCall(tx, sender, coin, sendParam, nativeFee, zroFee, refundAddress, messagingChannel);
64
+ * await oft.sendMoveCall(tx, sender, sendParam, coin, nativeFee, zroFee, refundAddress);
65
65
  * tx.transferObjects([coin], sender);
66
66
  * ...
67
67
  *
@@ -72,40 +72,45 @@ export const OFTErrorCode = {
72
72
  export class OFT {
73
73
  /** Sui client for blockchain interactions */
74
74
  public readonly client: SuiClient
75
+ /** The OFTCallCap ID */
76
+ public readonly oftCallCapId: string
75
77
  /** The package ID of the OFT */
76
- public oftPackageId: string
78
+ private oftPackageId?: string
77
79
  /** LayerZero protocol object references (endpoint, messaging channels, etc.) */
78
80
  private readonly objects: ObjectOptions
79
81
  /** The unique object ID of this OFT instance on Sui */
80
- private readonly oftObjectId: string
81
- /** Admin capability object ID for privileged operations (optional for read-only usage) */
82
- private readonly adminCapId?: string
82
+ private oftObjectId?: string
83
+ /** Admin capability object ID for privileged operations (retrieved dynamically when needed) */
84
+ private adminCapId?: string
83
85
  /** The Sui coin type this OFT represents (e.g., "0x123::mycoin::MYCOIN") */
84
- private readonly coinType: string
86
+ private coinType?: string
85
87
  /** The unique object ID of the associated OApp instance on Sui */
86
- private oappObjectId: string
88
+ private oappObjectId?: string
87
89
  /** Reference to the LayerZero protocol SDK for cross-chain operations */
88
90
  private readonly protocolSDK: SDK
91
+ /** The OFTInfoV1 structure */
92
+ private oftInfo?: OFTInfoV1
89
93
 
90
94
  /**
91
95
  * Creates a new OFT instance for interacting with an Omnichain Fungible Token
92
96
  *
93
97
  * @param protocolSDK - The LayerZero protocol SDK instance providing core cross-chain functionality
94
- * @param oftPackageId - The package ID of the core OFT framework (shared across all OFT implementations)
95
- * @param oftObjectId - The unique object ID of this OFT instance
96
- * @param coinType - The Sui coin type string (e.g., "0x123::mycoin::MYCOIN")
97
- * @param adminCapId - Optional admin capability object ID for privileged operations (required for admin functions)
98
+ * @param oftCallCapId - The OFT call capability ID used for OFT operations and accessing OFT information
99
+ * @param oftObjectId - Optional OFT object ID on Sui blockchain for direct OFT instance access
100
+ * @param coinType - Optional Sui coin type string (e.g., "0x123::mycoin::MYCOIN") that this OFT represents
101
+ * @param oappObjectId - Optional associated OApp object ID for cross-chain messaging operations
102
+ * @param adminCapId - Optional admin capability object ID for privileged operations
98
103
  */
99
104
  constructor(
100
105
  protocolSDK: SDK,
101
- oftPackageId: string, // the OFT package id
102
- oftObjectId: string,
103
- coinType: string,
104
- oappObjectId: string, // the associated oapp object id
106
+ oftCallCapId: string,
107
+ oftObjectId?: string,
108
+ coinType?: string,
109
+ oappObjectId?: string, // the associated oapp object id
105
110
  adminCapId?: string
106
111
  ) {
107
112
  this.protocolSDK = protocolSDK
108
- this.oftPackageId = oftPackageId
113
+ this.oftCallCapId = oftCallCapId
109
114
  this.client = protocolSDK.client
110
115
  this.objects = protocolSDK.objects
111
116
  this.oftObjectId = oftObjectId
@@ -131,7 +136,9 @@ export class OFT {
131
136
  * Initialize an OFT instance with a treasury capability
132
137
  * Creates a new OFT that mints its own tokens
133
138
  * @param tx - The transaction to add the move call to
139
+ * @param coinType - The Sui coin type string (e.g., "0x123::mycoin::MYCOIN")
134
140
  * @param ticket - The OFTCreationTicket object ID or TransactionArgument
141
+ * @param oapp - The OApp object ID or TransactionArgument
135
142
  * @param treasury - The TreasuryCap object ID or TransactionArgument for the coin type
136
143
  * @param metadata - The CoinMetadata object ID or TransactionArgument for the coin type
137
144
  * @param sharedDecimals - Number of decimals to use for cross-chain operations
@@ -139,6 +146,7 @@ export class OFT {
139
146
  */
140
147
  initOftMoveCall(
141
148
  tx: Transaction,
149
+ coinType: string,
142
150
  ticket: string | TransactionArgument,
143
151
  oapp: string | TransactionArgument,
144
152
  treasury: string | TransactionArgument,
@@ -146,8 +154,8 @@ export class OFT {
146
154
  sharedDecimals: number | TransactionArgument
147
155
  ): TransactionResult {
148
156
  return tx.moveCall({
149
- target: this.#target('init_oft', OFT_IMPL_MODULE_NAME),
150
- typeArguments: [this.coinType],
157
+ target: `${this.oftCallCapId}::${OFT_IMPL_MODULE_NAME}::init_oft`,
158
+ typeArguments: [coinType],
151
159
  arguments: [
152
160
  asObject(tx, ticket),
153
161
  asObject(tx, oapp),
@@ -162,21 +170,24 @@ export class OFT {
162
170
  * Initialize an OFT adapter instance
163
171
  * Creates an OFT adapter that wraps an existing coin type
164
172
  * @param tx - The transaction to add the move call to
173
+ * @param coinType - The Sui coin type string (e.g., "0x123::mycoin::MYCOIN")
165
174
  * @param ticket - The OFTCreationTicket object ID or TransactionArgument
175
+ * @param oapp - The OApp object ID or TransactionArgument
166
176
  * @param metadata - The CoinMetadata object ID or TransactionArgument for the coin type
167
177
  * @param sharedDecimals - Number of decimals to use for cross-chain operations
168
178
  * @returns TransactionResult array containing [AdminCap, MigrationCap] - MigrationCap must be transferred or stored
169
179
  */
170
180
  initOftAdapterMoveCall(
171
181
  tx: Transaction,
182
+ coinType: string,
172
183
  ticket: string | TransactionArgument,
173
184
  oapp: string | TransactionArgument,
174
185
  metadata: string | TransactionArgument,
175
186
  sharedDecimals: number | TransactionArgument
176
187
  ): TransactionResult {
177
188
  return tx.moveCall({
178
- target: this.#target('init_oft_adapter', OFT_IMPL_MODULE_NAME),
179
- typeArguments: [this.coinType],
189
+ target: `${this.oftCallCapId}::${OFT_IMPL_MODULE_NAME}::init_oft_adapter`,
190
+ typeArguments: [coinType],
180
191
  arguments: [asObject(tx, ticket), asObject(tx, oapp), asObject(tx, metadata), asU8(tx, sharedDecimals)],
181
192
  })
182
193
  }
@@ -185,7 +196,7 @@ export class OFT {
185
196
  // ADMIN FUNCTIONS
186
197
  // ==========================================
187
198
  // These functions require admin privileges and are used for OFT configuration
188
- // and management. They require the adminCapId to be provided during construction.
199
+ // and management. The admin capability is automatically retrieved from the OFT instance.
189
200
 
190
201
  /**
191
202
  * Get LayerZero receive information for OFT registration
@@ -197,12 +208,15 @@ export class OFT {
197
208
  * @param composerManager - The composer manager object ID for routing compose transfers
198
209
  * @returns TransactionResult containing serialized execution metadata for endpoint registration
199
210
  */
200
- lzReceiveInfoMoveCall(tx: Transaction, composerManager: string | TransactionArgument): TransactionResult {
211
+ async lzReceiveInfoMoveCall(
212
+ tx: Transaction,
213
+ composerManager: string | TransactionArgument
214
+ ): Promise<TransactionResult> {
201
215
  return tx.moveCall({
202
- target: this.#target('lz_receive_info', OFT_PTB_BUILDER_MODULE_NAME),
203
- typeArguments: [this.coinType],
216
+ target: await this.#target('lz_receive_info', OFT_PTB_BUILDER_MODULE_NAME),
217
+ typeArguments: [await this.#coinType()],
204
218
  arguments: [
205
- tx.object(this.oftObjectId),
219
+ tx.object(await this.#oftObjectId()),
206
220
  tx.object(this.objects.endpointV2),
207
221
  asObject(tx, composerManager),
208
222
  tx.object.clock(),
@@ -213,17 +227,52 @@ export class OFT {
213
227
  /**
214
228
  * Register OFT as an OApp with LayerZero endpoint
215
229
  * @param tx - The transaction to add the move call to
216
- * @param lzReceiveInfo - PTB Builder lzReceiveInfoMoveCall result, used for protocol SDK to dynamically build the PTB
217
- * for OFT's lzReceive operation
230
+ * @param coinType - The Sui coin type string (e.g., "0x123::mycoin::MYCOIN")
231
+ * @param oftObjectId - The OFT object ID
232
+ * @param oappObjectId - The OApp object ID
233
+ * @param composerManager - The composer manager object ID or TransactionArgument
234
+ * @param lzReceiveInfo - Optional LayerZero receive info as Uint8Array or TransactionArgument
218
235
  */
219
- registerOAppMoveCall(tx: Transaction, lzReceiveInfo: Uint8Array | TransactionArgument): void {
236
+ async registerOAppMoveCall(
237
+ tx: Transaction,
238
+ coinType: string,
239
+ oftObjectId: string,
240
+ oappObjectId: string,
241
+ composerManager: string | TransactionArgument,
242
+ lzReceiveInfo?: Uint8Array | TransactionArgument
243
+ ): Promise<void> {
244
+ const adminCapId = await executeSimulate(
245
+ this.client,
246
+ (tx) => {
247
+ tx.moveCall({
248
+ target: `${this.oftCallCapId}::${MODULE_NAME}::admin_cap`,
249
+ typeArguments: [coinType],
250
+ arguments: [tx.object(oftObjectId)],
251
+ })
252
+ },
253
+ (result) => bcs.Address.parse(result[0].value)
254
+ )
255
+
256
+ if (lzReceiveInfo === undefined) {
257
+ lzReceiveInfo = tx.moveCall({
258
+ target: `${this.oftCallCapId}::${OFT_PTB_BUILDER_MODULE_NAME}::lz_receive_info`,
259
+ typeArguments: [coinType],
260
+ arguments: [
261
+ tx.object(oftObjectId),
262
+ tx.object(this.objects.endpointV2),
263
+ asObject(tx, composerManager),
264
+ tx.object.clock(),
265
+ ],
266
+ })
267
+ }
268
+
220
269
  tx.moveCall({
221
- target: this.#target('register_oapp'),
222
- typeArguments: [this.coinType],
270
+ target: `${this.oftCallCapId}::${MODULE_NAME}::register_oapp`,
271
+ typeArguments: [coinType],
223
272
  arguments: [
224
- tx.object(this.oftObjectId),
225
- tx.object(this.#oappObjectId()),
226
- tx.object(this.#adminCapId()),
273
+ tx.object(oftObjectId),
274
+ tx.object(oappObjectId),
275
+ tx.object(adminCapId),
227
276
  tx.object(this.objects.endpointV2),
228
277
  asBytes(tx, lzReceiveInfo),
229
278
  ],
@@ -235,11 +284,11 @@ export class OFT {
235
284
  * @param tx - The transaction to add the move call to
236
285
  * @param pause - Whether to pause or unpause operations
237
286
  */
238
- setPauseMoveCall(tx: Transaction, pause: boolean | TransactionArgument): void {
287
+ async setPauseMoveCall(tx: Transaction, pause: boolean | TransactionArgument): Promise<void> {
239
288
  tx.moveCall({
240
- target: this.#target('set_pause'),
241
- typeArguments: [this.coinType],
242
- arguments: [tx.object(this.oftObjectId), tx.object(this.#adminCapId()), asBool(tx, pause)],
289
+ target: await this.#target('set_pause'),
290
+ typeArguments: [await this.#coinType()],
291
+ arguments: [tx.object(await this.#oftObjectId()), tx.object(await this.#adminCapId()), asBool(tx, pause)],
243
292
  })
244
293
  }
245
294
 
@@ -253,19 +302,34 @@ export class OFT {
253
302
  * @param tx - The transaction to add the move call to
254
303
  * @param feeDepositAddress - The new fee deposit address
255
304
  */
256
- setFeeDepositAddressMoveCall(tx: Transaction, feeDepositAddress: string | TransactionArgument): void {
305
+ async setFeeDepositAddressMoveCall(
306
+ tx: Transaction,
307
+ feeDepositAddress: string | TransactionArgument
308
+ ): Promise<void> {
257
309
  tx.moveCall({
258
- target: this.#target('set_fee_deposit_address'),
259
- typeArguments: [this.coinType],
260
- arguments: [tx.object(this.oftObjectId), tx.object(this.#adminCapId()), asAddress(tx, feeDepositAddress)],
310
+ target: await this.#target('set_fee_deposit_address'),
311
+ typeArguments: [await this.#coinType()],
312
+ arguments: [
313
+ tx.object(await this.#oftObjectId()),
314
+ tx.object(await this.#adminCapId()),
315
+ asAddress(tx, feeDepositAddress),
316
+ ],
261
317
  })
262
318
  }
263
319
 
264
- setDefaultFeeBpsMoveCall(tx: Transaction, feeBps: bigint | number | string | TransactionArgument): void {
320
+ /**
321
+ * Set default fee basis points for OFT transfers
322
+ * @param tx - The transaction to add the move call to
323
+ * @param feeBps - Default fee rate in basis points (0-10,000, where 10,000 = 100%)
324
+ */
325
+ async setDefaultFeeBpsMoveCall(
326
+ tx: Transaction,
327
+ feeBps: bigint | number | string | TransactionArgument
328
+ ): Promise<void> {
265
329
  tx.moveCall({
266
- target: this.#target('set_default_fee_bps'),
267
- typeArguments: [this.coinType],
268
- arguments: [tx.object(this.oftObjectId), tx.object(this.#adminCapId()), asU64(tx, feeBps)],
330
+ target: await this.#target('set_default_fee_bps'),
331
+ typeArguments: [await this.#coinType()],
332
+ arguments: [tx.object(await this.#oftObjectId()), tx.object(await this.#adminCapId()), asU64(tx, feeBps)],
269
333
  })
270
334
  }
271
335
 
@@ -275,17 +339,17 @@ export class OFT {
275
339
  * @param dstEid - Destination endpoint ID
276
340
  * @param feeBps - Fee rate in basis points (0-10,000, where 10,000 = 100%)
277
341
  */
278
- setFeeBpsMoveCall(
342
+ async setFeeBpsMoveCall(
279
343
  tx: Transaction,
280
344
  dstEid: number | TransactionArgument,
281
345
  feeBps: bigint | number | string | TransactionArgument
282
- ): void {
346
+ ): Promise<void> {
283
347
  tx.moveCall({
284
- target: this.#target('set_fee_bps'),
285
- typeArguments: [this.coinType],
348
+ target: await this.#target('set_fee_bps'),
349
+ typeArguments: [await this.#coinType()],
286
350
  arguments: [
287
- tx.object(this.oftObjectId),
288
- tx.object(this.#adminCapId()),
351
+ tx.object(await this.#oftObjectId()),
352
+ tx.object(await this.#adminCapId()),
289
353
  asU32(tx, dstEid),
290
354
  asU64(tx, feeBps),
291
355
  ],
@@ -297,11 +361,11 @@ export class OFT {
297
361
  * @param tx - The transaction to add the move call to
298
362
  * @param dstEid - Destination endpoint ID
299
363
  */
300
- unsetFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): void {
364
+ async unsetFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): Promise<void> {
301
365
  tx.moveCall({
302
- target: this.#target('unset_fee_bps'),
303
- typeArguments: [this.coinType],
304
- arguments: [tx.object(this.oftObjectId), tx.object(this.#adminCapId()), asU32(tx, dstEid)],
366
+ target: await this.#target('unset_fee_bps'),
367
+ typeArguments: [await this.#coinType()],
368
+ arguments: [tx.object(await this.#oftObjectId()), tx.object(await this.#adminCapId()), asU32(tx, dstEid)],
305
369
  })
306
370
  }
307
371
 
@@ -316,11 +380,11 @@ export class OFT {
316
380
  * @param migrationCap - Migration capability object ID or transaction argument
317
381
  * @returns TransactionResult containing the migration ticket
318
382
  */
319
- migrateMoveCall(tx: Transaction, migrationCap: string | TransactionArgument): TransactionResult {
383
+ async migrateMoveCall(tx: Transaction, migrationCap: string | TransactionArgument): Promise<TransactionResult> {
320
384
  return tx.moveCall({
321
- target: this.#target('migrate'),
322
- typeArguments: [this.coinType],
323
- arguments: [tx.object(this.oftObjectId), asObject(tx, migrationCap)],
385
+ target: await this.#target('migrate'),
386
+ typeArguments: [await this.#coinType()],
387
+ arguments: [tx.object(await this.#oftObjectId()), asObject(tx, migrationCap)],
324
388
  })
325
389
  }
326
390
 
@@ -337,19 +401,19 @@ export class OFT {
337
401
  * @param rateLimit - Rate limit amount
338
402
  * @param windowSeconds - Time window in seconds
339
403
  */
340
- setRateLimitMoveCall(
404
+ async setRateLimitMoveCall(
341
405
  tx: Transaction,
342
406
  eid: number | TransactionArgument,
343
407
  inbound: boolean | TransactionArgument,
344
408
  rateLimit: bigint | number | string | TransactionArgument,
345
409
  windowSeconds: bigint | number | string | TransactionArgument
346
- ): void {
410
+ ): Promise<void> {
347
411
  tx.moveCall({
348
- target: this.#target('set_rate_limit'),
349
- typeArguments: [this.coinType],
412
+ target: await this.#target('set_rate_limit'),
413
+ typeArguments: [await this.#coinType()],
350
414
  arguments: [
351
- tx.object(this.oftObjectId),
352
- tx.object(this.#adminCapId()),
415
+ tx.object(await this.#oftObjectId()),
416
+ tx.object(await this.#adminCapId()),
353
417
  asU32(tx, eid),
354
418
  asBool(tx, inbound),
355
419
  asU64(tx, rateLimit),
@@ -365,17 +429,17 @@ export class OFT {
365
429
  * @param eid - Endpoint ID
366
430
  * @param inbound - Whether this is for inbound or outbound transfers
367
431
  */
368
- unsetRateLimitMoveCall(
432
+ async unsetRateLimitMoveCall(
369
433
  tx: Transaction,
370
434
  eid: number | TransactionArgument,
371
435
  inbound: boolean | TransactionArgument
372
- ): void {
436
+ ): Promise<void> {
373
437
  tx.moveCall({
374
- target: this.#target('unset_rate_limit'),
375
- typeArguments: [this.coinType],
438
+ target: await this.#target('unset_rate_limit'),
439
+ typeArguments: [await this.#coinType()],
376
440
  arguments: [
377
- tx.object(this.oftObjectId),
378
- tx.object(this.#adminCapId()),
441
+ tx.object(await this.#oftObjectId()),
442
+ tx.object(await this.#adminCapId()),
379
443
  asU32(tx, eid),
380
444
  asBool(tx, inbound),
381
445
  ],
@@ -404,7 +468,7 @@ export class OFT {
404
468
  limit = 200,
405
469
  pageSize = 50
406
470
  ): Promise<TransactionResult> {
407
- return this.protocolSDK.getUtils().splitCoinMoveCall(tx, this.coinType, owner, amount, limit, pageSize)
471
+ return this.protocolSDK.getUtils().splitCoinMoveCall(tx, await this.#coinType(), owner, amount, limit, pageSize)
408
472
  }
409
473
 
410
474
  /**
@@ -416,7 +480,9 @@ export class OFT {
416
480
  * @param nativeFee - Native token fee amount
417
481
  * @param zroFee - ZRO token fee amount
418
482
  * @param refundAddress - Address for fee refunds
419
- * @returns Promise<TransactionResult> - Transaction result containing send operation and receipt objects
483
+ * @param validators - Optional PTB validators for transaction validation
484
+ * @param maxSimulationTimes - Optional maximum number of simulation attempts
485
+ * @returns Promise<void> - Completes when the send operation is processed
420
486
  */
421
487
  async sendMoveCall(
422
488
  tx: Transaction,
@@ -429,19 +495,19 @@ export class OFT {
429
495
  validators?: IPTBValidator[],
430
496
  maxSimulationTimes?: number
431
497
  ): Promise<void> {
432
- const sendParamArg = isTransactionArgument(sendParam) ? sendParam : this.#buildSendParam(tx, sendParam)
433
- const txSender = this.txSenderMoveCall(tx)
498
+ const sendParamArg = isTransactionArgument(sendParam) ? sendParam : await this.#buildSendParam(tx, sendParam)
499
+ const txSender = await this.txSenderMoveCall(tx)
434
500
  const addressArg = isTransactionArgument(refundAddress)
435
501
  ? refundAddress
436
502
  : tx.pure.option('address', refundAddress)
437
503
 
438
504
  // The oft::send returns a tuple (Call<EndpointSendParam, MessagingReceipt>, OFTReceipt)
439
505
  const transactionResult = tx.moveCall({
440
- target: this.#target('send'),
441
- typeArguments: [this.coinType],
506
+ target: await this.#target('send'),
507
+ typeArguments: [await this.#coinType()],
442
508
  arguments: [
443
- tx.object(this.oftObjectId),
444
- tx.object(this.#oappObjectId()),
509
+ tx.object(await this.#oftObjectId()),
510
+ tx.object(await this.#oappObjectId()),
445
511
  txSender,
446
512
  sendParamArg,
447
513
  asObject(tx, coinProvided),
@@ -467,11 +533,11 @@ export class OFT {
467
533
  )
468
534
 
469
535
  const confirmSendResult = tx.moveCall({
470
- target: this.#target('confirm_send'),
471
- typeArguments: [this.coinType],
536
+ target: await this.#target('confirm_send'),
537
+ typeArguments: [await this.#coinType()],
472
538
  arguments: [
473
- tx.object(this.oftObjectId),
474
- tx.object(this.#oappObjectId()),
539
+ tx.object(await this.#oftObjectId()),
540
+ tx.object(await this.#oappObjectId()),
475
541
  txSender,
476
542
  endpointCall,
477
543
  oftSendContext,
@@ -498,13 +564,13 @@ export class OFT {
498
564
  * @param call - LayerZero receive call containing the verified cross-chain message
499
565
  * @returns TransactionResult containing the processed transfer
500
566
  */
501
- lzReceiveMoveCall(tx: Transaction, call: string | TransactionArgument): TransactionResult {
567
+ async lzReceiveMoveCall(tx: Transaction, call: string | TransactionArgument): Promise<TransactionResult> {
502
568
  return tx.moveCall({
503
- target: this.#target('lz_receive'),
504
- typeArguments: [this.coinType],
569
+ target: await this.#target('lz_receive'),
570
+ typeArguments: [await this.#coinType()],
505
571
  arguments: [
506
- tx.object(this.oftObjectId),
507
- tx.object(this.#oappObjectId()),
572
+ tx.object(await this.#oftObjectId()),
573
+ tx.object(await this.#oappObjectId()),
508
574
  asObject(tx, call),
509
575
  tx.object.clock(),
510
576
  ],
@@ -519,18 +585,18 @@ export class OFT {
519
585
  * @param call - LayerZero receive call containing the verified cross-chain message
520
586
  * @returns TransactionResult containing the processed transfer
521
587
  */
522
- lzReceiveWithComposeMoveCall(
588
+ async lzReceiveWithComposeMoveCall(
523
589
  tx: Transaction,
524
590
  composeQueue: string | TransactionArgument,
525
591
  composerManager: string | TransactionArgument,
526
592
  call: string | TransactionArgument
527
- ): TransactionResult {
593
+ ): Promise<TransactionResult> {
528
594
  return tx.moveCall({
529
- target: this.#target('lz_receive_with_compose'),
530
- typeArguments: [this.coinType],
595
+ target: await this.#target('lz_receive_with_compose'),
596
+ typeArguments: [await this.#coinType()],
531
597
  arguments: [
532
- tx.object(this.oftObjectId),
533
- tx.object(this.#oappObjectId()),
598
+ tx.object(await this.#oftObjectId()),
599
+ tx.object(await this.#oappObjectId()),
534
600
  asObject(tx, composeQueue),
535
601
  asObject(tx, composerManager),
536
602
  asObject(tx, call),
@@ -545,11 +611,15 @@ export class OFT {
545
611
  * @param call - Completed Call object from quote_send() execution
546
612
  * @returns TransactionResult containing the messaging fee
547
613
  */
548
- confirmQuoteSendMoveCall(tx: Transaction, call: string | TransactionArgument): TransactionResult {
614
+ async confirmQuoteSendMoveCall(tx: Transaction, call: string | TransactionArgument): Promise<TransactionResult> {
549
615
  return tx.moveCall({
550
- target: this.#target('confirm_quote_send'),
551
- typeArguments: [this.coinType],
552
- arguments: [tx.object(this.oftObjectId), tx.object(this.#oappObjectId()), asObject(tx, call)],
616
+ target: await this.#target('confirm_quote_send'),
617
+ typeArguments: [await this.#coinType()],
618
+ arguments: [
619
+ tx.object(await this.#oftObjectId()),
620
+ tx.object(await this.#oappObjectId()),
621
+ asObject(tx, call),
622
+ ],
553
623
  })
554
624
  }
555
625
 
@@ -568,12 +638,14 @@ export class OFT {
568
638
  ): Promise<{ limit: OFTLimit; feeDetails: OFTFeeDetail[]; receipt: OFTReceipt }> {
569
639
  return executeSimulate(
570
640
  this.client,
571
- (tx) => {
572
- const sendParamArg = isTransactionArgument(sendParam) ? sendParam : this.#buildSendParam(tx, sendParam)
641
+ async (tx) => {
642
+ const sendParamArg = isTransactionArgument(sendParam)
643
+ ? sendParam
644
+ : await this.#buildSendParam(tx, sendParam)
573
645
  tx.moveCall({
574
- target: this.#target('quote_oft'),
575
- typeArguments: [this.coinType],
576
- arguments: [tx.object(this.oftObjectId), sendParamArg, tx.object.clock()],
646
+ target: await this.#target('quote_oft'),
647
+ typeArguments: [await this.#coinType()],
648
+ arguments: [tx.object(await this.#oftObjectId()), sendParamArg, tx.object.clock()],
577
649
  })
578
650
  },
579
651
  (result) => {
@@ -591,6 +663,8 @@ export class OFT {
591
663
  * @param sender - Sender address
592
664
  * @param sendParam - Send parameters for the OFT operation
593
665
  * @param payInZro - Whether to pay in ZRO tokens
666
+ * @param validators - Optional PTB validators for transaction validation
667
+ * @param maxSimulationTimes - Optional maximum number of simulation attempts
594
668
  * @returns Promise<MessagingFee> - The calculated messaging fees
595
669
  */
596
670
  async quoteSend(
@@ -601,14 +675,14 @@ export class OFT {
601
675
  maxSimulationTimes?: number
602
676
  ): Promise<MessagingFee> {
603
677
  const tx = new Transaction()
604
- const sendParamArg = isTransactionArgument(sendParam) ? sendParam : this.#buildSendParam(tx, sendParam)
678
+ const sendParamArg = isTransactionArgument(sendParam) ? sendParam : await this.#buildSendParam(tx, sendParam)
605
679
 
606
680
  const quoteCall = tx.moveCall({
607
- target: this.#target('quote_send'),
608
- typeArguments: [this.coinType],
681
+ target: await this.#target('quote_send'),
682
+ typeArguments: [await this.#coinType()],
609
683
  arguments: [
610
- tx.object(this.oftObjectId),
611
- tx.object(this.#oappObjectId()),
684
+ tx.object(await this.#oftObjectId()),
685
+ tx.object(await this.#oappObjectId()),
612
686
  asAddress(tx, sender),
613
687
  sendParamArg,
614
688
  asBool(tx, payInZro),
@@ -628,11 +702,11 @@ export class OFT {
628
702
  * @param tx - The transaction to add the move call to
629
703
  * @returns Transaction result containing the upgrade version
630
704
  */
631
- upgradeVersionMoveCall(tx: Transaction): TransactionResult {
705
+ async upgradeVersionMoveCall(tx: Transaction): Promise<TransactionResult> {
632
706
  return tx.moveCall({
633
- target: this.#target('upgrade_version'),
634
- typeArguments: [this.coinType],
635
- arguments: [tx.object(this.oftObjectId)],
707
+ target: await this.#target('upgrade_version'),
708
+ typeArguments: [await this.#coinType()],
709
+ arguments: [tx.object(await this.#oftObjectId())],
636
710
  })
637
711
  }
638
712
 
@@ -643,8 +717,8 @@ export class OFT {
643
717
  async upgradeVersion(): Promise<bigint> {
644
718
  return executeSimulate(
645
719
  this.client,
646
- (tx) => {
647
- this.upgradeVersionMoveCall(tx)
720
+ async (tx) => {
721
+ await this.upgradeVersionMoveCall(tx)
648
722
  },
649
723
  (result) => BigInt(bcs.U64.parse(result[0].value))
650
724
  )
@@ -655,11 +729,11 @@ export class OFT {
655
729
  * @param tx - The transaction to add the move call to
656
730
  * @returns Transaction result containing the OApp object address
657
731
  */
658
- oappObjectMoveCall(tx: Transaction): TransactionResult {
732
+ async oappObjectMoveCall(tx: Transaction): Promise<TransactionResult> {
659
733
  return tx.moveCall({
660
- target: this.#target('oapp_object'),
661
- typeArguments: [this.coinType],
662
- arguments: [tx.object(this.oftObjectId)],
734
+ target: await this.#target('oapp_object'),
735
+ typeArguments: [await this.#coinType()],
736
+ arguments: [tx.object(await this.#oftObjectId())],
663
737
  })
664
738
  }
665
739
 
@@ -670,8 +744,8 @@ export class OFT {
670
744
  async oappObject(): Promise<string> {
671
745
  return executeSimulate(
672
746
  this.client,
673
- (tx) => {
674
- this.oappObjectMoveCall(tx)
747
+ async (tx) => {
748
+ await this.oappObjectMoveCall(tx)
675
749
  },
676
750
  (result) => bcs.Address.parse(result[0].value)
677
751
  )
@@ -682,11 +756,11 @@ export class OFT {
682
756
  * @param tx - The transaction to add the move call to
683
757
  * @returns Transaction result containing version information
684
758
  */
685
- oftVersionMoveCall(tx: Transaction): TransactionResult {
759
+ async oftVersionMoveCall(tx: Transaction): Promise<TransactionResult> {
686
760
  return tx.moveCall({
687
- target: this.#target('oft_version'),
688
- typeArguments: [this.coinType],
689
- arguments: [tx.object(this.oftObjectId)],
761
+ target: await this.#target('oft_version'),
762
+ typeArguments: [await this.#coinType()],
763
+ arguments: [tx.object(await this.#oftObjectId())],
690
764
  })
691
765
  }
692
766
 
@@ -697,8 +771,8 @@ export class OFT {
697
771
  async oftVersion(): Promise<{ major: number; minor: number }> {
698
772
  return executeSimulate(
699
773
  this.client,
700
- (tx) => {
701
- this.oftVersionMoveCall(tx)
774
+ async (tx) => {
775
+ await this.oftVersionMoveCall(tx)
702
776
  },
703
777
  (result) => {
704
778
  const major = Number(bcs.U64.parse(result[0].value))
@@ -708,18 +782,29 @@ export class OFT {
708
782
  )
709
783
  }
710
784
 
711
- oftCapIdMoveCall(tx: Transaction): TransactionResult {
785
+ /**
786
+ * Get the OFT capability ID
787
+ * @param tx - The transaction to add the move call to
788
+ * @returns Transaction result containing the OFT capability ID
789
+ */
790
+ async oftCapIdMoveCall(tx: Transaction): Promise<TransactionResult> {
712
791
  return tx.moveCall({
713
- target: this.#target('oft_cap_id'),
714
- typeArguments: [this.coinType],
715
- arguments: [tx.object(this.oftObjectId)],
792
+ target: await this.#target('oft_cap_id'),
793
+ typeArguments: [await this.#coinType()],
794
+ arguments: [tx.object(await this.#oftObjectId())],
716
795
  })
717
796
  }
718
797
 
798
+ /**
799
+ * Get the OFT capability ID
800
+ * @returns Promise<string> - The OFT capability ID
801
+ */
719
802
  async oftCapId(): Promise<string> {
720
803
  return executeSimulate(
721
804
  this.client,
722
- (tx) => this.oftCapIdMoveCall(tx),
805
+ async (tx) => {
806
+ await this.oftCapIdMoveCall(tx)
807
+ },
723
808
  (result) => bcs.Address.parse(result[0].value)
724
809
  )
725
810
  }
@@ -729,11 +814,11 @@ export class OFT {
729
814
  * @param tx - The transaction to add the move call to
730
815
  * @returns Transaction result containing the migration capability address
731
816
  */
732
- migrationCapMoveCall(tx: Transaction): TransactionResult {
817
+ async migrationCapMoveCall(tx: Transaction): Promise<TransactionResult> {
733
818
  return tx.moveCall({
734
- target: this.#target('migration_cap'),
735
- typeArguments: [this.coinType],
736
- arguments: [tx.object(this.oftObjectId)],
819
+ target: await this.#target('migration_cap'),
820
+ typeArguments: [await this.#coinType()],
821
+ arguments: [tx.object(await this.#oftObjectId())],
737
822
  })
738
823
  }
739
824
 
@@ -744,8 +829,8 @@ export class OFT {
744
829
  async migrationCap(): Promise<string> {
745
830
  return executeSimulate(
746
831
  this.client,
747
- (tx) => {
748
- this.migrationCapMoveCall(tx)
832
+ async (tx) => {
833
+ await this.migrationCapMoveCall(tx)
749
834
  },
750
835
  (result) => bcs.Address.parse(result[0].value)
751
836
  )
@@ -754,8 +839,8 @@ export class OFT {
754
839
  async messagingChannel(): Promise<string> {
755
840
  return executeSimulate(
756
841
  this.client,
757
- (tx) => {
758
- const oftCapId = this.oftCapIdMoveCall(tx)
842
+ async (tx) => {
843
+ const oftCapId = await this.oftCapIdMoveCall(tx)
759
844
  this.protocolSDK.getEndpoint().getMessagingChannelMoveCall(tx, oftCapId)
760
845
  },
761
846
  (result) => bcs.Address.parse(result[0].value)
@@ -767,11 +852,11 @@ export class OFT {
767
852
  * @param tx - The transaction to add the move call to
768
853
  * @returns Transaction result containing coin metadata address
769
854
  */
770
- coinMetadataMoveCall(tx: Transaction): TransactionResult {
855
+ async coinMetadataMoveCall(tx: Transaction): Promise<TransactionResult> {
771
856
  return tx.moveCall({
772
- target: this.#target('coin_metadata'),
773
- typeArguments: [this.coinType],
774
- arguments: [tx.object(this.oftObjectId)],
857
+ target: await this.#target('coin_metadata'),
858
+ typeArguments: [await this.#coinType()],
859
+ arguments: [tx.object(await this.#oftObjectId())],
775
860
  })
776
861
  }
777
862
 
@@ -782,8 +867,8 @@ export class OFT {
782
867
  async coinMetadata(): Promise<string> {
783
868
  return executeSimulate(
784
869
  this.client,
785
- (tx) => {
786
- this.coinMetadataMoveCall(tx)
870
+ async (tx) => {
871
+ await this.coinMetadataMoveCall(tx)
787
872
  },
788
873
  (result) => bcs.Address.parse(result[0].value)
789
874
  )
@@ -794,11 +879,11 @@ export class OFT {
794
879
  * @param tx - The transaction to add the move call to
795
880
  * @returns Transaction result containing the admin capability address
796
881
  */
797
- adminCapMoveCall(tx: Transaction): TransactionResult {
882
+ async adminCapMoveCall(tx: Transaction): Promise<TransactionResult> {
798
883
  return tx.moveCall({
799
- target: this.#target('admin_cap'),
800
- typeArguments: [this.coinType],
801
- arguments: [tx.object(this.oftObjectId)],
884
+ target: await this.#target('admin_cap'),
885
+ typeArguments: [await this.#coinType()],
886
+ arguments: [tx.object(await this.#oftObjectId())],
802
887
  })
803
888
  }
804
889
 
@@ -809,8 +894,8 @@ export class OFT {
809
894
  async adminCap(): Promise<string> {
810
895
  return executeSimulate(
811
896
  this.client,
812
- (tx) => {
813
- this.adminCapMoveCall(tx)
897
+ async (tx) => {
898
+ await this.adminCapMoveCall(tx)
814
899
  },
815
900
  (result) => bcs.Address.parse(result[0].value)
816
901
  )
@@ -821,11 +906,11 @@ export class OFT {
821
906
  * @param tx - The transaction to add the move call to
822
907
  * @returns Transaction result containing shared decimals
823
908
  */
824
- sharedDecimalsMoveCall(tx: Transaction): TransactionResult {
909
+ async sharedDecimalsMoveCall(tx: Transaction): Promise<TransactionResult> {
825
910
  return tx.moveCall({
826
- target: this.#target('shared_decimals'),
827
- typeArguments: [this.coinType],
828
- arguments: [tx.object(this.oftObjectId)],
911
+ target: await this.#target('shared_decimals'),
912
+ typeArguments: [await this.#coinType()],
913
+ arguments: [tx.object(await this.#oftObjectId())],
829
914
  })
830
915
  }
831
916
 
@@ -836,8 +921,8 @@ export class OFT {
836
921
  async sharedDecimals(): Promise<number> {
837
922
  return executeSimulate(
838
923
  this.client,
839
- (tx) => {
840
- this.sharedDecimalsMoveCall(tx)
924
+ async (tx) => {
925
+ await this.sharedDecimalsMoveCall(tx)
841
926
  },
842
927
  (result) => bcs.U8.parse(result[0].value)
843
928
  )
@@ -848,11 +933,11 @@ export class OFT {
848
933
  * @param tx - The transaction to add the move call to
849
934
  * @returns Transaction result containing the decimal conversion rate
850
935
  */
851
- decimalConversionRateMoveCall(tx: Transaction): TransactionResult {
936
+ async decimalConversionRateMoveCall(tx: Transaction): Promise<TransactionResult> {
852
937
  return tx.moveCall({
853
- target: this.#target('decimal_conversion_rate'),
854
- typeArguments: [this.coinType],
855
- arguments: [tx.object(this.oftObjectId)],
938
+ target: await this.#target('decimal_conversion_rate'),
939
+ typeArguments: [await this.#coinType()],
940
+ arguments: [tx.object(await this.#oftObjectId())],
856
941
  })
857
942
  }
858
943
 
@@ -863,8 +948,8 @@ export class OFT {
863
948
  async decimalConversionRate(): Promise<bigint> {
864
949
  return executeSimulate(
865
950
  this.client,
866
- (tx) => {
867
- this.decimalConversionRateMoveCall(tx)
951
+ async (tx) => {
952
+ await this.decimalConversionRateMoveCall(tx)
868
953
  },
869
954
  (result) => BigInt(bcs.U64.parse(result[0].value))
870
955
  )
@@ -875,11 +960,11 @@ export class OFT {
875
960
  * @param tx - The transaction to add the move call to
876
961
  * @returns Transaction result containing the paused status
877
962
  */
878
- isPausedMoveCall(tx: Transaction): TransactionResult {
963
+ async isPausedMoveCall(tx: Transaction): Promise<TransactionResult> {
879
964
  return tx.moveCall({
880
- target: this.#target('is_paused'),
881
- typeArguments: [this.coinType],
882
- arguments: [tx.object(this.oftObjectId)],
965
+ target: await this.#target('is_paused'),
966
+ typeArguments: [await this.#coinType()],
967
+ arguments: [tx.object(await this.#oftObjectId())],
883
968
  })
884
969
  }
885
970
 
@@ -890,8 +975,8 @@ export class OFT {
890
975
  async isPaused(): Promise<boolean> {
891
976
  return executeSimulate(
892
977
  this.client,
893
- (tx) => {
894
- this.isPausedMoveCall(tx)
978
+ async (tx) => {
979
+ await this.isPausedMoveCall(tx)
895
980
  },
896
981
  (result) => bcs.Bool.parse(result[0].value)
897
982
  )
@@ -902,11 +987,11 @@ export class OFT {
902
987
  * @param tx - The transaction to add the move call to
903
988
  * @returns Transaction result containing the adapter status
904
989
  */
905
- isAdapterMoveCall(tx: Transaction): TransactionResult {
990
+ async isAdapterMoveCall(tx: Transaction): Promise<TransactionResult> {
906
991
  return tx.moveCall({
907
- target: this.#target('is_adapter'),
908
- typeArguments: [this.coinType],
909
- arguments: [tx.object(this.oftObjectId)],
992
+ target: await this.#target('is_adapter'),
993
+ typeArguments: [await this.#coinType()],
994
+ arguments: [tx.object(await this.#oftObjectId())],
910
995
  })
911
996
  }
912
997
 
@@ -917,13 +1002,41 @@ export class OFT {
917
1002
  async isAdapter(): Promise<boolean> {
918
1003
  return executeSimulate(
919
1004
  this.client,
920
- (tx) => {
921
- this.isAdapterMoveCall(tx)
1005
+ async (tx) => {
1006
+ await this.isAdapterMoveCall(tx)
922
1007
  },
923
1008
  (result) => bcs.Bool.parse(result[0].value)
924
1009
  )
925
1010
  }
926
1011
 
1012
+ /**
1013
+ * Decode OFTInfoV1 from encoded bytes
1014
+ * @param tx - The transaction to add the move call to
1015
+ * @param encodedBytes - The encoded OFTInfoV1 bytes to decode
1016
+ * @returns Transaction result containing the decoded OFTInfoV1
1017
+ */
1018
+ decodeOftInfoV1MoveCall(tx: Transaction, encodedBytes: Uint8Array | TransactionArgument): TransactionResult {
1019
+ return tx.moveCall({
1020
+ target: `${this.oftCallCapId}::oft_info_v1::decode`,
1021
+ arguments: [asBytes(tx, encodedBytes)],
1022
+ })
1023
+ }
1024
+
1025
+ /**
1026
+ * Decode OFTInfoV1 from encoded bytes
1027
+ * @param encodedBytes - The encoded OFTInfoV1 bytes to decode
1028
+ * @returns Promise<OFTInfoV1> - The decoded OFTInfoV1 structure
1029
+ */
1030
+ async decodeOftInfoV1(encodedBytes: Uint8Array): Promise<OFTInfoV1> {
1031
+ return executeSimulate(
1032
+ this.client,
1033
+ (tx) => {
1034
+ this.decodeOftInfoV1MoveCall(tx, encodedBytes)
1035
+ },
1036
+ (result) => parseOFTInfoV1(result[0].value)
1037
+ )
1038
+ }
1039
+
927
1040
  // ==========================================
928
1041
  // FEE VIEW FUNCTIONS
929
1042
  // ==========================================
@@ -935,11 +1048,11 @@ export class OFT {
935
1048
  * @param dstEid - Destination endpoint ID
936
1049
  * @returns Transaction result containing whether fee exists
937
1050
  */
938
- hasOftFeeMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
1051
+ async hasOftFeeMoveCall(tx: Transaction, dstEid: number | TransactionArgument): Promise<TransactionResult> {
939
1052
  return tx.moveCall({
940
- target: this.#target('has_oft_fee'),
941
- typeArguments: [this.coinType],
942
- arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
1053
+ target: await this.#target('has_oft_fee'),
1054
+ typeArguments: [await this.#coinType()],
1055
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, dstEid)],
943
1056
  })
944
1057
  }
945
1058
 
@@ -951,8 +1064,8 @@ export class OFT {
951
1064
  async hasOftFee(dstEid: number): Promise<boolean> {
952
1065
  return executeSimulate(
953
1066
  this.client,
954
- (tx) => {
955
- this.hasOftFeeMoveCall(tx, dstEid)
1067
+ async (tx) => {
1068
+ await this.hasOftFeeMoveCall(tx, dstEid)
956
1069
  },
957
1070
  (result) => bcs.Bool.parse(result[0].value)
958
1071
  )
@@ -964,11 +1077,11 @@ export class OFT {
964
1077
  * @param dstEid - Destination endpoint ID
965
1078
  * @returns Transaction result containing the effective fee basis points
966
1079
  */
967
- effectiveFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
1080
+ async effectiveFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): Promise<TransactionResult> {
968
1081
  return tx.moveCall({
969
- target: this.#target('effective_fee_bps'),
970
- typeArguments: [this.coinType],
971
- arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
1082
+ target: await this.#target('effective_fee_bps'),
1083
+ typeArguments: [await this.#coinType()],
1084
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, dstEid)],
972
1085
  })
973
1086
  }
974
1087
 
@@ -980,8 +1093,8 @@ export class OFT {
980
1093
  async effectiveFeeBps(dstEid: number): Promise<bigint> {
981
1094
  return executeSimulate(
982
1095
  this.client,
983
- (tx) => {
984
- this.effectiveFeeBpsMoveCall(tx, dstEid)
1096
+ async (tx) => {
1097
+ await this.effectiveFeeBpsMoveCall(tx, dstEid)
985
1098
  },
986
1099
  (result) => BigInt(bcs.U64.parse(result[0].value))
987
1100
  )
@@ -992,11 +1105,11 @@ export class OFT {
992
1105
  * @param tx - The transaction to add the move call to
993
1106
  * @returns Transaction result containing the default fee basis points
994
1107
  */
995
- defaultFeeBpsMoveCall(tx: Transaction): TransactionResult {
1108
+ async defaultFeeBpsMoveCall(tx: Transaction): Promise<TransactionResult> {
996
1109
  return tx.moveCall({
997
- target: this.#target('default_fee_bps'),
998
- typeArguments: [this.coinType],
999
- arguments: [tx.object(this.oftObjectId)],
1110
+ target: await this.#target('default_fee_bps'),
1111
+ typeArguments: [await this.#coinType()],
1112
+ arguments: [tx.object(await this.#oftObjectId())],
1000
1113
  })
1001
1114
  }
1002
1115
 
@@ -1007,8 +1120,8 @@ export class OFT {
1007
1120
  async defaultFeeBps(): Promise<bigint> {
1008
1121
  return executeSimulate(
1009
1122
  this.client,
1010
- (tx) => {
1011
- this.defaultFeeBpsMoveCall(tx)
1123
+ async (tx) => {
1124
+ await this.defaultFeeBpsMoveCall(tx)
1012
1125
  },
1013
1126
  (result) => BigInt(bcs.U64.parse(result[0].value))
1014
1127
  )
@@ -1020,11 +1133,11 @@ export class OFT {
1020
1133
  * @param dstEid - Destination endpoint ID
1021
1134
  * @returns Transaction result containing the fee basis points
1022
1135
  */
1023
- feeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
1136
+ async feeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): Promise<TransactionResult> {
1024
1137
  return tx.moveCall({
1025
- target: this.#target('fee_bps'),
1026
- typeArguments: [this.coinType],
1027
- arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
1138
+ target: await this.#target('fee_bps'),
1139
+ typeArguments: [await this.#coinType()],
1140
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, dstEid)],
1028
1141
  })
1029
1142
  }
1030
1143
 
@@ -1036,8 +1149,8 @@ export class OFT {
1036
1149
  async feeBps(dstEid: number): Promise<bigint> {
1037
1150
  return executeSimulate(
1038
1151
  this.client,
1039
- (tx) => {
1040
- this.feeBpsMoveCall(tx, dstEid)
1152
+ async (tx) => {
1153
+ await this.feeBpsMoveCall(tx, dstEid)
1041
1154
  },
1042
1155
  (result) => BigInt(bcs.U64.parse(result[0].value))
1043
1156
  )
@@ -1048,11 +1161,11 @@ export class OFT {
1048
1161
  * @param tx - The transaction to add the move call to
1049
1162
  * @returns Transaction result containing the fee deposit address
1050
1163
  */
1051
- feeDepositAddressMoveCall(tx: Transaction): TransactionResult {
1164
+ async feeDepositAddressMoveCall(tx: Transaction): Promise<TransactionResult> {
1052
1165
  return tx.moveCall({
1053
- target: this.#target('fee_deposit_address'),
1054
- typeArguments: [this.coinType],
1055
- arguments: [tx.object(this.oftObjectId)],
1166
+ target: await this.#target('fee_deposit_address'),
1167
+ typeArguments: [await this.#coinType()],
1168
+ arguments: [tx.object(await this.#oftObjectId())],
1056
1169
  })
1057
1170
  }
1058
1171
 
@@ -1063,8 +1176,8 @@ export class OFT {
1063
1176
  async feeDepositAddress(): Promise<string> {
1064
1177
  return executeSimulate(
1065
1178
  this.client,
1066
- (tx) => {
1067
- this.feeDepositAddressMoveCall(tx)
1179
+ async (tx) => {
1180
+ await this.feeDepositAddressMoveCall(tx)
1068
1181
  },
1069
1182
  (result) => bcs.Address.parse(result[0].value)
1070
1183
  )
@@ -1082,15 +1195,15 @@ export class OFT {
1082
1195
  * @param inbound - Whether this is for inbound or outbound transfers
1083
1196
  * @returns Transaction result containing rate limit configuration
1084
1197
  */
1085
- rateLimitConfigMoveCall(
1198
+ async rateLimitConfigMoveCall(
1086
1199
  tx: Transaction,
1087
1200
  eid: number | TransactionArgument,
1088
1201
  inbound: boolean | TransactionArgument
1089
- ): TransactionResult {
1202
+ ): Promise<TransactionResult> {
1090
1203
  return tx.moveCall({
1091
- target: this.#target('rate_limit_config'),
1092
- typeArguments: [this.coinType],
1093
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid), asBool(tx, inbound)],
1204
+ target: await this.#target('rate_limit_config'),
1205
+ typeArguments: [await this.#coinType()],
1206
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, eid), asBool(tx, inbound)],
1094
1207
  })
1095
1208
  }
1096
1209
 
@@ -1103,8 +1216,8 @@ export class OFT {
1103
1216
  async rateLimitConfig(eid: number, inbound: boolean): Promise<{ limit: bigint; windowSeconds: bigint }> {
1104
1217
  return executeSimulate(
1105
1218
  this.client,
1106
- (tx) => {
1107
- this.rateLimitConfigMoveCall(tx, eid, inbound)
1219
+ async (tx) => {
1220
+ await this.rateLimitConfigMoveCall(tx, eid, inbound)
1108
1221
  },
1109
1222
  (result) => {
1110
1223
  const limit = BigInt(bcs.U64.parse(result[0].value))
@@ -1121,15 +1234,15 @@ export class OFT {
1121
1234
  * @param inbound - Whether this is for inbound or outbound transfers
1122
1235
  * @returns Transaction result containing in-flight amount
1123
1236
  */
1124
- rateLimitInFlightMoveCall(
1237
+ async rateLimitInFlightMoveCall(
1125
1238
  tx: Transaction,
1126
1239
  eid: number | TransactionArgument,
1127
1240
  inbound: boolean | TransactionArgument
1128
- ): TransactionResult {
1241
+ ): Promise<TransactionResult> {
1129
1242
  return tx.moveCall({
1130
- target: this.#target('rate_limit_in_flight'),
1131
- typeArguments: [this.coinType],
1132
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid), asBool(tx, inbound), tx.object.clock()],
1243
+ target: await this.#target('rate_limit_in_flight'),
1244
+ typeArguments: [await this.#coinType()],
1245
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, eid), asBool(tx, inbound), tx.object.clock()],
1133
1246
  })
1134
1247
  }
1135
1248
 
@@ -1142,8 +1255,8 @@ export class OFT {
1142
1255
  async rateLimitInFlight(eid: number, inbound: boolean): Promise<bigint> {
1143
1256
  return executeSimulate(
1144
1257
  this.client,
1145
- (tx) => {
1146
- this.rateLimitInFlightMoveCall(tx, eid, inbound)
1258
+ async (tx) => {
1259
+ await this.rateLimitInFlightMoveCall(tx, eid, inbound)
1147
1260
  },
1148
1261
  (result) => BigInt(bcs.U64.parse(result[0].value))
1149
1262
  )
@@ -1156,15 +1269,15 @@ export class OFT {
1156
1269
  * @param inbound - Whether this is for inbound or outbound transfers
1157
1270
  * @returns Transaction result containing rate limit capacity
1158
1271
  */
1159
- rateLimitCapacityMoveCall(
1272
+ async rateLimitCapacityMoveCall(
1160
1273
  tx: Transaction,
1161
1274
  eid: number | TransactionArgument,
1162
1275
  inbound: boolean | TransactionArgument
1163
- ): TransactionResult {
1276
+ ): Promise<TransactionResult> {
1164
1277
  return tx.moveCall({
1165
- target: this.#target('rate_limit_capacity'),
1166
- typeArguments: [this.coinType],
1167
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid), asBool(tx, inbound), tx.object.clock()],
1278
+ target: await this.#target('rate_limit_capacity'),
1279
+ typeArguments: [await this.#coinType()],
1280
+ arguments: [tx.object(await this.#oftObjectId()), asU32(tx, eid), asBool(tx, inbound), tx.object.clock()],
1168
1281
  })
1169
1282
  }
1170
1283
 
@@ -1177,8 +1290,8 @@ export class OFT {
1177
1290
  async rateLimitCapacity(eid: number, inbound: boolean): Promise<bigint> {
1178
1291
  return executeSimulate(
1179
1292
  this.client,
1180
- (tx) => {
1181
- this.rateLimitCapacityMoveCall(tx, eid, inbound)
1293
+ async (tx) => {
1294
+ await this.rateLimitCapacityMoveCall(tx, eid, inbound)
1182
1295
  },
1183
1296
  (result) => BigInt(bcs.U64.parse(result[0].value))
1184
1297
  )
@@ -1188,9 +1301,14 @@ export class OFT {
1188
1301
  // OFT SENDER
1189
1302
  // ==========================================
1190
1303
 
1191
- txSenderMoveCall(tx: Transaction): TransactionResult {
1304
+ /**
1305
+ * Create a transaction sender object for OFT operations
1306
+ * @param tx - The transaction to add the move call to
1307
+ * @returns Transaction result containing the transaction sender object
1308
+ */
1309
+ async txSenderMoveCall(tx: Transaction): Promise<TransactionResult> {
1192
1310
  return tx.moveCall({
1193
- target: this.#target('tx_sender', OFT_SENDER_MODULE_NAME),
1311
+ target: await this.#target('tx_sender', OFT_SENDER_MODULE_NAME),
1194
1312
  })
1195
1313
  }
1196
1314
 
@@ -1206,9 +1324,9 @@ export class OFT {
1206
1324
  * @returns Transaction result containing the SendParam struct
1207
1325
  * @private
1208
1326
  */
1209
- #buildSendParam(tx: Transaction, param: SendParam): TransactionResult {
1327
+ async #buildSendParam(tx: Transaction, param: SendParam): Promise<TransactionResult> {
1210
1328
  return tx.moveCall({
1211
- target: this.#target('create', 'send_param'),
1329
+ target: await this.#target('create', 'send_param'),
1212
1330
  arguments: [
1213
1331
  asU32(tx, param.dstEid),
1214
1332
  asBytes32(tx, param.to, this.protocolSDK.getUtils()),
@@ -1228,8 +1346,8 @@ export class OFT {
1228
1346
  * @returns The full module path for the move call
1229
1347
  * @private
1230
1348
  */
1231
- #target(name: string, module_name = MODULE_NAME): string {
1232
- return `${this.oftPackageId}::${module_name}::${name}`
1349
+ async #target(name: string, module_name = MODULE_NAME): Promise<string> {
1350
+ return `${await this.#oftPackageId()}::${module_name}::${name}`
1233
1351
  }
1234
1352
 
1235
1353
  /**
@@ -1238,23 +1356,109 @@ export class OFT {
1238
1356
  * @throws Error if OApp object ID was not set
1239
1357
  * @private
1240
1358
  */
1241
- #oappObjectId(): string {
1242
- if (this.oappObjectId === '') {
1243
- throw new Error('OApp object ID not found')
1359
+ async #oappObjectId(): Promise<string> {
1360
+ if (this.oappObjectId === undefined) {
1361
+ const oappSdk = this.protocolSDK.getOApp(this.oftCallCapId)
1362
+ const oappInfo = await oappSdk.getOAppInfoV1()
1363
+ this.oappObjectId = oappInfo.oapp_object
1244
1364
  }
1245
1365
  return this.oappObjectId
1246
1366
  }
1247
1367
 
1248
1368
  /**
1249
- * Get the admin capability ID, throwing an error if not available
1369
+ * Get the OFT object ID, automatically retrieving it from the OFT info if not cached
1370
+ * @returns The OFT object ID
1371
+ * @throws Error if OFT object ID cannot be retrieved
1372
+ * @private
1373
+ */
1374
+ async #oftObjectId(): Promise<string> {
1375
+ if (this.oftObjectId === undefined) {
1376
+ const oftInfo = await this.#OftInfo()
1377
+ this.oftObjectId = oftInfo.oftObject
1378
+ }
1379
+ return this.oftObjectId
1380
+ }
1381
+
1382
+ /**
1383
+ * Get the admin capability ID, automatically retrieving it from the OFT instance if not cached
1250
1384
  * @returns The admin capability ID
1251
- * @throws Error if admin capability ID was not provided during construction
1385
+ * @throws Error if admin capability cannot be retrieved from the OFT instance
1252
1386
  * @private
1253
1387
  */
1254
- #adminCapId(): string {
1388
+ async #adminCapId(): Promise<string> {
1255
1389
  if (this.adminCapId === undefined) {
1256
- throw new Error('Admin cap ID not found')
1390
+ this.adminCapId = await this.adminCap()
1257
1391
  }
1258
1392
  return this.adminCapId
1259
1393
  }
1394
+
1395
+ /**
1396
+ * Get the coin type, automatically extracting it from the OFT object if not cached
1397
+ * @returns The coin type string (e.g., "0x123::mycoin::MYCOIN")
1398
+ * @throws Error if coin type cannot be extracted from the OFT object
1399
+ * @private
1400
+ */
1401
+ async #coinType(): Promise<string> {
1402
+ if (this.coinType === undefined) {
1403
+ const oftInfo = await this.client.getObject({
1404
+ id: await this.#oftObjectId(),
1405
+ options: {
1406
+ showContent: true,
1407
+ },
1408
+ })
1409
+
1410
+ const content = oftInfo.data?.content as { type?: string; dataType?: string } | undefined
1411
+ if (content?.dataType !== 'moveObject' || content.type == null || content.type.length === 0) {
1412
+ throw new Error('Invalid OFT object data or missing type field')
1413
+ }
1414
+
1415
+ // Extract the coin type from the first pair of angle brackets, e.g.:
1416
+ // "0xdd39db3a038c70a71fbffedf6b32a50383ace0b5f219a617238bd2fbee1995b0::oft::OFT<0x428907130f475ef50f76c8944d5960772e135e4d64bcb019e181030377049215::test_coin::TEST_COIN>"
1417
+ const typeStr = content.type
1418
+ // Match the first angle-bracketed substring
1419
+ const angleBracketMatch = typeStr.match(/<([^>]+)>/)
1420
+ const coinType = angleBracketMatch?.[1]
1421
+ if (coinType === undefined || coinType === '') {
1422
+ throw new Error('Failed to extract coinType from object type')
1423
+ }
1424
+ this.coinType = coinType
1425
+ }
1426
+ return this.coinType
1427
+ }
1428
+
1429
+ /**
1430
+ * Get OApp info, throwing if not set
1431
+ * @returns The OApp info
1432
+ * @throws Error if OApp info is not set
1433
+ * @private
1434
+ */
1435
+ async #OftInfo(): Promise<OFTInfoV1> {
1436
+ if (!this.oftInfo) {
1437
+ const oappSdk = this.protocolSDK.getOApp(this.oftCallCapId)
1438
+ this.oftInfo = await executeSimulate(
1439
+ this.client,
1440
+ (tx) => {
1441
+ const oappInfo = oappSdk.getOAppInfoV1MoveCall(tx)
1442
+ const extraInfo = oappSdk.getOAppInfoV1ExtraInfoMoveCall(tx, oappInfo)
1443
+ this.decodeOftInfoV1MoveCall(tx, extraInfo)
1444
+ },
1445
+ (result) => parseOFTInfoV1(result[0].value)
1446
+ )
1447
+ }
1448
+ return this.oftInfo
1449
+ }
1450
+
1451
+ /**
1452
+ * Get the OFT package ID, automatically retrieving it from the OFT info if not cached
1453
+ * @returns The OFT package ID
1454
+ * @throws Error if OFT package ID cannot be retrieved
1455
+ * @private
1456
+ */
1457
+ async #oftPackageId(): Promise<string> {
1458
+ if (this.oftPackageId === undefined) {
1459
+ const oftInfo = await this.#OftInfo()
1460
+ this.oftPackageId = oftInfo.oftPackage
1461
+ }
1462
+ return this.oftPackageId
1463
+ }
1260
1464
  }