@bolt-liquidity-hq/sui-client 0.1.0-beta.10 → 0.1.0-beta.12

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/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  AssetPairStruct: () => AssetPairStruct,
26
26
  AssetPairsResponsePaginatedStruct: () => AssetPairsResponsePaginatedStruct,
27
27
  AssetPairsResponseStruct: () => AssetPairsResponseStruct,
28
+ BaseLiquidityInfoStruct: () => BaseLiquidityInfoStruct,
28
29
  BaseLiquidityResponseStruct: () => BaseLiquidityResponseStruct,
29
30
  BcsAddressType: () => BcsAddressType,
30
31
  BoltSuiClient: () => BoltSuiClient,
@@ -44,10 +45,11 @@ __export(index_exports, {
44
45
  module.exports = __toCommonJS(index_exports);
45
46
 
46
47
  // src/lib/client.ts
47
- var import_core5 = require("@bolt-liquidity-hq/core");
48
+ var import_core8 = require("@bolt-liquidity-hq/core");
48
49
  var import_client = require("@mysten/sui/client");
49
50
 
50
51
  // src/config/mainnet.ts
52
+ var import_utils = require("@mysten/sui/utils");
51
53
  var MainnetChainConfig = {
52
54
  name: "Sui",
53
55
  id: "101",
@@ -58,13 +60,15 @@ var MainnetContracts = {
58
60
  router: "0x..."
59
61
  };
60
62
  var MainnetPackageId = "0x...";
63
+ var MainnetPoolGlobalConfigId = "0x...";
64
+ var MainnetNativeTokenDenom = import_utils.SUI_TYPE_ARG;
61
65
  var MainnetAssets = {
62
- "0x2::sui::SUI": {
66
+ [import_utils.SUI_TYPE_ARG]: {
63
67
  symbol: "SUI",
64
68
  name: "Sui",
65
69
  chainId: "101",
66
- denom: "0x2::sui::SUI",
67
- decimals: 9,
70
+ denom: import_utils.SUI_TYPE_ARG,
71
+ decimals: import_utils.SUI_DECIMALS,
68
72
  logo: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png",
69
73
  coingeckoId: "sui"
70
74
  },
@@ -80,6 +84,7 @@ var MainnetAssets = {
80
84
  };
81
85
 
82
86
  // src/config/testnet.ts
87
+ var import_utils2 = require("@mysten/sui/utils");
83
88
  var TestnetChainConfig = {
84
89
  name: "Sui Testnet",
85
90
  id: "103",
@@ -90,13 +95,15 @@ var TestnetContracts = {
90
95
  router: "0x3881fdcb4a7fbcda8edc230e6f92eb57b24c0be6b44af0b5e1d0b45564f3ed00"
91
96
  };
92
97
  var TestnetPackageId = "0x22384b1841229e2be878bb7e88833c03e23ff5dc39accd050fb932120602f85e";
98
+ var TestnetPoolGlobalConfigId = "0xa9491e59fa63e666cbfdea2e880b2d8ba0085eeb244220cefa3fb817559cd79c";
99
+ var TestnetNativeTokenDenom = import_utils2.SUI_TYPE_ARG;
93
100
  var TestnetAssets = {
94
- "0x2::sui::SUI": {
101
+ [import_utils2.SUI_TYPE_ARG]: {
95
102
  symbol: "SUI",
96
103
  name: "Sui",
97
104
  chainId: "103",
98
- denom: "0x2::sui::SUI",
99
- decimals: 9,
105
+ denom: import_utils2.SUI_TYPE_ARG,
106
+ decimals: import_utils2.SUI_DECIMALS,
100
107
  logo: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png",
101
108
  coingeckoId: "sui"
102
109
  },
@@ -159,8 +166,407 @@ var parseMultipleResults = (info, schema) => {
159
166
  return schema.map((bcsType, index) => parseDevInspectResult(info, bcsType, 0, index));
160
167
  };
161
168
 
162
- // src/lib/helpers/queries.ts
169
+ // src/lib/helpers/coin-manager.ts
163
170
  var import_core2 = require("@bolt-liquidity-hq/core");
171
+ var import_utils3 = require("@mysten/sui/utils");
172
+ var CoinManager = class {
173
+ /**
174
+ * Creates a new CoinManager instance.
175
+ *
176
+ * @param client - The SuiClient instance for blockchain interactions
177
+ * @param defaultOwner - Optional default owner address for coin operations.
178
+ * If not provided, owner must be specified in each method call.
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * // With default owner
183
+ * const coinManager = new CoinManager(suiClient, "0x123...");
184
+ *
185
+ * // Without default owner (must specify in each call)
186
+ * const coinManager = new CoinManager(suiClient);
187
+ * ```
188
+ */
189
+ constructor(client, defaultOwner) {
190
+ this.client = client;
191
+ this.defaultOwner = defaultOwner;
192
+ }
193
+ /**
194
+ * Fetches all coins of a specific type owned by an address.
195
+ *
196
+ * This method handles pagination automatically to retrieve all coins,
197
+ * regardless of how many exist. Coins are returned in the order
198
+ * provided by the blockchain.
199
+ *
200
+ * @param coinType - The fully qualified type of the coin (e.g., "0x2::sui::SUI")
201
+ * @param owner - Optional owner address. Uses defaultOwner if not provided.
202
+ *
203
+ * @returns A promise that resolves to an array of all coins of the specified type
204
+ *
205
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * // Get all SUI coins
210
+ * const suiCoins = await coinManager.getAllCoins("0x2::sui::SUI");
211
+ * console.log(`Found ${suiCoins.length} SUI coins`);
212
+ *
213
+ * // Get all USDC coins for a specific owner
214
+ * const usdcCoins = await coinManager.getAllCoins(
215
+ * "0x5d4b...::coin::COIN",
216
+ * "0xowner..."
217
+ * );
218
+ *
219
+ * // Display coin details
220
+ * suiCoins.forEach(coin => {
221
+ * console.log(`Coin ID: ${coin.coinObjectId}`);
222
+ * console.log(`Balance: ${coin.balance}`);
223
+ * });
224
+ * ```
225
+ */
226
+ async getAllCoins(coinType, owner) {
227
+ const ownerAddress = this.getOwnerAddress(owner);
228
+ const allCoins = [];
229
+ let cursor;
230
+ do {
231
+ const response = await this.client.getCoins({
232
+ owner: ownerAddress,
233
+ coinType,
234
+ cursor
235
+ });
236
+ allCoins.push(...response.data);
237
+ cursor = response.hasNextPage ? response.nextCursor : void 0;
238
+ } while (cursor);
239
+ return allCoins;
240
+ }
241
+ /**
242
+ * Resolves the owner address from the provided parameter or default.
243
+ *
244
+ * This is a helper method used internally to ensure an owner address
245
+ * is always available for coin operations.
246
+ *
247
+ * @param owner - Optional owner address to use
248
+ *
249
+ * @returns The resolved owner address
250
+ *
251
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * // With default owner set
256
+ * const address = coinManager.getOwnerAddress(); // Returns defaultOwner
257
+ *
258
+ * // With explicit owner
259
+ * const address = coinManager.getOwnerAddress("0x123..."); // Returns "0x123..."
260
+ *
261
+ * // Without default owner or parameter
262
+ * const address = coinManager.getOwnerAddress(); // Throws MissingParameterError
263
+ * ```
264
+ */
265
+ getOwnerAddress(owner) {
266
+ const address = owner || this.defaultOwner;
267
+ if (!address) throw new import_core2.MissingParameterError("owner");
268
+ return address;
269
+ }
270
+ /**
271
+ * Gets the total balance of a specific coin type for an owner.
272
+ *
273
+ * This method returns the sum of all coins of the specified type,
274
+ * providing a quick way to check if sufficient funds are available
275
+ * without fetching all coin objects.
276
+ *
277
+ * @param coinType - The fully qualified type of the coin (e.g., "0x2::sui::SUI")
278
+ * @param owner - Optional owner address. Uses defaultOwner if not provided.
279
+ *
280
+ * @returns A promise that resolves to the total balance as a string
281
+ *
282
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * // Get SUI balance
287
+ * const suiBalance = await coinManager.getTotalBalance("0x2::sui::SUI");
288
+ * console.log(`Total SUI: ${suiBalance}`);
289
+ *
290
+ * // Get USDC balance for specific owner
291
+ * const usdcBalance = await coinManager.getTotalBalance(
292
+ * "0x5d4b...::coin::COIN",
293
+ * "0xowner..."
294
+ * );
295
+ *
296
+ * // Convert to decimal for display (assuming 9 decimals for SUI)
297
+ * const suiDecimal = Number(suiBalance) / 1e9;
298
+ * console.log(`${suiDecimal} SUI`);
299
+ * ```
300
+ */
301
+ async getTotalBalance(coinType, owner) {
302
+ const ownerAddress = this.getOwnerAddress(owner);
303
+ const balance = await this.client.getBalance({
304
+ owner: ownerAddress,
305
+ coinType
306
+ });
307
+ return balance.totalBalance;
308
+ }
309
+ /**
310
+ * Asserts that the owner has sufficient balance for a transaction.
311
+ *
312
+ * This is a convenience method that checks the balance and throws
313
+ * a descriptive error if insufficient. Useful for fail-fast validation
314
+ * before attempting complex transaction preparation.
315
+ *
316
+ * @param coinType - The fully qualified type of the coin (e.g., "0x2::sui::SUI")
317
+ * @param amount - The required amount as a string
318
+ * @param owner - Optional owner address. Uses defaultOwner if not provided.
319
+ *
320
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
321
+ * @throws {InsufficientFundsError} When the balance is less than the required amount
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * try {
326
+ * // Check if user has 1 SUI
327
+ * await coinManager.assertEnoughBalance(
328
+ * "0x2::sui::SUI",
329
+ * "1000000000" // 1 SUI
330
+ * );
331
+ *
332
+ * // Proceed with transaction
333
+ * console.log("Sufficient balance confirmed");
334
+ * } catch (error) {
335
+ * if (error instanceof InsufficientFundsError) {
336
+ * console.error(`Need ${error.data.amount}, but only have ${error.data.available}`);
337
+ * }
338
+ * }
339
+ * ```
340
+ */
341
+ async assertEnoughBalance(coinType, amount, owner) {
342
+ const ownerAddress = this.getOwnerAddress(owner);
343
+ const totalBalance = await this.getTotalBalance(coinType, owner);
344
+ if (BigInt(totalBalance) < BigInt(amount)) {
345
+ throw new import_core2.InsufficientFundsError(amount, totalBalance, { coinType, amount, ownerAddress });
346
+ }
347
+ }
348
+ /**
349
+ * Selects optimal coins to cover a specific amount.
350
+ *
351
+ * This method implements intelligent coin selection algorithms that consider
352
+ * various factors like minimizing inputs, preserving large coins, and
353
+ * avoiding fragmentation. It determines whether merging or splitting is needed.
354
+ *
355
+ * @param coinType - The fully qualified type of the coin (e.g., "0x2::sui::SUI")
356
+ * @param amount - The target amount to select for, as a string
357
+ * @param options - Configuration options for the selection algorithm
358
+ * @param owner - Optional owner address. Uses defaultOwner if not provided.
359
+ *
360
+ * @returns A promise that resolves to a CoinSelectionResult with selected coins and metadata
361
+ *
362
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
363
+ * @throws {InsufficientFundsError} When available coins cannot cover the amount (unless allowPartial is true)
364
+ *
365
+ * @example
366
+ * ```typescript
367
+ * // Basic selection
368
+ * const selection = await coinManager.selectCoins(
369
+ * "0x2::sui::SUI",
370
+ * "1000000000" // 1 SUI
371
+ * );
372
+ *
373
+ * if (selection.requiresMerge) {
374
+ * console.log(`Need to merge ${selection.coins.length} coins`);
375
+ * }
376
+ * if (selection.requiresSplit) {
377
+ * console.log(`Need to split coin for exact amount`);
378
+ * }
379
+ *
380
+ * // Minimize number of inputs
381
+ * const minimalSelection = await coinManager.selectCoins(
382
+ * "0x2::sui::SUI",
383
+ * "5000000000",
384
+ * { minimizeInputs: true }
385
+ * );
386
+ *
387
+ * // Exclude specific coins and allow partial
388
+ * const partialSelection = await coinManager.selectCoins(
389
+ * "0x2::sui::SUI",
390
+ * "10000000000",
391
+ * {
392
+ * excludeIds: ["0x123..."],
393
+ * allowPartial: true
394
+ * }
395
+ * );
396
+ * ```
397
+ *
398
+ * @remarks
399
+ * The selection algorithm follows these priorities:
400
+ * 1. Exact match - single coin with exact amount
401
+ * 2. Single coin that covers amount (requires split)
402
+ * 3. Multiple coins (requires merge, possibly split)
403
+ *
404
+ * When minimizeInputs is false, smaller coins are used first to preserve larger ones.
405
+ */
406
+ async selectCoins(coinType, amount, options = {}, owner) {
407
+ const ownerAddress = this.getOwnerAddress(owner);
408
+ const coins = await this.getAllCoins(coinType, owner);
409
+ const availableCoins = options.excludeIds ? coins.filter((c) => !options.excludeIds?.includes(c.coinObjectId)) : coins;
410
+ if (availableCoins.length === 0) {
411
+ throw new import_core2.InsufficientFundsError(amount, "0", {
412
+ availableCoins,
413
+ coinType,
414
+ ownerAddress
415
+ });
416
+ }
417
+ const targetAmount = BigInt(amount);
418
+ availableCoins.sort((a, b) => {
419
+ const diff = BigInt(b.balance) - BigInt(a.balance);
420
+ return diff > 0n ? 1 : diff < 0n ? -1 : 0;
421
+ });
422
+ const exactMatch = availableCoins.find((c) => BigInt(c.balance) === targetAmount);
423
+ if (exactMatch) {
424
+ return {
425
+ coins: [exactMatch],
426
+ totalBalance: amount,
427
+ requiresMerge: false,
428
+ requiresSplit: false
429
+ };
430
+ }
431
+ const singleCoin = availableCoins.find((c) => BigInt(c.balance) > targetAmount);
432
+ if (singleCoin && !options.preferMerge) {
433
+ return {
434
+ coins: [singleCoin],
435
+ totalBalance: singleCoin.balance,
436
+ requiresMerge: false,
437
+ requiresSplit: true
438
+ };
439
+ }
440
+ const selectedCoins = [];
441
+ let totalBalance = 0n;
442
+ if (options.minimizeInputs) {
443
+ for (const coin of availableCoins) {
444
+ selectedCoins.push(coin);
445
+ totalBalance += BigInt(coin.balance);
446
+ if (totalBalance >= targetAmount) break;
447
+ }
448
+ } else {
449
+ const sortedAsc = [...availableCoins].sort((a, b) => {
450
+ const diff = BigInt(a.balance) - BigInt(b.balance);
451
+ return diff > 0n ? 1 : diff < 0n ? -1 : 0;
452
+ });
453
+ for (const coin of sortedAsc) {
454
+ if (totalBalance >= targetAmount) break;
455
+ selectedCoins.push(coin);
456
+ totalBalance += BigInt(coin.balance);
457
+ }
458
+ }
459
+ if (totalBalance < targetAmount) {
460
+ if (options.allowPartial) {
461
+ return {
462
+ coins: selectedCoins,
463
+ totalBalance: totalBalance.toString(),
464
+ requiresMerge: selectedCoins.length > 1,
465
+ requiresSplit: false
466
+ };
467
+ }
468
+ throw new import_core2.InsufficientFundsError(amount, totalBalance.toString(), {
469
+ amount,
470
+ coinType,
471
+ totalBalance: totalBalance.toString(),
472
+ ownerAddress
473
+ });
474
+ }
475
+ return {
476
+ coins: selectedCoins,
477
+ totalBalance: totalBalance.toString(),
478
+ requiresMerge: selectedCoins.length > 1,
479
+ requiresSplit: totalBalance > targetAmount
480
+ };
481
+ }
482
+ /**
483
+ * Prepares a coin input for a transaction with automatic merging and splitting.
484
+ *
485
+ * This is the main method for transaction preparation. It handles all the complexity
486
+ * of coin selection, merging multiple coins if needed, and splitting for exact amounts.
487
+ * Special handling is provided for SUI gas coins.
488
+ *
489
+ * @param tx - The Transaction object to add coin operations to
490
+ * @param coinType - The fully qualified type of the coin (e.g., "0x2::sui::SUI")
491
+ * @param amount - The exact amount needed for the transaction, as a string
492
+ * @param options - Configuration options for coin selection
493
+ * @param owner - Optional owner address. Uses defaultOwner if not provided.
494
+ *
495
+ * @returns A promise that resolves to an Argument that can be used in Move calls
496
+ *
497
+ * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set
498
+ * @throws {InsufficientFundsError} When available coins cannot cover the amount
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * const tx = new Transaction();
503
+ *
504
+ * // Prepare exact SUI amount (uses gas coin)
505
+ * const suiCoin = await coinManager.prepareCoinInput(
506
+ * tx,
507
+ * "0x2::sui::SUI",
508
+ * "1000000000" // 1 SUI
509
+ * );
510
+ *
511
+ * // Prepare custom coin with options
512
+ * const customCoin = await coinManager.prepareCoinInput(
513
+ * tx,
514
+ * "0x5d4b...::coin::COIN",
515
+ * "1000000", // 1 USDC
516
+ * {
517
+ * minimizeInputs: true,
518
+ * excludeIds: ["0x123..."]
519
+ * }
520
+ * );
521
+ *
522
+ * // Use in a Move call
523
+ * tx.moveCall({
524
+ * target: `${packageId}::module::swap`,
525
+ * arguments: [suiCoin, customCoin],
526
+ * });
527
+ * ```
528
+ *
529
+ * @remarks
530
+ * - SUI coins are handled specially by splitting from the gas coin
531
+ * - Single coins matching the exact amount are used directly
532
+ * - Multiple coins are automatically merged
533
+ * - Coins with excess balance are automatically split
534
+ * - The resulting Argument can be used directly in Move calls
535
+ */
536
+ async prepareCoinInput(tx, coinType, amount, options = {}, owner) {
537
+ const ownerAddress = this.getOwnerAddress(owner);
538
+ if (coinType === import_utils3.SUI_TYPE_ARG) {
539
+ const [coin] = tx.splitCoins(tx.gas, [amount]);
540
+ return coin;
541
+ }
542
+ const selection = await this.selectCoins(coinType, amount, options, owner);
543
+ if (!selection.coins[0]) {
544
+ throw new import_core2.InsufficientFundsError(amount, "0", {
545
+ coinType,
546
+ amount,
547
+ ownerAddress
548
+ });
549
+ }
550
+ if (selection.coins.length === 1 && !selection.requiresSplit) {
551
+ return tx.object(selection.coins[0].coinObjectId);
552
+ }
553
+ if (selection.coins.length === 1 && selection.requiresSplit) {
554
+ const [split] = tx.splitCoins(tx.object(selection.coins[0].coinObjectId), [amount]);
555
+ return split;
556
+ }
557
+ const primaryCoin = tx.object(selection.coins[0].coinObjectId);
558
+ const mergeCoins = selection.coins.slice(1).map((c) => tx.object(c.coinObjectId));
559
+ tx.mergeCoins(primaryCoin, mergeCoins);
560
+ if (selection.requiresSplit) {
561
+ const [split] = tx.splitCoins(primaryCoin, [amount]);
562
+ return split;
563
+ }
564
+ return primaryCoin;
565
+ }
566
+ };
567
+
568
+ // src/lib/helpers/queries.ts
569
+ var import_core3 = require("@bolt-liquidity-hq/core");
164
570
  var import_transactions = require("@mysten/sui/transactions");
165
571
  var queryDevInspect = async (suiClient, target, args, typeArguments, senderAddress) => {
166
572
  const tx = new import_transactions.Transaction();
@@ -181,10 +587,10 @@ var queryDevInspect = async (suiClient, target, args, typeArguments, senderAddre
181
587
  if (result.effects.status.status === "success") {
182
588
  return result;
183
589
  } else {
184
- throw new import_core2.TransactionFailedError("N/A", "Failed to query smart contract", { result });
590
+ throw new import_core3.TransactionFailedError("N/A", "Failed to query smart contract", { result });
185
591
  }
186
592
  } catch (error) {
187
- throw import_core2.UnexpectedError.from(error, "Failed to query smart contract", {
593
+ throw import_core3.UnexpectedError.from(error, "Failed to query smart contract", {
188
594
  target: targetString,
189
595
  args,
190
596
  typeArguments
@@ -192,9 +598,84 @@ var queryDevInspect = async (suiClient, target, args, typeArguments, senderAddre
192
598
  }
193
599
  };
194
600
 
195
- // src/lib/oracle/parsers.ts
196
- var import_core3 = require("@bolt-liquidity-hq/core");
601
+ // src/lib/helpers/txs.ts
602
+ var import_core4 = require("@bolt-liquidity-hq/core");
603
+ var import_transactions2 = require("@mysten/sui/transactions");
604
+ var import_utils4 = require("@mysten/sui/utils");
197
605
  var import_bignumber = require("bignumber.js");
606
+ var signAndExecuteTx = async (suiClient, signer, target, args, typeArguments, transaction, options) => {
607
+ const tx = transaction ?? new import_transactions2.Transaction();
608
+ const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;
609
+ const txArgs = args?.map(
610
+ (item) => typeof item === "string" ? tx.object(item) : "toBytes" in item ? tx.pure(item.toBytes()) : item
611
+ );
612
+ tx.moveCall({
613
+ target: targetString,
614
+ arguments: txArgs,
615
+ typeArguments
616
+ });
617
+ try {
618
+ const result = await suiClient.signAndExecuteTransaction({
619
+ signer,
620
+ transaction: tx,
621
+ options
622
+ });
623
+ if (result.effects?.status.status === "success") {
624
+ return result;
625
+ } else {
626
+ throw new import_core4.TransactionFailedError(result.digest, result.effects?.status.error, { result });
627
+ }
628
+ } catch (error) {
629
+ throw import_core4.UnexpectedError.from(error, "Failed to execute transaction", {
630
+ target: targetString,
631
+ args,
632
+ typeArguments
633
+ });
634
+ }
635
+ };
636
+ var estimateTxGasPrice = async (suiClient, target, args, typeArguments, transaction, gasAdjustment = import_core4.DEFAULT_GAS_ADJUSTMENT) => {
637
+ const tx = transaction ?? new import_transactions2.Transaction();
638
+ const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;
639
+ const txArgs = args?.map(
640
+ (item) => typeof item === "string" ? tx.object(item) : "toBytes" in item ? tx.pure(item.toBytes()) : item
641
+ );
642
+ tx.moveCall({
643
+ target: targetString,
644
+ arguments: txArgs,
645
+ typeArguments
646
+ });
647
+ try {
648
+ const transactionBytes = await tx.build({ client: suiClient });
649
+ const dryRunResult = await suiClient.dryRunTransactionBlock({
650
+ transactionBlock: transactionBytes
651
+ });
652
+ if (dryRunResult.effects.status.status !== "success") {
653
+ throw new import_core4.UnexpectedError(
654
+ `Dry run failed: ${dryRunResult.effects.status.error}`,
655
+ "Failed to estimate gas",
656
+ {
657
+ target: targetString,
658
+ args,
659
+ typeArguments,
660
+ error: dryRunResult.effects.status.error
661
+ }
662
+ );
663
+ }
664
+ const gasUsed = dryRunResult.effects.gasUsed;
665
+ const totalGasCost = (0, import_bignumber.BigNumber)(gasUsed.computationCost).plus(gasUsed.storageCost).minus(gasUsed.storageRebate);
666
+ const adjustedGasCost = totalGasCost.times(gasAdjustment);
667
+ return {
668
+ denom: import_utils4.SUI_TYPE_ARG,
669
+ amount: adjustedGasCost.toFixed(0, import_bignumber.BigNumber.ROUND_CEIL)
670
+ };
671
+ } catch {
672
+ return;
673
+ }
674
+ };
675
+
676
+ // src/lib/oracle/parsers.ts
677
+ var import_core5 = require("@bolt-liquidity-hq/core");
678
+ var import_bignumber2 = require("bignumber.js");
198
679
  var parseOracleConfigStructOutput = (output) => {
199
680
  return {
200
681
  admin: output.admin,
@@ -219,25 +700,26 @@ var parseAssetPairStructOutput = (output) => {
219
700
  }
220
701
  };
221
702
  };
222
- var parsePriceDataStructOutput = (response, baseDenom, quoteDenom) => {
703
+ var parsePriceDataStructOutput = (output) => {
223
704
  return {
224
- assetPair: `${baseDenom}:${quoteDenom}`,
225
- price: response.price,
226
- expiryTime: (0, import_bignumber.BigNumber)(response.expiry_time_ms).times(1e6).toFixed(),
705
+ baseDenom: output.base_symbol,
706
+ quoteDenom: output.quote_symbol,
707
+ price: output.price,
708
+ expiryTime: (0, import_bignumber2.BigNumber)(output.expiry_time_ms).times(1e6).toFixed(),
227
709
  isInverse: false
228
710
  };
229
711
  };
230
- var parsePriceResponseStructOutput = (response, baseDenom, quoteDenom) => {
231
- if (!response.pair_data) {
232
- throw new import_core3.InvalidObjectError("Can't find pair data price");
712
+ var parsePriceResponseStructOutput = (output) => {
713
+ if (!output.pair_data) {
714
+ throw new import_core5.InvalidObjectError("Can't find pair data price");
233
715
  }
234
- return parsePriceDataStructOutput(response.pair_data, baseDenom, quoteDenom);
716
+ return parsePriceDataStructOutput(output.pair_data);
235
717
  };
236
718
  var parseAssetPairsResponsePaginatedStructOutput = (output) => {
237
719
  return output.asset_pairs.map((item) => parseAssetPairStructOutput(item));
238
720
  };
239
721
  var parsePricesResponsePaginatedStructOutput = (output) => {
240
- return output.prices.map((item) => parsePriceDataStructOutput(item, "", ""));
722
+ return output.prices.map((item) => parsePriceDataStructOutput(item));
241
723
  };
242
724
 
243
725
  // src/types/bcs.ts
@@ -287,6 +769,8 @@ var AssetPairsResponsePaginatedStruct = import_bcs3.bcs.struct("AssetPairsRespon
287
769
  ...PaginationStruct
288
770
  });
289
771
  var PriceDataStruct = import_bcs3.bcs.struct("PriceData", {
772
+ base_symbol: import_bcs3.bcs.string(),
773
+ quote_symbol: import_bcs3.bcs.string(),
290
774
  price: import_bcs3.bcs.u128(),
291
775
  expiry_time_ms: import_bcs3.bcs.u64(),
292
776
  last_updated_ms: import_bcs3.bcs.u64(),
@@ -326,8 +810,12 @@ var MarketsResponsePaginatedStruct = import_bcs5.bcs.struct("MarketsResponsePagi
326
810
  markets: import_bcs5.bcs.vector(MarketStruct),
327
811
  ...PaginationStruct
328
812
  });
813
+ var BaseLiquidityInfoStruct = import_bcs5.bcs.struct("BaseLiquidityInfo", {
814
+ denom: import_bcs5.bcs.string(),
815
+ amount: import_bcs5.bcs.u64()
816
+ });
329
817
  var BaseLiquidityResponseStruct = import_bcs5.bcs.struct("BaseLiquidityResponse", {
330
- base_assets: import_bcs5.bcs.vector(import_bcs5.bcs.string()),
818
+ base_assets: import_bcs5.bcs.vector(BaseLiquidityInfoStruct),
331
819
  ...PaginationStruct
332
820
  });
333
821
 
@@ -402,7 +890,7 @@ var getOracleConfig = async (client) => {
402
890
 
403
891
  // src/lib/oracle/get-price.ts
404
892
  var import_bcs10 = require("@mysten/bcs");
405
- var import_utils = require("@mysten/sui/utils");
893
+ var import_utils5 = require("@mysten/sui/utils");
406
894
  var getPrice = async (client, baseDenom, quoteDenom) => {
407
895
  const GET_PRICE_FUNCTION = "get_price";
408
896
  const response = await queryDevInspect(
@@ -412,11 +900,11 @@ var getPrice = async (client, baseDenom, quoteDenom) => {
412
900
  client.contracts.oracle,
413
901
  import_bcs10.bcs.string().serialize(baseDenom),
414
902
  import_bcs10.bcs.string().serialize(quoteDenom),
415
- import_utils.SUI_CLOCK_OBJECT_ID
903
+ import_utils5.SUI_CLOCK_OBJECT_ID
416
904
  ]
417
905
  );
418
906
  const output = parseDevInspectResult(response, PriceResponseStruct);
419
- return parsePriceResponseStructOutput(output, baseDenom, quoteDenom);
907
+ return parsePriceResponseStructOutput(output);
420
908
  };
421
909
 
422
910
  // src/lib/oracle/get-prices.ts
@@ -445,11 +933,42 @@ var getPrices = async (client) => {
445
933
  return result;
446
934
  };
447
935
 
448
- // src/lib/router/get-all-base-liquidity.ts
936
+ // src/lib/router/estimate-swap-exact-in-gas-fees.ts
937
+ var import_core6 = require("@bolt-liquidity-hq/core");
449
938
  var import_bcs12 = require("@mysten/bcs");
939
+ var import_transactions3 = require("@mysten/sui/transactions");
940
+ var import_utils6 = require("@mysten/sui/utils");
941
+ var estimateSwapExactInGasFees = async (client, { assetIn, amountIn, assetOut, minimumAmountOut, receiver }, signer, gasAdjustment = import_core6.DEFAULT_GAS_ADJUSTMENT) => {
942
+ const SWAP_EXACT_IN_FUNCTION = "swap_exact_in";
943
+ const finalSigner = client.getSigner(signer);
944
+ const tx = new import_transactions3.Transaction();
945
+ const coinManager = new CoinManager(client.suiClient, finalSigner.toSuiAddress());
946
+ const coinInput = await coinManager.prepareCoinInput(tx, assetIn, amountIn);
947
+ return await estimateTxGasPrice(
948
+ client.suiClient,
949
+ [client.packageId, ROUTER_MODULE, SWAP_EXACT_IN_FUNCTION],
950
+ [
951
+ client.contracts.router,
952
+ import_bcs12.bcs.string().serialize(assetOut),
953
+ "",
954
+ // TODO: pass correct pool when router can actually route to the pools depending on other arguments
955
+ import_bcs12.bcs.string().serialize(assetIn),
956
+ import_bcs12.bcs.option(import_bcs12.bcs.string()).serialize(minimumAmountOut),
957
+ import_bcs12.bcs.option(import_bcs12.bcs.string()).serialize(receiver),
958
+ coinInput,
959
+ import_utils6.SUI_CLOCK_OBJECT_ID
960
+ ],
961
+ [assetIn, assetOut],
962
+ tx,
963
+ gasAdjustment
964
+ );
965
+ };
966
+
967
+ // src/lib/router/get-all-base-liquidity.ts
968
+ var import_bcs13 = require("@mysten/bcs");
450
969
 
451
970
  // src/lib/router/parsers.ts
452
- var import_core4 = require("@bolt-liquidity-hq/core");
971
+ var import_core7 = require("@bolt-liquidity-hq/core");
453
972
  var parseMarketStructOutput = (output) => {
454
973
  return {
455
974
  poolAddress: output.market_address,
@@ -457,14 +976,14 @@ var parseMarketStructOutput = (output) => {
457
976
  quoteDenoms: output.quote_assets_symbols
458
977
  };
459
978
  };
460
- var parseMarketResponseStructOutput = (response) => {
461
- if (!response.market) {
462
- throw new import_core4.NotFoundError("Market", void 0, { response });
979
+ var parseMarketResponseStructOutput = (output) => {
980
+ if (!output.market) {
981
+ throw new import_core7.NotFoundError("Market", void 0, { output });
463
982
  }
464
- return parseMarketStructOutput(response.market);
983
+ return parseMarketStructOutput(output.market);
465
984
  };
466
- var parseMarketsResponsePaginatedStructOutput = (response) => {
467
- return response.markets.map((item) => parseMarketStructOutput(item));
985
+ var parseMarketsResponsePaginatedStructOutput = (output) => {
986
+ return output.markets.map((item) => parseMarketStructOutput(item));
468
987
  };
469
988
  var parseRouterConfigStructOutput = (output) => {
470
989
  return {
@@ -478,10 +997,11 @@ var parseRouterConfigStructOutput = (output) => {
478
997
  var parseBaseLiquidityResponseStructOutput = (output) => {
479
998
  return output.base_assets.map((item) => ({
480
999
  baseLiquidity: {
481
- denom: item,
482
- amount: "10"
1000
+ denom: item.denom,
1001
+ amount: item.amount
483
1002
  },
484
- totalShares: "10"
1003
+ totalShares: ""
1004
+ // TODO: add real total shares if it is returned by the smart contract later
485
1005
  }));
486
1006
  };
487
1007
 
@@ -497,8 +1017,8 @@ var getAllBaseLiquidity = async (client) => {
497
1017
  [client.packageId, ROUTER_MODULE, BASE_LIQUIDITY_ALL_PAGINATED_FUNCTION],
498
1018
  [
499
1019
  client.contracts.router,
500
- import_bcs12.bcs.option(import_bcs12.bcs.u64()).serialize(DEFAULT_PAGINATION_LIMIT),
501
- import_bcs12.bcs.option(import_bcs12.bcs.string()).serialize(currentCursor)
1020
+ import_bcs13.bcs.option(import_bcs13.bcs.u64()).serialize(DEFAULT_PAGINATION_LIMIT),
1021
+ import_bcs13.bcs.option(import_bcs13.bcs.string()).serialize(currentCursor)
502
1022
  ]
503
1023
  );
504
1024
  const output = parseDevInspectResult(response, BaseLiquidityResponseStruct);
@@ -513,33 +1033,33 @@ var getAllBaseLiquidity = async (client) => {
513
1033
  };
514
1034
 
515
1035
  // src/lib/router/get-all-quotes-for-user.ts
516
- var import_bcs13 = require("@mysten/bcs");
1036
+ var import_bcs14 = require("@mysten/bcs");
517
1037
  var getAllQuotesForUser = async (client, lpAddress) => {
518
1038
  const QUOTES_FOR_USER_ALL_FUNCTION = "quotes_for_user_all";
519
1039
  const response = await queryDevInspect(
520
1040
  client.suiClient,
521
1041
  [client.packageId, ROUTER_MODULE, QUOTES_FOR_USER_ALL_FUNCTION],
522
- [client.contracts.router, import_bcs13.bcs.string().serialize(lpAddress)]
1042
+ [client.contracts.router, import_bcs14.bcs.string().serialize(lpAddress)]
523
1043
  );
524
1044
  console.log(response);
525
1045
  return {};
526
1046
  };
527
1047
 
528
1048
  // src/lib/router/get-pool-for-base.ts
529
- var import_bcs14 = require("@mysten/bcs");
1049
+ var import_bcs15 = require("@mysten/bcs");
530
1050
  var getPoolForBase = async (client, baseDenom) => {
531
1051
  const MARKET_FOR_BASE_FUNCTION = "market_for_base";
532
1052
  const response = await queryDevInspect(
533
1053
  client.suiClient,
534
1054
  [client.packageId, ROUTER_MODULE, MARKET_FOR_BASE_FUNCTION],
535
- [client.contracts.router, import_bcs14.bcs.string().serialize(baseDenom)]
1055
+ [client.contracts.router, import_bcs15.bcs.string().serialize(baseDenom)]
536
1056
  );
537
1057
  const output = parseDevInspectResult(response, MarketResponseStruct);
538
1058
  return parseMarketResponseStructOutput(output);
539
1059
  };
540
1060
 
541
1061
  // src/lib/router/get-pools.ts
542
- var import_bcs15 = require("@mysten/bcs");
1062
+ var import_bcs16 = require("@mysten/bcs");
543
1063
  var getPools = async (client) => {
544
1064
  const MARKETS_PAGINATED_FUNCTION = "markets_paginated";
545
1065
  const result = [];
@@ -551,8 +1071,8 @@ var getPools = async (client) => {
551
1071
  [client.packageId, ROUTER_MODULE, MARKETS_PAGINATED_FUNCTION],
552
1072
  [
553
1073
  client.contracts.router,
554
- import_bcs15.bcs.option(import_bcs15.bcs.u64()).serialize(DEFAULT_PAGINATION_LIMIT),
555
- import_bcs15.bcs.option(import_bcs15.bcs.string()).serialize(currentCursor)
1074
+ import_bcs16.bcs.option(import_bcs16.bcs.u64()).serialize(DEFAULT_PAGINATION_LIMIT),
1075
+ import_bcs16.bcs.option(import_bcs16.bcs.string()).serialize(currentCursor)
556
1076
  ]
557
1077
  );
558
1078
  const output = parseDevInspectResult(response, MarketsResponsePaginatedStruct);
@@ -577,60 +1097,89 @@ var getRouterConfig = async (client) => {
577
1097
  };
578
1098
 
579
1099
  // src/lib/router/swap-exact-in.ts
580
- var swapExactIn = async (client, signer, { assetIn, amountIn, assetOut, minimumAmountOut, receiver }) => {
581
- console.log(client, signer, assetIn, amountIn, assetOut, minimumAmountOut, receiver);
582
- await new Promise((resolve) => setTimeout(resolve, 1e3));
583
- return {};
1100
+ var import_bcs17 = require("@mysten/bcs");
1101
+ var import_transactions4 = require("@mysten/sui/transactions");
1102
+ var import_utils7 = require("@mysten/sui/utils");
1103
+ var swapExactIn = async (client, { assetIn, amountIn, assetOut, minimumAmountOut, receiver }, signer) => {
1104
+ const SWAP_EXACT_IN_FUNCTION = "swap_exact_in";
1105
+ const finalSigner = client.getSigner(signer);
1106
+ const tx = new import_transactions4.Transaction();
1107
+ const coinManager = new CoinManager(client.suiClient, finalSigner.toSuiAddress());
1108
+ const coinInput = await coinManager.prepareCoinInput(tx, assetIn, amountIn);
1109
+ const txOutput = await signAndExecuteTx(
1110
+ client.suiClient,
1111
+ finalSigner,
1112
+ [client.packageId, ROUTER_MODULE, SWAP_EXACT_IN_FUNCTION],
1113
+ [
1114
+ client.contracts.router,
1115
+ import_bcs17.bcs.string().serialize(assetOut),
1116
+ "",
1117
+ // TODO: pass correct pool when router can actually route to the pools depending on other arguments
1118
+ import_bcs17.bcs.string().serialize(assetIn),
1119
+ import_bcs17.bcs.option(import_bcs17.bcs.string()).serialize(minimumAmountOut),
1120
+ import_bcs17.bcs.option(import_bcs17.bcs.string()).serialize(receiver),
1121
+ coinInput,
1122
+ import_utils7.SUI_CLOCK_OBJECT_ID
1123
+ ],
1124
+ [assetIn, assetOut],
1125
+ tx,
1126
+ { showEffects: true, showEvents: true, showBalanceChanges: true }
1127
+ );
1128
+ return {
1129
+ txOutput,
1130
+ txHash: txOutput.digest,
1131
+ amountOut: "",
1132
+ // TODO: implement when contract emits event
1133
+ assetOut
1134
+ };
584
1135
  };
585
1136
 
586
1137
  // src/lib/settlement/get-pool-info.ts
587
- var import_utils2 = require("@mysten/sui/utils");
1138
+ var import_utils8 = require("@mysten/sui/utils");
588
1139
 
589
1140
  // src/lib/settlement/parsers.ts
590
- var parseSettlementConfigStructOutput = (_poolInfoOutput, feesOutput) => {
1141
+ var parseSettlementConfigStructOutput = (globalConfig, feesOutput) => {
591
1142
  return {
592
1143
  priceOracleContract: "0x",
593
- // Should come from poolInfoOutput
594
- protocolFeeRecipient: "0x",
595
- // Should be feesOutput[1]
1144
+ // Should come from pool config
1145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
1146
+ protocolFeeRecipient: globalConfig.data?.content?.fields.protocol_fee_recipient || "",
596
1147
  protocolFee: feesOutput[0],
597
1148
  // Protocol fee percentage
598
1149
  lpFee: feesOutput[2],
599
1150
  // LP fee percentage
600
1151
  allowanceMode: "allow",
601
- // Should come from poolInfoOutput
1152
+ // Should come from pool config
602
1153
  lps: ["0x"],
603
- // Should come from poolInfoOutput
1154
+ // Should come from pool config
604
1155
  minBaseOut: "1"
605
- // Should come from poolInfoOutput
1156
+ // Should come from pool config
606
1157
  };
607
1158
  };
608
1159
 
609
1160
  // src/lib/settlement/get-pool-info.ts
610
1161
  var getPoolInfo = async (client, contractAddress) => {
611
- const GET_POOL_INFO = "get_pool_info";
612
1162
  const GET_FEES_FUNCTION = "get_fees";
613
- const [info, fees] = await Promise.all([
614
- // Query pool information (LP configuration, allowance mode)
615
- queryDevInspect(
616
- client.suiClient,
617
- [client.packageId, POOL_MODULE, GET_POOL_INFO],
618
- [contractAddress],
619
- // TODO: get the base token of the pool to pass it here instead of hardcoded SUI token
620
- [import_utils2.SUI_TYPE_ARG]
621
- ),
622
- // Query fee structure (protocol fee, LP fee, recipients)
1163
+ const [globalConfig, fees] = await Promise.all([
1164
+ // Fetch the global pool configuration object
1165
+ client.suiClient.getObject({
1166
+ id: client.poolGlobalConfigId,
1167
+ options: {
1168
+ showContent: true,
1169
+ showType: true
1170
+ }
1171
+ }),
1172
+ // Query pool-specific fee structure
623
1173
  queryDevInspect(
624
1174
  client.suiClient,
625
1175
  [client.packageId, POOL_MODULE, GET_FEES_FUNCTION],
626
1176
  [contractAddress],
627
1177
  // TODO: get the base token of the pool to pass it here instead of hardcoded SUI token
628
- [import_utils2.SUI_TYPE_ARG]
1178
+ [import_utils8.SUI_TYPE_ARG]
629
1179
  )
630
1180
  ]);
631
- const infoOutput = parseMultipleResults(info, GetPoolInfoResponseStruct);
632
1181
  const feesOutput = parseMultipleResults(fees, GetFeesResponseStruct);
633
- return parseSettlementConfigStructOutput(infoOutput, feesOutput);
1182
+ return parseSettlementConfigStructOutput(globalConfig, feesOutput);
634
1183
  };
635
1184
 
636
1185
  // src/tests/constants/sui-objects.ts
@@ -643,25 +1192,29 @@ var getPoolInfoForBase = async (client, baseDenom) => {
643
1192
  };
644
1193
 
645
1194
  // src/lib/client.ts
646
- var BoltSuiClient = class extends import_core5.BaseClient {
1195
+ var BoltSuiClient = class extends import_core8.BaseClient {
647
1196
  /**
648
1197
  * Creates a new instance of the BoltSuiClient.
649
1198
  *
650
- * The client automatically configures itself based on the specified chain and environment,
651
- * loading the appropriate contract addresses, chain configuration, and assets from configuration files.
1199
+ * The client automatically configures itself based on the specified environment,
1200
+ * loading the appropriate contract addresses, chain configuration, native token denomination,
1201
+ * and assets from configuration files.
652
1202
  *
653
1203
  * @param config - (Optional) Configuration for the client
654
1204
  * @param config.environment - (Optional) The deployment environment ('mainnet' or 'testnet'). Defaults to 'mainnet'
655
- * @param config.customOverride - (Optional) Custom overrides for chain configuration, contracts, and assets
1205
+ * @param config.customOverride - (Optional) Custom overrides for chain configuration, contracts, native token, and assets
656
1206
  * @param config.customOverride.chainConfig - (Optional) Override chain configuration
657
1207
  * @param config.customOverride.chainConfig.id - (Optional) Custom chain ID
658
1208
  * @param config.customOverride.chainConfig.name - (Optional) Custom chain name
659
1209
  * @param config.customOverride.chainConfig.rpcEndpoint - (Optional) Custom RPC endpoint URL
660
1210
  * @param config.customOverride.packageId - (Optional) Custom package ID for Bolt contracts
1211
+ * @param config.customOverride.poolGlobalConfigId - (Optional) Custom Object ID for the Pool contracts' Global Config
661
1212
  * @param config.customOverride.contracts - (Optional) Override contract addresses
662
1213
  * @param config.customOverride.contracts.oracle - (Optional) Custom oracle contract address
663
1214
  * @param config.customOverride.contracts.router - (Optional) Custom router contract address
1215
+ * @param config.customOverride.nativeTokenDenom - (Optional) Custom native token denomination (e.g., "SUI")
664
1216
  * @param config.customOverride.assetsConfig - (Optional) Custom asset configurations indexed by denom
1217
+ * @param config.signer - (Optional) Pre-existing Signer for transaction signing
665
1218
  * @param config.suiClient - (Optional) Pre-existing SuiClient to use for blockchain queries
666
1219
  *
667
1220
  * @throws {InvalidObjectError} Thrown when required configuration fields are missing
@@ -685,10 +1238,12 @@ var BoltSuiClient = class extends import_core5.BaseClient {
685
1238
  * rpcEndpoint: 'https://custom-rpc.example.com'
686
1239
  * },
687
1240
  * packageId: '0xcustom_package_id...',
1241
+ * poolGlobalConfigId: '0xcustom_global_config_id...',
688
1242
  * contracts: {
689
1243
  * oracle: '0xcustom_oracle...',
690
1244
  * router: '0xcustom_router...'
691
1245
  * },
1246
+ * nativeTokenDenom: 'SUI',
692
1247
  * assetsConfig: {
693
1248
  * '0x2::sui::SUI': {
694
1249
  * symbol: 'SUI',
@@ -703,17 +1258,20 @@ var BoltSuiClient = class extends import_core5.BaseClient {
703
1258
  * }
704
1259
  * });
705
1260
  *
706
- * // Use pre-existing Sui client
1261
+ * // Use pre-existing Sui client and signer
707
1262
  * const clientWithCustomClient = new BoltSuiClient({
708
- * suiClient: mySuiClient
1263
+ * suiClient: mySuiClient,
1264
+ * signer: mySigner
709
1265
  * });
710
1266
  * ```
711
1267
  */
712
1268
  constructor(config) {
713
- const { environment = "mainnet", customOverride, suiClient } = config ?? {};
1269
+ const { environment = "mainnet", customOverride, signer, suiClient } = config ?? {};
714
1270
  const defaultChainConfig = environment === "mainnet" ? MainnetChainConfig : TestnetChainConfig;
715
1271
  const defaultContracts = environment === "mainnet" ? MainnetContracts : TestnetContracts;
716
1272
  const defaultPackageId = environment === "mainnet" ? MainnetPackageId : TestnetPackageId;
1273
+ const defaultPoolGlobalConfigId = environment === "mainnet" ? MainnetPoolGlobalConfigId : TestnetPoolGlobalConfigId;
1274
+ const defaultNativeTokenDenom = environment === "mainnet" ? MainnetNativeTokenDenom : TestnetNativeTokenDenom;
717
1275
  const assetsConfig = environment === "mainnet" ? MainnetAssets : TestnetAssets;
718
1276
  const chainConfig = {
719
1277
  id: customOverride?.chainConfig?.id ?? defaultChainConfig.id,
@@ -721,10 +1279,12 @@ var BoltSuiClient = class extends import_core5.BaseClient {
721
1279
  rpcEndpoint: customOverride?.chainConfig?.rpcEndpoint ?? defaultChainConfig.rpcEndpoint
722
1280
  };
723
1281
  const packageId = customOverride?.packageId ?? defaultPackageId;
1282
+ const poolGlobalConfigId = customOverride?.poolGlobalConfigId ?? defaultPoolGlobalConfigId;
724
1283
  const contracts = {
725
1284
  oracle: customOverride?.contracts?.oracle ?? defaultContracts.oracle,
726
1285
  router: customOverride?.contracts?.router ?? defaultContracts.router
727
1286
  };
1287
+ const nativeTokenDenom = customOverride?.nativeTokenDenom ?? defaultNativeTokenDenom;
728
1288
  for (const item of Object.values(customOverride?.assetsConfig ?? {})) {
729
1289
  assetsConfig[item.denom] = item;
730
1290
  }
@@ -732,6 +1292,7 @@ var BoltSuiClient = class extends import_core5.BaseClient {
732
1292
  customOverride: {
733
1293
  chainConfig,
734
1294
  contracts,
1295
+ nativeTokenDenom,
735
1296
  assetsConfig
736
1297
  }
737
1298
  });
@@ -743,14 +1304,55 @@ var BoltSuiClient = class extends import_core5.BaseClient {
743
1304
  * Package Id for the deployed Bolt contracts on Sui
744
1305
  */
745
1306
  __publicField(this, "packageId");
1307
+ /**
1308
+ * Object Id for the GlobalConfig of the deployed Pool contracts
1309
+ */
1310
+ __publicField(this, "poolGlobalConfigId");
1311
+ /**
1312
+ * Cached instance of the Signer for transaction execution
1313
+ * @private
1314
+ */
1315
+ __publicField(this, "signer");
746
1316
  /**
747
1317
  * Instance of the Sui client to interact with the blockchain
748
1318
  */
749
1319
  __publicField(this, "suiClient");
750
1320
  this.chainConfig = chainConfig;
751
1321
  this.packageId = packageId;
1322
+ this.poolGlobalConfigId = poolGlobalConfigId;
1323
+ this.signer = signer;
752
1324
  this.suiClient = suiClient ?? new import_client.SuiClient({ url: chainConfig.rpcEndpoint });
753
1325
  }
1326
+ /**
1327
+ * Gets or sets the signer for transaction execution.
1328
+ *
1329
+ * This method manages the signer instance used for signing transactions.
1330
+ * A signer must be provided either when creating the client, on first call,
1331
+ * or to replace the existing signer.
1332
+ *
1333
+ * @param newSigner - Optional new signer to replace the existing one
1334
+ *
1335
+ * @returns The current signer instance
1336
+ *
1337
+ * @throws {MissingParameterError} Thrown when no signer is available and none is provided
1338
+ *
1339
+ * @example
1340
+ * ```typescript
1341
+ * // Get the current signer (throws if none exists)
1342
+ * const currentSigner = client.getSigner();
1343
+ *
1344
+ * // Set a new signer
1345
+ * const newSigner = // ... obtain signer from wallet
1346
+ * const signer = client.getSigner(newSigner);
1347
+ * ```
1348
+ */
1349
+ getSigner(newSigner) {
1350
+ this.signer = newSigner ?? this.signer;
1351
+ if (!this.signer) {
1352
+ throw new import_core8.MissingParameterError("signer");
1353
+ }
1354
+ return this.signer;
1355
+ }
754
1356
  // The following methods inherit their documentation from BaseClient
755
1357
  // Only add documentation here if you need to override or add implementation-specific details
756
1358
  /** @inheritdoc */
@@ -810,13 +1412,13 @@ var BoltSuiClient = class extends import_core5.BaseClient {
810
1412
  * const signer = // ... obtain signer from wallet
811
1413
  *
812
1414
  * // Execute swap: 1 SUI for USDC
813
- * const result = await client.swap(signer, {
1415
+ * const result = await client.swap({
814
1416
  * assetIn: "0x2::sui::SUI",
815
1417
  * amountIn: "1000000000", // 1 SUI (9 decimals)
816
1418
  * assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN", // USDC address
817
1419
  * minimumAmountOut: "1950000", // Minimum 1.95 USDC expected (6 decimals)
818
1420
  * receiver: "0x..." // Optional custom receiver address
819
- * });
1421
+ * }, signer);
820
1422
  *
821
1423
  * console.log(`Swap successful!`);
822
1424
  * console.log(`Transaction digest: ${result.txHash}`);
@@ -829,8 +1431,39 @@ var BoltSuiClient = class extends import_core5.BaseClient {
829
1431
  * This implementation returns a SuiTransactionBlockResponse as the transaction output,
830
1432
  * which includes details like gas costs, transaction effects, object changes, and events.
831
1433
  */
832
- async swap(signer, params) {
833
- return await swapExactIn(this, signer, params);
1434
+ async swap(params, signer) {
1435
+ return await swapExactIn(this, params, signer);
1436
+ }
1437
+ /**
1438
+ * @inheritdoc
1439
+ *
1440
+ * @example
1441
+ * ```typescript
1442
+ * // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)
1443
+ * const signer = // ... obtain signer from wallet
1444
+ *
1445
+ * // Estimate gas for swapping 1 SUI to USDC
1446
+ * const gasEstimate = await client.estimateSwapGasFees({
1447
+ * assetIn: "0x2::sui::SUI",
1448
+ * amountIn: "1000000000", // 1 SUI (9 decimals)
1449
+ * assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN", // USDC
1450
+ * minimumAmountOut: "1950000" // Min 1.95 USDC (6 decimals)
1451
+ * }, signer, 1.3); // 30% safety margin
1452
+ *
1453
+ * if (gasEstimate) {
1454
+ * console.log(`Estimated gas: ${gasEstimate.amount} ${gasEstimate.denom}`);
1455
+ * }
1456
+ * ```
1457
+ *
1458
+ * @remarks
1459
+ * - For Sui, gas is always paid in SUI tokens
1460
+ * - The returned amount is in MIST (smallest unit, 9 decimals)
1461
+ * - Gas estimation uses Sui's dry run transaction capability
1462
+ * - The gasAdjustment parameter helps account for variations in actual execution
1463
+ * - Sui's gas model includes computation, storage, and storage rebates
1464
+ */
1465
+ async estimateSwapGasFees(params, signer, gasAdjustment) {
1466
+ return await estimateSwapExactInGasFees(this, params, signer, gasAdjustment);
834
1467
  }
835
1468
  };
836
1469
  //# sourceMappingURL=index.cjs.map