0xtrails 0.13.0 → 0.13.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.
Files changed (307) hide show
  1. package/dist/{ccip-Cg9-lJ6K.js → ccip-CT_An6eM.js} +39 -39
  2. package/dist/chains.d.ts +4 -3
  3. package/dist/chains.d.ts.map +1 -1
  4. package/dist/constants.d.ts +1 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/customTokens.d.ts.map +1 -1
  7. package/dist/error.d.ts +1 -0
  8. package/dist/error.d.ts.map +1 -1
  9. package/dist/gasless.d.ts +1 -2
  10. package/dist/gasless.d.ts.map +1 -1
  11. package/dist/{index-DEojZg7b.js → index-RfqL5Foz.js} +56672 -43550
  12. package/dist/index.d.ts +5 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +385 -333
  15. package/dist/intents.d.ts +8 -2
  16. package/dist/intents.d.ts.map +1 -1
  17. package/dist/keyMachineClient.d.ts +9 -0
  18. package/dist/keyMachineClient.d.ts.map +1 -0
  19. package/dist/keymachine/index.d.ts +14 -0
  20. package/dist/keymachine/index.d.ts.map +1 -0
  21. package/dist/keymachine/key-machine.gen.d.ts +461 -0
  22. package/dist/keymachine/key-machine.gen.d.ts.map +1 -0
  23. package/dist/onramp/MeshConnectFlow.d.ts +18 -0
  24. package/dist/onramp/MeshConnectFlow.d.ts.map +1 -0
  25. package/dist/onramp/MeshConnectIframe.d.ts +13 -0
  26. package/dist/onramp/MeshConnectIframe.d.ts.map +1 -0
  27. package/dist/onramp/SendFromExchangeButton.d.ts +16 -0
  28. package/dist/onramp/SendFromExchangeButton.d.ts.map +1 -0
  29. package/dist/onramp/TrailsOnRampProvider.d.ts +31 -0
  30. package/dist/onramp/TrailsOnRampProvider.d.ts.map +1 -0
  31. package/dist/onramp/index.d.ts +13 -0
  32. package/dist/onramp/index.d.ts.map +1 -0
  33. package/dist/onramp/meshconnect.d.ts +30 -0
  34. package/dist/onramp/meshconnect.d.ts.map +1 -0
  35. package/dist/onramp/trailsOnramp.d.ts +24 -0
  36. package/dist/onramp/trailsOnramp.d.ts.map +1 -0
  37. package/dist/onramp-client/index.d.ts +3 -3
  38. package/dist/onramp-client/index.d.ts.map +1 -1
  39. package/dist/paymasterSend.d.ts.map +1 -1
  40. package/dist/prepareSend.d.ts.map +1 -1
  41. package/dist/query/balance.fetchers.d.ts +31 -2
  42. package/dist/query/balance.fetchers.d.ts.map +1 -1
  43. package/dist/query/balance.hooks.d.ts +21 -2
  44. package/dist/query/balance.hooks.d.ts.map +1 -1
  45. package/dist/query/balance.queries.d.ts +18 -1
  46. package/dist/query/balance.queries.d.ts.map +1 -1
  47. package/dist/query/chains.queries.d.ts.map +1 -1
  48. package/dist/query/meld.fetchers.d.ts +1 -1
  49. package/dist/query/meld.fetchers.d.ts.map +1 -1
  50. package/dist/query/meld.hooks.d.ts +3 -3
  51. package/dist/query/meld.hooks.d.ts.map +1 -1
  52. package/dist/query/meld.queries.d.ts +1 -1
  53. package/dist/query/meld.queries.d.ts.map +1 -1
  54. package/dist/query/price.fetchers.d.ts +15 -0
  55. package/dist/query/price.fetchers.d.ts.map +1 -0
  56. package/dist/query/price.hooks.d.ts +352 -0
  57. package/dist/query/price.hooks.d.ts.map +1 -0
  58. package/dist/query/price.queries.d.ts +34 -0
  59. package/dist/query/price.queries.d.ts.map +1 -0
  60. package/dist/query/tokenList.queries.d.ts +54 -0
  61. package/dist/query/tokenList.queries.d.ts.map +1 -0
  62. package/dist/recover.d.ts +6 -4
  63. package/dist/recover.d.ts.map +1 -1
  64. package/dist/tokens.d.ts +13 -0
  65. package/dist/tokens.d.ts.map +1 -1
  66. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +2 -2
  67. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  68. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +2 -2
  69. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
  70. package/dist/transactionIntent/deposits/standardDeposit.d.ts +1 -1
  71. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  72. package/dist/transactionIntent/handlers/intentHandler.d.ts.map +1 -1
  73. package/dist/transactionIntent/helpers/transactionStateHelpers.d.ts.map +1 -1
  74. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  75. package/dist/transactionIntent/types.d.ts +1 -1
  76. package/dist/transactionIntent/types.d.ts.map +1 -1
  77. package/dist/transactions.d.ts +4 -0
  78. package/dist/transactions.d.ts.map +1 -1
  79. package/dist/umd/trails.min.js +291 -202
  80. package/dist/utils/format.d.ts +7 -0
  81. package/dist/utils/format.d.ts.map +1 -1
  82. package/dist/walletUtils.d.ts +2 -1
  83. package/dist/walletUtils.d.ts.map +1 -1
  84. package/dist/wallets.d.ts +13 -54
  85. package/dist/wallets.d.ts.map +1 -1
  86. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  87. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  88. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  89. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  90. package/dist/widget/components/DirectTransfer.d.ts +1 -1
  91. package/dist/widget/components/DirectTransfer.d.ts.map +1 -1
  92. package/dist/widget/components/EarnPools.d.ts.map +1 -1
  93. package/dist/widget/components/ExecutionStatusBadge.d.ts.map +1 -1
  94. package/dist/widget/components/Fund.d.ts.map +1 -1
  95. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  96. package/dist/widget/components/HighPriceImpactBlock.d.ts +7 -0
  97. package/dist/widget/components/HighPriceImpactBlock.d.ts.map +1 -0
  98. package/dist/widget/components/MeldHistory.d.ts.map +1 -1
  99. package/dist/widget/components/MeshExchangeSelection.d.ts +11 -0
  100. package/dist/widget/components/MeshExchangeSelection.d.ts.map +1 -0
  101. package/dist/widget/components/OnrampHistoryRow.d.ts +1 -1
  102. package/dist/widget/components/OnrampHistoryRow.d.ts.map +1 -1
  103. package/dist/widget/components/OnrampProviderConfirmation.d.ts.map +1 -1
  104. package/dist/widget/components/Pay.d.ts.map +1 -1
  105. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  106. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
  107. package/dist/widget/components/QRCodeWalletSelect.d.ts +1 -1
  108. package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -1
  109. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  110. package/dist/widget/components/Receipt.d.ts.map +1 -1
  111. package/dist/widget/components/Recipients.d.ts.map +1 -1
  112. package/dist/widget/components/RefundWarning.d.ts.map +1 -1
  113. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  114. package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
  115. package/dist/widget/components/TransactionHistoryItem.d.ts +2 -0
  116. package/dist/widget/components/TransactionHistoryItem.d.ts.map +1 -1
  117. package/dist/widget/components/TransferPendingVertical.d.ts +1 -0
  118. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  119. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
  120. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  121. package/dist/widget/components/WalletImage.d.ts.map +1 -1
  122. package/dist/widget/components/WalletList.d.ts.map +1 -1
  123. package/dist/widget/components/Withdraw.d.ts.map +1 -1
  124. package/dist/widget/css/compiled.css +1 -1
  125. package/dist/widget/hooks/useAddressWalletIcon.d.ts.map +1 -1
  126. package/dist/widget/hooks/useCombinedHistory.d.ts +6 -5
  127. package/dist/widget/hooks/useCombinedHistory.d.ts.map +1 -1
  128. package/dist/widget/hooks/useCustomTokenSearch.d.ts +6 -1
  129. package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -1
  130. package/dist/widget/hooks/useDefaultDestinationToken.d.ts.map +1 -1
  131. package/dist/widget/hooks/useDefaultOriginToken.d.ts.map +1 -1
  132. package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts +1 -1
  133. package/dist/widget/hooks/useFiatOnRampCurrencies.d.ts.map +1 -1
  134. package/dist/widget/hooks/useGetIntent.d.ts +3 -2
  135. package/dist/widget/hooks/useGetIntent.d.ts.map +1 -1
  136. package/dist/widget/hooks/useIntentReceiptBalances.d.ts +1 -1
  137. package/dist/widget/hooks/useIntentReceiptBalances.d.ts.map +1 -1
  138. package/dist/widget/hooks/useIntentTransactionHistory.d.ts +3 -2
  139. package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
  140. package/dist/widget/hooks/useMeldTransactionHistory.d.ts +1 -1
  141. package/dist/widget/hooks/useMeldTransactionHistory.d.ts.map +1 -1
  142. package/dist/widget/hooks/useMeldTransactionStatus.d.ts +1 -1
  143. package/dist/widget/hooks/useMeldTransactionStatus.d.ts.map +1 -1
  144. package/dist/widget/hooks/useOnRampQuote.d.ts +1 -1
  145. package/dist/widget/hooks/useOnRampQuote.d.ts.map +1 -1
  146. package/dist/widget/hooks/useOnRampTransactionStatus.d.ts +1 -1
  147. package/dist/widget/hooks/useOnRampTransactionStatus.d.ts.map +1 -1
  148. package/dist/widget/hooks/useQuote.d.ts +2 -2
  149. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  150. package/dist/widget/hooks/useSelectedFundMethod.d.ts +7 -0
  151. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
  152. package/dist/widget/hooks/useSendForm.d.ts +0 -1
  153. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  154. package/dist/widget/hooks/useTokenList.d.ts +7 -1
  155. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  156. package/dist/widget/hooks/useViewManager.d.ts +1 -1
  157. package/dist/widget/hooks/useViewManager.d.ts.map +1 -1
  158. package/dist/widget/index.js +1 -1
  159. package/dist/widget/providers/TrailsProvider.d.ts +2 -0
  160. package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
  161. package/dist/widget/utils/createWagmiConfig.d.ts +2 -2
  162. package/dist/widget/utils/createWagmiConfig.d.ts.map +1 -1
  163. package/dist/widget/utils/fundMethodSwitchState.d.ts +1 -0
  164. package/dist/widget/utils/fundMethodSwitchState.d.ts.map +1 -1
  165. package/dist/widget/utils/historyFilters.d.ts +13 -0
  166. package/dist/widget/utils/historyFilters.d.ts.map +1 -0
  167. package/dist/widget/utils/meldProviderUtils.d.ts +1 -1
  168. package/dist/widget/utils/meldProviderUtils.d.ts.map +1 -1
  169. package/dist/widget/utils/meshSupportedTokens.d.ts +4 -0
  170. package/dist/widget/utils/meshSupportedTokens.d.ts.map +1 -0
  171. package/dist/widget/utils/onrampConfig.d.ts +11 -0
  172. package/dist/widget/utils/onrampConfig.d.ts.map +1 -0
  173. package/dist/widget/utils/statusLabel.d.ts +2 -0
  174. package/dist/widget/utils/statusLabel.d.ts.map +1 -0
  175. package/dist/widget/utils/trailsOnrampConfig.d.ts +18 -0
  176. package/dist/widget/utils/trailsOnrampConfig.d.ts.map +1 -0
  177. package/dist/widget/widget.d.ts +24 -8
  178. package/dist/widget/widget.d.ts.map +1 -1
  179. package/package.json +9 -7
  180. package/src/chains.ts +26 -9
  181. package/src/constants.ts +2 -0
  182. package/src/customTokens.ts +22 -7
  183. package/src/error.ts +7 -0
  184. package/src/gasless.ts +5 -2
  185. package/src/index.ts +8 -5
  186. package/src/intents.ts +56 -60
  187. package/src/keyMachineClient.ts +29 -0
  188. package/src/keymachine/index.ts +175 -0
  189. package/src/keymachine/key-machine.gen.ts +993 -0
  190. package/src/onramp/MeshConnectFlow.tsx +86 -0
  191. package/src/onramp/MeshConnectIframe.tsx +661 -0
  192. package/src/onramp/SendFromExchangeButton.tsx +81 -0
  193. package/src/onramp/TrailsOnRampProvider.tsx +59 -0
  194. package/src/onramp/index.ts +31 -0
  195. package/src/onramp/meshconnect.ts +277 -0
  196. package/src/onramp/trailsOnramp.tsx +130 -0
  197. package/src/onramp-client/index.ts +4 -6
  198. package/src/paymasterSend.ts +0 -5
  199. package/src/prepareSend.ts +45 -44
  200. package/src/query/balance.fetchers.ts +172 -17
  201. package/src/query/balance.hooks.ts +69 -6
  202. package/src/query/balance.queries.ts +63 -0
  203. package/src/query/chains.queries.ts +1 -6
  204. package/src/query/meld.fetchers.ts +1 -1
  205. package/src/query/meld.hooks.ts +1 -1
  206. package/src/query/meld.queries.ts +1 -1
  207. package/src/query/price.fetchers.ts +53 -0
  208. package/src/query/price.hooks.ts +46 -0
  209. package/src/query/price.queries.ts +364 -0
  210. package/src/query/tokenList.queries.ts +118 -0
  211. package/src/recover.ts +89 -26
  212. package/src/tokens.ts +108 -26
  213. package/src/transactionIntent/deposits/depositOrchestrator.ts +11 -11
  214. package/src/transactionIntent/deposits/gaslessDeposit.ts +38 -39
  215. package/src/transactionIntent/deposits/standardDeposit.ts +5 -30
  216. package/src/transactionIntent/handlers/intentHandler.ts +29 -12
  217. package/src/transactionIntent/helpers/transactionStateHelpers.ts +5 -2
  218. package/src/transactionIntent/quote/normalizeQuote.ts +11 -5
  219. package/src/transactionIntent/types.ts +1 -1
  220. package/src/transactions.ts +5 -1
  221. package/src/utils/format.ts +85 -1
  222. package/src/walletUtils.ts +2 -1
  223. package/src/wallets.ts +184 -380
  224. package/src/widget/compiled.css +1 -1
  225. package/src/widget/components/AccountIntentTransactionHistory.tsx +134 -109
  226. package/src/widget/components/ClassicSwap.tsx +26 -24
  227. package/src/widget/components/ConnectWallet.tsx +4 -2
  228. package/src/widget/components/ConnectedWallets.tsx +2 -5
  229. package/src/widget/components/DirectTransfer.tsx +5 -2
  230. package/src/widget/components/EarnPools.tsx +1 -2
  231. package/src/widget/components/ExecutionStatusBadge.tsx +10 -4
  232. package/src/widget/components/Fund.tsx +169 -110
  233. package/src/widget/components/FundMethods.tsx +5 -9
  234. package/src/widget/components/HighPriceImpactBlock.tsx +44 -0
  235. package/src/widget/components/MeldHistory.tsx +4 -28
  236. package/src/widget/components/MeshExchangeSelection.tsx +218 -0
  237. package/src/widget/components/OnrampHistoryRow.tsx +3 -27
  238. package/src/widget/components/OnrampProviderConfirmation.tsx +0 -25
  239. package/src/widget/components/Pay.tsx +20 -36
  240. package/src/widget/components/PoolDeposit.tsx +14 -24
  241. package/src/widget/components/PoolWithdraw.tsx +1 -63
  242. package/src/widget/components/QRCodeWalletSelect.tsx +5 -2
  243. package/src/widget/components/QuoteDetails.tsx +113 -106
  244. package/src/widget/components/Receipt.tsx +0 -11
  245. package/src/widget/components/Recipients.tsx +2 -1
  246. package/src/widget/components/RefundWarning.tsx +5 -10
  247. package/src/widget/components/ThemeProvider.tsx +4 -4
  248. package/src/widget/components/TokenSelector.tsx +85 -16
  249. package/src/widget/components/TransactionDetails.tsx +46 -0
  250. package/src/widget/components/TransactionHistoryItem.tsx +14 -23
  251. package/src/widget/components/TransferPendingVertical.tsx +17 -11
  252. package/src/widget/components/WaasFeeOptions.tsx +4 -42
  253. package/src/widget/components/WalletConnect.tsx +2 -5
  254. package/src/widget/components/WalletImage.tsx +6 -18
  255. package/src/widget/components/WalletList.tsx +1 -1
  256. package/src/widget/components/Withdraw.tsx +22 -23
  257. package/src/widget/hooks/useAddressWalletIcon.ts +2 -1
  258. package/src/widget/hooks/useAmountUsd.ts +1 -1
  259. package/src/widget/hooks/useCombinedHistory.ts +37 -93
  260. package/src/widget/hooks/useCustomTokenSearch.tsx +63 -33
  261. package/src/widget/hooks/useDefaultDestinationToken.tsx +2 -5
  262. package/src/widget/hooks/useDefaultOriginToken.tsx +2 -5
  263. package/src/widget/hooks/useFiatOnRampCurrencies.ts +1 -1
  264. package/src/widget/hooks/useGetIntent.ts +5 -4
  265. package/src/widget/hooks/useIntentReceiptBalances.ts +3 -3
  266. package/src/widget/hooks/useIntentTransactionHistory.ts +24 -47
  267. package/src/widget/hooks/useMeldTransactionHistory.ts +4 -2
  268. package/src/widget/hooks/useMeldTransactionStatus.ts +13 -11
  269. package/src/widget/hooks/useOnRampQuote.ts +3 -3
  270. package/src/widget/hooks/useOnRampTransactionStatus.ts +8 -6
  271. package/src/widget/hooks/useQuote.ts +56 -48
  272. package/src/widget/hooks/useSelectedFundMethod.tsx +14 -1
  273. package/src/widget/hooks/useSendForm.ts +52 -31
  274. package/src/widget/hooks/useTokenList.ts +209 -140
  275. package/src/widget/hooks/useTrailsSendTransaction.ts +1 -1
  276. package/src/widget/hooks/useViewManager.tsx +1 -0
  277. package/src/widget/providers/TrailsProvider.tsx +5 -0
  278. package/src/widget/styles.ts +1 -1
  279. package/src/widget/utils/createWagmiConfig.ts +7 -2
  280. package/src/widget/utils/fundMethodSwitchState.ts +2 -0
  281. package/src/widget/utils/historyFilters.ts +157 -0
  282. package/src/widget/utils/meldProviderUtils.ts +8 -2
  283. package/src/widget/utils/meshSupportedTokens.ts +28 -0
  284. package/src/widget/utils/onrampConfig.ts +15 -0
  285. package/src/widget/utils/statusLabel.ts +3 -0
  286. package/src/widget/utils/trailsOnrampConfig.ts +39 -0
  287. package/src/widget/widget.tsx +235 -185
  288. package/dist/onramp-client/trails-onramp.gen.d.ts +0 -570
  289. package/dist/onramp-client/trails-onramp.gen.d.ts.map +0 -1
  290. package/dist/prices.d.ts +0 -34
  291. package/dist/prices.d.ts.map +0 -1
  292. package/dist/useGasEstimation.d.ts +0 -34
  293. package/dist/useGasEstimation.d.ts.map +0 -1
  294. package/dist/widget/hooks/useCustomTokenFetch.d.ts +0 -19
  295. package/dist/widget/hooks/useCustomTokenFetch.d.ts.map +0 -1
  296. package/dist/widget/hooks/useTokenWithFreshBalance.d.ts +0 -18
  297. package/dist/widget/hooks/useTokenWithFreshBalance.d.ts.map +0 -1
  298. package/src/onramp-client/trails-onramp.gen.ts +0 -1320
  299. package/src/prices.ts +0 -528
  300. package/src/useGasEstimation.ts +0 -147
  301. package/src/widget/assets/Binance_Icon_Logo.svg +0 -14
  302. package/src/widget/assets/Bitfinex_Icon_Logo.svg +0 -5
  303. package/src/widget/assets/Coinbase_Icon_Logo.svg +0 -1
  304. package/src/widget/assets/WalletConnect-logo-blue-bg.svg +0 -11
  305. package/src/widget/assets/sequence-logo.svg +0 -15
  306. package/src/widget/hooks/useCustomTokenFetch.tsx +0 -74
  307. package/src/widget/hooks/useTokenWithFreshBalance.ts +0 -246
package/src/chains.ts CHANGED
@@ -47,12 +47,17 @@ import {
47
47
  } from "viem/chains"
48
48
  import { somnia } from "./customChains.js"
49
49
 
50
- export function getShouldFetchVersions(): boolean {
51
- const trailsApiUrl = getConfig("trailsApiUrl")
50
+ export function getShouldFetchVersions(overrideTrailsApiUrl?: string): boolean {
51
+ const trailsApiUrl = overrideTrailsApiUrl || getConfig("trailsApiUrl") || ""
52
+ const normalized = trailsApiUrl.toLowerCase()
53
+
52
54
  const isDev =
53
- trailsApiUrl?.includes("dev2-trails-api.sequence-dev.app") === true
55
+ normalized.includes("dev-trails-api.sequence-dev.app") ||
56
+ normalized.includes("dev2-trails-api.sequence-dev.app")
57
+ const isLocal =
58
+ normalized.includes("localhost") || normalized.includes("127.0.0.1")
54
59
 
55
- return isDev
60
+ return isDev || isLocal
56
61
  }
57
62
 
58
63
  // Extended Chain type with imageUrl
@@ -214,15 +219,21 @@ function createHttpTransport(
214
219
  chainId: number,
215
220
  trailsApiKey?: string,
216
221
  sequenceNodeGatewayUrl?: string,
222
+ retryCount?: number,
217
223
  ) {
224
+ const transportOptions =
225
+ retryCount === undefined
226
+ ? TRANSPORT_OPTIONS
227
+ : { ...TRANSPORT_OPTIONS, retryCount }
228
+
218
229
  if (trailsApiKey && sequenceNodeGatewayUrl) {
219
230
  const rpcUrl = getRpcUrl(chainId, trailsApiKey, sequenceNodeGatewayUrl)
220
231
  if (rpcUrl) {
221
- return http(rpcUrl, TRANSPORT_OPTIONS)
232
+ return http(rpcUrl, transportOptions)
222
233
  }
223
234
  }
224
235
 
225
- return http(undefined, TRANSPORT_OPTIONS)
236
+ return http(undefined, transportOptions)
226
237
  }
227
238
 
228
239
  export function getChainTransport(
@@ -231,12 +242,14 @@ export function getChainTransport(
231
242
  trailsApiKey?: string
232
243
  sequenceNodeGatewayUrl?: string
233
244
  },
245
+ retryCount?: number,
234
246
  ) {
235
247
  const resolvedConfig = config ?? getConfig()
236
248
  return createHttpTransport(
237
249
  chainId,
238
250
  resolvedConfig.trailsApiKey,
239
251
  resolvedConfig.sequenceNodeGatewayUrl,
252
+ retryCount,
240
253
  )
241
254
  }
242
255
 
@@ -244,21 +257,25 @@ export function getChainTransport(
244
257
  * Create a public RPC client for a chain using Sequence RPC URLs
245
258
  * This is a temporary solution to use global config for RPC URLs
246
259
  * @param chainId - The chain ID to create the public client for
260
+ * @param retryCount - The number of retry attempts for the RPC client
247
261
  * @returns Viem PublicClient configured with Sequence RPC URL if available
248
262
  */
249
- export function getChainRpcClient(chainId: number): PublicClient {
263
+ export function getChainRpcClient(
264
+ chainId: number,
265
+ retryCount?: number,
266
+ ): PublicClient {
250
267
  const chainInfo = getChainInfo(chainId)
251
268
  if (!chainInfo) {
252
269
  logger.console.warn(
253
270
  `[trails-sdk] Chain ${chainId} not found. Falling back to a generic public client.`,
254
271
  )
255
272
  return createPublicClient({
256
- transport: getChainTransport(chainId),
273
+ transport: getChainTransport(chainId, undefined, retryCount),
257
274
  })
258
275
  }
259
276
  return createPublicClient({
260
277
  chain: chainInfo,
261
- transport: getChainTransport(chainId),
278
+ transport: getChainTransport(chainId, undefined, retryCount),
262
279
  })
263
280
  }
264
281
 
package/src/constants.ts CHANGED
@@ -50,6 +50,8 @@ export const PROD_TRAILS_APP_URL = "https://app.trails.build"
50
50
  // when trails is used inside of the sequence wallet app.
51
51
  export const PROD_SEQUENCE_API_URL = "https://api.sequence.app"
52
52
 
53
+ export const PROD_KEYMACHINE_URL = "https://keymachine.sequence.app"
54
+
53
55
  export const DATABEAT_SERVER = "https://databeat.sequence.app"
54
56
  export const DATABEAT_KEY =
55
57
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJzZXEtdHJhaWxzIiwiZXhwIjoyMDI4MTIwOTg4fQ.KZIjEziul_nZ4kjEXudvfqeWmVekc5ftXKx_EqDrmZU"
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useEffect } from "react"
1
+ import { useState, useCallback } from "react"
2
2
  import type { Token } from "./tokens.js"
3
3
  import { logger } from "./logger.js"
4
4
 
@@ -90,12 +90,6 @@ export function useCustomTokens(): {
90
90
  return getCustomTokensFromStorage()
91
91
  })
92
92
 
93
- // Sync with localStorage on mount
94
- useEffect(() => {
95
- const stored = getCustomTokensFromStorage()
96
- setCustomTokens(stored)
97
- }, [])
98
-
99
93
  const addCustomToken = useCallback((token: Token) => {
100
94
  setCustomTokens((prev) => {
101
95
  // Check if token already exists (same chainId + contractAddress)
@@ -111,6 +105,27 @@ export function useCustomTokens(): {
111
105
 
112
106
  let updated: Token[]
113
107
  if (existingIndex >= 0) {
108
+ const existingToken = prev[existingIndex]
109
+ if (!existingToken) {
110
+ return prev
111
+ }
112
+
113
+ // Avoid unnecessary state updates when token payload is unchanged.
114
+ const isSameTokenData =
115
+ existingToken.symbol === tokenWithFlag.symbol &&
116
+ existingToken.name === tokenWithFlag.name &&
117
+ existingToken.decimals === tokenWithFlag.decimals &&
118
+ (existingToken.chainId || 0) === (tokenWithFlag.chainId || 0) &&
119
+ normalizeAddress(existingToken.contractAddress) ===
120
+ normalizeAddress(tokenWithFlag.contractAddress) &&
121
+ existingToken.chainName === tokenWithFlag.chainName &&
122
+ existingToken.imageUrl === tokenWithFlag.imageUrl &&
123
+ existingToken.isCustomToken === true
124
+
125
+ if (isSameTokenData) {
126
+ return prev
127
+ }
128
+
114
129
  // Update existing token
115
130
  updated = [...prev]
116
131
  updated[existingIndex] = tokenWithFlag
package/src/error.ts CHANGED
@@ -138,6 +138,10 @@ export function getIsQuoteInputError(err: unknown) {
138
138
  return isQuoteInputError
139
139
  }
140
140
 
141
+ export function getIsHighPriceImpactError(err: unknown) {
142
+ return /HighPriceImpact|high price impact/gi.test(getFullErrorMessage(err))
143
+ }
144
+
141
145
  export function getIsInsufficientLiquidityError(err: unknown) {
142
146
  const isInsufficientLiquidity =
143
147
  /insufficient liquidity|higher than the available liquidity/gi.test(
@@ -243,6 +247,9 @@ export function getPrettifiedErrorMessage(
243
247
  if (fullErrorMessage.toLowerCase().includes("transaction aborted")) {
244
248
  return "The transaction was aborted. Please try again."
245
249
  }
250
+ if (getIsHighPriceImpactError(err)) {
251
+ return "This quote is unavailable due to high price impact (>30%) on a large transfer. Try a smaller amount."
252
+ }
246
253
  const isOnrampAmountTooLow = getIsOnrampAmountTooLowError(err)
247
254
  if (isOnrampAmountTooLow) {
248
255
  // Try to extract minimum amount from error message
package/src/gasless.ts CHANGED
@@ -9,6 +9,7 @@ import type {
9
9
  import { encodeFunctionData, erc20Abi, getAddress, parseAbi } from "viem"
10
10
  import { PERMIT_ABI, TRANSFER_ABI, TRANSFER_FROM_ABI } from "./abi.js"
11
11
  import { attemptSwitchChain } from "./chainSwitch.js"
12
+ import { getChainRpcClient } from "./chains.js"
12
13
  import { logger } from "./logger.js"
13
14
  import { checkProviderHealth, signWithTimeout } from "./walletUtils.js"
14
15
  import { toSeconds, now, HOUR_S } from "./utils/time.js"
@@ -96,7 +97,6 @@ export function getTransferCalldata({
96
97
  }
97
98
 
98
99
  export type GetPermitSignatureParams = {
99
- publicClient: PublicClient
100
100
  walletClient: WalletClient
101
101
  signer: `0x${string}`
102
102
  spender: `0x${string}`
@@ -107,7 +107,6 @@ export type GetPermitSignatureParams = {
107
107
  }
108
108
 
109
109
  export async function getPermitSignature({
110
- publicClient,
111
110
  walletClient,
112
111
  signer,
113
112
  spender,
@@ -126,6 +125,10 @@ export async function getPermitSignature({
126
125
  throw new Error("No account found")
127
126
  }
128
127
 
128
+ // Use a dedicated read client with no retries for permit domain probing.
129
+ // This avoids waiting on repeated deterministic failures (e.g. missing eip712Domain()).
130
+ const publicClient = getChainRpcClient(chain.id, 0)
131
+
129
132
  // Validate that the connected wallet matches the token owner
130
133
  if (!addressEqual(walletClient.account.address, signer)) {
131
134
  throw new Error(
package/src/index.ts CHANGED
@@ -140,15 +140,17 @@ export { getCurrencyInfo } from "./utils/fiat.js"
140
140
  export {
141
141
  getTokenPrice,
142
142
  getTokenPrices,
143
- useTokenPrice,
144
- useTokenPrices,
145
143
  invalidateTokenPricesCache,
144
+ priceQueries,
145
+ } from "./query/price.queries.js"
146
+ export { useTokenPrice, useTokenPrices } from "./query/price.hooks.js"
147
+ export {
146
148
  calcAmountUsdPrice,
147
149
  normalizeNumber,
148
150
  formatTvl,
149
151
  isValidNumeric,
150
152
  isValidInteger,
151
- } from "./prices.js"
153
+ } from "./utils/format.js"
152
154
  export { getTxTimeDiff } from "./transactions.js"
153
155
  export { useCommitIntent, useExecuteIntent } from "./mutations.js"
154
156
  export type { Mode } from "./widget/hooks/useViewManager.js"
@@ -160,6 +162,7 @@ export type {
160
162
  SequenceEnv,
161
163
  } from "./widget/providers/TrailsProvider.js"
162
164
  export { logger, getMinLogLevel } from "./logger.js"
165
+ export * from "./onramp/index.js"
163
166
  export {
164
167
  getTrailsClient,
165
168
  useTrailsClient,
@@ -182,8 +185,8 @@ export type {
182
185
  BuildRefundTransactionWithSignatureParams,
183
186
  UseIntentRecoverParams,
184
187
  UseIntentRecoverReturn,
185
- UseIntentRecoverWithSignatureParams,
186
- UseIntentRecoverWithSignatureReturn,
188
+ UseIntentRecoverWithAddressParams,
189
+ UseIntentRecoverWithAddressReturn,
187
190
  } from "./recover.js"
188
191
  export type {
189
192
  IntentReceipt,
package/src/intents.ts CHANGED
@@ -18,8 +18,9 @@ import type {
18
18
  TransactionStateInfo,
19
19
  } from "@0xtrails/api"
20
20
  import { logger } from "./logger.js"
21
- import { IntentProtocolVersion, IntentSource, JsonEncode } from "@0xtrails/api"
21
+ import { IntentProtocolVersion, JsonEncode } from "@0xtrails/api"
22
22
  import type { TrailsClient } from "./trailsClient.js"
23
+ import type { KeyMachineClient } from "./keyMachineClient.js"
23
24
  import { getIntentStatusFromError } from "./error.js"
24
25
 
25
26
  import { Config, type Context, Payload } from "@0xsequence/wallet-primitives"
@@ -46,7 +47,7 @@ import { getChainInfo, getChainRpcClient } from "./chains.js"
46
47
  import { attemptSwitchChain } from "./chainSwitch.js"
47
48
  import { SEQUENCE_V3_CONTRACT_ADDRESSES } from "./constants.js"
48
49
  import { getFullErrorMessage } from "./error.js"
49
- import { GAS_BUFFER, getFeeData } from "./estimate.js"
50
+ import { getFeeData } from "./estimate.js"
50
51
  import { zeroAddress } from "viem"
51
52
  import { addressEqual, isNativeToken } from "./utils/address.js"
52
53
  import { sendWalletTransaction } from "./walletUtils.js"
@@ -251,10 +252,43 @@ export async function quoteIntent(
251
252
  }
252
253
  }
253
254
 
255
+ export async function getIntentConfigurationFromAddress(
256
+ keyMachineClient: KeyMachineClient,
257
+ intentAddress: Address.Address,
258
+ ): Promise<{
259
+ address: Address.Address
260
+ imageHash: Hex.Hex
261
+ config: Config.Config
262
+ }> {
263
+ const deployConfig = await keyMachineClient.getDeploy(intentAddress)
264
+ if (!deployConfig) {
265
+ throw new Error("Deploy config not found")
266
+ }
267
+ const { imageHash, context } = deployConfig
268
+ const config = await keyMachineClient.getConfiguration(imageHash)
269
+ if (!config) {
270
+ throw new Error("Configuration not found")
271
+ }
272
+ // Construct the address from the configuration as a double check
273
+ const derivedImageHash = Config.hashConfiguration(config)
274
+ const derivedAddress = calculateIntentAddressFromImageHash(
275
+ context,
276
+ derivedImageHash,
277
+ )
278
+ if (!Address.isEqual(derivedAddress, intentAddress)) {
279
+ throw new Error("Derived address does not match intent address")
280
+ }
281
+ return {
282
+ address: derivedAddress,
283
+ imageHash: Bytes.toHex(derivedImageHash),
284
+ config,
285
+ }
286
+ }
287
+
254
288
  export async function getIntentConfigurationFromCalls(
255
- trailsClient: TrailsClient,
256
- intentId: string,
257
- intentProtocolVersion: IntentProtocolVersion,
289
+ _trailsClient: TrailsClient,
290
+ _intentId: string,
291
+ intentProtocol: IntentProtocolVersion,
258
292
  mainSigner: string,
259
293
  checkpoint: number,
260
294
  calls: IntentCalls,
@@ -268,57 +302,31 @@ export async function getIntentConfigurationFromCalls(
268
302
  logger.console.log(
269
303
  "[trails-sdk] [intent-protocol] === Intent Configuration Calculation ===",
270
304
  {
271
- intentProtocolVersion,
305
+ intentProtocol,
272
306
  mainSigner,
273
307
  checkpoint,
274
308
  callsCount: calls?.calls?.length ?? 0,
275
309
  isOrigin,
276
310
  calculationMethod:
277
- intentProtocolVersion === IntentProtocolVersion.v1
311
+ intentProtocol === IntentProtocolVersion.v1
278
312
  ? "client-side (Merkle tree)"
279
- : "server-side (API call)",
313
+ : "(NOT IMPLEMENTED)",
280
314
  },
281
315
  )
282
- if (intentProtocolVersion === IntentProtocolVersion.v1) {
316
+ if (intentProtocol === IntentProtocolVersion.v1) {
283
317
  logger.console.log(
284
318
  "[trails-sdk] [intent-protocol] v1: Calculating intent config client-side (deprecated)",
285
319
  {
286
- intentProtocolVersion,
320
+ intentProtocol,
287
321
  method: "buildMerkleTreeFromMembers + counterfactual address",
288
322
  },
289
323
  )
290
324
  return getIntentConfigurationFromCallsV1(mainSigner, calls, context)
291
325
  }
292
326
 
293
- logger.console.log(
294
- "[trails-sdk] [intent-protocol] v1.5: Fetching intent config from API",
295
- {
296
- intentProtocolVersion,
297
- intentId,
298
- isOrigin,
299
- },
327
+ throw new Error(
328
+ "Intent protocol v1.5 configuration derivation is not implemented",
300
329
  )
301
-
302
- const response = await trailsClient.getIntentConfig({
303
- intentId,
304
- intentSource: isOrigin ? IntentSource.ORIGIN : IntentSource.DESTINATION,
305
- })
306
-
307
- const config = fromServiceConfig(response.walletConfiguration)
308
-
309
- logger.console.log(
310
- "[trails-sdk] [intent-protocol] v1.5: Received config from API",
311
- {
312
- address: response.address.toString(),
313
- imageHash: response.imageHash.toString(),
314
- hasConfig: !!config,
315
- },
316
- )
317
- return {
318
- address: response.address.toString() as `0x${string}`,
319
- imageHash: response.imageHash.toString() as `0x${string}`,
320
- config,
321
- }
322
330
  }
323
331
 
324
332
  // @deprecated - v1 only
@@ -398,7 +406,7 @@ function calculateIntentAddressFromImageHash(
398
406
  export async function calculateOriginAndDestinationIntentAddresses(
399
407
  trailsClient: TrailsClient,
400
408
  intentId: string,
401
- intentProtocolVersion: IntentProtocolVersion,
409
+ intentProtocol: IntentProtocolVersion,
402
410
  mainSigner: string,
403
411
  checkpoint: number,
404
412
  calls: Array<IntentCalls>,
@@ -429,7 +437,7 @@ export async function calculateOriginAndDestinationIntentAddresses(
429
437
  await getIntentConfigurationFromCalls(
430
438
  trailsClient,
431
439
  intentId,
432
- intentProtocolVersion,
440
+ intentProtocol,
433
441
  mainSigner,
434
442
  checkpoint,
435
443
  originCalls[0]!,
@@ -449,7 +457,7 @@ export async function calculateOriginAndDestinationIntentAddresses(
449
457
  const { address } = await getIntentConfigurationFromCalls(
450
458
  trailsClient,
451
459
  intentId,
452
- intentProtocolVersion,
460
+ intentProtocol,
453
461
  mainSigner,
454
462
  checkpoint,
455
463
  originCalls[0]!,
@@ -650,8 +658,8 @@ export async function sendOriginTransaction(
650
658
  }
651
659
  const publicClient = getChainRpcClient(chainInfo.id)
652
660
 
653
- // Use provided gasLimit if available, otherwise estimate
654
- let gasLimit: bigint
661
+ // Use provided gasLimit if available, otherwise let the wallet estimate
662
+ let gasLimit: bigint | undefined
655
663
  if (originParams.gasLimit) {
656
664
  gasLimit = originParams.gasLimit
657
665
  logger.console.log(
@@ -659,22 +667,8 @@ export async function sendOriginTransaction(
659
667
  gasLimit,
660
668
  )
661
669
  } else {
662
- const estimatedGasLimit = await publicClient.estimateGas({
663
- account: account,
664
- to: originParams.to as `0x${string}`,
665
- data: originParams.data as `0x${string}`,
666
- value: BigInt(originParams.value),
667
- })
668
-
669
- gasLimit = estimatedGasLimit + GAS_BUFFER
670
670
  logger.console.log(
671
- "[trails-sdk][gas-estimation] estimated gasLimit in sendOriginTransaction:",
672
- gasLimit,
673
- "(estimated:",
674
- estimatedGasLimit,
675
- "buffer:",
676
- GAS_BUFFER,
677
- ")",
671
+ "[trails-sdk][gas-estimation] no gasLimit provided, let wallet estimate",
678
672
  )
679
673
  }
680
674
 
@@ -726,7 +720,9 @@ export async function sendOriginTransaction(
726
720
  data: originParams.data as `0x${string}`,
727
721
  value: BigInt(originParams.value),
728
722
  chain: originParams.chain,
729
- gas: gasLimit,
723
+ }
724
+ if (gasLimit) {
725
+ txParams.gas = gasLimit
730
726
  }
731
727
 
732
728
  // Add fee parameters based on transaction type
@@ -909,7 +905,7 @@ function buildMerkleTreeFromMembers(
909
905
  return currentLevel[0]!
910
906
  }
911
907
 
912
- function fromServiceConfig(config: any): Config.Config {
908
+ function _fromServiceConfig(config: any): Config.Config {
913
909
  if (config.checkpointer !== undefined) {
914
910
  Address.assert(config.checkpointer)
915
911
  }
@@ -0,0 +1,29 @@
1
+ import { useMemo } from "react"
2
+ import { KeyMachine } from "./keymachine/index.js"
3
+ import { useTrails } from "./widget/providers/TrailsProvider.js"
4
+
5
+ export type KeyMachineClientConfig = {
6
+ hostname?: string
7
+ }
8
+
9
+ export class KeyMachineClient extends KeyMachine {}
10
+
11
+ export function getKeyMachineClient({
12
+ hostname,
13
+ }: KeyMachineClientConfig): KeyMachine {
14
+ return new KeyMachine(hostname)
15
+ }
16
+
17
+ export const useKeyMachineClient = (
18
+ configOverride?: Partial<KeyMachineClientConfig>,
19
+ ) => {
20
+ const trailsConfig = useTrails()
21
+
22
+ const keyMachineClient = useMemo(() => {
23
+ return getKeyMachineClient({
24
+ hostname: configOverride?.hostname || trailsConfig.keyMachineUrl,
25
+ })
26
+ }, [configOverride?.hostname, trailsConfig.keyMachineUrl])
27
+
28
+ return keyMachineClient
29
+ }
@@ -0,0 +1,175 @@
1
+ import type {
2
+ Config,
3
+ Context,
4
+ GenericTree,
5
+ } from "@0xsequence/wallet-primitives"
6
+ import { Address, Hex } from "ox"
7
+ import {
8
+ KeyMachine as KeyMachineService,
9
+ type Fetch,
10
+ } from "./key-machine.gen.js"
11
+
12
+ export class KeyMachine {
13
+ private readonly service: KeyMachineService
14
+
15
+ constructor(host = "https://keymachine.sequence.app", fetcher?: Fetch) {
16
+ const resolvedFetch = fetcher ?? (globalThis as any).fetch
17
+ if (!resolvedFetch) {
18
+ throw new Error("fetch is not available")
19
+ }
20
+ this.service = new KeyMachineService(host, resolvedFetch)
21
+ }
22
+
23
+ async getConfiguration(
24
+ imageHash: Hex.Hex,
25
+ ): Promise<Config.Config | undefined> {
26
+ const { version, config } = await this.service.config({ imageHash })
27
+
28
+ if (version !== 3) {
29
+ throw new Error(
30
+ `invalid configuration version ${version}, expected version 3`,
31
+ )
32
+ }
33
+
34
+ return fromServiceConfig(config)
35
+ }
36
+
37
+ async getDeploy(
38
+ wallet: Address.Address,
39
+ ): Promise<{ imageHash: Hex.Hex; context: Context.Context } | undefined> {
40
+ const { deployHash, context } = await this.service.deployHash({ wallet })
41
+
42
+ Hex.assert(deployHash)
43
+ Address.assert(context.factory)
44
+ Address.assert(context.mainModule)
45
+ Address.assert(context.mainModuleUpgradable)
46
+ Hex.assert(context.walletCreationCode)
47
+
48
+ return {
49
+ imageHash: deployHash,
50
+ context: {
51
+ factory: context.factory,
52
+ stage1: context.mainModule,
53
+ stage2: context.mainModuleUpgradable,
54
+ creationCode: context.walletCreationCode,
55
+ },
56
+ }
57
+ }
58
+
59
+ async getTree(rootHash: Hex.Hex): Promise<GenericTree.Tree | undefined> {
60
+ const { version, tree } = await this.service.tree({ imageHash: rootHash })
61
+
62
+ if (version !== 3) {
63
+ throw new Error(`invalid tree version ${version}, expected version 3`)
64
+ }
65
+
66
+ return fromServiceTree(tree)
67
+ }
68
+ }
69
+
70
+ type ServiceConfig = {
71
+ threshold: number | string
72
+ checkpoint: number | string
73
+ checkpointer?: string
74
+ tree: ServiceConfigTree
75
+ }
76
+
77
+ type ServiceConfigTree =
78
+ | [ServiceConfigTree, ServiceConfigTree]
79
+ | string
80
+ | { weight: number | string; address: string; imageHash?: string }
81
+ | {
82
+ weight: number | string
83
+ threshold: number | string
84
+ tree: ServiceConfigTree
85
+ }
86
+ | { subdigest: string; isAnyAddress?: boolean }
87
+
88
+ type ServiceTree = string | { data: string } | ServiceTree[]
89
+
90
+ function fromServiceConfig(config: ServiceConfig): Config.Config {
91
+ if (config.checkpointer !== undefined) {
92
+ Address.assert(config.checkpointer)
93
+ }
94
+
95
+ return {
96
+ threshold: BigInt(config.threshold),
97
+ checkpoint: BigInt(config.checkpoint),
98
+ checkpointer: config.checkpointer,
99
+ topology: fromServiceConfigTree(config.tree),
100
+ }
101
+ }
102
+
103
+ function fromServiceConfigTree(tree: ServiceConfigTree): Config.Topology {
104
+ switch (typeof tree) {
105
+ case "string":
106
+ Hex.assert(tree)
107
+ return tree
108
+
109
+ case "object":
110
+ if (Array.isArray(tree)) {
111
+ return [fromServiceConfigTree(tree[0]), fromServiceConfigTree(tree[1])]
112
+ }
113
+
114
+ if ("weight" in tree) {
115
+ if ("address" in tree) {
116
+ Address.assert(tree.address)
117
+
118
+ if (tree.imageHash) {
119
+ Hex.assert(tree.imageHash)
120
+ return {
121
+ type: "sapient-signer",
122
+ address: tree.address,
123
+ weight: BigInt(tree.weight),
124
+ imageHash: tree.imageHash,
125
+ }
126
+ } else {
127
+ return {
128
+ type: "signer",
129
+ address: tree.address,
130
+ weight: BigInt(tree.weight),
131
+ }
132
+ }
133
+ }
134
+
135
+ if ("tree" in tree) {
136
+ return {
137
+ type: "nested",
138
+ weight: BigInt(tree.weight),
139
+ threshold: BigInt(tree.threshold),
140
+ tree: fromServiceConfigTree(tree.tree),
141
+ }
142
+ }
143
+ }
144
+
145
+ if ("subdigest" in tree) {
146
+ Hex.assert(tree.subdigest)
147
+ return {
148
+ type: tree.isAnyAddress ? "any-address-subdigest" : "subdigest",
149
+ digest: tree.subdigest,
150
+ }
151
+ }
152
+ }
153
+
154
+ throw new Error(`unknown config tree '${JSON.stringify(tree)}'`)
155
+ }
156
+
157
+ function fromServiceTree(tree: ServiceTree): GenericTree.Tree {
158
+ switch (typeof tree) {
159
+ case "string":
160
+ Hex.assert(tree)
161
+ return tree
162
+
163
+ case "object":
164
+ if (Array.isArray(tree)) {
165
+ return tree.map(fromServiceTree) as GenericTree.Branch
166
+ }
167
+
168
+ if ("data" in tree) {
169
+ Hex.assert(tree.data)
170
+ return { type: "leaf", value: Hex.toBytes(tree.data) }
171
+ }
172
+ }
173
+
174
+ throw new Error(`unknown tree '${JSON.stringify(tree)}'`)
175
+ }