@rhinestone/deposit-modal 0.1.60 → 0.1.62

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.
@@ -809,6 +809,16 @@ function formatUserError(raw) {
809
809
  return cleaned;
810
810
  }
811
811
 
812
+ // src/core/useLatestRef.ts
813
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
814
+ function useLatestRef(value) {
815
+ const ref = useRef2(value);
816
+ useEffect2(() => {
817
+ ref.current = value;
818
+ }, [value]);
819
+ return ref;
820
+ }
821
+
812
822
  // src/core/theme.ts
813
823
  var RADIUS_SCALE = {
814
824
  none: { sm: "0", md: "0", lg: "0" },
@@ -1262,7 +1272,7 @@ function accountFromPrivateKey(privateKey) {
1262
1272
  }
1263
1273
 
1264
1274
  // src/components/steps/ProcessingStep.tsx
1265
- import { useEffect as useEffect2, useRef as useRef2, useState } from "react";
1275
+ import { useEffect as useEffect3, useRef as useRef3, useState } from "react";
1266
1276
  import { formatUnits } from "viem";
1267
1277
 
1268
1278
  // src/components/ui/PoweredBy.tsx
@@ -1529,10 +1539,10 @@ function ProcessingStep({
1529
1539
  onDepositFailed,
1530
1540
  onError
1531
1541
  }) {
1532
- const startTimeRef = useRef2(Date.now());
1533
- const pollIntervalRef = useRef2(INITIAL_POLL_INTERVAL);
1534
- const pollTimeoutRef = useRef2(null);
1535
- const escalatedDelayRef = useRef2(false);
1542
+ const startTimeRef = useRef3(Date.now());
1543
+ const pollIntervalRef = useRef3(INITIAL_POLL_INTERVAL);
1544
+ const pollTimeoutRef = useRef3(null);
1545
+ const escalatedDelayRef = useRef3(false);
1536
1546
  const [state, setState] = useState(
1537
1547
  directTransfer ? { type: "complete" } : { type: "processing" }
1538
1548
  );
@@ -1546,7 +1556,7 @@ function ProcessingStep({
1546
1556
  return { startedAt: startTimeRef.current };
1547
1557
  });
1548
1558
  const [hasEscalatedDelay, setHasEscalatedDelay] = useState(false);
1549
- useEffect2(() => {
1559
+ useEffect3(() => {
1550
1560
  if (!directTransfer) return;
1551
1561
  const completedAt = Date.now();
1552
1562
  setPhaseTimings({
@@ -1577,7 +1587,7 @@ function ProcessingStep({
1577
1587
  targetToken,
1578
1588
  txHash
1579
1589
  ]);
1580
- useEffect2(() => {
1590
+ useEffect3(() => {
1581
1591
  if (directTransfer || state.type !== "processing") return;
1582
1592
  const updateElapsed = () => {
1583
1593
  setElapsedSeconds(
@@ -1588,7 +1598,7 @@ function ProcessingStep({
1588
1598
  const intervalId = setInterval(updateElapsed, 1e3);
1589
1599
  return () => clearInterval(intervalId);
1590
1600
  }, [directTransfer, state.type]);
1591
- useEffect2(() => {
1601
+ useEffect3(() => {
1592
1602
  if (state.type === "processing") return;
1593
1603
  const endedAt = state.type === "complete" ? phaseTimings.completedAt ?? Date.now() : Date.now();
1594
1604
  setElapsedSeconds(Math.floor((endedAt - startTimeRef.current) / 1e3));
@@ -1596,14 +1606,14 @@ function ProcessingStep({
1596
1606
  (previous) => previous.endedAt !== void 0 ? previous : { ...previous, endedAt }
1597
1607
  );
1598
1608
  }, [phaseTimings.completedAt, state.type]);
1599
- useEffect2(() => {
1609
+ useEffect3(() => {
1600
1610
  if (!state.lastEvent) return;
1601
1611
  setPhaseTimings((previous) => syncPhaseTimings(previous, state.lastEvent));
1602
1612
  }, [state.lastEvent?.time, state.lastEvent?.type]);
1603
- useEffect2(() => {
1613
+ useEffect3(() => {
1604
1614
  savePhaseTimings(txHash, phaseTimings);
1605
1615
  }, [txHash, phaseTimings]);
1606
- useEffect2(() => {
1616
+ useEffect3(() => {
1607
1617
  if (directTransfer) return;
1608
1618
  if (state.type !== "processing") {
1609
1619
  pollIntervalRef.current = INITIAL_POLL_INTERVAL;
@@ -1741,7 +1751,7 @@ function ProcessingStep({
1741
1751
  txHash,
1742
1752
  waitForFinalTx
1743
1753
  ]);
1744
- useEffect2(() => {
1754
+ useEffect3(() => {
1745
1755
  if (directTransfer || state.type !== "processing") return;
1746
1756
  const timeoutId = setTimeout(() => {
1747
1757
  if (escalatedDelayRef.current) return;
@@ -2094,5 +2104,6 @@ export {
2094
2104
  txRefsMatch,
2095
2105
  ProcessingStep,
2096
2106
  getPublicClient,
2107
+ useLatestRef,
2097
2108
  applyTheme
2098
2109
  };
@@ -24,8 +24,9 @@ import {
24
24
  saveSessionOwnerToStorage,
25
25
  toEvmCaip2,
26
26
  tokenFormatter,
27
- txRefsMatch
28
- } from "./chunk-7TTEHQBD.mjs";
27
+ txRefsMatch,
28
+ useLatestRef
29
+ } from "./chunk-NDTY5AUU.mjs";
29
30
  import {
30
31
  DEFAULT_BACKEND_URL,
31
32
  DEFAULT_SIGNER_ADDRESS,
@@ -2592,6 +2593,9 @@ function DepositFlow({
2592
2593
  onError,
2593
2594
  debug
2594
2595
  }) {
2596
+ const onStepChangeRef = useLatestRef(onStepChange);
2597
+ const onTotalBalanceChangeRef = useLatestRef(onTotalBalanceChange);
2598
+ const onEventRef = useLatestRef(onEvent);
2595
2599
  const hasInitialReownSession = Boolean(
2596
2600
  enableSolana ? reownWallet?.isConnected || reownWallet?.address : reownWallet?.address
2597
2601
  );
@@ -2916,11 +2920,22 @@ function DepositFlow({
2916
2920
  const stepIndex = step.type === "setup" ? 0 : step.type === "deposit-address" ? 1 : step.type === "select-asset" ? 1 : step.type === "solana-token-select" ? 1 : step.type === "solana-amount" ? 2 : step.type === "amount" ? 2 : step.type === "confirm" ? 3 : step.type === "solana-confirm" ? 3 : 4;
2917
2921
  const currentBackHandler = step.type === "deposit-address" ? handleBackFromDepositAddress : step.type === "select-asset" && signerContext && !canAutoLock ? handleBackFromSelectAsset : step.type === "solana-token-select" ? handleBackFromSolanaTokenSelect : step.type === "solana-amount" ? handleBackFromSolanaAmount : step.type === "solana-confirm" ? handleBackFromSolanaConfirm : step.type === "amount" ? handleBackFromAmount : step.type === "confirm" ? handleBackFromConfirm : void 0;
2918
2922
  useEffect9(() => {
2919
- onStepChange?.(stepIndex, currentBackHandler);
2920
- }, [stepIndex, currentBackHandler, onStepChange]);
2923
+ onStepChangeRef.current?.(stepIndex, currentBackHandler);
2924
+ }, [stepIndex, currentBackHandler, onStepChangeRef]);
2925
+ const stepSendToken = step.type === "amount" ? step.asset.symbol : null;
2926
+ const stepOpenEventKey = step.type === "select-asset" ? "select-asset" : step.type === "deposit-address" ? "deposit-address" : step.type === "amount" && stepSendToken ? `amount:${stepSendToken.toLowerCase()}` : null;
2927
+ const lastStepOpenEventKeyRef = useRef5(null);
2921
2928
  useEffect9(() => {
2929
+ if (!stepOpenEventKey) {
2930
+ lastStepOpenEventKeyRef.current = null;
2931
+ return;
2932
+ }
2933
+ if (lastStepOpenEventKeyRef.current === stepOpenEventKey) {
2934
+ return;
2935
+ }
2936
+ lastStepOpenEventKeyRef.current = stepOpenEventKey;
2922
2937
  if (step.type === "select-asset") {
2923
- onEvent?.({
2938
+ onEventRef.current?.({
2924
2939
  type: "deposit_modal_connected_wallet_select_source_open",
2925
2940
  total_balance_in_external_wallet: totalBalanceUsd,
2926
2941
  pred_balance: totalBalanceUsd
@@ -2928,22 +2943,30 @@ function DepositFlow({
2928
2943
  } else if (step.type === "deposit-address") {
2929
2944
  const chainName = getChainName(targetChain);
2930
2945
  const tokenSymbol = getTokenSymbol(targetToken, targetChain);
2931
- onEvent?.({
2946
+ onEventRef.current?.({
2932
2947
  type: "deposit_modal_transfer_crypto_open",
2933
2948
  default_chain: chainName,
2934
2949
  default_token: tokenSymbol,
2935
2950
  pred_balance: totalBalanceUsd
2936
2951
  });
2937
- } else if (step.type === "amount") {
2952
+ } else if (step.type === "amount" && stepSendToken) {
2938
2953
  const receiveSymbol = getTokenSymbol(targetToken, targetChain);
2939
- onEvent?.({
2954
+ onEventRef.current?.({
2940
2955
  type: "deposit_modal_connected_wallet_enter_value_open",
2941
- send_token: step.asset.symbol,
2956
+ send_token: stepSendToken,
2942
2957
  receive_token: receiveSymbol,
2943
2958
  pred_balance: totalBalanceUsd
2944
2959
  });
2945
2960
  }
2946
- }, [step, onEvent, totalBalanceUsd, targetChain, targetToken]);
2961
+ }, [
2962
+ step.type,
2963
+ stepOpenEventKey,
2964
+ stepSendToken,
2965
+ targetChain,
2966
+ targetToken,
2967
+ totalBalanceUsd,
2968
+ onEventRef
2969
+ ]);
2947
2970
  useEffect9(() => {
2948
2971
  logFlow("state:changed", {
2949
2972
  step: step.type,
@@ -2961,8 +2984,8 @@ function DepositFlow({
2961
2984
  targetToken
2962
2985
  ]);
2963
2986
  useEffect9(() => {
2964
- onTotalBalanceChange?.(totalBalanceUsd);
2965
- }, [totalBalanceUsd, onTotalBalanceChange]);
2987
+ onTotalBalanceChangeRef.current?.(totalBalanceUsd);
2988
+ }, [totalBalanceUsd, onTotalBalanceChangeRef]);
2966
2989
  const isDepositAddressMode = flowMode === "deposit-address";
2967
2990
  const isSolanaWalletMode = flowMode === "solana-wallet";
2968
2991
  const handleSelectProvider = useCallback3(() => {
@@ -3639,7 +3662,7 @@ function DepositFlow({
3639
3662
  // src/DepositModal.tsx
3640
3663
  import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
3641
3664
  var ReownDepositInner = lazy(
3642
- () => import("./DepositModalReown-S24YS35X.mjs").then((m) => ({ default: m.DepositModalReown }))
3665
+ () => import("./DepositModalReown-5CFJIJO5.mjs").then((m) => ({ default: m.DepositModalReown }))
3643
3666
  );
3644
3667
  function DepositModal(props) {
3645
3668
  const needsReown = !!props.reownAppId;
@@ -3708,6 +3731,7 @@ function DepositModalInner({
3708
3731
  debug
3709
3732
  }) {
3710
3733
  const modalRef = useRef6(null);
3734
+ const onReadyRef = useLatestRef(onReady);
3711
3735
  const [currentStepIndex, setCurrentStepIndex] = useState11(0);
3712
3736
  const [totalBalanceUsd, setTotalBalanceUsd] = useState11(null);
3713
3737
  const backHandlerRef = useRef6(void 0);
@@ -3732,9 +3756,9 @@ function DepositModalInner({
3732
3756
  useEffect10(() => {
3733
3757
  if (isOpen && !hasCalledReady.current) {
3734
3758
  hasCalledReady.current = true;
3735
- onReady?.();
3759
+ onReadyRef.current?.();
3736
3760
  }
3737
- }, [isOpen, onReady]);
3761
+ }, [isOpen, onReadyRef]);
3738
3762
  useEffect10(() => {
3739
3763
  if (!isOpen) {
3740
3764
  setCurrentStepIndex(0);
package/dist/deposit.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkHX7LLE2Vcjs = require('./chunk-HX7LLE2V.cjs');
4
- require('./chunk-TQ6IIGRS.cjs');
3
+ var _chunk6UBIFHRVcjs = require('./chunk-6UBIFHRV.cjs');
4
+ require('./chunk-MVFMDKAS.cjs');
5
5
  require('./chunk-R6U6BHCV.cjs');
6
6
 
7
7
 
8
- exports.DepositModal = _chunkHX7LLE2Vcjs.DepositModal;
8
+ exports.DepositModal = _chunk6UBIFHRVcjs.DepositModal;
package/dist/deposit.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DepositModal
3
- } from "./chunk-6SM3IQKZ.mjs";
4
- import "./chunk-7TTEHQBD.mjs";
3
+ } from "./chunk-QME5ZAI6.mjs";
4
+ import "./chunk-NDTY5AUU.mjs";
5
5
  import "./chunk-CIXHTOO3.mjs";
6
6
  export {
7
7
  DepositModal
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkHX7LLE2Vcjs = require('./chunk-HX7LLE2V.cjs');
3
+ var _chunk6UBIFHRVcjs = require('./chunk-6UBIFHRV.cjs');
4
4
 
5
5
 
6
- var _chunk3CANBYBNcjs = require('./chunk-3CANBYBN.cjs');
7
- require('./chunk-TQ6IIGRS.cjs');
6
+ var _chunkMKU7VETPcjs = require('./chunk-MKU7VETP.cjs');
7
+ require('./chunk-MVFMDKAS.cjs');
8
8
 
9
9
 
10
10
 
@@ -66,4 +66,4 @@ var _chunkR6U6BHCVcjs = require('./chunk-R6U6BHCV.cjs');
66
66
 
67
67
 
68
68
 
69
- exports.CHAIN_BY_ID = _chunkR6U6BHCVcjs.CHAIN_BY_ID; exports.DEFAULT_BACKEND_URL = _chunkR6U6BHCVcjs.DEFAULT_BACKEND_URL; exports.DEFAULT_SIGNER_ADDRESS = _chunkR6U6BHCVcjs.DEFAULT_SIGNER_ADDRESS; exports.DepositModal = _chunkHX7LLE2Vcjs.DepositModal; exports.NATIVE_TOKEN_ADDRESS = _chunkR6U6BHCVcjs.NATIVE_TOKEN_ADDRESS; exports.SOURCE_CHAINS = _chunkR6U6BHCVcjs.SOURCE_CHAINS; exports.SUPPORTED_CHAINS = _chunkR6U6BHCVcjs.SUPPORTED_CHAINS; exports.WithdrawModal = _chunk3CANBYBNcjs.WithdrawModal; exports.chainRegistry = _chunkR6U6BHCVcjs.chainRegistry; exports.findChainIdForToken = _chunkR6U6BHCVcjs.findChainIdForToken; exports.getChainBadge = _chunkR6U6BHCVcjs.getChainBadge; exports.getChainIcon = _chunkR6U6BHCVcjs.getChainIcon; exports.getChainId = _chunkR6U6BHCVcjs.getChainId; exports.getChainName = _chunkR6U6BHCVcjs.getChainName; exports.getChainObject = _chunkR6U6BHCVcjs.getChainObject; exports.getExplorerName = _chunkR6U6BHCVcjs.getExplorerName; exports.getExplorerTxUrl = _chunkR6U6BHCVcjs.getExplorerTxUrl; exports.getExplorerUrl = _chunkR6U6BHCVcjs.getExplorerUrl; exports.getSupportedChainIds = _chunkR6U6BHCVcjs.getSupportedChainIds; exports.getSupportedTargetTokens = _chunkR6U6BHCVcjs.getSupportedTargetTokens; exports.getSupportedTokenSymbolsForChain = _chunkR6U6BHCVcjs.getSupportedTokenSymbolsForChain; exports.getTargetTokenSymbolsForChain = _chunkR6U6BHCVcjs.getTargetTokenSymbolsForChain; exports.getTokenAddress = _chunkR6U6BHCVcjs.getTokenAddress; exports.getTokenDecimals = _chunkR6U6BHCVcjs.getTokenDecimals; exports.getTokenDecimalsByAddress = _chunkR6U6BHCVcjs.getTokenDecimalsByAddress; exports.getTokenIcon = _chunkR6U6BHCVcjs.getTokenIcon; exports.getTokenSymbol = _chunkR6U6BHCVcjs.getTokenSymbol; exports.getUsdcAddress = _chunkR6U6BHCVcjs.getUsdcAddress; exports.getUsdcDecimals = _chunkR6U6BHCVcjs.getUsdcDecimals; exports.isSupportedTokenAddressForChain = _chunkR6U6BHCVcjs.isSupportedTokenAddressForChain;
69
+ exports.CHAIN_BY_ID = _chunkR6U6BHCVcjs.CHAIN_BY_ID; exports.DEFAULT_BACKEND_URL = _chunkR6U6BHCVcjs.DEFAULT_BACKEND_URL; exports.DEFAULT_SIGNER_ADDRESS = _chunkR6U6BHCVcjs.DEFAULT_SIGNER_ADDRESS; exports.DepositModal = _chunk6UBIFHRVcjs.DepositModal; exports.NATIVE_TOKEN_ADDRESS = _chunkR6U6BHCVcjs.NATIVE_TOKEN_ADDRESS; exports.SOURCE_CHAINS = _chunkR6U6BHCVcjs.SOURCE_CHAINS; exports.SUPPORTED_CHAINS = _chunkR6U6BHCVcjs.SUPPORTED_CHAINS; exports.WithdrawModal = _chunkMKU7VETPcjs.WithdrawModal; exports.chainRegistry = _chunkR6U6BHCVcjs.chainRegistry; exports.findChainIdForToken = _chunkR6U6BHCVcjs.findChainIdForToken; exports.getChainBadge = _chunkR6U6BHCVcjs.getChainBadge; exports.getChainIcon = _chunkR6U6BHCVcjs.getChainIcon; exports.getChainId = _chunkR6U6BHCVcjs.getChainId; exports.getChainName = _chunkR6U6BHCVcjs.getChainName; exports.getChainObject = _chunkR6U6BHCVcjs.getChainObject; exports.getExplorerName = _chunkR6U6BHCVcjs.getExplorerName; exports.getExplorerTxUrl = _chunkR6U6BHCVcjs.getExplorerTxUrl; exports.getExplorerUrl = _chunkR6U6BHCVcjs.getExplorerUrl; exports.getSupportedChainIds = _chunkR6U6BHCVcjs.getSupportedChainIds; exports.getSupportedTargetTokens = _chunkR6U6BHCVcjs.getSupportedTargetTokens; exports.getSupportedTokenSymbolsForChain = _chunkR6U6BHCVcjs.getSupportedTokenSymbolsForChain; exports.getTargetTokenSymbolsForChain = _chunkR6U6BHCVcjs.getTargetTokenSymbolsForChain; exports.getTokenAddress = _chunkR6U6BHCVcjs.getTokenAddress; exports.getTokenDecimals = _chunkR6U6BHCVcjs.getTokenDecimals; exports.getTokenDecimalsByAddress = _chunkR6U6BHCVcjs.getTokenDecimalsByAddress; exports.getTokenIcon = _chunkR6U6BHCVcjs.getTokenIcon; exports.getTokenSymbol = _chunkR6U6BHCVcjs.getTokenSymbol; exports.getUsdcAddress = _chunkR6U6BHCVcjs.getUsdcAddress; exports.getUsdcDecimals = _chunkR6U6BHCVcjs.getUsdcDecimals; exports.isSupportedTokenAddressForChain = _chunkR6U6BHCVcjs.isSupportedTokenAddressForChain;
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  DepositModal
3
- } from "./chunk-6SM3IQKZ.mjs";
3
+ } from "./chunk-QME5ZAI6.mjs";
4
4
  import {
5
5
  WithdrawModal
6
- } from "./chunk-JJMPCRKB.mjs";
7
- import "./chunk-7TTEHQBD.mjs";
6
+ } from "./chunk-7YERRXZ4.mjs";
7
+ import "./chunk-NDTY5AUU.mjs";
8
8
  import {
9
9
  CHAIN_BY_ID,
10
10
  DEFAULT_BACKEND_URL,
package/dist/reown.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkHX7LLE2Vcjs = require('./chunk-HX7LLE2V.cjs');
3
+ var _chunk6UBIFHRVcjs = require('./chunk-6UBIFHRV.cjs');
4
4
 
5
5
 
6
- var _chunk3CANBYBNcjs = require('./chunk-3CANBYBN.cjs');
7
- require('./chunk-TQ6IIGRS.cjs');
6
+ var _chunkMKU7VETPcjs = require('./chunk-MKU7VETP.cjs');
7
+ require('./chunk-MVFMDKAS.cjs');
8
8
  require('./chunk-R6U6BHCV.cjs');
9
9
 
10
10
 
11
11
 
12
- exports.DepositModal = _chunkHX7LLE2Vcjs.DepositModal; exports.WithdrawModal = _chunk3CANBYBNcjs.WithdrawModal;
12
+ exports.DepositModal = _chunk6UBIFHRVcjs.DepositModal; exports.WithdrawModal = _chunkMKU7VETPcjs.WithdrawModal;
package/dist/reown.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  DepositModal
3
- } from "./chunk-6SM3IQKZ.mjs";
3
+ } from "./chunk-QME5ZAI6.mjs";
4
4
  import {
5
5
  WithdrawModal
6
- } from "./chunk-JJMPCRKB.mjs";
7
- import "./chunk-7TTEHQBD.mjs";
6
+ } from "./chunk-7YERRXZ4.mjs";
7
+ import "./chunk-NDTY5AUU.mjs";
8
8
  import "./chunk-CIXHTOO3.mjs";
9
9
  export {
10
10
  DepositModal,
package/dist/withdraw.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk3CANBYBNcjs = require('./chunk-3CANBYBN.cjs');
4
- require('./chunk-TQ6IIGRS.cjs');
3
+ var _chunkMKU7VETPcjs = require('./chunk-MKU7VETP.cjs');
4
+ require('./chunk-MVFMDKAS.cjs');
5
5
  require('./chunk-R6U6BHCV.cjs');
6
6
 
7
7
 
8
- exports.WithdrawModal = _chunk3CANBYBNcjs.WithdrawModal;
8
+ exports.WithdrawModal = _chunkMKU7VETPcjs.WithdrawModal;
package/dist/withdraw.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  WithdrawModal
3
- } from "./chunk-JJMPCRKB.mjs";
4
- import "./chunk-7TTEHQBD.mjs";
3
+ } from "./chunk-7YERRXZ4.mjs";
4
+ import "./chunk-NDTY5AUU.mjs";
5
5
  import "./chunk-CIXHTOO3.mjs";
6
6
  export {
7
7
  WithdrawModal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhinestone/deposit-modal",
3
- "version": "0.1.60",
3
+ "version": "0.1.62",
4
4
  "description": "React modal component for Rhinestone cross-chain deposits",
5
5
  "author": "Rhinestone <dev@rhinestone.wtf>",
6
6
  "bugs": {