@t2000/sdk 4.2.0 → 4.2.2

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
@@ -678,7 +678,15 @@ async function fetchAllCoins(client, owner, coinType) {
678
678
  }
679
679
  async function selectAndSplitCoin(tx, client, owner, coinType, amount, options = {}) {
680
680
  if (options.sponsoredContext) {
681
- return selectCoinObjectsOnly(tx, client, owner, coinType, amount, options.allowSwapAll ?? true);
681
+ return selectCoinObjectsOnly(
682
+ tx,
683
+ client,
684
+ owner,
685
+ coinType,
686
+ amount,
687
+ options.allowSwapAll ?? true,
688
+ options.mergeCache
689
+ );
682
690
  }
683
691
  const balanceResp = await client.getBalance({ owner, coinType });
684
692
  const totalBalance = BigInt(balanceResp.totalBalance);
@@ -698,7 +706,23 @@ async function selectAndSplitCoin(tx, client, owner, coinType, amount, options =
698
706
  const coin = transactions.coinWithBalance({ type: coinType, balance: effectiveAmount })(tx);
699
707
  return { coin, effectiveAmount, swapAll };
700
708
  }
701
- async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowSwapAll) {
709
+ async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowSwapAll, mergeCache) {
710
+ const cached = mergeCache?.get(coinType);
711
+ if (cached) {
712
+ const requested2 = amount === "all" ? cached.remaining : amount;
713
+ if (cached.remaining === 0n || requested2 > cached.remaining) {
714
+ throw new exports.T2000Error(
715
+ "ADDRESS_BALANCE_UNSPONSORABLE",
716
+ `Not enough ${coinType} in coin objects to cover all legs of this sponsored bundle. The remaining funds are in your address balance, which sponsored transactions can't access yet.`,
717
+ { remaining: cached.remaining.toString(), requested: requested2.toString(), coinType }
718
+ );
719
+ }
720
+ const swapAll2 = amount === "all" || requested2 >= cached.remaining;
721
+ const effectiveAmount2 = swapAll2 ? cached.remaining : requested2;
722
+ const coin2 = swapAll2 ? cached.primary : tx.splitCoins(cached.primary, [effectiveAmount2])[0];
723
+ cached.remaining -= effectiveAmount2;
724
+ return { coin: coin2, effectiveAmount: effectiveAmount2, swapAll: swapAll2 };
725
+ }
702
726
  const objects = [];
703
727
  let coinObjectTotal = 0n;
704
728
  let cursor;
@@ -737,12 +761,16 @@ async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowS
737
761
  );
738
762
  }
739
763
  const coin = swapAll ? primary : tx.splitCoins(primary, [effectiveAmount])[0];
764
+ mergeCache?.set(coinType, {
765
+ primary,
766
+ remaining: coinObjectTotal - effectiveAmount
767
+ });
740
768
  return { coin, effectiveAmount, swapAll };
741
769
  }
742
- async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext) {
770
+ async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext, mergeCache) {
743
771
  if (sponsoredContext) {
744
772
  const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
745
- return selectCoinObjectsOnly(tx, client, owner, SUI_TYPE2, amountMist, false);
773
+ return selectCoinObjectsOnly(tx, client, owner, SUI_TYPE2, amountMist, false, mergeCache);
746
774
  }
747
775
  const [coin] = tx.splitCoins(tx.gas, [amountMist]);
748
776
  return { coin, effectiveAmount: amountMist, swapAll: false };
@@ -964,14 +992,16 @@ async function addSwapToTx(tx, client, address, input) {
964
992
  client,
965
993
  address,
966
994
  requestedRaw,
967
- input.sponsoredContext ?? false
995
+ input.sponsoredContext ?? false,
996
+ input.coinMergeCache
968
997
  );
969
998
  inputCoin = result.coin;
970
999
  effectiveRaw = result.effectiveAmount;
971
1000
  } else {
972
1001
  const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
973
1002
  const result = await selectAndSplitCoin2(tx, client, address, fromType, requestedRaw, {
974
- sponsoredContext: input.sponsoredContext ?? false
1003
+ sponsoredContext: input.sponsoredContext ?? false,
1004
+ mergeCache: input.coinMergeCache
975
1005
  });
976
1006
  inputCoin = result.coin;
977
1007
  effectiveRaw = result.effectiveAmount;
@@ -7952,7 +7982,8 @@ var WRITE_APPENDER_REGISTRY = {
7952
7982
  effectiveAmount = rawAmount;
7953
7983
  } else {
7954
7984
  const r = await selectAndSplitCoin(tx, ctx.client, ctx.sender, assetInfo.type, rawAmount, {
7955
- sponsoredContext: ctx.sponsoredContext
7985
+ sponsoredContext: ctx.sponsoredContext,
7986
+ mergeCache: ctx.coinMergeCache
7956
7987
  });
7957
7988
  coin = r.coin;
7958
7989
  effectiveAmount = r.effectiveAmount;
@@ -8026,7 +8057,8 @@ var WRITE_APPENDER_REGISTRY = {
8026
8057
  effectiveAmount = rawAmount;
8027
8058
  } else {
8028
8059
  const r = await selectAndSplitCoin(tx, ctx.client, ctx.sender, assetInfo.type, rawAmount, {
8029
- sponsoredContext: ctx.sponsoredContext
8060
+ sponsoredContext: ctx.sponsoredContext,
8061
+ mergeCache: ctx.coinMergeCache
8030
8062
  });
8031
8063
  coin = r.coin;
8032
8064
  effectiveAmount = r.effectiveAmount;
@@ -8070,7 +8102,14 @@ var WRITE_APPENDER_REGISTRY = {
8070
8102
  };
8071
8103
  }
8072
8104
  if (asset === "SUI") {
8073
- const result = await selectSuiCoin(tx, ctx.client, ctx.sender, rawAmount, ctx.sponsoredContext);
8105
+ const result = await selectSuiCoin(
8106
+ tx,
8107
+ ctx.client,
8108
+ ctx.sender,
8109
+ rawAmount,
8110
+ ctx.sponsoredContext,
8111
+ ctx.coinMergeCache
8112
+ );
8074
8113
  addSendToTx(tx, result.coin, recipient);
8075
8114
  return {
8076
8115
  preview: {
@@ -8132,7 +8171,8 @@ var WRITE_APPENDER_REGISTRY = {
8132
8171
  providers,
8133
8172
  inputCoin: ctx.chainedCoin,
8134
8173
  precomputedRoute: input.precomputedRoute,
8135
- sponsoredContext: ctx.sponsoredContext
8174
+ sponsoredContext: ctx.sponsoredContext,
8175
+ coinMergeCache: ctx.coinMergeCache
8136
8176
  });
8137
8177
  if (!ctx.isOutputConsumed) {
8138
8178
  tx.transferObjects([result.coin], ctx.sender);
@@ -8235,7 +8275,11 @@ async function composeTx(opts) {
8235
8275
  sender: opts.sender,
8236
8276
  sponsoredContext: opts.sponsoredContext ?? false,
8237
8277
  overlayFee: opts.overlayFee,
8238
- feeHooks: opts.feeHooks
8278
+ feeHooks: opts.feeHooks,
8279
+ // One cache per compose run — shared across all legs (any coin type)
8280
+ // so multi-leg sponsored bundles that source the same coin (two SUI
8281
+ // swaps, swap USDC + save USDC, ...) merge that coin's objects once.
8282
+ coinMergeCache: /* @__PURE__ */ new Map()
8239
8283
  };
8240
8284
  const consumedSteps = /* @__PURE__ */ new Set();
8241
8285
  for (let i = 0; i < opts.steps.length; i++) {