@mysten/sui 2.14.1 → 2.16.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/bcs/bcs.d.mts +6 -6
  3. package/dist/bcs/index.d.mts +20 -20
  4. package/dist/client/mvr.d.mts.map +1 -1
  5. package/dist/client/mvr.mjs +3 -0
  6. package/dist/client/mvr.mjs.map +1 -1
  7. package/dist/grpc/index.d.mts +3 -1
  8. package/dist/grpc/index.mjs +2 -1
  9. package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
  10. package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
  11. package/dist/transactions/Transaction.d.mts +9 -9
  12. package/dist/transactions/Transaction.d.mts.map +1 -1
  13. package/dist/transactions/data/v1.d.mts +220 -220
  14. package/dist/transactions/data/v1.d.mts.map +1 -1
  15. package/dist/transactions/data/v2.d.mts +16 -16
  16. package/dist/transactions/data/v2.d.mts.map +1 -1
  17. package/dist/transactions/intents/CoinWithBalance.mjs +35 -5
  18. package/dist/transactions/intents/CoinWithBalance.mjs.map +1 -1
  19. package/dist/utils/format.d.mts +5 -1
  20. package/dist/utils/format.d.mts.map +1 -1
  21. package/dist/utils/format.mjs +19 -1
  22. package/dist/utils/format.mjs.map +1 -1
  23. package/dist/utils/index.d.mts +2 -2
  24. package/dist/utils/index.mjs +2 -2
  25. package/dist/version.mjs +2 -2
  26. package/dist/version.mjs.map +1 -1
  27. package/dist/zklogin/bcs.d.mts +14 -14
  28. package/dist/zklogin/bcs.d.mts.map +1 -1
  29. package/docs/clients/grpc.md +55 -2
  30. package/docs/llms-index.md +5 -5
  31. package/docs/utils/index.md +7 -0
  32. package/package.json +4 -2
  33. package/src/client/mvr.ts +12 -0
  34. package/src/grpc/index.ts +6 -0
  35. package/src/transactions/intents/CoinWithBalance.ts +41 -6
  36. package/src/utils/format.ts +36 -0
  37. package/src/utils/index.ts +1 -1
  38. package/src/version.ts +2 -2
@@ -140,6 +140,12 @@ export async function resolveCoinBalance(
140
140
  intentsByType.get(type)!.push({ balance, outputKind: outputKind ?? 'coin' });
141
141
  }
142
142
 
143
+ if (totalByType.has('gas') && totalByType.has(SUI_TYPE)) {
144
+ throw new Error(
145
+ 'Cannot mix SUI CoinWithBalance intents that use the gas coin with ones that do not (useGasCoin: false). Use one or the other.',
146
+ );
147
+ }
148
+
143
149
  const usedIds = new Set<string>();
144
150
 
145
151
  for (const input of transactionData.inputs) {
@@ -188,6 +194,7 @@ export async function resolveCoinBalance(
188
194
 
189
195
  const mergedCoins = new Map<string, Argument>();
190
196
  const exactBalanceByType = new Map<string, boolean>();
197
+ const usedAddressBalance = new Set<string>();
191
198
 
192
199
  // Per-type state for Path 2 combined splits
193
200
  type TypeState = { results: Argument[]; nextIntent: number };
@@ -251,7 +258,31 @@ export async function resolveCoinBalance(
251
258
  // Step 1: Build sources and merge
252
259
  const sources: Argument[] = [];
253
260
 
254
- if (type === 'gas') {
261
+ if (addressBalance >= totalRequired) {
262
+ // AB sufficient — source entirely from address balance, no coins needed.
263
+ usedAddressBalance.add(type);
264
+
265
+ commands.push(
266
+ TransactionCommands.MoveCall({
267
+ target: '0x2::coin::redeem_funds',
268
+ typeArguments: [coinType],
269
+ arguments: [
270
+ transactionData.addInput(
271
+ 'withdrawal',
272
+ Inputs.FundsWithdrawal({
273
+ reservation: {
274
+ $kind: 'MaxAmountU64',
275
+ MaxAmountU64: String(totalRequired),
276
+ },
277
+ typeArg: { $kind: 'Balance', Balance: coinType },
278
+ withdrawFrom: { $kind: 'Sender', Sender: true },
279
+ }),
280
+ ),
281
+ ],
282
+ }),
283
+ );
284
+ sources.push({ $kind: 'Result', Result: index + commands.length - 1 });
285
+ } else if (type === 'gas') {
255
286
  sources.push({ $kind: 'GasCoin', GasCoin: true });
256
287
  } else {
257
288
  const coins = coinsByType.get(type)!;
@@ -275,6 +306,7 @@ export async function resolveCoinBalance(
275
306
  }
276
307
 
277
308
  if (abNeeded > 0n) {
309
+ usedAddressBalance.add(type);
278
310
  commands.push(
279
311
  TransactionCommands.MoveCall({
280
312
  target: '0x2::coin::redeem_funds',
@@ -363,17 +395,20 @@ export async function resolveCoinBalance(
363
395
 
364
396
  // Step 3: Remainder handling
365
397
  for (const [type, mergedCoin] of mergedCoins) {
366
- if (type === 'gas') continue;
398
+ // When gas type used GasCoin (not AB), leftover stays in the gas coin — no remainder needed.
399
+ if (type === 'gas' && !usedAddressBalance.has(type)) continue;
367
400
 
401
+ const coinType = type === 'gas' ? SUI_TYPE : type;
368
402
  const hasBalanceIntent = intentsByType.get(type)?.some((i) => i.outputKind === 'balance');
403
+ const sourcedFromAB = usedAddressBalance.has(type);
369
404
 
370
- if (hasBalanceIntent) {
371
- // Balance intents exist: send remainder coin back to sender's address balance.
405
+ if (hasBalanceIntent || sourcedFromAB) {
406
+ // Sourced from AB or balance intents exist: send remainder back to sender's address balance.
372
407
  // coin::send_funds is gasless-eligible and handles zero amounts.
373
408
  transactionData.commands.push(
374
409
  TransactionCommands.MoveCall({
375
410
  target: '0x2::coin::send_funds',
376
- typeArguments: [type],
411
+ typeArguments: [coinType],
377
412
  arguments: [
378
413
  mergedCoin,
379
414
  transactionData.addInput(
@@ -388,7 +423,7 @@ export async function resolveCoinBalance(
388
423
  transactionData.commands.push(
389
424
  TransactionCommands.MoveCall({
390
425
  target: '0x2::coin::destroy_zero',
391
- typeArguments: [type],
426
+ typeArguments: [coinType],
392
427
  arguments: [mergedCoin],
393
428
  }),
394
429
  );
@@ -1,6 +1,8 @@
1
1
  // Copyright (c) Mysten Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { SUI_DECIMALS } from './constants.js';
5
+
4
6
  const ELLIPSIS = '\u{2026}';
5
7
 
6
8
  export function formatAddress(address: string) {
@@ -17,3 +19,37 @@ export function formatDigest(digest: string) {
17
19
  // Use 10 first characters
18
20
  return `${digest.slice(0, 10)}${ELLIPSIS}`;
19
21
  }
22
+
23
+ const AMOUNT_REGEX = /^-?(?:[0-9]+(?:\.[0-9]+)?|\.[0-9]+)$/;
24
+
25
+ /** Parse a decimal string into its smallest-unit bigint representation. No floating point. */
26
+ export function parseToUnits(amount: string, decimals: number): bigint {
27
+ if (decimals < 0 || !Number.isInteger(decimals)) {
28
+ throw new Error(`Invalid decimals: ${decimals}`);
29
+ }
30
+
31
+ if (!AMOUNT_REGEX.test(amount)) {
32
+ throw new Error(`Invalid amount: "${amount}"`);
33
+ }
34
+
35
+ const negative = amount.startsWith('-');
36
+ const stripped = negative ? amount.slice(1) : amount;
37
+
38
+ const [whole, fraction = ''] = stripped.split('.');
39
+
40
+ if (fraction.length > decimals) {
41
+ throw new Error(
42
+ `Too many decimal places: "${amount}" has ${fraction.length} but max is ${decimals}`,
43
+ );
44
+ }
45
+
46
+ const paddedFraction = fraction.padEnd(decimals, '0') || '0';
47
+ const result = BigInt(whole || '0') * 10n ** BigInt(decimals) + BigInt(paddedFraction);
48
+
49
+ return negative ? -result : result;
50
+ }
51
+
52
+ /** Parse a SUI decimal string into MIST. */
53
+ export function parseToMist(amount: string): bigint {
54
+ return parseToUnits(amount, SUI_DECIMALS);
55
+ }
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Mysten Labs, Inc.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- export { formatAddress, formatDigest } from './format.js';
4
+ export { formatAddress, formatDigest, parseToUnits, parseToMist } from './format.js';
5
5
  export {
6
6
  isValidStructTag,
7
7
  isValidSuiAddress,
package/src/version.ts CHANGED
@@ -3,5 +3,5 @@
3
3
 
4
4
  // This file is generated by genversion.mjs. Do not edit it directly.
5
5
 
6
- export const PACKAGE_VERSION = '2.14.1';
7
- export const TARGETED_RPC_VERSION = '1.70.0';
6
+ export const PACKAGE_VERSION = '2.16.0';
7
+ export const TARGETED_RPC_VERSION = '1.71.0';