@trustware/sdk-staging 1.1.12-staging.1 → 1.1.12-staging.3

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
@@ -514,7 +514,7 @@ var init_constants = __esm({
514
514
  "src/constants.ts"() {
515
515
  "use strict";
516
516
  SDK_NAME = "@trustware/sdk";
517
- SDK_VERSION = "1.1.12-staging.1";
517
+ SDK_VERSION = "1.1.12-staging.3";
518
518
  API_ROOT = "https://bv-staging-api.trustware.io";
519
519
  GTM_ID = "GTM-TZDGNCXB";
520
520
  API_PREFIX = "/api";
@@ -5679,6 +5679,15 @@ function isNativeTokenAddress(address, chainType) {
5679
5679
  if (!chainType) return false;
5680
5680
  return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
5681
5681
  }
5682
+ function isEvmAddress2(value) {
5683
+ return !!value && EVM_ADDRESS_RE.test(value);
5684
+ }
5685
+ function needsErc20Approval(tokenAddress, chainType) {
5686
+ if (!isEvmAddress2(tokenAddress)) return false;
5687
+ const normalizedType = normalizeChainType2(chainType ?? void 0);
5688
+ if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
5689
+ return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
5690
+ }
5682
5691
  function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
5683
5692
  const chainType = normalizeChainType2(chain);
5684
5693
  const rawAddress = (address ?? "").trim();
@@ -5701,7 +5710,7 @@ function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
5701
5710
  }
5702
5711
  return lowerAddress;
5703
5712
  }
5704
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID;
5713
+ var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID, EVM_ADDRESS_RE, NON_EVM_CHAIN_TYPES;
5705
5714
  var init_chainHelpers = __esm({
5706
5715
  "src/widget/helpers/chainHelpers.ts"() {
5707
5716
  "use strict";
@@ -5717,6 +5726,8 @@ var init_chainHelpers = __esm({
5717
5726
  };
5718
5727
  SEI_EVM_CHAIN_ID = "1329";
5719
5728
  SEI_COSMOS_CHAIN_ID = "pacific-1";
5729
+ EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
5730
+ NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
5720
5731
  }
5721
5732
  });
5722
5733
 
@@ -31882,7 +31893,18 @@ async function sendRouteAsUserOperation(params) {
31882
31893
  );
31883
31894
  }
31884
31895
  console.debug("[send] UserOp included", { userOpHash, txHash });
31885
- await submitReceipt(intentId, txHash, getSponsorshipRequestId(), eoaAddress);
31896
+ try {
31897
+ void submitReceipt(
31898
+ intentId,
31899
+ txHash,
31900
+ getSponsorshipRequestId(),
31901
+ eoaAddress
31902
+ ).catch((err) => {
31903
+ console.debug("[send] receipt submission failed (non-fatal)", err);
31904
+ });
31905
+ } catch (err) {
31906
+ console.debug("[send] receipt submission failed (non-fatal)", err);
31907
+ }
31886
31908
  return { userOpHash, txHash, intentId };
31887
31909
  }
31888
31910
  var NATIVE_ADDRS;
@@ -33830,8 +33852,7 @@ function useSwapExecution(fromChain) {
33830
33852
  return;
33831
33853
  }
33832
33854
  const chainType = normalizeChainType2(fromChain);
33833
- const isNative = !fromTokenAddress || isNativeTokenAddress(fromTokenAddress, chainType) || isZeroAddrLike(fromTokenAddress, chainType);
33834
- if (isNative) {
33855
+ if (!needsErc20Approval(fromTokenAddress, chainType)) {
33835
33856
  setState((p) => ({ ...p, allowanceStatus: "sufficient" }));
33836
33857
  return;
33837
33858
  }
@@ -33845,7 +33866,7 @@ function useSwapExecution(fromChain) {
33845
33866
  BigInt(a.amount || "0"),
33846
33867
  amountWei
33847
33868
  );
33848
- if (!token || !a.spender) return [];
33869
+ if (!isEvmAddress2(token) || !isEvmAddress2(a.spender)) return [];
33849
33870
  return [
33850
33871
  {
33851
33872
  chainId: a.chainId || chainIdStr,
@@ -33993,7 +34014,8 @@ function useSwapExecution(fromChain) {
33993
34014
  const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33994
34015
  const token = a.tokenAddress ?? fromTokenAddress;
33995
34016
  const approvalSpender = a.spender;
33996
- if (!token || !approvalSpender) return [];
34017
+ if (!isEvmAddress2(token) || !isEvmAddress2(approvalSpender))
34018
+ return [];
33997
34019
  const amountWei = requiredApprovalAmount(
33998
34020
  BigInt(a.amount || "0"),
33999
34021
  fromAmountWei
@@ -34016,7 +34038,8 @@ function useSwapExecution(fromChain) {
34016
34038
  chainId: chainIdStr
34017
34039
  }
34018
34040
  ] : [];
34019
- const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
34041
+ const coversEveryPlannedApproval = plannedApprovals.length === 0 || requiredApprovals.length === plannedApprovals.length;
34042
+ const ownsApprovals = coversEveryPlannedApproval && needsErc20Approval(fromTokenAddress, chainType) && !!walletAddress && !!chainIdStr;
34020
34043
  const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
34021
34044
  for (const required of requiredApprovals) {
34022
34045
  if (!ownsApprovals) break;
@@ -34106,10 +34129,6 @@ function useSwapExecution(fromChain) {
34106
34129
  numericChainId,
34107
34130
  { approvalsEnsured: ownsApprovals }
34108
34131
  );
34109
- try {
34110
- await submitReceipt(routeResult.intentId, hash);
34111
- } catch {
34112
- }
34113
34132
  setState((p) => ({
34114
34133
  ...p,
34115
34134
  isSubmitting: false,
@@ -34118,6 +34137,8 @@ function useSwapExecution(fromChain) {
34118
34137
  txStatus: "processing"
34119
34138
  }));
34120
34139
  startPolling(routeResult.intentId, onSuccess, onError);
34140
+ void submitReceipt(routeResult.intentId, hash).catch(() => {
34141
+ });
34121
34142
  } catch (err) {
34122
34143
  const msg = mapTxError(err);
34123
34144
  setState((p) => ({
@@ -36199,6 +36220,10 @@ function SwapMode({
36199
36220
  }, [lockDestToken, fromToken, fromChain, toToken, toChain, route, emitEvent]);
36200
36221
  const fromChainType = normalizeChainType2(fromChain);
36201
36222
  const toChainType = normalizeChainType2(toChain);
36223
+ const canSetMaxApproval = needsErc20Approval(
36224
+ fromToken?.address,
36225
+ fromChainType
36226
+ );
36202
36227
  const needsDestAddress = !!fromChainType && !!toChainType && fromChainType !== toChainType;
36203
36228
  const isValidDestAddress = !needsDestAddress || validateDestAddress(destAddress, toChainType ?? "");
36204
36229
  const handleReview = (0, import_react50.useCallback)(async () => {
@@ -36553,6 +36578,7 @@ function SwapMode({
36553
36578
  }, [route.loading]);
36554
36579
  (0, import_react50.useEffect)(() => {
36555
36580
  if (!route.data) return;
36581
+ if (stage !== "home" && stage !== "review") return;
36556
36582
  const id = setInterval(() => {
36557
36583
  const ts = quoteTimestampRef.current;
36558
36584
  if (ts === null) return;
@@ -36564,7 +36590,11 @@ function SwapMode({
36564
36590
  }
36565
36591
  }, 1e3);
36566
36592
  return () => clearInterval(id);
36567
- }, [route.data]);
36593
+ }, [route.data, stage]);
36594
+ const handleRetryQuote = (0, import_react50.useCallback)(() => {
36595
+ if (!latestFetchParamsRef.current) return;
36596
+ void fetchRef.current(latestFetchParamsRef.current);
36597
+ }, []);
36568
36598
  (0, import_react50.useEffect)(() => {
36569
36599
  if (stage !== "review") return;
36570
36600
  if (!route.data || !walletAddress) return;
@@ -38093,6 +38123,10 @@ function SwapMode({
38093
38123
  txStatus: execution.txStatus,
38094
38124
  isSubmitting: execution.isSubmitting,
38095
38125
  isGasSponsored,
38126
+ hasQuote: !!route.data,
38127
+ isQuoteRefreshing: route.loading,
38128
+ quoteError: route.error,
38129
+ onRetryQuote: handleRetryQuote,
38096
38130
  onExecute: () => void handleExecute()
38097
38131
  }
38098
38132
  )
@@ -38410,7 +38444,7 @@ function SwapMode({
38410
38444
  }
38411
38445
  )
38412
38446
  ] }),
38413
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
38447
+ canSetMaxApproval && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
38414
38448
  "div",
38415
38449
  {
38416
38450
  style: {
@@ -39429,10 +39463,15 @@ function SwapActionArea({
39429
39463
  txStatus,
39430
39464
  isSubmitting,
39431
39465
  isGasSponsored,
39466
+ hasQuote,
39467
+ isQuoteRefreshing,
39468
+ quoteError,
39469
+ onRetryQuote,
39432
39470
  onExecute
39433
39471
  }) {
39434
39472
  const needsApproval = allowanceStatus === "needed" && !isGasSponsored;
39435
39473
  const isChecking = allowanceStatus === "checking";
39474
+ const quoteUnavailable = !hasQuote && !isQuoteRefreshing && !isSubmitting && txStatus === "idle";
39436
39475
  let label;
39437
39476
  if (isChecking) {
39438
39477
  label = "Checking approval...";
@@ -39440,12 +39479,14 @@ function SwapActionArea({
39440
39479
  label = `Approving ${fromTokenSymbol}...`;
39441
39480
  } else if (isSubmitting) {
39442
39481
  label = "Confirm in wallet...";
39482
+ } else if (isQuoteRefreshing) {
39483
+ label = "Refreshing quote...";
39443
39484
  } else if (needsApproval) {
39444
39485
  label = `Approve ${fromTokenSymbol}`;
39445
39486
  } else {
39446
39487
  label = "Swap";
39447
39488
  }
39448
- const isDisabled = isSubmitting || isChecking;
39489
+ const isDisabled = isSubmitting || isChecking || isQuoteRefreshing || !hasQuote;
39449
39490
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { style: { marginTop: spacing[6] }, children: [
39450
39491
  isGasSponsored && !isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
39451
39492
  "div",
@@ -39485,7 +39526,38 @@ function SwapActionArea({
39485
39526
  ]
39486
39527
  }
39487
39528
  ),
39488
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
39529
+ quoteUnavailable ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
39530
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
39531
+ "p",
39532
+ {
39533
+ style: {
39534
+ fontSize: fontSize.xs,
39535
+ color: colors.destructive,
39536
+ textAlign: "center",
39537
+ marginBottom: spacing[3]
39538
+ },
39539
+ children: quoteError ?? "This quote expired."
39540
+ }
39541
+ ),
39542
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
39543
+ "button",
39544
+ {
39545
+ onClick: onRetryQuote,
39546
+ style: {
39547
+ width: "100%",
39548
+ height: "3.5rem",
39549
+ borderRadius: "1.5rem",
39550
+ backgroundColor: colors.primary,
39551
+ color: colors.primaryForeground,
39552
+ fontSize: fontSize.base,
39553
+ fontWeight: fontWeight.semibold,
39554
+ border: 0,
39555
+ cursor: "pointer"
39556
+ },
39557
+ children: "Get a new quote"
39558
+ }
39559
+ )
39560
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
39489
39561
  "button",
39490
39562
  {
39491
39563
  onClick: onExecute,