@vultisig/core-chain 2.25.1 → 2.27.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 (173) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/chains/cosmos/account/getCosmosAccountInfo.d.ts +1 -0
  3. package/dist/chains/cosmos/account/getCosmosAccountInfo.d.ts.map +1 -1
  4. package/dist/chains/cosmos/account/getCosmosAccountInfo.js +112 -30
  5. package/dist/chains/cosmos/account/getCosmosAccountInfo.js.map +1 -1
  6. package/dist/chains/cosmos/parseUint64.d.ts +6 -0
  7. package/dist/chains/cosmos/parseUint64.d.ts.map +1 -0
  8. package/dist/chains/cosmos/parseUint64.js +12 -0
  9. package/dist/chains/cosmos/parseUint64.js.map +1 -0
  10. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.d.ts.map +1 -1
  11. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.js +3 -28
  12. package/dist/chains/cosmos/qbtc/claim/broadcastClaimTx.js.map +1 -1
  13. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.d.ts +2 -0
  14. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.d.ts.map +1 -1
  15. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.js +15 -4
  16. package/dist/chains/cosmos/qbtc/getQbtcAccountInfo.js.map +1 -1
  17. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.d.ts +32 -0
  18. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.d.ts.map +1 -0
  19. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.js +33 -0
  20. package/dist/chains/cosmos/qbtc/waitForQbtcTxInclusion.js.map +1 -0
  21. package/dist/chains/cosmos/thor/brune-bond/config.d.ts +9 -0
  22. package/dist/chains/cosmos/thor/brune-bond/config.d.ts.map +1 -0
  23. package/dist/chains/cosmos/thor/brune-bond/config.js +9 -0
  24. package/dist/chains/cosmos/thor/brune-bond/config.js.map +1 -0
  25. package/dist/chains/evm/chainInfo.d.ts +2 -2
  26. package/dist/chains/evm/chainInfo.d.ts.map +1 -1
  27. package/dist/chains/evm/chainInfo.js +3 -1
  28. package/dist/chains/evm/chainInfo.js.map +1 -1
  29. package/dist/chains/ripple/address.d.ts +12 -0
  30. package/dist/chains/ripple/address.d.ts.map +1 -0
  31. package/dist/chains/ripple/address.js +44 -0
  32. package/dist/chains/ripple/address.js.map +1 -0
  33. package/dist/coin/balance/getEvmChainBalances.d.ts +6 -0
  34. package/dist/coin/balance/getEvmChainBalances.d.ts.map +1 -1
  35. package/dist/coin/balance/getEvmChainBalances.js +11 -5
  36. package/dist/coin/balance/getEvmChainBalances.js.map +1 -1
  37. package/dist/coin/find/resolvers/cosmos.d.ts.map +1 -1
  38. package/dist/coin/find/resolvers/cosmos.js +2 -1
  39. package/dist/coin/find/resolvers/cosmos.js.map +1 -1
  40. package/dist/coin/knownTokens/cosmos.d.ts.map +1 -1
  41. package/dist/coin/knownTokens/cosmos.js +6 -0
  42. package/dist/coin/knownTokens/cosmos.js.map +1 -1
  43. package/dist/coin/knownTokens/thorchain.d.ts.map +1 -1
  44. package/dist/coin/knownTokens/thorchain.js +5 -0
  45. package/dist/coin/knownTokens/thorchain.js.map +1 -1
  46. package/dist/coin/price/resolveTokenPriceId.d.ts +8 -10
  47. package/dist/coin/price/resolveTokenPriceId.d.ts.map +1 -1
  48. package/dist/coin/price/resolveTokenPriceId.js +21 -14
  49. package/dist/coin/price/resolveTokenPriceId.js.map +1 -1
  50. package/dist/swap/general/GeneralSwapQuote.d.ts +19 -3
  51. package/dist/swap/general/GeneralSwapQuote.d.ts.map +1 -1
  52. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts +0 -9
  53. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts.map +1 -1
  54. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js +52 -22
  55. package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js.map +1 -1
  56. package/dist/swap/general/knownAggregatorRouters.d.ts +59 -2
  57. package/dist/swap/general/knownAggregatorRouters.d.ts.map +1 -1
  58. package/dist/swap/general/knownAggregatorRouters.js +118 -12
  59. package/dist/swap/general/knownAggregatorRouters.js.map +1 -1
  60. package/dist/swap/general/kyber/chains.d.ts +1 -1
  61. package/dist/swap/general/kyber/chains.d.ts.map +1 -1
  62. package/dist/swap/general/kyber/chains.js +5 -2
  63. package/dist/swap/general/kyber/chains.js.map +1 -1
  64. package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts +2 -9
  65. package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts.map +1 -1
  66. package/dist/swap/general/lifi/api/getLifiSwapQuote.js +29 -81
  67. package/dist/swap/general/lifi/api/getLifiSwapQuote.js.map +1 -1
  68. package/dist/swap/general/lifi/api/lifiSlippage.d.ts +25 -0
  69. package/dist/swap/general/lifi/api/lifiSlippage.d.ts.map +1 -0
  70. package/dist/swap/general/lifi/api/lifiSlippage.js +51 -0
  71. package/dist/swap/general/lifi/api/lifiSlippage.js.map +1 -0
  72. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.d.ts.map +1 -1
  73. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.js +8 -0
  74. package/dist/swap/general/oneInch/api/getOneInchSwapQuote.js.map +1 -1
  75. package/dist/swap/general/swapkit/api/getSwapKitQuote.d.ts.map +1 -1
  76. package/dist/swap/general/swapkit/api/getSwapKitQuote.js +23 -2
  77. package/dist/swap/general/swapkit/api/getSwapKitQuote.js.map +1 -1
  78. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.d.ts +43 -0
  79. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.d.ts.map +1 -0
  80. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.js +47 -0
  81. package/dist/swap/general/swapkit/getSwapKitTrackerUrl.js.map +1 -0
  82. package/dist/swap/native/NativeSwapChain.d.ts +2 -0
  83. package/dist/swap/native/NativeSwapChain.d.ts.map +1 -1
  84. package/dist/swap/native/NativeSwapChain.js +1 -0
  85. package/dist/swap/native/NativeSwapChain.js.map +1 -1
  86. package/dist/swap/native/asset/toNativeSwapAsset.d.ts.map +1 -1
  87. package/dist/swap/native/asset/toNativeSwapAsset.js +9 -1
  88. package/dist/swap/native/asset/toNativeSwapAsset.js.map +1 -1
  89. package/dist/swap/native/halts/getNativeSwapTradingHalt.d.ts.map +1 -1
  90. package/dist/swap/native/halts/getNativeSwapTradingHalt.js +2 -2
  91. package/dist/swap/native/halts/getNativeSwapTradingHalt.js.map +1 -1
  92. package/dist/swap/native/limitSwapMemo.d.ts.map +1 -1
  93. package/dist/swap/native/limitSwapMemo.js +1 -24
  94. package/dist/swap/native/limitSwapMemo.js.map +1 -1
  95. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.d.ts.map +1 -1
  96. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.js +9 -3
  97. package/dist/swap/native/minimum/getNativeSwapMinAmountIn.js.map +1 -1
  98. package/dist/swap/native/thorchainMemoAsset.d.ts +76 -0
  99. package/dist/swap/native/thorchainMemoAsset.d.ts.map +1 -0
  100. package/dist/swap/native/thorchainMemoAsset.js +126 -0
  101. package/dist/swap/native/thorchainMemoAsset.js.map +1 -0
  102. package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
  103. package/dist/swap/quote/findSwapQuote.js +6 -1
  104. package/dist/swap/quote/findSwapQuote.js.map +1 -1
  105. package/dist/swap/swapEnabledChains.d.ts.map +1 -1
  106. package/dist/swap/swapEnabledChains.js +12 -0
  107. package/dist/swap/swapEnabledChains.js.map +1 -1
  108. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts +10 -7
  109. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts.map +1 -1
  110. package/dist/swap/utils/getSwapExplorerUrl/index.js +13 -12
  111. package/dist/swap/utils/getSwapExplorerUrl/index.js.map +1 -1
  112. package/dist/tx/broadcast/index.d.ts.map +1 -1
  113. package/dist/tx/broadcast/index.js +10 -1
  114. package/dist/tx/broadcast/index.js.map +1 -1
  115. package/dist/tx/broadcast/resolvers/bittensor.d.ts.map +1 -1
  116. package/dist/tx/broadcast/resolvers/bittensor.js +21 -15
  117. package/dist/tx/broadcast/resolvers/bittensor.js.map +1 -1
  118. package/dist/tx/broadcast/resolvers/cardano.d.ts +5 -0
  119. package/dist/tx/broadcast/resolvers/cardano.d.ts.map +1 -1
  120. package/dist/tx/broadcast/resolvers/cardano.js +24 -4
  121. package/dist/tx/broadcast/resolvers/cardano.js.map +1 -1
  122. package/dist/tx/broadcast/resolvers/cosmos.d.ts +1 -0
  123. package/dist/tx/broadcast/resolvers/cosmos.d.ts.map +1 -1
  124. package/dist/tx/broadcast/resolvers/cosmos.js +30 -2
  125. package/dist/tx/broadcast/resolvers/cosmos.js.map +1 -1
  126. package/dist/tx/broadcast/resolvers/polkadot.d.ts.map +1 -1
  127. package/dist/tx/broadcast/resolvers/polkadot.js +3 -36
  128. package/dist/tx/broadcast/resolvers/polkadot.js.map +1 -1
  129. package/dist/tx/broadcast/resolvers/qbtc.d.ts.map +1 -1
  130. package/dist/tx/broadcast/resolvers/qbtc.js +37 -7
  131. package/dist/tx/broadcast/resolvers/qbtc.js.map +1 -1
  132. package/dist/tx/broadcast/resolvers/ripple.d.ts +1 -0
  133. package/dist/tx/broadcast/resolvers/ripple.d.ts.map +1 -1
  134. package/dist/tx/broadcast/resolvers/ripple.js +12 -4
  135. package/dist/tx/broadcast/resolvers/ripple.js.map +1 -1
  136. package/dist/tx/broadcast/resolvers/substrate.d.ts +8 -0
  137. package/dist/tx/broadcast/resolvers/substrate.d.ts.map +1 -0
  138. package/dist/tx/broadcast/resolvers/substrate.js +15 -0
  139. package/dist/tx/broadcast/resolvers/substrate.js.map +1 -0
  140. package/dist/tx/broadcast/resolvers/sui.d.ts +8 -0
  141. package/dist/tx/broadcast/resolvers/sui.d.ts.map +1 -1
  142. package/dist/tx/broadcast/resolvers/sui.js +33 -7
  143. package/dist/tx/broadcast/resolvers/sui.js.map +1 -1
  144. package/dist/tx/broadcast/transientRetry.d.ts +21 -0
  145. package/dist/tx/broadcast/transientRetry.d.ts.map +1 -0
  146. package/dist/tx/broadcast/transientRetry.js +105 -0
  147. package/dist/tx/broadcast/transientRetry.js.map +1 -0
  148. package/dist/tx/status/index.d.ts +3 -8
  149. package/dist/tx/status/index.d.ts.map +1 -1
  150. package/dist/tx/status/index.js.map +1 -1
  151. package/dist/tx/status/resolver.d.ts +4 -2
  152. package/dist/tx/status/resolver.d.ts.map +1 -1
  153. package/dist/tx/status/resolvers/bittensor.js +1 -1
  154. package/dist/tx/status/resolvers/bittensor.js.map +1 -1
  155. package/dist/tx/status/resolvers/cardano.d.ts.map +1 -1
  156. package/dist/tx/status/resolvers/cardano.js +19 -3
  157. package/dist/tx/status/resolvers/cardano.js.map +1 -1
  158. package/dist/tx/status/resolvers/qbtc.js +1 -1
  159. package/dist/tx/status/resolvers/qbtc.js.map +1 -1
  160. package/dist/tx/status/resolvers/solana.d.ts.map +1 -1
  161. package/dist/tx/status/resolvers/solana.js +16 -2
  162. package/dist/tx/status/resolvers/solana.js.map +1 -1
  163. package/dist/tx/status/resolvers/sui.js +2 -2
  164. package/dist/tx/status/resolvers/sui.js.map +1 -1
  165. package/dist/tx/status/resolvers/ton.js +1 -1
  166. package/dist/tx/status/resolvers/ton.js.map +1 -1
  167. package/dist/tx/status/resolvers/tron.d.ts.map +1 -1
  168. package/dist/tx/status/resolvers/tron.js +9 -3
  169. package/dist/tx/status/resolvers/tron.js.map +1 -1
  170. package/dist/utils/isValidAddress.d.ts.map +1 -1
  171. package/dist/utils/isValidAddress.js +4 -0
  172. package/dist/utils/isValidAddress.js.map +1 -1
  173. package/package.json +48 -2
@@ -1,24 +1,21 @@
1
1
  import { Chain } from '@vultisig/core-chain/Chain';
2
+ import { getCowSwapExplorerOrderUrl } from '@vultisig/core-chain/swap/general/cowswap/getCowSwapExplorerOrderUrl';
3
+ import { generalSwapProviders } from '@vultisig/core-chain/swap/general/GeneralSwapProvider';
4
+ import { getSwapKitTrackerUrl } from '@vultisig/core-chain/swap/general/swapkit/getSwapKitTrackerUrl';
2
5
  import { getBlockExplorerUrl } from '@vultisig/core-chain/utils/getBlockExplorerUrl';
3
6
  /**
4
7
  * Swap-provider scanners covered by `getSwapExplorerUrl`.
5
8
  *
6
9
  * - `li.fi` → scan.li.fi (or orb.helius.dev for Solana settlement)
10
+ * - `swapkit` → track.swapkit.dev
11
+ * - `cowswap` → explorer.cow.fi order page
7
12
  * - `thorchain` / `mayachain` → native chain scanner
8
- * - `1inch`, `kyber`, `swapkit`, `jupiter` → no per-tx aggregator page; fall back to source-chain explorer
13
+ * - `1inch`, `kyber`, `jupiter` → source-chain explorer fallback
9
14
  *
10
15
  * Keep this union in sync with iOS `ExplorerLinkBuilder.swift` and Android
11
16
  * `ExplorerLinkRepository.getSwapProgressLink`.
12
17
  */
13
- export const swapExplorerProviders = [
14
- '1inch',
15
- 'kyber',
16
- 'li.fi',
17
- 'mayachain',
18
- 'swapkit',
19
- 'jupiter',
20
- 'thorchain',
21
- ];
18
+ export const swapExplorerProviders = [...generalSwapProviders, 'mayachain', 'thorchain'];
22
19
  const stripHexPrefix = (value) => value.startsWith('0x') || value.startsWith('0X') ? value.slice(2) : value;
23
20
  /**
24
21
  * Resolve the canonical "view on explorer" URL for a swap-provider transaction.
@@ -27,11 +24,13 @@ const stripHexPrefix = (value) => value.startsWith('0x') || value.startsWith('0X
27
24
  * so every consumer (vultisig-windows, vultiagent-app, future RN SDK) routes
28
25
  * tx-history links to the same scanner.
29
26
  *
30
- * For aggregators without a public per-tx page (`1inch`, `kyber`, `swapkit`),
27
+ * For aggregators without a public per-tx page (`1inch`, `kyber`, `jupiter`),
31
28
  * the source-chain explorer is returned so the row never renders as a dead link.
32
29
  */
33
30
  export const getSwapExplorerUrl = ({ provider, txHash, fromChain }) => {
34
31
  switch (provider) {
32
+ case 'cowswap':
33
+ return getCowSwapExplorerOrderUrl({ chain: fromChain, uid: txHash });
35
34
  case 'li.fi':
36
35
  // LI.FI's scanner has no per-tx page for Solana cross-chain settlement;
37
36
  // Helius is the canonical view there.
@@ -43,9 +42,11 @@ export const getSwapExplorerUrl = ({ provider, txHash, fromChain }) => {
43
42
  return `https://runescan.io/tx/${stripHexPrefix(txHash)}`;
44
43
  case 'mayachain':
45
44
  return `https://www.explorer.mayachain.info/tx/${stripHexPrefix(txHash)}`;
45
+ case 'swapkit':
46
+ return (getSwapKitTrackerUrl({ chain: fromChain, txHash }) ??
47
+ getBlockExplorerUrl({ chain: fromChain, entity: 'tx', value: txHash }));
46
48
  case '1inch':
47
49
  case 'kyber':
48
- case 'swapkit':
49
50
  case 'jupiter':
50
51
  // No public aggregator scanner. Source-chain explorer keeps the link
51
52
  // useful (Etherscan / Solscan / etc.) without fabricating a URL.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/utils/getSwapExplorerUrl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAA;AAEpF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO;IACP,OAAO;IACP,OAAO;IACP,WAAW;IACX,SAAS;IACT,SAAS;IACT,WAAW;CACH,CAAA;AAeV,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAC/C,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAE3E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAA2B,EAAU,EAAE;IACrG,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,wEAAwE;YACxE,sCAAsC;YACtC,IAAI,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC/B,OAAO,6BAA6B,MAAM,EAAE,CAAA;YAC9C,CAAC;YACD,OAAO,yBAAyB,MAAM,EAAE,CAAA;QAC1C,KAAK,WAAW;YACd,OAAO,0BAA0B,cAAc,CAAC,MAAM,CAAC,EAAE,CAAA;QAC3D,KAAK,WAAW;YACd,OAAO,0CAA0C,cAAc,CAAC,MAAM,CAAC,EAAE,CAAA;QAC3E,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACZ,qEAAqE;YACrE,iEAAiE;YACjE,OAAO,mBAAmB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAC/E,OAAO,CAAC,CAAC,CAAC;YACR,0EAA0E;YAC1E,uEAAuE;YACvE,iEAAiE;YACjE,MAAM,WAAW,GAAU,QAAQ,CAAA;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAC3E,CAAC;IACH,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/utils/getSwapExplorerUrl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sEAAsE,CAAA;AACjH,OAAO,EAAE,oBAAoB,EAAE,MAAM,uDAAuD,CAAA;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,gEAAgE,CAAA;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,gDAAgD,CAAA;AAEpF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,oBAAoB,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AAgBjG,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAC/C,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAE3E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAA2B,EAAU,EAAE;IACrG,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,0BAA0B,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAA;QACtE,KAAK,OAAO;YACV,wEAAwE;YACxE,sCAAsC;YACtC,IAAI,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC/B,OAAO,6BAA6B,MAAM,EAAE,CAAA;YAC9C,CAAC;YACD,OAAO,yBAAyB,MAAM,EAAE,CAAA;QAC1C,KAAK,WAAW;YACd,OAAO,0BAA0B,cAAc,CAAC,MAAM,CAAC,EAAE,CAAA;QAC3D,KAAK,WAAW;YACd,OAAO,0CAA0C,cAAc,CAAC,MAAM,CAAC,EAAE,CAAA;QAC3E,KAAK,SAAS;YACZ,OAAO,CACL,oBAAoB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;gBAClD,mBAAmB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACvE,CAAA;QACH,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,SAAS;YACZ,qEAAqE;YACrE,iEAAiE;YACjE,OAAO,mBAAmB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAC/E,OAAO,CAAC,CAAC,CAAC;YACR,0EAA0E;YAC1E,uEAAuE;YACvE,iEAAiE;YACjE,MAAM,WAAW,GAAU,QAAQ,CAAA;YACnC,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAC3E,CAAC;IACH,CAAC;AACH,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/tx/broadcast/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AA6BhD,eAAO,MAAM,WAAW,EAAE,mBAA0E,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/tx/broadcast/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAgChD,eAAO,MAAM,WAAW,EAAE,mBASzB,CAAA"}
@@ -11,6 +11,7 @@ import { broadcastSuiTx } from './resolvers/sui.js';
11
11
  import { broadcastTonTx } from './resolvers/ton.js';
12
12
  import { broadcastTronTx } from './resolvers/tron.js';
13
13
  import { broadcastUtxoTx } from './resolvers/utxo.js';
14
+ import { withTransientBroadcastRetry } from './transientRetry.js';
14
15
  const resolvers = {
15
16
  bittensor: broadcastBittensorTx,
16
17
  cardano: broadcastCardanoTx,
@@ -25,5 +26,13 @@ const resolvers = {
25
26
  utxo: broadcastUtxoTx,
26
27
  tron: broadcastTronTx,
27
28
  };
28
- export const broadcastTx = input => resolvers[getChainKind(input.chain)](input);
29
+ const hasResolverOwnedRetry = (chainKind) => chainKind === 'evm' || chainKind === 'solana';
30
+ export const broadcastTx = input => {
31
+ const chainKind = getChainKind(input.chain);
32
+ const resolver = resolvers[chainKind];
33
+ if (hasResolverOwnedRetry(chainKind)) {
34
+ return resolver(input);
35
+ }
36
+ return withTransientBroadcastRetry(() => resolver(input));
37
+ };
29
38
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/tx/broadcast/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAGxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,MAAM,SAAS,GAAgD;IAC7D,SAAS,EAAE,oBAAoB;IAC/B,OAAO,EAAE,kBAAkB;IAC3B,MAAM,EAAE,iBAAiB;IACzB,GAAG,EAAE,cAAc;IACnB,QAAQ,EAAE,mBAAmB;IAC7B,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,iBAAiB;IACzB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,cAAc;IACnB,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,eAAe;CACtB,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAwB,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/tx/broadcast/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAGxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAA;AAE9D,MAAM,SAAS,GAAgD;IAC7D,SAAS,EAAE,oBAAoB;IAC/B,OAAO,EAAE,kBAAkB;IAC3B,MAAM,EAAE,iBAAiB;IACzB,GAAG,EAAE,cAAc;IACnB,QAAQ,EAAE,mBAAmB;IAC7B,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,iBAAiB;IACzB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,cAAc;IACnB,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,eAAe;CACtB,CAAA;AAED,MAAM,qBAAqB,GAAG,CAAC,SAAoB,EAAW,EAAE,CAAC,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,QAAQ,CAAA;AAE9G,MAAM,CAAC,MAAM,WAAW,GAAwB,KAAK,CAAC,EAAE;IACtD,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IAErC,IAAI,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,2BAA2B,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;AAC3D,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"bittensor.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/bittensor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAKvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAQjD,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,UAAU,CAAC,SAAS,CAqB1E,CAAA"}
1
+ {"version":3,"file":"bittensor.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/bittensor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAKvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AASjD,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,UAAU,CAAC,SAAS,CA0B1E,CAAA"}
@@ -2,24 +2,30 @@ import { bittensorRpcUrl } from '@vultisig/core-chain/chains/bittensor/client';
2
2
  import { ensureHexPrefix } from '@vultisig/lib-utils/hex/ensureHexPrefix';
3
3
  import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
4
4
  import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
5
+ import { formatSubstrateRpcError, isIdempotentSubstrateBroadcastError } from './substrate.js';
5
6
  export const broadcastBittensorTx = async ({ chain, tx }) => {
6
7
  const hexWithPrefix = ensureHexPrefix(Buffer.from(tx.encoded).toString('hex'));
7
- const response = await queryUrl(bittensorRpcUrl, {
8
- body: {
9
- jsonrpc: '2.0',
10
- method: 'author_submitExtrinsic',
11
- params: [hexWithPrefix],
12
- id: 1,
13
- },
14
- });
15
- if (response.error) {
16
- const message = response.error.message ?? '';
17
- // "Already Imported" means another device already broadcast this tx — not an error
18
- if (message.includes('Already Imported')) {
19
- return;
8
+ try {
9
+ const response = await queryUrl(bittensorRpcUrl, {
10
+ body: {
11
+ jsonrpc: '2.0',
12
+ method: 'author_submitExtrinsic',
13
+ params: [hexWithPrefix],
14
+ id: 1,
15
+ },
16
+ });
17
+ if (response.error) {
18
+ if (isIdempotentSubstrateBroadcastError(response.error)) {
19
+ return;
20
+ }
21
+ throw new Error(`Bittensor broadcast failed: ${formatSubstrateRpcError(response.error)}`);
20
22
  }
21
- const err = new Error(`Bittensor broadcast failed: ${message || `code ${response.error.code}`}`);
22
- await verifyBroadcastByHash({ chain, tx, error: err });
23
+ if (!response.result) {
24
+ throw new Error('Bittensor broadcast failed: missing extrinsic hash in RPC response');
25
+ }
26
+ }
27
+ catch (error) {
28
+ await verifyBroadcastByHash({ chain, tx, error });
23
29
  }
24
30
  };
25
31
  //# sourceMappingURL=bittensor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bittensor.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/bittensor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAA;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAG7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAOhE,MAAM,CAAC,MAAM,oBAAoB,GAA8C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACrG,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAE9E,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAc,eAAe,EAAE;QAC5D,IAAI,EAAE;YACJ,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE,CAAC,aAAa,CAAC;YACvB,EAAE,EAAE,CAAC;SACN;KACF,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAA;QAC5C,mFAAmF;QACnF,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACzC,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,+BAA+B,OAAO,IAAI,QAAQ,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAChG,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IACxD,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"bittensor.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/bittensor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAA;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAG7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,uBAAuB,EAAE,mCAAmC,EAAqB,MAAM,aAAa,CAAA;AAO7G,MAAM,CAAC,MAAM,oBAAoB,GAA8C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACrG,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAE9E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAc,eAAe,EAAE;YAC5D,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,CAAC,aAAa,CAAC;gBACvB,EAAE,EAAE,CAAC;aACN;SACF,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,mCAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,OAAM;YACR,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC3F,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;QACvF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACnD,CAAC;AACH,CAAC,CAAA"}
@@ -1,4 +1,9 @@
1
1
  import { OtherChain } from '@vultisig/core-chain/Chain';
2
2
  import { BroadcastTxResolver } from '../resolver.js';
3
+ export declare const getCardanoTtlFreshnessError: ({ currentSlot, ttl, }: {
4
+ currentSlot: bigint | null;
5
+ ttl: bigint;
6
+ }) => Error | null;
7
+ export declare const assertCardanoTtlFreshForBroadcast: (encodedBytes: Uint8Array) => Promise<void>;
3
8
  export declare const broadcastCardanoTx: BroadcastTxResolver<OtherChain.Cardano>;
4
9
  //# sourceMappingURL=cardano.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cardano.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAOvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAsBjD,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,CAAC,UAAU,CAAC,OAAO,CAuBtE,CAAA"}
1
+ {"version":3,"file":"cardano.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAQvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAoBjD,eAAO,MAAM,2BAA2B,GAAI,uBAGzC;IACD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;CACZ,KAAG,KAAK,GAAG,IAcX,CAAA;AAED,eAAO,MAAM,iCAAiC,GAAU,cAAc,UAAU,kBAQ/E,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,CAAC,UAAU,CAAC,OAAO,CAuBtE,CAAA"}
@@ -2,6 +2,7 @@ import { getCardanoTxTtl } from '@vultisig/core-chain/chains/cardano/cip30/carda
2
2
  import { getCardanoCurrentSlot } from '@vultisig/core-chain/chains/cardano/client/currentSlot';
3
3
  import { cardanoBroadcastTtlSafetyMargin } from '@vultisig/core-chain/chains/cardano/config';
4
4
  import { getCardanoTxHash } from '@vultisig/core-chain/tx/hash/resolvers/cardano';
5
+ import { attempt } from '@vultisig/lib-utils/attempt';
5
6
  import { submitCardanoCbor } from '../../../chains/cardano/submit/submitCardanoCbor.js';
6
7
  import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
7
8
  import { selectEncodedBytes } from './utxo.js';
@@ -10,12 +11,31 @@ import { selectEncodedBytes } from './utxo.js';
10
11
  * reports this, we hash the tx locally to return the deterministic id.
11
12
  */
12
13
  const alreadyCommittedCode = 3117;
13
- const assertCardanoTtlFreshForBroadcast = async (encodedBytes) => {
14
- const ttl = getCardanoTxTtl(encodedBytes);
15
- const currentSlot = await getCardanoCurrentSlot();
14
+ const getCardanoCurrentSlotForBroadcast = async () => {
15
+ const first = await attempt(getCardanoCurrentSlot());
16
+ if (!('error' in first))
17
+ return first.data;
18
+ const second = await attempt(getCardanoCurrentSlot());
19
+ if (!('error' in second))
20
+ return second.data;
21
+ return null;
22
+ };
23
+ export const getCardanoTtlFreshnessError = ({ currentSlot, ttl, }) => {
24
+ if (currentSlot === null) {
25
+ return null;
26
+ }
16
27
  const minimumFreshTtl = currentSlot + BigInt(cardanoBroadcastTtlSafetyMargin);
17
28
  if (ttl <= minimumFreshTtl) {
18
- throw new Error(`Cardano transaction TTL is expired or too close to expiry; rebuild the transaction and retry (ttl=${ttl}, currentSlot=${currentSlot}, safetyMargin=${cardanoBroadcastTtlSafetyMargin} slots)`);
29
+ return new Error(`Cardano transaction TTL is expired or too close to expiry; rebuild the transaction and retry (ttl=${ttl}, currentSlot=${currentSlot}, safetyMargin=${cardanoBroadcastTtlSafetyMargin} slots)`);
30
+ }
31
+ return null;
32
+ };
33
+ export const assertCardanoTtlFreshForBroadcast = async (encodedBytes) => {
34
+ const ttl = getCardanoTxTtl(encodedBytes);
35
+ const currentSlot = await getCardanoCurrentSlotForBroadcast();
36
+ const freshnessError = getCardanoTtlFreshnessError({ currentSlot, ttl });
37
+ if (freshnessError) {
38
+ throw freshnessError;
19
39
  }
20
40
  };
21
41
  export const broadcastCardanoTx = async ({ chain, tx }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"cardano.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wDAAwD,CAAA;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAA;AAC9F,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAA;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAA;AAEjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAA;AAEpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAE3C;;;GAGG;AACH,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAEjC,MAAM,iCAAiC,GAAG,KAAK,EAAE,YAAwB,EAAE,EAAE;IAC3E,MAAM,GAAG,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;IACzC,MAAM,WAAW,GAAG,MAAM,qBAAqB,EAAE,CAAA;IACjD,MAAM,eAAe,GAAG,WAAW,GAAG,MAAM,CAAC,+BAA+B,CAAC,CAAA;IAE7E,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,qGAAqG,GAAG,iBAAiB,WAAW,kBAAkB,+BAA+B,SAAS,CAC/L,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAA4C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACjG,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAClD,MAAM,iCAAiC,CAAC,YAAY,CAAC,CAAA;IAErD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEzD,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAE/E,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,IAAI,YAAY,KAAK,oBAAoB,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,IAAI,2BAA2B,CAAA;IAEzD,mGAAmG;IACnG,uGAAuG;IACvG,mGAAmG;IACnG,kGAAkG;IAClG,MAAM,cAAc,GAAG,IAAI,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAA;IAC7E,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;IACjE,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
1
+ {"version":3,"file":"cardano.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { CosmosChain } from '@vultisig/core-chain/Chain';
2
2
  import { BroadcastTxResolver } from '../resolver.js';
3
+ export declare const getCosmosBroadcastTimeoutTxId: (error: unknown) => string | undefined;
3
4
  export declare const broadcastCosmosTx: BroadcastTxResolver<CosmosChain>;
4
5
  //# sourceMappingURL=cosmos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cosmos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cosmos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAKxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,eAAO,MAAM,iBAAiB,EAAE,mBAAmB,CAAC,WAAW,CAiB9D,CAAA"}
1
+ {"version":3,"file":"cosmos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cosmos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAKxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAIjD,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAMvE,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,mBAAmB,CAAC,WAAW,CAqC9D,CAAA"}
@@ -1,19 +1,47 @@
1
+ import { assertIsDeliverTxSuccess, TimeoutError } from '@cosmjs/stargate';
1
2
  import { getCosmosClient } from '@vultisig/core-chain/chains/cosmos/client';
2
3
  import { attempt } from '@vultisig/lib-utils/attempt';
3
4
  import { isInError } from '@vultisig/lib-utils/error/isInError';
5
+ import { DeliverTxFailedError } from '../transientRetry.js';
4
6
  import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
7
+ export const getCosmosBroadcastTimeoutTxId = (error) => {
8
+ if (!(error instanceof TimeoutError))
9
+ return undefined;
10
+ const { txId } = error;
11
+ return txId.trim() || undefined;
12
+ };
5
13
  export const broadcastCosmosTx = async ({ chain, tx }) => {
6
14
  const { serialized } = tx;
7
15
  const { tx_bytes } = JSON.parse(serialized);
8
16
  const decodedTxBytes = Buffer.from(tx_bytes, 'base64');
9
17
  const client = await getCosmosClient(chain);
10
- const { error } = await attempt(client.broadcastTx(decodedTxBytes));
11
- if (!error) {
18
+ const { data, error } = await attempt(client.broadcastTx(decodedTxBytes));
19
+ if (data) {
20
+ // client.broadcastTx resolves (does not throw) once the tx is INCLUDED in a
21
+ // block, even when execution itself failed (DeliverTx code !== 0 — e.g.
22
+ // out-of-gas, wasm revert, a THORChain/Maya deposit-handler rejection). The
23
+ // tx is on-chain but nothing moved, so this must not be reported as success.
24
+ try {
25
+ assertIsDeliverTxSuccess(data);
26
+ }
27
+ catch (deliverTxError) {
28
+ // Marker type, not a bare Error: cosmos has no resolver-owned retry, so
29
+ // this throws into `withTransientBroadcastRetry`. A rawLog like "wasm
30
+ // contract aborted" would otherwise match the transient message regex
31
+ // and get resent, then swallowed as an idempotent "already in cache"
32
+ // success — reopening the bug this assert exists to close.
33
+ const message = deliverTxError instanceof Error ? deliverTxError.message : String(deliverTxError);
34
+ throw new DeliverTxFailedError(message, { cause: deliverTxError });
35
+ }
12
36
  return;
13
37
  }
14
38
  if (isInError(error, 'tx already exists in cache')) {
15
39
  return;
16
40
  }
41
+ const timeoutTxId = getCosmosBroadcastTimeoutTxId(error);
42
+ if (timeoutTxId) {
43
+ return timeoutTxId;
44
+ }
17
45
  await verifyBroadcastByHash({ chain, tx, error });
18
46
  };
19
47
  //# sourceMappingURL=cosmos.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cosmos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cosmos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAG/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,CAAC,MAAM,iBAAiB,GAAqC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACzF,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAA;IACzB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC3C,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAEtD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAA;IAEnE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAM;IACR,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,EAAE,4BAA4B,CAAC,EAAE,CAAC;QACnD,OAAM;IACR,CAAC;IAED,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AACnD,CAAC,CAAA"}
1
+ {"version":3,"file":"cosmos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cosmos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEzE,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,KAAc,EAAsB,EAAE;IAClF,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;QAAE,OAAO,SAAS,CAAA;IAEtD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;IAEtB,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,SAAS,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAqC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACzF,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAA;IACzB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC3C,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAEtD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAA;IAEzE,IAAI,IAAI,EAAE,CAAC;QACT,4EAA4E;QAC5E,wEAAwE;QACxE,4EAA4E;QAC5E,6EAA6E;QAC7E,IAAI,CAAC;YACH,wBAAwB,CAAC,IAAI,CAAC,CAAA;QAChC,CAAC;QAAC,OAAO,cAAc,EAAE,CAAC;YACxB,wEAAwE;YACxE,sEAAsE;YACtE,sEAAsE;YACtE,qEAAqE;YACrE,2DAA2D;YAC3D,MAAM,OAAO,GAAG,cAAc,YAAY,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YACjG,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;QACpE,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,EAAE,4BAA4B,CAAC,EAAE,CAAC;QACnD,OAAM;IACR,CAAC;IAED,MAAM,WAAW,GAAG,6BAA6B,CAAC,KAAK,CAAC,CAAA;IACxD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AACnD,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"polkadot.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/polkadot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAKvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AA6CjD,eAAO,MAAM,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC,QAAQ,CAkCxE,CAAA"}
1
+ {"version":3,"file":"polkadot.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/polkadot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAKvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AASjD,eAAO,MAAM,mBAAmB,EAAE,mBAAmB,CAAC,UAAU,CAAC,QAAQ,CAiCxE,CAAA"}
@@ -2,39 +2,7 @@ import { ensureHexPrefix } from '@vultisig/lib-utils/hex/ensureHexPrefix';
2
2
  import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
3
3
  import { polkadotRpcUrl } from '../../../chains/polkadot/client.js';
4
4
  import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
5
- /**
6
- * Substrate Pool errors that mean "this extrinsic is already in the pool /
7
- * imported / banned because a peer just submitted it." In an MPC ceremony,
8
- * the initiator and the joiner both broadcast the same signed extrinsic; the
9
- * slower device hits exactly these messages while the tx is in fact already
10
- * on chain. Treat them as idempotent successes — the alternative is showing
11
- * the slower device a "Signing Error" screen for a transaction that did
12
- * confirm. Fast path so we don't rely on `verifyBroadcastByHash`, which can't
13
- * help on Polkadot until tx-status polling moves off the gated Subscan API.
14
- *
15
- * Substrate sources for the exact strings:
16
- * substrate/client/transaction-pool/api/src/error.rs (AlreadyImported,
17
- * TemporarilyBanned, NoTagsProvided, ImmediatelyDropped) and
18
- * primitives/runtime/src/transaction_validity.rs (Stale).
19
- */
20
- const idempotentBroadcastErrorPatterns = [
21
- /already imported/i,
22
- /already known/i,
23
- /temporarily banned/i,
24
- ];
25
- const isIdempotentBroadcastError = (text) => idempotentBroadcastErrorPatterns.some(pattern => pattern.test(text));
26
- /**
27
- * Substrate's JSON-RPC error shape is `{ code, message, data? }`. For
28
- * `InvalidTransaction::*` rejections (code 1010) the `message` is the
29
- * generic `"Invalid Transaction"` and the specific reason ("Transaction has
30
- * a bad signature", "Transaction is outdated", "Inability to pay some fees",
31
- * etc.) lives in `data`. Surfacing only `message` makes every failure look
32
- * identical in the UI and strips the information we need to triage.
33
- */
34
- const formatRpcError = ({ code, message, data }) => {
35
- const head = message ?? `code ${code}`;
36
- return data ? `${head}: ${data}` : head;
37
- };
5
+ import { formatSubstrateRpcError, isIdempotentSubstrateBroadcastError } from './substrate.js';
38
6
  export const broadcastPolkadotTx = async ({ chain, tx }) => {
39
7
  const hexWithPrefix = ensureHexPrefix(Buffer.from(tx.encoded).toString('hex'));
40
8
  try {
@@ -51,11 +19,10 @@ export const broadcastPolkadotTx = async ({ chain, tx }) => {
51
19
  // already submitted this exact tx; the node tells us with a Pool error
52
20
  // (string usually in `message`) or, less commonly, an Invalid
53
21
  // Transaction variant whose duplicate signal lives in `data`.
54
- const errorText = `${response.error.message ?? ''} ${response.error.data ?? ''}`;
55
- if (isIdempotentBroadcastError(errorText)) {
22
+ if (isIdempotentSubstrateBroadcastError(response.error)) {
56
23
  return;
57
24
  }
58
- throw new Error(`Polkadot broadcast failed: ${formatRpcError(response.error)}`);
25
+ throw new Error(`Polkadot broadcast failed: ${formatSubstrateRpcError(response.error)}`);
59
26
  }
60
27
  // Per JSON-RPC 2.0 a valid response must have exactly one of `result` /
61
28
  // `error`. If both are missing (malformed gateway response, truncated
@@ -1 +1 @@
1
- {"version":3,"file":"polkadot.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/polkadot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAOhE;;;;;;;;;;;;;;GAcG;AACH,MAAM,gCAAgC,GAAsB;IAC1D,mBAAmB;IACnB,gBAAgB;IAChB,qBAAqB;CACtB,CAAA;AAED,MAAM,0BAA0B,GAAG,CAAC,IAAY,EAAW,EAAE,CAC3D,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAEtE;;;;;;;GAOG;AACH,MAAM,cAAc,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAoD,EAAU,EAAE;IAC3G,MAAM,IAAI,GAAG,OAAO,IAAI,QAAQ,IAAI,EAAE,CAAA;IACtC,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACzC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAA6C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACnG,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAE9E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAc,cAAc,EAAE;YAC3D,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,CAAC,aAAa,CAAC;gBACvB,EAAE,EAAE,CAAC;aACN;SACF,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,sEAAsE;YACtE,uEAAuE;YACvE,8DAA8D;YAC9D,8DAA8D;YAC9D,MAAM,SAAS,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAA;YAChF,IAAI,0BAA0B,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,OAAM;YACR,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,8BAA8B,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACjF,CAAC;QAED,wEAAwE;QACxE,sEAAsE;QACtE,qEAAqE;QACrE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAA;QACtF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACnD,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"polkadot.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/polkadot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,uBAAuB,EAAE,mCAAmC,EAAqB,MAAM,aAAa,CAAA;AAO7G,MAAM,CAAC,MAAM,mBAAmB,GAA6C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IACnG,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAE9E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAc,cAAc,EAAE;YAC3D,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,CAAC,aAAa,CAAC;gBACvB,EAAE,EAAE,CAAC;aACN;SACF,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,sEAAsE;YACtE,uEAAuE;YACvE,8DAA8D;YAC9D,8DAA8D;YAC9D,IAAI,mCAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,OAAM;YACR,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,8BAA8B,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC1F,CAAC;QAED,wEAAwE;QACxE,sEAAsE;QACtE,qEAAqE;QACrE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAA;QACtF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACnD,CAAC;AACH,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"qbtc.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/qbtc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAKlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,eAAO,MAAM,eAAe,EAAE,mBAAmB,CAAC,OAAO,KAAK,CAAC,IAAI,CAyClE,CAAA"}
1
+ {"version":3,"file":"qbtc.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/qbtc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAMlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AASjD,eAAO,MAAM,eAAe,EAAE,mBAAmB,CAAC,OAAO,KAAK,CAAC,IAAI,CAqElE,CAAA"}
@@ -1,7 +1,13 @@
1
1
  import { qbtcRestUrl } from '@vultisig/core-chain/chains/cosmos/qbtc/tendermintRpcUrl';
2
+ import { waitForQbtcTxInclusion } from '@vultisig/core-chain/chains/cosmos/qbtc/waitForQbtcTxInclusion';
2
3
  import { attempt } from '@vultisig/lib-utils/attempt';
3
4
  import { isInError } from '@vultisig/lib-utils/error/isInError';
5
+ import { DeliverTxFailedError } from '../transientRetry.js';
4
6
  import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
7
+ // QBTC block time is ~5-7s; give a DeliverTx a generous window to land before treating the tx as
8
+ // in-flight (the status resolver reports the final code either way).
9
+ const QBTC_INCLUSION_TIMEOUT_MS = 30_000;
10
+ const QBTC_INCLUSION_POLL_INTERVAL_MS = 1_000;
5
11
  export const broadcastQbtcTx = async ({ chain, tx }) => {
6
12
  const { serialized } = tx;
7
13
  const { tx_bytes } = JSON.parse(serialized);
@@ -23,17 +29,41 @@ export const broadcastQbtcTx = async ({ chain, tx }) => {
23
29
  return;
24
30
  }
25
31
  const data = (await resp.json());
26
- const { error } = await attempt(async () => {
27
- if (data.tx_response?.code && data.tx_response.code !== 0) {
28
- throw new Error(`QBTC tx error: ${data.tx_response.raw_log || data.tx_response.log}`);
32
+ const checkTx = data.tx_response;
33
+ // CheckTx (mempool admission). A missing code, or a non-zero code, is NOT a confirmed on-chain
34
+ // state verify by hash rather than trusting it. Reading it as `code && code !== 0` (the old
35
+ // guard) treated a MISSING tx_response as a silent success: half of this false-success bug.
36
+ if (typeof checkTx?.code !== 'number' || checkTx.code !== 0) {
37
+ const log = checkTx?.raw_log || checkTx?.log;
38
+ if (log && isInError(log, 'tx already exists in cache')) {
39
+ return;
29
40
  }
30
- });
31
- if (!error) {
41
+ const err = new Error(`QBTC CheckTx failed: ${log ?? 'missing tx_response.code'}`);
42
+ await verifyBroadcastByHash({ chain, tx, error: err });
32
43
  return;
33
44
  }
34
- if (isInError(error, 'tx already exists in cache')) {
45
+ // CheckTx passed but BROADCAST_MODE_SYNC only surfaces CheckTx. A DeliverTx failure (out-of-gas,
46
+ // execution revert) still comes back code=0 HERE, so returning now would report an on-chain tx that
47
+ // moved nothing as a success. Poll for inclusion and re-check the DeliverTx code (mirrors the QBTC
48
+ // claim helper, broadcastClaimTx). A CONFIRMED DeliverTx failure throws a non-retryable
49
+ // DeliverTxFailedError; if we cannot confirm within the window (timeout / transient RPC error) the
50
+ // tx is in the mempool, not failed, so leave it in-flight — the status resolver reports the final
51
+ // code.
52
+ const txHash = checkTx.txhash;
53
+ if (!txHash) {
54
+ await verifyBroadcastByHash({ chain, tx, error: new Error('QBTC broadcast: missing txhash on CheckTx response') });
35
55
  return;
36
56
  }
37
- await verifyBroadcastByHash({ chain, tx, error });
57
+ const { data: included, error: inclusionError } = await attempt(waitForQbtcTxInclusion({
58
+ txHash,
59
+ timeoutMs: QBTC_INCLUSION_TIMEOUT_MS,
60
+ intervalMs: QBTC_INCLUSION_POLL_INTERVAL_MS,
61
+ }));
62
+ if (inclusionError || included === undefined || typeof included.code !== 'number') {
63
+ return;
64
+ }
65
+ if (included.code !== 0) {
66
+ throw new DeliverTxFailedError(`QBTC transaction execution failed: ${included.raw_log || included.log}`);
67
+ }
38
68
  };
39
69
  //# sourceMappingURL=qbtc.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"qbtc.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/qbtc.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0DAA0D,CAAA;AACtF,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAG/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,CAAC,MAAM,eAAe,GAA2C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IAC7F,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAA;IACzB,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAyB,CAAA;IAEnE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,wBAAwB,EAAE;QAC/D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,QAAQ;YACR,IAAI,EAAE,qBAAqB;SAC5B,CAAC;KACH,CAAC,CAAA;IAEF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAC9B,IAAI,SAAS,CAAC,IAAI,EAAE,4BAA4B,CAAC,EAAE,CAAC;YAClD,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAA;QACxE,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QACtD,OAAM;IACR,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAE9B,CAAA;IACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,IAAI,EAAE;QACzC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAA;QACvF,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAM;IACR,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,EAAE,4BAA4B,CAAC,EAAE,CAAC;QACnD,OAAM;IACR,CAAC;IAED,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AACnD,CAAC,CAAA"}
1
+ {"version":3,"file":"qbtc.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/qbtc.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { OtherChain } from '@vultisig/core-chain/Chain';
2
2
  import { BroadcastTxResolver } from '../resolver.js';
3
+ export declare const isRippleInFlightEngineResult: (engineResult: string) => boolean;
3
4
  export declare const broadcastRippleTx: BroadcastTxResolver<OtherChain.Ripple>;
4
5
  //# sourceMappingURL=ripple.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AA0BjD,eAAO,MAAM,iBAAiB,EAAE,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAsCpE,CAAA"}
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AA8BjD,eAAO,MAAM,4BAA4B,GAAI,cAAc,MAAM,KAAG,OAAuC,CAAA;AAE3G,eAAO,MAAM,iBAAiB,EAAE,mBAAmB,CAAC,UAAU,CAAC,MAAM,CA0CpE,CAAA"}
@@ -9,9 +9,13 @@ import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
9
9
  * consumed this sequence.
10
10
  *
11
11
  * For these we go through `verifyBroadcastByHash` to confirm the tx is
12
- * actually on-chain before swallowing the duplicate error. Any OTHER
13
- * non-success engine result (`tem*` malformed, `tec*` claim failures,
14
- * `tel*` local-policy rejections, `ter*` retry-later, the remaining
12
+ * actually on-chain before swallowing the duplicate error.
13
+ *
14
+ * `terQUEUED` is different from other `ter*` retry-later results: XRPL
15
+ * accepted the transaction into the transaction queue, so it is in flight.
16
+ *
17
+ * Any OTHER non-success engine result (`tem*` malformed, `tec*` claim failures,
18
+ * `tel*` local-policy rejections, remaining `ter*` retry-later, remaining
15
19
  * `tef*` failures) is the chain's authoritative "no" at preflight —
16
20
  * propagate directly so the caller sees the real failure.
17
21
  *
@@ -22,6 +26,7 @@ import { verifyBroadcastByHash } from '../verifyBroadcastByHash.js';
22
26
  * where rejected txs are never on-chain).
23
27
  */
24
28
  const PEER_RACE_ENGINE_RESULTS = new Set(['tefALREADY', 'tefPAST_SEQ']);
29
+ export const isRippleInFlightEngineResult = (engineResult) => engineResult === 'terQUEUED';
25
30
  export const broadcastRippleTx = async ({ chain, tx }) => {
26
31
  const client = await getRippleClient();
27
32
  // RPC-level errors (network blip, connection drop) get the safety-net
@@ -51,7 +56,10 @@ export const broadcastRippleTx = async ({ chain, tx }) => {
51
56
  await verifyBroadcastByHash({ chain, tx, error });
52
57
  return;
53
58
  }
54
- // Authoritative rejection at preflight (tem*/tec*/tel*/ter*/remaining tef*).
59
+ if (isRippleInFlightEngineResult(engineResult)) {
60
+ return;
61
+ }
62
+ // Authoritative rejection at preflight (tem*/tec*/tel*/remaining ter*/remaining tef*).
55
63
  // Propagate so the caller sees the real failure instead of a fake hash.
56
64
  throw error;
57
65
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/ripple.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAG3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,iBAAiB,GAA2C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IAC/F,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAA;IAEtC,sEAAsE;IACtE,wEAAwE;IACxE,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YAC9B,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;SACjD,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACjD,OAAM;IACR,CAAC;IAED,MAAM,gBAAgB,GAAG,QAAQ,EAAE,MAAM,EAAE,kBAAkB,CAAA;IAC7D,IAAI,OAAO,gBAAgB,KAAK,QAAQ,IAAI,gBAAgB,KAAK,CAAC,EAAE,CAAC;QACnE,2DAA2D;QAC3D,OAAM;IACR,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAA;IAC/D,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,qBAAqB,IAAI,EAAE,CAAA;IACvE,MAAM,KAAK,GAAG,IAAI,KAAK,CACrB,8BAA8B,YAAY,GAAG,mBAAmB,CAAC,CAAC,CAAC,MAAM,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACtG,CAAA;IAED,IAAI,wBAAwB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,gEAAgE;QAChE,mDAAmD;QACnD,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACjD,OAAM;IACR,CAAC;IAED,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,KAAK,CAAA;AACb,CAAC,CAAA"}
1
+ {"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/ripple.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAG3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,YAAoB,EAAW,EAAE,CAAC,YAAY,KAAK,WAAW,CAAA;AAE3G,MAAM,CAAC,MAAM,iBAAiB,GAA2C,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IAC/F,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAA;IAEtC,sEAAsE;IACtE,wEAAwE;IACxE,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YAC9B,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;SACjD,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACjD,OAAM;IACR,CAAC;IAED,MAAM,gBAAgB,GAAG,QAAQ,EAAE,MAAM,EAAE,kBAAkB,CAAA;IAC7D,IAAI,OAAO,gBAAgB,KAAK,QAAQ,IAAI,gBAAgB,KAAK,CAAC,EAAE,CAAC;QACnE,2DAA2D;QAC3D,OAAM;IACR,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAA;IAC/D,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,qBAAqB,IAAI,EAAE,CAAA;IACvE,MAAM,KAAK,GAAG,IAAI,KAAK,CACrB,8BAA8B,YAAY,GAAG,mBAAmB,CAAC,CAAC,CAAC,MAAM,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACtG,CAAA;IAED,IAAI,wBAAwB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,gEAAgE;QAChE,mDAAmD;QACnD,MAAM,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACjD,OAAM;IACR,CAAC;IAED,IAAI,4BAA4B,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,OAAM;IACR,CAAC;IAED,uFAAuF;IACvF,wEAAwE;IACxE,MAAM,KAAK,CAAA;AACb,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ export type SubstrateRpcError = {
2
+ code: number;
3
+ message?: string;
4
+ data?: string;
5
+ };
6
+ export declare const isIdempotentSubstrateBroadcastError: ({ message, data }: SubstrateRpcError) => boolean;
7
+ export declare const formatSubstrateRpcError: ({ code, message, data }: SubstrateRpcError) => string;
8
+ //# sourceMappingURL=substrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substrate.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/substrate.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAWD,eAAO,MAAM,mCAAmC,GAAI,mBAAmB,iBAAiB,KAAG,OACO,CAAA;AAIlG,eAAO,MAAM,uBAAuB,GAAI,yBAAyB,iBAAiB,KAAG,MAGpF,CAAA"}
@@ -0,0 +1,15 @@
1
+ // These pool errors mean another MPC peer has already submitted the same
2
+ // deterministic extrinsic. Treat them as idempotent success so the slower peer
3
+ // does not show a signing failure for a transaction that is already in flight.
4
+ const idempotentBroadcastErrorPatterns = [/already imported/i, /already known/i];
5
+ // `TemporarilyBanned` is deliberately not a fast success. Substrate bans
6
+ // hashes after known block imports, but it can also ban transactions removed
7
+ // as invalid or dropped. Only hash verification can disambiguate those cases.
8
+ export const isIdempotentSubstrateBroadcastError = ({ message, data }) => idempotentBroadcastErrorPatterns.some(pattern => pattern.test(`${message ?? ''} ${data ?? ''}`));
9
+ // Substrate often carries the actionable InvalidTransaction reason in `data`
10
+ // while `message` contains only the generic "Invalid Transaction" label.
11
+ export const formatSubstrateRpcError = ({ code, message, data }) => {
12
+ const head = message ?? `code ${code}`;
13
+ return data ? `${head}: ${data}` : head;
14
+ };
15
+ //# sourceMappingURL=substrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substrate.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/substrate.ts"],"names":[],"mappings":"AAMA,yEAAyE;AACzE,+EAA+E;AAC/E,+EAA+E;AAC/E,MAAM,gCAAgC,GAAsB,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAA;AAEnG,yEAAyE;AACzE,6EAA6E;AAC7E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAqB,EAAW,EAAE,CACnG,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;AAElG,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAqB,EAAU,EAAE;IAC5F,MAAM,IAAI,GAAG,OAAO,IAAI,QAAQ,IAAI,EAAE,CAAA;IACtC,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACzC,CAAC,CAAA"}
@@ -1,4 +1,12 @@
1
1
  import { OtherChain } from '@vultisig/core-chain/Chain';
2
2
  import { BroadcastTxResolver } from '../resolver.js';
3
+ type SuiExecutionEffects = {
4
+ status?: {
5
+ status?: string;
6
+ error?: string | null;
7
+ };
8
+ };
9
+ export declare const assertSuiTxSucceeded: (effects: SuiExecutionEffects | null | undefined) => void;
3
10
  export declare const broadcastSuiTx: BroadcastTxResolver<OtherChain.Sui>;
11
+ export {};
4
12
  //# sourceMappingURL=sui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/sui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,eAAO,MAAM,cAAc,EAAE,mBAAmB,CAAC,UAAU,CAAC,GAAG,CAS9D,CAAA"}
1
+ {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/sui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAIvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAIjD,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,SAAS,mBAAmB,GAAG,IAAI,GAAG,SAAS,KAAG,IAQtF,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,mBAAmB,CAAC,UAAU,CAAC,GAAG,CAkC9D,CAAA"}