@layerzerolabs/lz-sui-oft-sdk-v2 3.0.132 → 3.0.134-sui.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.
@@ -11,9 +11,9 @@ import {
11
11
  asBytes,
12
12
  asBytes32,
13
13
  asObject,
14
- asU16,
15
14
  asU32,
16
15
  asU64,
16
+ asU8,
17
17
  executeSimulate,
18
18
  isTransactionArgument,
19
19
  } from '@layerzerolabs/lz-sui-sdk-v2'
@@ -24,6 +24,8 @@ import { OFTFeeDetail, OFTLimit, OFTReceipt, SendParam } from '../types'
24
24
 
25
25
  const MODULE_NAME = 'oft'
26
26
  const OFT_SENDER_MODULE_NAME = 'oft_sender'
27
+ const OFT_IMPL_MODULE_NAME = 'oft_impl'
28
+ const OFT_PTB_BUILDER_MODULE_NAME = 'oft_ptb_builder'
27
29
 
28
30
  // ==========================================
29
31
  // ERROR CODES
@@ -32,14 +34,16 @@ const OFT_SENDER_MODULE_NAME = 'oft_sender'
32
34
 
33
35
  export const OFTErrorCode = {
34
36
  // OFT related errors
35
- OFT_EComposeMsgNotAllowed: 1,
36
- OFT_EComposeMsgRequired: 2,
37
- OFT_EInvalidComposeQueue: 3,
38
- OFT_EInvalidLocalDecimals: 4,
39
- OFT_EPaused: 5,
40
- OFT_EPauseUnchanged: 6,
41
- OFT_ESlippageExceeded: 7,
42
- OFT_EInsufficientBalance: 8,
37
+ EComposeMsgNotAllowed: 1,
38
+ EComposeMsgRequired: 2,
39
+ EInsufficientBalance: 3,
40
+ EInvalidAdminCap: 4,
41
+ EInvalidComposeQueue: 5,
42
+ EInvalidLocalDecimals: 6,
43
+ EInvalidMigrationCap: 7,
44
+ EInvalidSendContext: 8,
45
+ ESlippageExceeded: 9,
46
+ EWrongPackageVersion: 10,
43
47
  } as const
44
48
 
45
49
  /**
@@ -52,7 +56,7 @@ export const OFTErrorCode = {
52
56
  * @example
53
57
  * ```typescript
54
58
  * // Initialize OFT instance
55
- * const oft = new OFT(protocolSDK, corePackageId, packageId, oftObjectId, coinType, adminCapId);
59
+ * const oft = new OFT(protocolSDK, oftPackageId, oftObjectId, coinType, oappObjectId, adminCapId);
56
60
  *
57
61
  * // Send tokens cross-chain
58
62
  * const tx = new Transaction();
@@ -68,7 +72,7 @@ export const OFTErrorCode = {
68
72
  export class OFT {
69
73
  /** Sui client for blockchain interactions */
70
74
  public readonly client: SuiClient
71
- /** The package ID of the core OFT framework (shared OFT functionality) */
75
+ /** The package ID of the OFT */
72
76
  public oftPackageId: string
73
77
  /** LayerZero protocol object references (endpoint, messaging channels, etc.) */
74
78
  private readonly objects: ObjectOptions
@@ -78,6 +82,8 @@ export class OFT {
78
82
  private readonly adminCapId?: string
79
83
  /** The Sui coin type this OFT represents (e.g., "0x123::mycoin::MYCOIN") */
80
84
  private readonly coinType: string
85
+ /** The unique object ID of the associated OApp instance on Sui */
86
+ private oappObjectId: string
81
87
  /** Reference to the LayerZero protocol SDK for cross-chain operations */
82
88
  private readonly protocolSDK: SDK
83
89
 
@@ -95,6 +101,7 @@ export class OFT {
95
101
  oftPackageId: string, // the OFT package id
96
102
  oftObjectId: string,
97
103
  coinType: string,
104
+ oappObjectId: string, // the associated oapp object id
98
105
  adminCapId?: string
99
106
  ) {
100
107
  this.protocolSDK = protocolSDK
@@ -102,102 +109,123 @@ export class OFT {
102
109
  this.client = protocolSDK.client
103
110
  this.objects = protocolSDK.objects
104
111
  this.oftObjectId = oftObjectId
112
+ this.oappObjectId = oappObjectId
105
113
  this.adminCapId = adminCapId
106
114
  this.coinType = coinType
107
115
  }
108
116
 
117
+ /**
118
+ * Updates the associated OApp object ID
119
+ * @param oappObjectId - The new OApp object ID
120
+ */
121
+ setOappObjectId(oappObjectId: string): void {
122
+ this.oappObjectId = oappObjectId
123
+ }
124
+
109
125
  // ==========================================
110
- // ADMIN FUNCTIONS
126
+ // INITIALIZATION FUNCTIONS
111
127
  // ==========================================
112
- // These functions require admin privileges and are used for OFT configuration
113
- // and management. They require the adminCapId to be provided during construction.
128
+ // These functions are used to initialize OFT instances from OFTCreationTicket
114
129
 
115
130
  /**
116
- * Register OFT as an OApp with LayerZero endpoint
131
+ * Initialize an OFT instance with a treasury capability
132
+ * Creates a new OFT that mints its own tokens
117
133
  * @param tx - The transaction to add the move call to
118
- * @param lzReceiveInfo - PTB Builder lzReceiveInfoMoveCall result, used for protocol SDK to dynamically build the PTB
119
- * for OFT's lzReceive operation
134
+ * @param ticket - The OFTCreationTicket object ID or TransactionArgument
135
+ * @param treasury - The TreasuryCap object ID or TransactionArgument for the coin type
136
+ * @param metadata - The CoinMetadata object ID or TransactionArgument for the coin type
137
+ * @param sharedDecimals - Number of decimals to use for cross-chain operations
138
+ * @returns TransactionResult array containing [AdminCap, MigrationCap] - MigrationCap must be transferred or stored
120
139
  */
121
- registerOAppMoveCall(tx: Transaction, lzReceiveInfo: Uint8Array | TransactionArgument): void {
122
- tx.moveCall({
123
- target: this.#target('register_oapp'),
140
+ initOftMoveCall(
141
+ tx: Transaction,
142
+ ticket: string | TransactionArgument,
143
+ oapp: string | TransactionArgument,
144
+ treasury: string | TransactionArgument,
145
+ metadata: string | TransactionArgument,
146
+ sharedDecimals: number | TransactionArgument
147
+ ): TransactionResult {
148
+ return tx.moveCall({
149
+ target: this.#target('init_oft', OFT_IMPL_MODULE_NAME),
124
150
  typeArguments: [this.coinType],
125
151
  arguments: [
126
- tx.object(this.oftObjectId),
127
- tx.object(this.#adminCapId()),
128
- tx.object(this.objects.endpointV2),
129
- asBytes(tx, lzReceiveInfo),
152
+ asObject(tx, ticket),
153
+ asObject(tx, oapp),
154
+ asObject(tx, treasury),
155
+ asObject(tx, metadata),
156
+ asU8(tx, sharedDecimals),
130
157
  ],
131
158
  })
132
159
  }
133
160
 
134
161
  /**
135
- * Set enforced options for OFT messaging to a destination
162
+ * Initialize an OFT adapter instance
163
+ * Creates an OFT adapter that wraps an existing coin type
136
164
  * @param tx - The transaction to add the move call to
137
- * @param eid - Endpoint ID
138
- * @param msgType - Message type (SEND or SEND_AND_CALL)
139
- * @param options - Enforced options as bytes
165
+ * @param ticket - The OFTCreationTicket object ID or TransactionArgument
166
+ * @param metadata - The CoinMetadata object ID or TransactionArgument for the coin type
167
+ * @param sharedDecimals - Number of decimals to use for cross-chain operations
168
+ * @returns TransactionResult array containing [AdminCap, MigrationCap] - MigrationCap must be transferred or stored
140
169
  */
141
- setEnforcedOptionsMoveCall(
170
+ initOftAdapterMoveCall(
142
171
  tx: Transaction,
143
- eid: number | TransactionArgument,
144
- msgType: number | TransactionArgument,
145
- options: Uint8Array | TransactionArgument
146
- ): void {
147
- tx.moveCall({
148
- target: this.#target('set_enforced_options'),
172
+ ticket: string | TransactionArgument,
173
+ oapp: string | TransactionArgument,
174
+ metadata: string | TransactionArgument,
175
+ sharedDecimals: number | TransactionArgument
176
+ ): TransactionResult {
177
+ return tx.moveCall({
178
+ target: this.#target('init_oft_adapter', OFT_IMPL_MODULE_NAME),
149
179
  typeArguments: [this.coinType],
150
- arguments: [
151
- tx.object(this.oftObjectId),
152
- tx.object(this.#adminCapId()),
153
- asU32(tx, eid),
154
- asU16(tx, msgType),
155
- asBytes(tx, options),
156
- ],
180
+ arguments: [asObject(tx, ticket), asObject(tx, oapp), asObject(tx, metadata), asU8(tx, sharedDecimals)],
157
181
  })
158
182
  }
159
183
 
184
+ // ==========================================
185
+ // ADMIN FUNCTIONS
186
+ // ==========================================
187
+ // These functions require admin privileges and are used for OFT configuration
188
+ // and management. They require the adminCapId to be provided during construction.
189
+
160
190
  /**
161
- * Set peer OFT on another chain
191
+ * Get LayerZero receive information for OFT registration
192
+ *
193
+ * This function prepares the necessary metadata for registering an OFT
194
+ * with the LayerZero endpoint, enabling it to receive cross-chain messages.
195
+ *
162
196
  * @param tx - The transaction to add the move call to
163
- * @param messagingChannel - The messaging channel object ID
164
- * @param eid - Peer endpoint ID
165
- * @param peer - Peer OFT address as bytes
197
+ * @param composerManager - The composer manager object ID for routing compose transfers
198
+ * @returns TransactionResult containing serialized execution metadata for endpoint registration
166
199
  */
167
- setPeerMoveCall(
168
- tx: Transaction,
169
- messagingChannel: string | TransactionArgument,
170
- eid: number | TransactionArgument,
171
- peer: Uint8Array | TransactionArgument
172
- ): void {
173
- tx.moveCall({
174
- target: this.#target('set_peer'),
200
+ lzReceiveInfoMoveCall(tx: Transaction, composerManager: string | TransactionArgument): TransactionResult {
201
+ return tx.moveCall({
202
+ target: this.#target('lz_receive_info', OFT_PTB_BUILDER_MODULE_NAME),
175
203
  typeArguments: [this.coinType],
176
204
  arguments: [
177
205
  tx.object(this.oftObjectId),
178
- tx.object(this.#adminCapId()),
179
206
  tx.object(this.objects.endpointV2),
180
- asObject(tx, messagingChannel),
181
- asU32(tx, eid),
182
- asBytes32(tx, peer, this.protocolSDK.getUtils()),
207
+ asObject(tx, composerManager),
208
+ tx.object.clock(),
183
209
  ],
184
210
  })
185
211
  }
186
212
 
187
213
  /**
188
- * Set delegate for OFT
214
+ * Register OFT as an OApp with LayerZero endpoint
189
215
  * @param tx - The transaction to add the move call to
190
- * @param newDelegate - The new delegate address
216
+ * @param lzReceiveInfo - PTB Builder lzReceiveInfoMoveCall result, used for protocol SDK to dynamically build the PTB
217
+ * for OFT's lzReceive operation
191
218
  */
192
- setDelegateMoveCall(tx: Transaction, newDelegate: string | TransactionArgument): void {
219
+ registerOAppMoveCall(tx: Transaction, lzReceiveInfo: Uint8Array | TransactionArgument): void {
193
220
  tx.moveCall({
194
- target: this.#target('set_delegate'),
221
+ target: this.#target('register_oapp'),
195
222
  typeArguments: [this.coinType],
196
223
  arguments: [
197
224
  tx.object(this.oftObjectId),
225
+ tx.object(this.#oappObjectId()),
198
226
  tx.object(this.#adminCapId()),
199
227
  tx.object(this.objects.endpointV2),
200
- asAddress(tx, newDelegate),
228
+ asBytes(tx, lzReceiveInfo),
201
229
  ],
202
230
  })
203
231
  }
@@ -233,16 +261,66 @@ export class OFT {
233
261
  })
234
262
  }
235
263
 
264
+ setDefaultFeeBpsMoveCall(tx: Transaction, feeBps: bigint | number | string | TransactionArgument): void {
265
+ 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)],
269
+ })
270
+ }
271
+
236
272
  /**
237
- * Set fee basis points for OFT transfers
273
+ * Set fee basis points for a specific destination chain
238
274
  * @param tx - The transaction to add the move call to
239
- * @param feeBps - The fee in basis points
275
+ * @param dstEid - Destination endpoint ID
276
+ * @param feeBps - Fee rate in basis points (0-10,000, where 10,000 = 100%)
240
277
  */
241
- setFeeBpsMoveCall(tx: Transaction, feeBps: bigint | number | string | TransactionArgument): void {
278
+ setFeeBpsMoveCall(
279
+ tx: Transaction,
280
+ dstEid: number | TransactionArgument,
281
+ feeBps: bigint | number | string | TransactionArgument
282
+ ): void {
242
283
  tx.moveCall({
243
284
  target: this.#target('set_fee_bps'),
244
285
  typeArguments: [this.coinType],
245
- arguments: [tx.object(this.oftObjectId), tx.object(this.#adminCapId()), asU64(tx, feeBps)],
286
+ arguments: [
287
+ tx.object(this.oftObjectId),
288
+ tx.object(this.#adminCapId()),
289
+ asU32(tx, dstEid),
290
+ asU64(tx, feeBps),
291
+ ],
292
+ })
293
+ }
294
+
295
+ /**
296
+ * Removes the fee rate for a specific destination chain
297
+ * @param tx - The transaction to add the move call to
298
+ * @param dstEid - Destination endpoint ID
299
+ */
300
+ unsetFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): void {
301
+ 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)],
305
+ })
306
+ }
307
+
308
+ // ==========================================
309
+ // MIGRATION ADMIN FUNCTIONS
310
+ // ==========================================
311
+ // Handle OFT migration to new contracts
312
+
313
+ /**
314
+ * Migrate OFT instance to a new contract
315
+ * @param tx - The transaction to add the move call to
316
+ * @param migrationCap - Migration capability object ID or transaction argument
317
+ * @returns TransactionResult containing the migration ticket
318
+ */
319
+ migrateMoveCall(tx: Transaction, migrationCap: string | TransactionArgument): TransactionResult {
320
+ return tx.moveCall({
321
+ target: this.#target('migrate'),
322
+ typeArguments: [this.coinType],
323
+ arguments: [tx.object(this.oftObjectId), asObject(tx, migrationCap)],
246
324
  })
247
325
  }
248
326
 
@@ -363,6 +441,7 @@ export class OFT {
363
441
  typeArguments: [this.coinType],
364
442
  arguments: [
365
443
  tx.object(this.oftObjectId),
444
+ tx.object(this.#oappObjectId()),
366
445
  txSender,
367
446
  sendParamArg,
368
447
  asObject(tx, coinProvided),
@@ -390,7 +469,13 @@ export class OFT {
390
469
  const confirmSendResult = tx.moveCall({
391
470
  target: this.#target('confirm_send'),
392
471
  typeArguments: [this.coinType],
393
- arguments: [tx.object(this.oftObjectId), txSender, endpointCall, oftSendContext],
472
+ arguments: [
473
+ tx.object(this.oftObjectId),
474
+ tx.object(this.#oappObjectId()),
475
+ txSender,
476
+ endpointCall,
477
+ oftSendContext,
478
+ ],
394
479
  })
395
480
  // destroy the empty coins
396
481
  const nativeCoin = confirmSendResult[2]
@@ -407,6 +492,67 @@ export class OFT {
407
492
  })
408
493
  }
409
494
 
495
+ /**
496
+ * Process inbound cross-chain token transfers
497
+ * @param tx - The transaction to add the move call to
498
+ * @param call - LayerZero receive call containing the verified cross-chain message
499
+ * @returns TransactionResult containing the processed transfer
500
+ */
501
+ lzReceiveMoveCall(tx: Transaction, call: string | TransactionArgument): TransactionResult {
502
+ return tx.moveCall({
503
+ target: this.#target('lz_receive'),
504
+ typeArguments: [this.coinType],
505
+ arguments: [
506
+ tx.object(this.oftObjectId),
507
+ tx.object(this.#oappObjectId()),
508
+ asObject(tx, call),
509
+ tx.object.clock(),
510
+ ],
511
+ })
512
+ }
513
+
514
+ /**
515
+ * Process inbound cross-chain token transfers with compose functionality
516
+ * @param tx - The transaction to add the move call to
517
+ * @param composeQueue - The composer's message queue for sequencing operations
518
+ * @param composerManager - Manager managing token deposits for composers
519
+ * @param call - LayerZero receive call containing the verified cross-chain message
520
+ * @returns TransactionResult containing the processed transfer
521
+ */
522
+ lzReceiveWithComposeMoveCall(
523
+ tx: Transaction,
524
+ composeQueue: string | TransactionArgument,
525
+ composerManager: string | TransactionArgument,
526
+ call: string | TransactionArgument
527
+ ): TransactionResult {
528
+ return tx.moveCall({
529
+ target: this.#target('lz_receive_with_compose'),
530
+ typeArguments: [this.coinType],
531
+ arguments: [
532
+ tx.object(this.oftObjectId),
533
+ tx.object(this.#oappObjectId()),
534
+ asObject(tx, composeQueue),
535
+ asObject(tx, composerManager),
536
+ asObject(tx, call),
537
+ tx.object.clock(),
538
+ ],
539
+ })
540
+ }
541
+
542
+ /**
543
+ * Confirms and extracts results from a quote operation
544
+ * @param tx - The transaction to add the move call to
545
+ * @param call - Completed Call object from quote_send() execution
546
+ * @returns TransactionResult containing the messaging fee
547
+ */
548
+ confirmQuoteSendMoveCall(tx: Transaction, call: string | TransactionArgument): TransactionResult {
549
+ 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)],
553
+ })
554
+ }
555
+
410
556
  // ==========================================
411
557
  // QUOTE FUNCTIONS
412
558
  // ==========================================
@@ -460,7 +606,13 @@ export class OFT {
460
606
  const quoteCall = tx.moveCall({
461
607
  target: this.#target('quote_send'),
462
608
  typeArguments: [this.coinType],
463
- arguments: [tx.object(this.oftObjectId), asAddress(tx, sender), sendParamArg, asBool(tx, payInZro)],
609
+ arguments: [
610
+ tx.object(this.oftObjectId),
611
+ tx.object(this.#oappObjectId()),
612
+ asAddress(tx, sender),
613
+ sendParamArg,
614
+ asBool(tx, payInZro),
615
+ ],
464
616
  })
465
617
 
466
618
  return this.protocolSDK.getEndpoint().quote(tx, quoteCall, sender, validators, maxSimulationTimes)
@@ -471,6 +623,60 @@ export class OFT {
471
623
  // ==========================================
472
624
  // Read-only functions to query OFT state and configuration
473
625
 
626
+ /**
627
+ * Get the upgrade version of this OFT instance
628
+ * @param tx - The transaction to add the move call to
629
+ * @returns Transaction result containing the upgrade version
630
+ */
631
+ upgradeVersionMoveCall(tx: Transaction): TransactionResult {
632
+ return tx.moveCall({
633
+ target: this.#target('upgrade_version'),
634
+ typeArguments: [this.coinType],
635
+ arguments: [tx.object(this.oftObjectId)],
636
+ })
637
+ }
638
+
639
+ /**
640
+ * Get the upgrade version of this OFT instance
641
+ * @returns Promise<bigint> - The upgrade version
642
+ */
643
+ async upgradeVersion(): Promise<bigint> {
644
+ return executeSimulate(
645
+ this.client,
646
+ (tx) => {
647
+ this.upgradeVersionMoveCall(tx)
648
+ },
649
+ (result) => BigInt(bcs.U64.parse(result[0].value))
650
+ )
651
+ }
652
+
653
+ /**
654
+ * Get the associated OApp object address
655
+ * @param tx - The transaction to add the move call to
656
+ * @returns Transaction result containing the OApp object address
657
+ */
658
+ oappObjectMoveCall(tx: Transaction): TransactionResult {
659
+ return tx.moveCall({
660
+ target: this.#target('oapp_object'),
661
+ typeArguments: [this.coinType],
662
+ arguments: [tx.object(this.oftObjectId)],
663
+ })
664
+ }
665
+
666
+ /**
667
+ * Get the associated OApp object address
668
+ * @returns Promise<string> - The OApp object address
669
+ */
670
+ async oappObject(): Promise<string> {
671
+ return executeSimulate(
672
+ this.client,
673
+ (tx) => {
674
+ this.oappObjectMoveCall(tx)
675
+ },
676
+ (result) => bcs.Address.parse(result[0].value)
677
+ )
678
+ }
679
+
474
680
  /**
475
681
  * Get OFT version information
476
682
  * @param tx - The transaction to add the move call to
@@ -502,18 +708,45 @@ export class OFT {
502
708
  )
503
709
  }
504
710
 
505
- oftAddressMoveCall(tx: Transaction): TransactionResult {
711
+ oftCapIdMoveCall(tx: Transaction): TransactionResult {
712
+ return tx.moveCall({
713
+ target: this.#target('oft_cap_id'),
714
+ typeArguments: [this.coinType],
715
+ arguments: [tx.object(this.oftObjectId)],
716
+ })
717
+ }
718
+
719
+ async oftCapId(): Promise<string> {
720
+ return executeSimulate(
721
+ this.client,
722
+ (tx) => this.oftCapIdMoveCall(tx),
723
+ (result) => bcs.Address.parse(result[0].value)
724
+ )
725
+ }
726
+
727
+ /**
728
+ * Get the migration capability address for this OFT
729
+ * @param tx - The transaction to add the move call to
730
+ * @returns Transaction result containing the migration capability address
731
+ */
732
+ migrationCapMoveCall(tx: Transaction): TransactionResult {
506
733
  return tx.moveCall({
507
- target: this.#target('oft_address'),
734
+ target: this.#target('migration_cap'),
508
735
  typeArguments: [this.coinType],
509
736
  arguments: [tx.object(this.oftObjectId)],
510
737
  })
511
738
  }
512
739
 
513
- async oftAddress(): Promise<string> {
740
+ /**
741
+ * Get the migration capability address for this OFT
742
+ * @returns Promise<string> - The migration capability address
743
+ */
744
+ async migrationCap(): Promise<string> {
514
745
  return executeSimulate(
515
746
  this.client,
516
- (tx) => this.oftAddressMoveCall(tx),
747
+ (tx) => {
748
+ this.migrationCapMoveCall(tx)
749
+ },
517
750
  (result) => bcs.Address.parse(result[0].value)
518
751
  )
519
752
  }
@@ -522,8 +755,8 @@ export class OFT {
522
755
  return executeSimulate(
523
756
  this.client,
524
757
  (tx) => {
525
- const oftAddress = this.oftAddressMoveCall(tx)
526
- this.protocolSDK.getEndpoint().getMessagingChannelMoveCall(tx, oftAddress)
758
+ const oftCapId = this.oftCapIdMoveCall(tx)
759
+ this.protocolSDK.getEndpoint().getMessagingChannelMoveCall(tx, oftCapId)
527
760
  },
528
761
  (result) => bcs.Address.parse(result[0].value)
529
762
  )
@@ -557,27 +790,27 @@ export class OFT {
557
790
  }
558
791
 
559
792
  /**
560
- * Get OFT admin address
793
+ * Get OFT admin capability address
561
794
  * @param tx - The transaction to add the move call to
562
- * @returns Transaction result containing the admin address
795
+ * @returns Transaction result containing the admin capability address
563
796
  */
564
- adminMoveCall(tx: Transaction): TransactionResult {
797
+ adminCapMoveCall(tx: Transaction): TransactionResult {
565
798
  return tx.moveCall({
566
- target: this.#target('admin'),
799
+ target: this.#target('admin_cap'),
567
800
  typeArguments: [this.coinType],
568
801
  arguments: [tx.object(this.oftObjectId)],
569
802
  })
570
803
  }
571
804
 
572
805
  /**
573
- * Get OFT admin address
574
- * @returns Promise<string> - The admin address
806
+ * Get OFT admin capability address
807
+ * @returns Promise<string> - The admin capability address
575
808
  */
576
- async admin(): Promise<string> {
809
+ async adminCap(): Promise<string> {
577
810
  return executeSimulate(
578
811
  this.client,
579
812
  (tx) => {
580
- this.adminMoveCall(tx)
813
+ this.adminCapMoveCall(tx)
581
814
  },
582
815
  (result) => bcs.Address.parse(result[0].value)
583
816
  )
@@ -610,6 +843,33 @@ export class OFT {
610
843
  )
611
844
  }
612
845
 
846
+ /**
847
+ * Get the decimal conversion rate for this OFT
848
+ * @param tx - The transaction to add the move call to
849
+ * @returns Transaction result containing the decimal conversion rate
850
+ */
851
+ decimalConversionRateMoveCall(tx: Transaction): TransactionResult {
852
+ return tx.moveCall({
853
+ target: this.#target('decimal_conversion_rate'),
854
+ typeArguments: [this.coinType],
855
+ arguments: [tx.object(this.oftObjectId)],
856
+ })
857
+ }
858
+
859
+ /**
860
+ * Get the decimal conversion rate for this OFT
861
+ * @returns Promise<bigint> - The decimal conversion rate multiplier
862
+ */
863
+ async decimalConversionRate(): Promise<bigint> {
864
+ return executeSimulate(
865
+ this.client,
866
+ (tx) => {
867
+ this.decimalConversionRateMoveCall(tx)
868
+ },
869
+ (result) => BigInt(bcs.U64.parse(result[0].value))
870
+ )
871
+ }
872
+
613
873
  /**
614
874
  * Check if OFT is paused
615
875
  * @param tx - The transaction to add the move call to
@@ -670,27 +930,114 @@ export class OFT {
670
930
  // Query current fee configuration and settings
671
931
 
672
932
  /**
673
- * Get fee basis points for OFT transfers
933
+ * Check if the OFT has a fee rate greater than 0 for the specified destination
934
+ * @param tx - The transaction to add the move call to
935
+ * @param dstEid - Destination endpoint ID
936
+ * @returns Transaction result containing whether fee exists
937
+ */
938
+ hasOftFeeMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
939
+ return tx.moveCall({
940
+ target: this.#target('has_oft_fee'),
941
+ typeArguments: [this.coinType],
942
+ arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
943
+ })
944
+ }
945
+
946
+ /**
947
+ * Check if the OFT has a fee rate greater than 0 for the specified destination
948
+ * @param dstEid - Destination endpoint ID
949
+ * @returns Promise<boolean> - True if fee exists
950
+ */
951
+ async hasOftFee(dstEid: number): Promise<boolean> {
952
+ return executeSimulate(
953
+ this.client,
954
+ (tx) => {
955
+ this.hasOftFeeMoveCall(tx, dstEid)
956
+ },
957
+ (result) => bcs.Bool.parse(result[0].value)
958
+ )
959
+ }
960
+
961
+ /**
962
+ * Get the effective fee rate for a specific destination chain
963
+ * @param tx - The transaction to add the move call to
964
+ * @param dstEid - Destination endpoint ID
965
+ * @returns Transaction result containing the effective fee basis points
966
+ */
967
+ effectiveFeeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
968
+ return tx.moveCall({
969
+ target: this.#target('effective_fee_bps'),
970
+ typeArguments: [this.coinType],
971
+ arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
972
+ })
973
+ }
974
+
975
+ /**
976
+ * Get the effective fee rate for a specific destination chain
977
+ * @param dstEid - Destination endpoint ID
978
+ * @returns Promise<bigint> - The effective fee in basis points
979
+ */
980
+ async effectiveFeeBps(dstEid: number): Promise<bigint> {
981
+ return executeSimulate(
982
+ this.client,
983
+ (tx) => {
984
+ this.effectiveFeeBpsMoveCall(tx, dstEid)
985
+ },
986
+ (result) => BigInt(bcs.U64.parse(result[0].value))
987
+ )
988
+ }
989
+
990
+ /**
991
+ * Get the default fee rate
992
+ * @param tx - The transaction to add the move call to
993
+ * @returns Transaction result containing the default fee basis points
994
+ */
995
+ defaultFeeBpsMoveCall(tx: Transaction): TransactionResult {
996
+ return tx.moveCall({
997
+ target: this.#target('default_fee_bps'),
998
+ typeArguments: [this.coinType],
999
+ arguments: [tx.object(this.oftObjectId)],
1000
+ })
1001
+ }
1002
+
1003
+ /**
1004
+ * Get the default fee rate
1005
+ * @returns Promise<bigint> - The default fee in basis points
1006
+ */
1007
+ async defaultFeeBps(): Promise<bigint> {
1008
+ return executeSimulate(
1009
+ this.client,
1010
+ (tx) => {
1011
+ this.defaultFeeBpsMoveCall(tx)
1012
+ },
1013
+ (result) => BigInt(bcs.U64.parse(result[0].value))
1014
+ )
1015
+ }
1016
+
1017
+ /**
1018
+ * Get fee basis points for a specific destination chain
674
1019
  * @param tx - The transaction to add the move call to
1020
+ * @param dstEid - Destination endpoint ID
675
1021
  * @returns Transaction result containing the fee basis points
676
1022
  */
677
- feeBpsMoveCall(tx: Transaction): TransactionResult {
1023
+ feeBpsMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
678
1024
  return tx.moveCall({
679
1025
  target: this.#target('fee_bps'),
680
1026
  typeArguments: [this.coinType],
681
- arguments: [tx.object(this.oftObjectId)],
1027
+ arguments: [tx.object(this.oftObjectId), asU32(tx, dstEid)],
682
1028
  })
683
1029
  }
684
1030
 
685
1031
  /**
686
- * Get fee basis points for OFT transfers
1032
+ * Get fee basis points for a specific destination chain
1033
+ * @param dstEid - Destination endpoint ID
687
1034
  * @returns Promise<bigint> - The fee in basis points
688
1035
  */
689
- async feeBps(): Promise<bigint> {
1036
+ async feeBps(dstEid: number): Promise<bigint> {
690
1037
  return executeSimulate(
691
1038
  this.client,
692
1039
  (tx) => {
693
- this.feeBpsMoveCall(tx)
1040
+ this.feeBpsMoveCall(tx, dstEid)
694
1041
  },
695
1042
  (result) => BigInt(bcs.U64.parse(result[0].value))
696
1043
  )
@@ -837,140 +1184,6 @@ export class OFT {
837
1184
  )
838
1185
  }
839
1186
 
840
- /**
841
- * Combine enforced options with extra options
842
- * @param tx - The transaction to add the move call to
843
- * @param eid - Endpoint ID
844
- * @param msgType - Message type
845
- * @param extraOptions - Extra options to combine with enforced options
846
- * @returns Transaction result containing the combined options
847
- */
848
- combineOptionsMoveCall(
849
- tx: Transaction,
850
- eid: number | TransactionArgument,
851
- msgType: number | TransactionArgument,
852
- extraOptions: Uint8Array | TransactionArgument
853
- ): TransactionResult {
854
- return tx.moveCall({
855
- target: this.#target('combine_options'),
856
- typeArguments: [this.coinType],
857
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid), asU16(tx, msgType), asBytes(tx, extraOptions)],
858
- })
859
- }
860
-
861
- /**
862
- * Combine enforced options with extra options
863
- * @param eid - Endpoint ID
864
- * @param msgType - Message type
865
- * @param extraOptions - Extra options to combine with enforced options
866
- * @returns Promise<Uint8Array> - The combined options as bytes
867
- */
868
- async combineOptions(eid: number, msgType: number, extraOptions: Uint8Array): Promise<Uint8Array> {
869
- return executeSimulate(
870
- this.client,
871
- (tx) => {
872
- this.combineOptionsMoveCall(tx, eid, msgType, extraOptions)
873
- },
874
- (result) => new Uint8Array(bcs.vector(bcs.u8()).parse(result[0].value))
875
- )
876
- }
877
-
878
- /**
879
- * Get enforced options for OFT messaging
880
- * @param tx - The transaction to add the move call to
881
- * @param eid - Endpoint ID
882
- * @param msgType - Message type
883
- * @returns Transaction result containing the enforced options
884
- */
885
- getEnforcedOptionsMoveCall(
886
- tx: Transaction,
887
- eid: number | TransactionArgument,
888
- msgType: number | TransactionArgument
889
- ): TransactionResult {
890
- return tx.moveCall({
891
- target: this.#target('get_enforced_options'),
892
- typeArguments: [this.coinType],
893
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid), asU16(tx, msgType)],
894
- })
895
- }
896
-
897
- /**
898
- * Get enforced options for OFT messaging
899
- * @param eid - Endpoint ID
900
- * @param msgType - Message type
901
- * @returns Promise<Uint8Array> - The enforced options as bytes
902
- */
903
- async getEnforcedOptions(eid: number, msgType: number): Promise<Uint8Array> {
904
- return executeSimulate(
905
- this.client,
906
- (tx) => {
907
- this.getEnforcedOptionsMoveCall(tx, eid, msgType)
908
- },
909
- (result) => new Uint8Array(bcs.vector(bcs.u8()).parse(result[0].value))
910
- )
911
- }
912
-
913
- /**
914
- * Check if OFT has a peer on specific endpoint
915
- * @param tx - The transaction to add the move call to
916
- * @param eid - Endpoint ID
917
- * @returns Transaction result containing the peer existence status
918
- */
919
- hasPeerMoveCall(tx: Transaction, eid: number | TransactionArgument): TransactionResult {
920
- return tx.moveCall({
921
- target: this.#target('has_peer'),
922
- typeArguments: [this.coinType],
923
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid)],
924
- })
925
- }
926
-
927
- /**
928
- * Check if OFT has a peer on specific endpoint
929
- * @param eid - Endpoint ID
930
- * @returns Promise<boolean> - True if peer exists on the endpoint
931
- */
932
- async hasPeer(eid: number): Promise<boolean> {
933
- return executeSimulate(
934
- this.client,
935
- (tx) => {
936
- this.hasPeerMoveCall(tx, eid)
937
- },
938
- (result) => bcs.Bool.parse(result[0].value)
939
- )
940
- }
941
-
942
- /**
943
- * Get peer OFT address on specific endpoint
944
- * @param tx - The transaction to add the move call to
945
- * @param eid - Endpoint ID
946
- * @returns Transaction result containing the peer address
947
- */
948
- getPeerMoveCall(tx: Transaction, eid: number | TransactionArgument): TransactionResult {
949
- return tx.moveCall({
950
- target: this.#target('get_peer'),
951
- typeArguments: [this.coinType],
952
- arguments: [tx.object(this.oftObjectId), asU32(tx, eid)],
953
- })
954
- }
955
-
956
- /**
957
- * Get peer OFT address on specific endpoint
958
- * @param eid - Endpoint ID
959
- * @returns Promise<Uint8Array> - The peer address as bytes32
960
- */
961
- async getPeer(eid: number): Promise<Uint8Array> {
962
- return executeSimulate(
963
- this.client,
964
- (tx) => {
965
- this.getPeerMoveCall(tx, eid)
966
- },
967
- (result) => {
968
- // Assuming Bytes32 is returned as vector<u8>
969
- return new Uint8Array(bcs.vector(bcs.u8()).parse(result[0].value))
970
- }
971
- )
972
- }
973
-
974
1187
  // ==========================================
975
1188
  // OFT SENDER
976
1189
  // ==========================================
@@ -1019,6 +1232,19 @@ export class OFT {
1019
1232
  return `${this.oftPackageId}::${module_name}::${name}`
1020
1233
  }
1021
1234
 
1235
+ /**
1236
+ * Get the OApp object ID, throwing an error if not available
1237
+ * @returns The OApp object ID
1238
+ * @throws Error if OApp object ID was not set
1239
+ * @private
1240
+ */
1241
+ #oappObjectId(): string {
1242
+ if (this.oappObjectId === '') {
1243
+ throw new Error('OApp object ID not found')
1244
+ }
1245
+ return this.oappObjectId
1246
+ }
1247
+
1022
1248
  /**
1023
1249
  * Get the admin capability ID, throwing an error if not available
1024
1250
  * @returns The admin capability ID