@rainlanguage/ui-components 0.0.1-alpha.21 → 0.0.1-alpha.211

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 (260) hide show
  1. package/dist/__fixtures__/settings.yaml +125 -0
  2. package/dist/__mocks__/CodeMirrorRainlang.svelte +4 -0
  3. package/dist/__mocks__/CodeMirrorRainlang.svelte.d.ts +18 -0
  4. package/dist/__mocks__/MockComponent.svelte +4 -0
  5. package/dist/__mocks__/MockComponent.svelte.d.ts +3 -1
  6. package/dist/__mocks__/stores.d.ts +47 -33
  7. package/dist/__mocks__/stores.js +61 -38
  8. package/dist/components/ButtonLoading.svelte +1 -1
  9. package/dist/components/ButtonVaultLink.svelte +11 -11
  10. package/dist/components/ButtonVaultLink.svelte.d.ts +4 -3
  11. package/dist/components/CheckboxInactiveOrdersVault.svelte +20 -0
  12. package/dist/components/CheckboxInactiveOrdersVault.svelte.d.ts +19 -0
  13. package/dist/components/CheckboxMyItemsOnly.svelte +3 -2
  14. package/dist/components/CheckboxMyItemsOnly.svelte.d.ts +2 -3
  15. package/dist/components/CheckboxZeroBalanceVault.svelte.d.ts +2 -2
  16. package/dist/components/CodeMirrorDotrain.svelte +4 -0
  17. package/dist/components/CodeMirrorDotrain.svelte.d.ts +1 -0
  18. package/dist/components/CodeMirrorRainlang.svelte +3 -12
  19. package/dist/components/CodeMirrorRainlang.svelte.d.ts +2 -2
  20. package/dist/components/EditableSpan.svelte +3 -14
  21. package/dist/components/EditableSpan.svelte.d.ts +0 -1
  22. package/dist/components/Hash.svelte +3 -3
  23. package/dist/components/License.svelte +5 -4
  24. package/dist/components/ListViewOrderbookFilters.svelte +45 -23
  25. package/dist/components/ListViewOrderbookFilters.svelte.d.ts +27 -22
  26. package/dist/components/LocalDbStatusBadge.svelte +27 -0
  27. package/dist/components/LocalDbStatusBadge.svelte.d.ts +19 -0
  28. package/dist/components/LocalDbStatusCard.svelte +40 -0
  29. package/dist/components/LocalDbStatusCard.svelte.d.ts +20 -0
  30. package/dist/components/LocalDbStatusModal.svelte +103 -0
  31. package/dist/components/LocalDbStatusModal.svelte.d.ts +21 -0
  32. package/dist/components/OrderOrVaultHash.svelte +12 -12
  33. package/dist/components/OrderOrVaultHash.svelte.d.ts +4 -4
  34. package/dist/components/PageHeader.svelte +1 -1
  35. package/dist/components/TanstackAppTable.svelte +179 -28
  36. package/dist/components/TanstackAppTable.svelte.d.ts +14 -8
  37. package/dist/components/ToastDetail.svelte +42 -0
  38. package/dist/components/ToastDetail.svelte.d.ts +20 -0
  39. package/dist/components/Tooltip.svelte +8 -0
  40. package/dist/components/Tooltip.svelte.d.ts +21 -0
  41. package/dist/components/VaultBalanceChangeTypeFilter.svelte +23 -0
  42. package/dist/components/VaultBalanceChangeTypeFilter.svelte.d.ts +19 -0
  43. package/dist/components/VaultCard.svelte +18 -0
  44. package/dist/components/VaultCard.svelte.d.ts +19 -0
  45. package/dist/components/charts/LightweightChart.svelte +1 -1
  46. package/dist/components/charts/LightweightChart.svelte.d.ts +5 -5
  47. package/dist/components/charts/OrderTradesChart.svelte +300 -28
  48. package/dist/components/charts/OrderTradesChart.svelte.d.ts +4 -4
  49. package/dist/components/charts/TanstackLightweightChartLine.svelte +5 -9
  50. package/dist/components/charts/VaultBalanceChart.svelte +8 -26
  51. package/dist/components/charts/VaultBalanceChart.svelte.d.ts +1 -7
  52. package/dist/components/charts/transformAndSortData.d.ts +24 -0
  53. package/dist/components/charts/transformAndSortData.js +111 -0
  54. package/dist/components/checkbox/CheckboxActiveOrders.svelte +11 -0
  55. package/dist/components/checkbox/CheckboxActiveOrders.svelte.d.ts +19 -0
  56. package/dist/components/deployment/ButtonSelectOption.svelte +2 -0
  57. package/dist/components/deployment/ButtonSelectOption.svelte.d.ts +1 -0
  58. package/dist/components/deployment/ComposedRainlangModal.svelte +2 -1
  59. package/dist/components/deployment/ComposedRainlangModal.svelte.d.ts +1 -4
  60. package/dist/components/deployment/DeploymentSectionHeader.svelte +7 -4
  61. package/dist/components/deployment/DeploymentSteps.svelte +209 -216
  62. package/dist/components/deployment/DeploymentSteps.svelte.d.ts +6 -12
  63. package/dist/components/deployment/DeploymentTile.svelte +2 -2
  64. package/dist/components/deployment/DeploymentTile.svelte.d.ts +1 -1
  65. package/dist/components/deployment/DeploymentsSection.svelte +15 -22
  66. package/dist/components/deployment/DeploymentsSection.svelte.d.ts +3 -2
  67. package/dist/components/deployment/DepositInput.svelte +8 -10
  68. package/dist/components/deployment/DepositInput.svelte.d.ts +1 -2
  69. package/dist/components/deployment/DisclaimerModal.svelte +6 -7
  70. package/dist/components/deployment/FieldDefinitionInput.svelte +7 -11
  71. package/dist/components/deployment/FieldDefinitionInput.svelte.d.ts +1 -2
  72. package/dist/components/deployment/InvalidOrdersSection.svelte +17 -0
  73. package/dist/components/deployment/InvalidOrdersSection.svelte.d.ts +19 -0
  74. package/dist/components/deployment/{StrategyPage.svelte → OrderPage.svelte} +15 -24
  75. package/dist/components/deployment/OrderPage.svelte.d.ts +21 -0
  76. package/dist/components/deployment/SelectToken.svelte +125 -48
  77. package/dist/components/deployment/SelectToken.svelte.d.ts +4 -3
  78. package/dist/components/deployment/TokenBalance.svelte +19 -0
  79. package/dist/components/deployment/TokenBalance.svelte.d.ts +19 -0
  80. package/dist/components/deployment/TokenIOInput.svelte +25 -15
  81. package/dist/components/deployment/TokenIOInput.svelte.d.ts +3 -3
  82. package/dist/components/deployment/TokenSelectionModal.svelte +148 -0
  83. package/dist/components/deployment/TokenSelectionModal.svelte.d.ts +20 -0
  84. package/dist/components/deployment/{ValidStrategiesSection.svelte → ValidOrdersSection.svelte} +7 -7
  85. package/dist/components/deployment/ValidOrdersSection.svelte.d.ts +19 -0
  86. package/dist/components/deployment/VaultIdInformation.svelte +17 -0
  87. package/dist/components/deployment/VaultIdInformation.svelte.d.ts +21 -0
  88. package/dist/components/detail/OrderDetail.svelte +184 -80
  89. package/dist/components/detail/OrderDetail.svelte.d.ts +21 -15
  90. package/dist/components/detail/TanstackOrderQuote.svelte +92 -46
  91. package/dist/components/detail/TanstackOrderQuote.svelte.d.ts +14 -16
  92. package/dist/components/detail/VaultDetail.svelte +78 -77
  93. package/dist/components/detail/VaultDetail.svelte.d.ts +12 -18
  94. package/dist/components/dropdown/DropdownActiveNetworks.svelte +44 -0
  95. package/dist/components/dropdown/DropdownActiveNetworks.svelte.d.ts +19 -0
  96. package/dist/components/dropdown/DropdownCheckbox.svelte +4 -4
  97. package/dist/components/dropdown/DropdownOrderListAccounts.svelte +5 -2
  98. package/dist/components/dropdown/DropdownOrderListAccounts.svelte.d.ts +2 -3
  99. package/dist/components/dropdown/DropdownOrderbooksFilter.svelte +172 -0
  100. package/dist/components/dropdown/DropdownOrderbooksFilter.svelte.d.ts +25 -0
  101. package/dist/components/dropdown/DropdownTokensFilter.svelte +152 -0
  102. package/dist/components/dropdown/DropdownTokensFilter.svelte.d.ts +28 -0
  103. package/dist/components/icon/Refresh.svelte +2 -1
  104. package/dist/components/icon/Refresh.svelte.d.ts +1 -0
  105. package/dist/components/input/InputOrderHash.svelte +1 -1
  106. package/dist/components/input/InputOrderHash.svelte.d.ts +3 -3
  107. package/dist/components/input/InputRegistryUrl.svelte +36 -14
  108. package/dist/components/input/InputToken.svelte +2 -2
  109. package/dist/components/input/InputTokenAmount.svelte +16 -21
  110. package/dist/components/input/InputTokenAmount.svelte.d.ts +3 -3
  111. package/dist/components/tables/OrderAPY.svelte +6 -33
  112. package/dist/components/tables/OrderAPY.svelte.d.ts +1 -4
  113. package/dist/components/tables/OrderTradesListTable.svelte +84 -81
  114. package/dist/components/tables/OrderTradesListTable.svelte.d.ts +4 -4
  115. package/dist/components/tables/OrderVaultsVolTable.svelte +17 -22
  116. package/dist/components/tables/OrderVaultsVolTable.svelte.d.ts +2 -2
  117. package/dist/components/tables/OrdersListTable.svelte +200 -108
  118. package/dist/components/tables/OrdersListTable.svelte.d.ts +17 -21
  119. package/dist/components/tables/VaultBalanceChangesTable.svelte +83 -43
  120. package/dist/components/tables/VaultBalanceChangesTable.svelte.d.ts +13 -11
  121. package/dist/components/tables/VaultsListTable.svelte +268 -145
  122. package/dist/components/tables/VaultsListTable.svelte.d.ts +24 -32
  123. package/dist/components/transactions/FixedBottomTransaction.svelte +63 -0
  124. package/dist/components/transactions/FixedBottomTransaction.svelte.d.ts +16 -0
  125. package/dist/components/transactions/TransactionDetail.svelte +31 -0
  126. package/dist/components/transactions/TransactionDetail.svelte.d.ts +20 -0
  127. package/dist/components/transactions/TransactionList.svelte +17 -0
  128. package/dist/components/transactions/TransactionList.svelte.d.ts +16 -0
  129. package/dist/components/transactions/getStatusEmoji.d.ts +2 -0
  130. package/dist/components/transactions/getStatusEmoji.js +20 -0
  131. package/dist/components/wallet/WalletConnect.svelte +5 -4
  132. package/dist/components/wallet/WalletConnect.svelte.d.ts +0 -1
  133. package/dist/consts.d.ts +1 -0
  134. package/dist/consts.js +1 -0
  135. package/dist/errors/DeploymentStepsError.d.ts +8 -2
  136. package/dist/errors/DeploymentStepsError.js +7 -1
  137. package/dist/hooks/useGui.d.ts +1 -1
  138. package/dist/hooks/useGui.js +1 -1
  139. package/dist/hooks/useLocalDb.d.ts +3 -0
  140. package/dist/hooks/useLocalDb.js +10 -0
  141. package/dist/hooks/useRaindexClient.d.ts +3 -0
  142. package/dist/hooks/useRaindexClient.js +11 -0
  143. package/dist/index.d.ts +42 -19
  144. package/dist/index.js +41 -16
  145. package/dist/models/Transaction.d.ts +75 -0
  146. package/dist/models/Transaction.js +100 -0
  147. package/dist/providers/GuiProvider.svelte +1 -1
  148. package/dist/providers/GuiProvider.svelte.d.ts +1 -1
  149. package/dist/providers/LocalDbProvider.svelte +8 -0
  150. package/dist/providers/LocalDbProvider.svelte.d.ts +21 -0
  151. package/dist/providers/RaindexClientProvider.svelte +8 -0
  152. package/dist/providers/RaindexClientProvider.svelte.d.ts +21 -0
  153. package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte +8 -0
  154. package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte.d.ts +24 -0
  155. package/dist/providers/dotrainRegistry/context.d.ts +9 -0
  156. package/dist/providers/dotrainRegistry/context.js +40 -0
  157. package/dist/providers/dotrainRegistry/useDotrainRegistry.d.ts +5 -0
  158. package/dist/providers/dotrainRegistry/useDotrainRegistry.js +35 -0
  159. package/dist/providers/registry/RegistryManager.d.ts +65 -0
  160. package/dist/providers/registry/RegistryManager.js +133 -0
  161. package/dist/providers/registry/RegistryProvider.svelte +6 -0
  162. package/dist/providers/registry/RegistryProvider.svelte.d.ts +21 -0
  163. package/dist/providers/registry/context.d.ts +10 -0
  164. package/dist/providers/registry/context.js +46 -0
  165. package/dist/providers/registry/useRegistry.d.ts +7 -0
  166. package/dist/providers/registry/useRegistry.js +29 -0
  167. package/dist/providers/toasts/ToastProvider.svelte +17 -0
  168. package/dist/providers/toasts/ToastProvider.svelte.d.ts +18 -0
  169. package/dist/providers/toasts/context.d.ts +14 -0
  170. package/dist/providers/toasts/context.js +22 -0
  171. package/dist/providers/toasts/useToasts.d.ts +16 -0
  172. package/dist/providers/toasts/useToasts.js +63 -0
  173. package/dist/providers/transactions/TransactionManager.d.ts +235 -0
  174. package/dist/providers/transactions/TransactionManager.js +509 -0
  175. package/dist/providers/transactions/TransactionProvider.svelte +11 -0
  176. package/dist/providers/transactions/TransactionProvider.svelte.d.ts +24 -0
  177. package/dist/providers/transactions/context.d.ts +19 -0
  178. package/dist/providers/transactions/context.js +28 -0
  179. package/dist/providers/transactions/useTransactions.d.ts +13 -0
  180. package/dist/providers/transactions/useTransactions.js +18 -0
  181. package/dist/providers/wallet/WalletProvider.svelte +7 -0
  182. package/dist/providers/wallet/WalletProvider.svelte.d.ts +21 -0
  183. package/dist/providers/wallet/context.d.ts +10 -0
  184. package/dist/providers/wallet/context.js +47 -0
  185. package/dist/providers/wallet/useAccount.d.ts +8 -0
  186. package/dist/providers/wallet/useAccount.js +148 -0
  187. package/dist/queries/keys.d.ts +1 -0
  188. package/dist/queries/keys.js +1 -0
  189. package/dist/queries/queryClient.d.ts +1 -1
  190. package/dist/queries/queryClient.js +11 -6
  191. package/dist/services/awaitTransactionIndexing.d.ts +107 -0
  192. package/dist/services/awaitTransactionIndexing.js +58 -0
  193. package/dist/services/getExplorerLink.d.ts +1 -1
  194. package/dist/services/getExplorerLink.js +2 -4
  195. package/dist/services/handleShareChoices.d.ts +2 -2
  196. package/dist/services/handleShareChoices.js +7 -2
  197. package/dist/services/historicalOrderCharts.d.ts +2 -2
  198. package/dist/services/historicalOrderCharts.js +267 -333
  199. package/dist/services/index.d.ts +2 -1
  200. package/dist/services/index.js +2 -1
  201. package/dist/services/loadRegistryUrl.d.ts +2 -0
  202. package/dist/services/loadRegistryUrl.js +22 -0
  203. package/dist/services/pairTradesChartData.d.ts +47 -0
  204. package/dist/services/pairTradesChartData.js +190 -0
  205. package/dist/services/registry.d.ts +5 -5
  206. package/dist/services/registry.js +8 -208
  207. package/dist/services/time.d.ts +12 -0
  208. package/dist/services/time.js +88 -6
  209. package/dist/storesGeneric/cachedWritableStore.d.ts +57 -0
  210. package/dist/storesGeneric/cachedWritableStore.js +93 -0
  211. package/dist/types/account.d.ts +3 -0
  212. package/dist/types/appStores.d.ts +9 -14
  213. package/dist/types/modal.d.ts +26 -14
  214. package/dist/types/{strategy.d.ts → order.d.ts} +3 -3
  215. package/dist/types/order.js +1 -0
  216. package/dist/types/toast.d.ts +11 -0
  217. package/dist/types/toast.js +1 -0
  218. package/dist/types/tokenBalance.d.ts +6 -0
  219. package/dist/types/tokenBalance.js +1 -0
  220. package/dist/types/transaction.d.ts +66 -21
  221. package/dist/types/transaction.js +31 -1
  222. package/dist/utils/configHelpers.d.ts +4 -0
  223. package/dist/utils/configHelpers.js +21 -0
  224. package/dist/utils/constructHashLink.d.ts +24 -0
  225. package/dist/utils/constructHashLink.js +115 -0
  226. package/dist/utils/getNetworkName.d.ts +1 -0
  227. package/dist/utils/getNetworkName.js +13 -0
  228. package/dist/utils/number.d.ts +0 -7
  229. package/dist/utils/number.js +0 -27
  230. package/dist/utils/tokens.d.ts +2 -0
  231. package/dist/utils/tokens.js +3 -0
  232. package/dist/utils/vaultBalanceChangeLabels.d.ts +4 -0
  233. package/dist/utils/vaultBalanceChangeLabels.js +18 -0
  234. package/package.json +39 -34
  235. package/dist/__fixtures__/orderDetail.d.ts +0 -99
  236. package/dist/__fixtures__/orderDetail.js +0 -204
  237. package/dist/__fixtures__/settings-12-11-24.json +0 -160
  238. package/dist/__mocks__/mockTransactionStore.d.ts +0 -22
  239. package/dist/__mocks__/mockTransactionStore.js +0 -56
  240. package/dist/__mocks__/settings.d.ts +0 -3
  241. package/dist/__mocks__/settings.js +0 -37
  242. package/dist/components/deployment/InvalidStrategiesSection.svelte +0 -19
  243. package/dist/components/deployment/InvalidStrategiesSection.svelte.d.ts +0 -19
  244. package/dist/components/deployment/StrategyPage.svelte.d.ts +0 -19
  245. package/dist/components/deployment/ValidStrategiesSection.svelte.d.ts +0 -19
  246. package/dist/components/deployment/getDeploymentTransactionArgs.d.ts +0 -17
  247. package/dist/components/deployment/getDeploymentTransactionArgs.js +0 -28
  248. package/dist/components/detail/DepositOrWithdrawButtons.svelte +0 -44
  249. package/dist/components/detail/DepositOrWithdrawButtons.svelte.d.ts +0 -26
  250. package/dist/components/dropdown/DropdownActiveSubgraphs.svelte +0 -38
  251. package/dist/components/dropdown/DropdownActiveSubgraphs.svelte.d.ts +0 -21
  252. package/dist/components/dropdown/DropdownOrderStatus.svelte +0 -31
  253. package/dist/components/dropdown/DropdownOrderStatus.svelte.d.ts +0 -19
  254. package/dist/stores/transactionStore.d.ts +0 -98
  255. package/dist/stores/transactionStore.js +0 -303
  256. package/dist/utils/time.d.ts +0 -12
  257. package/dist/utils/time.js +0 -27
  258. package/dist/utils/vault.d.ts +0 -2
  259. package/dist/utils/vault.js +0 -29
  260. /package/dist/types/{strategy.js → account.js} +0 -0
@@ -1,2 +1,3 @@
1
- export { fetchParseRegistry, fetchRegistryDotrains, validateStrategies } from './registry';
1
+ export { fetchParseRegistry, fetchRegistryDotrains, validateOrders } from './registry';
2
+ export { loadRegistryUrl } from './loadRegistryUrl';
2
3
  export type { RegistryDotrain, RegistryFile } from './registry';
@@ -1 +1,2 @@
1
- export { fetchParseRegistry, fetchRegistryDotrains, validateStrategies } from './registry';
1
+ export { fetchParseRegistry, fetchRegistryDotrains, validateOrders } from './registry';
2
+ export { loadRegistryUrl } from './loadRegistryUrl';
@@ -0,0 +1,2 @@
1
+ import { RegistryManager } from '../providers/registry/RegistryManager';
2
+ export declare function loadRegistryUrl(url: string, registryManager: RegistryManager): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { RegistryManager } from '../providers/registry/RegistryManager';
2
+ import { DotrainRegistry } from '@rainlanguage/orderbook';
3
+ export async function loadRegistryUrl(url, registryManager) {
4
+ if (!url) {
5
+ throw new Error('No URL provided');
6
+ }
7
+ if (!registryManager) {
8
+ throw new Error('Registry manager is required');
9
+ }
10
+ try {
11
+ const validationResult = await DotrainRegistry.validate(url);
12
+ if (validationResult.error) {
13
+ throw new Error(validationResult.error.readableMsg);
14
+ }
15
+ registryManager.setRegistry(url);
16
+ window.location.reload();
17
+ }
18
+ catch (e) {
19
+ const errorMessage = e instanceof Error ? e.message : 'Failed to update registry URL';
20
+ throw new Error(errorMessage);
21
+ }
22
+ }
@@ -0,0 +1,47 @@
1
+ import type { RaindexTrade, RaindexVaultToken } from '@rainlanguage/orderbook';
2
+ import type { UTCTimestamp } from 'lightweight-charts';
3
+ export declare const BUCKET_SECONDS_24_HOURS = 900;
4
+ export declare const BUCKET_SECONDS_7_DAYS = 3600;
5
+ export declare const BUCKET_SECONDS_30_DAYS = 14400;
6
+ export declare const BUCKET_SECONDS_1_YEAR = 86400;
7
+ export declare const CHART_COLORS: {
8
+ readonly BUY_VOLUME: "#26a69a";
9
+ readonly BUY_VOLUME_TRANSPARENT: "rgba(38, 166, 154, 0.5)";
10
+ readonly SELL_VOLUME: "#ef5350";
11
+ readonly SELL_VOLUME_TRANSPARENT: "rgba(239, 83, 80, 0.5)";
12
+ readonly PRICE_LINE: "#5c6bc0";
13
+ readonly ZERO_LINE: "#888888";
14
+ };
15
+ export declare function getBucketSecondsForTimeDelta(timeDeltaSeconds: number): number;
16
+ export type TradingPair = {
17
+ baseToken: RaindexVaultToken;
18
+ quoteToken: RaindexVaultToken;
19
+ };
20
+ export type PricePoint = {
21
+ time: UTCTimestamp;
22
+ value: number;
23
+ };
24
+ export type VolumePoint = {
25
+ time: UTCTimestamp;
26
+ value: number;
27
+ color?: string;
28
+ };
29
+ export type PairTradesChartData = {
30
+ pricePoints: PricePoint[];
31
+ buyVolumePoints: VolumePoint[];
32
+ sellVolumePoints: VolumePoint[];
33
+ };
34
+ export declare function extractPairsFromTrades(trades: RaindexTrade[]): TradingPair[];
35
+ export declare function getDefaultPair(trades: RaindexTrade[]): TradingPair | null;
36
+ export declare function getTokenLabel(token: RaindexVaultToken): string;
37
+ export declare function pairsAreEqual(pairA: TradingPair, pairB: TradingPair): boolean;
38
+ export declare function findPairIndex(pairs: TradingPair[], targetPair: TradingPair): number;
39
+ export declare function flipTradingPair(pair: TradingPair): TradingPair;
40
+ export declare function formatChartTimestamp(timestampSeconds: number, timeDeltaSeconds: number): string;
41
+ export type TransformPairTradesInput = {
42
+ trades: RaindexTrade[];
43
+ baseTokenAddress: string;
44
+ quoteTokenAddress: string;
45
+ timeDeltaSeconds: number;
46
+ };
47
+ export declare function transformPairTrades(input: TransformPairTradesInput): PairTradesChartData;
@@ -0,0 +1,190 @@
1
+ import { sortBy } from 'lodash';
2
+ import { TIME_DELTA_24_HOURS, TIME_DELTA_7_DAYS, TIME_DELTA_30_DAYS } from './time';
3
+ export const BUCKET_SECONDS_24_HOURS = 900;
4
+ export const BUCKET_SECONDS_7_DAYS = 3600;
5
+ export const BUCKET_SECONDS_30_DAYS = 14400;
6
+ export const BUCKET_SECONDS_1_YEAR = 86400;
7
+ export const CHART_COLORS = {
8
+ BUY_VOLUME: '#26a69a',
9
+ BUY_VOLUME_TRANSPARENT: 'rgba(38, 166, 154, 0.5)',
10
+ SELL_VOLUME: '#ef5350',
11
+ SELL_VOLUME_TRANSPARENT: 'rgba(239, 83, 80, 0.5)',
12
+ PRICE_LINE: '#5c6bc0',
13
+ ZERO_LINE: '#888888'
14
+ };
15
+ export function getBucketSecondsForTimeDelta(timeDeltaSeconds) {
16
+ if (timeDeltaSeconds <= TIME_DELTA_24_HOURS)
17
+ return BUCKET_SECONDS_24_HOURS;
18
+ if (timeDeltaSeconds <= TIME_DELTA_7_DAYS)
19
+ return BUCKET_SECONDS_7_DAYS;
20
+ if (timeDeltaSeconds <= TIME_DELTA_30_DAYS)
21
+ return BUCKET_SECONDS_30_DAYS;
22
+ return BUCKET_SECONDS_1_YEAR;
23
+ }
24
+ function getTokenAddressLower(trade, which) {
25
+ const change = which === 'in' ? trade.inputVaultBalanceChange : trade.outputVaultBalanceChange;
26
+ return change.token.address.toLowerCase();
27
+ }
28
+ function tradeMatchesPair(trade, baseTokenAddress, quoteTokenAddress) {
29
+ const inAddr = getTokenAddressLower(trade, 'in');
30
+ const outAddr = getTokenAddressLower(trade, 'out');
31
+ const baseLower = baseTokenAddress.toLowerCase();
32
+ const quoteLower = quoteTokenAddress.toLowerCase();
33
+ return ((inAddr === baseLower && outAddr === quoteLower) ||
34
+ (inAddr === quoteLower && outAddr === baseLower));
35
+ }
36
+ function getTradeAmounts(trade, baseTokenAddress) {
37
+ const inAddr = getTokenAddressLower(trade, 'in');
38
+ const baseLower = baseTokenAddress.toLowerCase();
39
+ const inFormattedAmount = trade.inputVaultBalanceChange.formattedAmount;
40
+ const outFormattedAmount = trade.outputVaultBalanceChange.formattedAmount;
41
+ const inAmt = Math.abs(parseFloat(inFormattedAmount));
42
+ const outAmt = Math.abs(parseFloat(outFormattedAmount));
43
+ if (!Number.isFinite(inAmt) || !Number.isFinite(outAmt))
44
+ return null;
45
+ const isBuy = inAddr === baseLower;
46
+ return {
47
+ baseAmount: isBuy ? inAmt : outAmt,
48
+ quoteAmount: isBuy ? outAmt : inAmt,
49
+ isBuy
50
+ };
51
+ }
52
+ export function extractPairsFromTrades(trades) {
53
+ const pairMap = new Map();
54
+ for (const trade of trades) {
55
+ const inToken = trade.inputVaultBalanceChange.token;
56
+ const outToken = trade.outputVaultBalanceChange.token;
57
+ const inAddr = inToken.address.toLowerCase();
58
+ const outAddr = outToken.address.toLowerCase();
59
+ const [firstAddr, secondAddr] = inAddr < outAddr ? [inAddr, outAddr] : [outAddr, inAddr];
60
+ const pairKey = `${firstAddr}-${secondAddr}`;
61
+ if (!pairMap.has(pairKey)) {
62
+ const [baseToken, quoteToken] = inAddr < outAddr ? [inToken, outToken] : [outToken, inToken];
63
+ pairMap.set(pairKey, { baseToken, quoteToken });
64
+ }
65
+ }
66
+ return Array.from(pairMap.values());
67
+ }
68
+ export function getDefaultPair(trades) {
69
+ if (trades.length === 0)
70
+ return null;
71
+ const sortedTrades = sortBy(trades, (t) => Number(t.timestamp));
72
+ const oldestTrade = sortedTrades[0];
73
+ const inToken = oldestTrade.inputVaultBalanceChange.token;
74
+ const outToken = oldestTrade.outputVaultBalanceChange.token;
75
+ const inAddr = inToken.address.toLowerCase();
76
+ const outAddr = outToken.address.toLowerCase();
77
+ if (inAddr < outAddr) {
78
+ return { baseToken: inToken, quoteToken: outToken };
79
+ }
80
+ else {
81
+ return { baseToken: outToken, quoteToken: inToken };
82
+ }
83
+ }
84
+ export function getTokenLabel(token) {
85
+ if (token.symbol && token.symbol.trim() !== '') {
86
+ return token.symbol;
87
+ }
88
+ const addr = token.address;
89
+ if (addr.length >= 10) {
90
+ return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
91
+ }
92
+ return addr;
93
+ }
94
+ export function pairsAreEqual(pairA, pairB) {
95
+ return (pairA.baseToken.address.toLowerCase() === pairB.baseToken.address.toLowerCase() &&
96
+ pairA.quoteToken.address.toLowerCase() === pairB.quoteToken.address.toLowerCase());
97
+ }
98
+ export function findPairIndex(pairs, targetPair) {
99
+ return pairs.findIndex((p) => pairsAreEqual(p, targetPair));
100
+ }
101
+ export function flipTradingPair(pair) {
102
+ return {
103
+ baseToken: pair.quoteToken,
104
+ quoteToken: pair.baseToken
105
+ };
106
+ }
107
+ export function formatChartTimestamp(timestampSeconds, timeDeltaSeconds) {
108
+ const date = new Date(timestampSeconds * 1000);
109
+ const day = date.getDate();
110
+ const month = date.toLocaleString('en-US', { month: 'short' });
111
+ const hours = date.getHours().toString().padStart(2, '0');
112
+ const minutes = date.getMinutes().toString().padStart(2, '0');
113
+ if (timeDeltaSeconds <= TIME_DELTA_24_HOURS) {
114
+ return `${month} ${day} ${hours}:${minutes}`;
115
+ }
116
+ else if (timeDeltaSeconds <= TIME_DELTA_7_DAYS) {
117
+ return `${month} ${day} ${hours}:00`;
118
+ }
119
+ else {
120
+ return `${month} ${day}`;
121
+ }
122
+ }
123
+ export function transformPairTrades(input) {
124
+ const { trades, baseTokenAddress, quoteTokenAddress, timeDeltaSeconds } = input;
125
+ const bucketSeconds = getBucketSecondsForTimeDelta(timeDeltaSeconds);
126
+ const now = Math.floor(Date.now() / 1000);
127
+ const cutoff = now - timeDeltaSeconds;
128
+ const filteredTrades = trades.filter((trade) => {
129
+ const ts = Number(trade.timestamp);
130
+ if (ts < cutoff || ts > now)
131
+ return false;
132
+ return tradeMatchesPair(trade, baseTokenAddress, quoteTokenAddress);
133
+ });
134
+ const priceAggregator = new Map();
135
+ const buyVolumeBuckets = new Map();
136
+ const sellVolumeBuckets = new Map();
137
+ for (const trade of filteredTrades) {
138
+ const amounts = getTradeAmounts(trade, baseTokenAddress);
139
+ if (!amounts)
140
+ continue;
141
+ const { baseAmount, quoteAmount, isBuy } = amounts;
142
+ if (baseAmount === 0)
143
+ continue;
144
+ const ts = Number(trade.timestamp);
145
+ const existing = priceAggregator.get(ts);
146
+ if (existing) {
147
+ priceAggregator.set(ts, {
148
+ sumBase: existing.sumBase + baseAmount,
149
+ sumQuote: existing.sumQuote + quoteAmount
150
+ });
151
+ }
152
+ else {
153
+ priceAggregator.set(ts, { sumBase: baseAmount, sumQuote: quoteAmount });
154
+ }
155
+ const bucketTime = Math.floor(ts / bucketSeconds) * bucketSeconds;
156
+ const volumeMap = isBuy ? buyVolumeBuckets : sellVolumeBuckets;
157
+ const existingVol = volumeMap.get(bucketTime) ?? 0;
158
+ volumeMap.set(bucketTime, existingVol + baseAmount);
159
+ }
160
+ const pricePoints = [];
161
+ for (const [ts, agg] of priceAggregator.entries()) {
162
+ if (agg.sumBase === 0)
163
+ continue;
164
+ const price = agg.sumQuote / agg.sumBase;
165
+ if (!Number.isFinite(price))
166
+ continue;
167
+ pricePoints.push({ time: ts, value: price });
168
+ }
169
+ const buyVolumePoints = [];
170
+ for (const [bucketTime, vol] of buyVolumeBuckets.entries()) {
171
+ buyVolumePoints.push({
172
+ time: bucketTime,
173
+ value: vol,
174
+ color: CHART_COLORS.BUY_VOLUME
175
+ });
176
+ }
177
+ const sellVolumePoints = [];
178
+ for (const [bucketTime, vol] of sellVolumeBuckets.entries()) {
179
+ sellVolumePoints.push({
180
+ time: bucketTime,
181
+ value: -vol,
182
+ color: CHART_COLORS.SELL_VOLUME
183
+ });
184
+ }
185
+ return {
186
+ pricePoints: sortBy(pricePoints, (p) => p.time),
187
+ buyVolumePoints: sortBy(buyVolumePoints, (p) => p.time),
188
+ sellVolumePoints: sortBy(sellVolumePoints, (p) => p.time)
189
+ };
190
+ }
@@ -1,4 +1,4 @@
1
- import type { InvalidStrategyDetail, ValidStrategyDetail } from '../types/strategy';
1
+ import type { InvalidOrderDetail, ValidOrderDetail } from '../types/order';
2
2
  export type RegistryFile = {
3
3
  name: string;
4
4
  url: string;
@@ -7,9 +7,9 @@ export type RegistryDotrain = {
7
7
  name: string;
8
8
  dotrain: string;
9
9
  };
10
- export interface StrategyValidationResult {
11
- validStrategies: ValidStrategyDetail[];
12
- invalidStrategies: InvalidStrategyDetail[];
10
+ export interface OrderValidationResult {
11
+ validOrders: ValidOrderDetail[];
12
+ invalidOrders: InvalidOrderDetail[];
13
13
  }
14
14
  /**
15
15
  * Fetches and parses a file registry from a given URL.
@@ -28,4 +28,4 @@ export declare const fetchParseRegistry: (url: string) => Promise<{
28
28
  url: string;
29
29
  }[]>;
30
30
  export declare const fetchRegistryDotrains: (url: string) => Promise<RegistryDotrain[]>;
31
- export declare function validateStrategies(registryDotrains: RegistryDotrain[]): Promise<StrategyValidationResult>;
31
+ export declare function validateOrders(registryDotrains: RegistryDotrain[]): Promise<OrderValidationResult>;
@@ -1,4 +1,4 @@
1
- import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api';
1
+ import { DotrainOrderGui } from '@rainlanguage/orderbook';
2
2
  /**
3
3
  * Fetches and parses a file registry from a given URL.
4
4
  * The registry is expected to be a text file where each line contains a file name and URL separated by a space.
@@ -53,10 +53,10 @@ export const fetchRegistryDotrains = async (url) => {
53
53
  }));
54
54
  return dotrains;
55
55
  };
56
- export async function validateStrategies(registryDotrains) {
57
- const strategiesPromises = registryDotrains.map(async (registryDotrain) => {
56
+ export async function validateOrders(registryDotrains) {
57
+ const ordersPromises = registryDotrains.map(async (registryDotrain) => {
58
58
  try {
59
- const result = await DotrainOrderGui.getStrategyDetails(registryDotrain.dotrain);
59
+ const result = await DotrainOrderGui.getOrderDetails(registryDotrain.dotrain);
60
60
  if (result.error) {
61
61
  throw new Error(result.error.msg);
62
62
  }
@@ -78,212 +78,12 @@ export async function validateStrategies(registryDotrains) {
78
78
  };
79
79
  }
80
80
  });
81
- const strategiesResults = await Promise.all(strategiesPromises);
82
- const validStrategies = strategiesResults
81
+ const ordersResults = await Promise.all(ordersPromises);
82
+ const validOrders = ordersResults
83
83
  .filter((result) => result.valid)
84
84
  .map((result) => result.data);
85
- const invalidStrategies = strategiesResults
85
+ const invalidOrders = ordersResults
86
86
  .filter((result) => !result.valid)
87
87
  .map((result) => result.data);
88
- return { validStrategies, invalidStrategies };
89
- }
90
- if (import.meta.vitest) {
91
- const { describe, it, expect, vi } = import.meta.vitest;
92
- describe('getFileRegistry', () => {
93
- it('should parse registry file content correctly', async () => {
94
- const mockResponse = `file1.js https://example.com/file1.js
95
- file2.js https://example.com/file2.js`;
96
- global.fetch = vi.fn().mockResolvedValue({
97
- ok: true,
98
- text: () => Promise.resolve(mockResponse)
99
- });
100
- const result = await fetchParseRegistry('https://example.com/registry');
101
- expect(result).toEqual([
102
- { name: 'file1.js', url: 'https://example.com/file1.js' },
103
- { name: 'file2.js', url: 'https://example.com/file2.js' }
104
- ]);
105
- });
106
- it('should handle failed fetch response', async () => {
107
- global.fetch = vi.fn().mockResolvedValue({
108
- ok: false
109
- });
110
- await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow('Failed to fetch registry');
111
- });
112
- it('should handle network errors', async () => {
113
- global.fetch = vi.fn().mockRejectedValue(new Error('Network error'));
114
- await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow('Network error');
115
- });
116
- });
117
- describe('fetchRegistryDotrains', () => {
118
- it('should fetch and parse dotrains correctly', async () => {
119
- const mockRegistry = `file1.rain https://example.com/file1.rain
120
- file2.rain https://example.com/file2.rain`;
121
- const mockDotrain1 = 'content of file1';
122
- const mockDotrain2 = 'content of file2';
123
- global.fetch = vi
124
- .fn()
125
- .mockResolvedValueOnce({
126
- ok: true,
127
- text: () => Promise.resolve(mockRegistry)
128
- })
129
- .mockResolvedValueOnce({
130
- ok: true,
131
- text: () => Promise.resolve(mockDotrain1)
132
- })
133
- .mockResolvedValueOnce({
134
- ok: true,
135
- text: () => Promise.resolve(mockDotrain2)
136
- });
137
- const result = await fetchRegistryDotrains('https://example.com/registry');
138
- expect(result).toEqual([
139
- { name: 'file1.rain', dotrain: mockDotrain1 },
140
- { name: 'file2.rain', dotrain: mockDotrain2 }
141
- ]);
142
- });
143
- it('should handle failed dotrain fetch', async () => {
144
- const mockRegistry = `file1.rain https://example.com/file1.rain`;
145
- global.fetch = vi
146
- .fn()
147
- .mockResolvedValueOnce({
148
- ok: true,
149
- text: () => Promise.resolve(mockRegistry)
150
- })
151
- .mockResolvedValueOnce({
152
- ok: false
153
- });
154
- await expect(fetchRegistryDotrains('https://example.com/registry')).rejects.toThrow('Failed to fetch dotrain for file1.rain');
155
- });
156
- it('should handle network errors during dotrain fetch', async () => {
157
- const mockRegistry = `file1.rain https://example.com/file1.rain`;
158
- global.fetch = vi
159
- .fn()
160
- .mockResolvedValueOnce({
161
- ok: true,
162
- text: () => Promise.resolve(mockRegistry)
163
- })
164
- .mockRejectedValueOnce(new Error('Network error'));
165
- await expect(fetchRegistryDotrains('https://example.com/registry')).rejects.toThrow('Error fetching dotrain for file1.rain: Network error');
166
- });
167
- });
168
- describe('validateStrategies', async () => {
169
- // Mock the DotrainOrderGui dependency
170
- vi.mock('@rainlanguage/orderbook/js_api', () => ({
171
- DotrainOrderGui: {
172
- getStrategyDetails: vi.fn()
173
- }
174
- }));
175
- // Import DotrainOrderGui after mocking
176
- const { DotrainOrderGui } = await import('@rainlanguage/orderbook/js_api');
177
- beforeEach(() => {
178
- vi.resetAllMocks();
179
- });
180
- it('should validate strategies and categorize them properly', async () => {
181
- // Input data
182
- const registryDotrains = [
183
- { name: 'valid.rain', dotrain: 'valid dotrain content' },
184
- { name: 'invalid.rain', dotrain: 'invalid dotrain content' },
185
- { name: 'another-valid.rain', dotrain: 'another valid content' }
186
- ];
187
- // Set up mock responses for the DotrainOrderGui
188
- DotrainOrderGui.getStrategyDetails
189
- .mockResolvedValueOnce({
190
- value: { name: 'Valid Strategy', description: 'A valid strategy' },
191
- error: null
192
- })
193
- .mockResolvedValueOnce({
194
- error: { msg: 'Invalid syntax' },
195
- value: null
196
- })
197
- .mockResolvedValueOnce({
198
- value: { name: 'Another Valid', description: 'Another valid strategy' },
199
- error: null
200
- });
201
- // Call the function with our test data
202
- const result = await validateStrategies(registryDotrains);
203
- // Verify DotrainOrderGui was called correctly
204
- expect(DotrainOrderGui.getStrategyDetails).toHaveBeenCalledTimes(3);
205
- expect(DotrainOrderGui.getStrategyDetails).toHaveBeenCalledWith('valid dotrain content');
206
- expect(DotrainOrderGui.getStrategyDetails).toHaveBeenCalledWith('invalid dotrain content');
207
- expect(DotrainOrderGui.getStrategyDetails).toHaveBeenCalledWith('another valid content');
208
- // Verify the valid strategies are processed correctly
209
- expect(result.validStrategies).toHaveLength(2);
210
- expect(result.validStrategies[0].name).toBe('valid.rain');
211
- expect(result.validStrategies[0].dotrain).toBe('valid dotrain content');
212
- expect(result.validStrategies[0].details).toEqual({
213
- name: 'Valid Strategy',
214
- description: 'A valid strategy'
215
- });
216
- // Verify the invalid strategies are processed correctly
217
- expect(result.invalidStrategies).toHaveLength(1);
218
- expect(result.invalidStrategies[0].name).toBe('invalid.rain');
219
- expect(result.invalidStrategies[0].error).toBe('Invalid syntax');
220
- });
221
- it('should handle exceptions thrown during strategy validation', async () => {
222
- // Input data
223
- const registryDotrains = [{ name: 'error.rain', dotrain: 'will throw error' }];
224
- // Mock the DotrainOrderGui to throw an exception
225
- DotrainOrderGui.getStrategyDetails.mockRejectedValueOnce(new Error('Unexpected parsing error'));
226
- // Call the function
227
- const result = await validateStrategies(registryDotrains);
228
- // Verify results
229
- expect(result.validStrategies).toHaveLength(0);
230
- expect(result.invalidStrategies).toHaveLength(1);
231
- expect(result.invalidStrategies[0].name).toBe('error.rain');
232
- expect(result.invalidStrategies[0].error).toBe('Unexpected parsing error');
233
- });
234
- it('should handle non-Error objects being thrown', async () => {
235
- // Input data
236
- const registryDotrains = [{ name: 'string-error.rain', dotrain: 'will throw string' }];
237
- // Mock the DotrainOrderGui to throw a string instead of an Error
238
- DotrainOrderGui.getStrategyDetails.mockRejectedValueOnce('String error message');
239
- // Call the function
240
- const result = await validateStrategies(registryDotrains);
241
- // Verify results
242
- expect(result.validStrategies).toHaveLength(0);
243
- expect(result.invalidStrategies).toHaveLength(1);
244
- expect(result.invalidStrategies[0].name).toBe('string-error.rain');
245
- expect(result.invalidStrategies[0].error).toBe('String error message');
246
- });
247
- it('should process an empty array of strategies', async () => {
248
- const result = await validateStrategies([]);
249
- expect(result.validStrategies).toEqual([]);
250
- expect(result.invalidStrategies).toEqual([]);
251
- expect(DotrainOrderGui.getStrategyDetails).not.toHaveBeenCalled();
252
- });
253
- it('should handle mixed validation results correctly', async () => {
254
- // Create a mix of scenarios
255
- const registryDotrains = [
256
- { name: 'valid1.rain', dotrain: 'valid content 1' },
257
- { name: 'error.rain', dotrain: 'will throw error' },
258
- { name: 'valid2.rain', dotrain: 'valid content 2' },
259
- { name: 'invalid.rain', dotrain: 'invalid content' }
260
- ];
261
- // Set up mock responses
262
- DotrainOrderGui.getStrategyDetails
263
- .mockResolvedValueOnce({
264
- value: { strategyName: 'Strategy 1', description: 'Description 1' },
265
- error: null
266
- })
267
- .mockRejectedValueOnce(new Error('Processing error'))
268
- .mockResolvedValueOnce({
269
- value: { strategyName: 'Strategy 2', description: 'Description 2' },
270
- error: null
271
- })
272
- .mockResolvedValueOnce({
273
- error: { msg: 'Validation failed' },
274
- value: null
275
- });
276
- // Call the function
277
- const result = await validateStrategies(registryDotrains);
278
- // Verify results
279
- expect(result.validStrategies).toHaveLength(2);
280
- expect(result.validStrategies[0].name).toBe('valid1.rain');
281
- expect(result.validStrategies[1].name).toBe('valid2.rain');
282
- expect(result.invalidStrategies).toHaveLength(2);
283
- expect(result.invalidStrategies[0].name).toBe('error.rain');
284
- expect(result.invalidStrategies[0].error).toBe('Processing error');
285
- expect(result.invalidStrategies[1].name).toBe('invalid.rain');
286
- expect(result.invalidStrategies[1].error).toBe('Validation failed');
287
- });
288
- });
88
+ return { validOrders, invalidOrders };
289
89
  }
@@ -1,6 +1,18 @@
1
+ import type { UTCTimestamp } from 'lightweight-charts';
1
2
  export declare const TIME_DELTA_24_HOURS: number;
2
3
  export declare const TIME_DELTA_48_HOURS: number;
3
4
  export declare const TIME_DELTA_7_DAYS: number;
4
5
  export declare const TIME_DELTA_30_DAYS: number;
5
6
  export declare const TIME_DELTA_1_YEAR: number;
6
7
  export declare function dateTimestamp(date: Date): number;
8
+ export declare function formatTimestampSecondsAsLocal(timestampSeconds: bigint): string;
9
+ export declare function timestampSecondsToUTCTimestamp(timestampSeconds: bigint): UTCTimestamp;
10
+ /**
11
+ * Method to put a timeout on a promise, throws the exception if promise is not settled within the time
12
+ * @param promise - The original promise
13
+ * @param time - The time in ms
14
+ * @param exception - The exception to reject with if time runs out before original promise settlement
15
+ * @returns A new promise that gets settled with initial promise settlement or rejected with exception value
16
+ * if the time runs out before the main promise settlement
17
+ */
18
+ export declare function promiseTimeout<T>(promise: Promise<T>, time: number, exception: unknown): Promise<T>;
@@ -1,3 +1,10 @@
1
+ import dayjs from 'dayjs';
2
+ import bigIntSupport from 'dayjs/plugin/bigIntSupport';
3
+ import localizedFormat from 'dayjs/plugin/localizedFormat';
4
+ import utc from 'dayjs/plugin/utc';
5
+ dayjs.extend(bigIntSupport);
6
+ dayjs.extend(localizedFormat);
7
+ dayjs.extend(utc);
1
8
  export const TIME_DELTA_24_HOURS = 60 * 60 * 24;
2
9
  export const TIME_DELTA_48_HOURS = TIME_DELTA_24_HOURS * 2;
3
10
  export const TIME_DELTA_7_DAYS = TIME_DELTA_24_HOURS * 7;
@@ -6,12 +13,87 @@ export const TIME_DELTA_1_YEAR = TIME_DELTA_24_HOURS * 365;
6
13
  export function dateTimestamp(date) {
7
14
  return Math.floor(date.getTime() / 1000);
8
15
  }
16
+ export function formatTimestampSecondsAsLocal(timestampSeconds) {
17
+ return dayjs(timestampSeconds * BigInt('1000'))
18
+ .utc()
19
+ .format('L LT');
20
+ }
21
+ export function timestampSecondsToUTCTimestamp(timestampSeconds) {
22
+ return dayjs(timestampSeconds * BigInt('1000')).unix();
23
+ }
24
+ /**
25
+ * Method to put a timeout on a promise, throws the exception if promise is not settled within the time
26
+ * @param promise - The original promise
27
+ * @param time - The time in ms
28
+ * @param exception - The exception to reject with if time runs out before original promise settlement
29
+ * @returns A new promise that gets settled with initial promise settlement or rejected with exception value
30
+ * if the time runs out before the main promise settlement
31
+ */
32
+ export async function promiseTimeout(promise, time, exception) {
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ let timeout;
35
+ return Promise.race([
36
+ promise,
37
+ new Promise((_resolve, reject) => (timeout = setTimeout(reject, time, exception)))
38
+ ]).finally(() => clearTimeout(timeout));
39
+ }
9
40
  if (import.meta.vitest) {
10
- const { it, expect } = import.meta.vitest;
11
- it('should get date timestamp in seconds', () => {
12
- const date = new Date(2022, 1, 16, 17, 32, 11, 168);
13
- const result = dateTimestamp(date);
14
- const expected = Math.floor(date.getTime() / 1000);
15
- expect(result).toEqual(expected);
41
+ const { describe, it, expect, vi } = import.meta.vitest;
42
+ describe('Date and timestamp utilities', () => {
43
+ describe('formatTimestampSecondsAsLocal', () => {
44
+ it('converts timestamp to local format', () => {
45
+ const result = formatTimestampSecondsAsLocal(BigInt('1672531200')); // Jan 1, 2023 12:00 AM
46
+ expect(result).toBe('01/01/2023 12:00 AM');
47
+ });
48
+ });
49
+ describe('timestampSecondsToUTCTimestamp', () => {
50
+ it('converts bigint timestamp to UTCTimestamp', () => {
51
+ const result = timestampSecondsToUTCTimestamp(BigInt('1672531200'));
52
+ expect(result).toBe(1672531200);
53
+ });
54
+ });
55
+ });
56
+ describe('promiseTimeout', () => {
57
+ it('resolves when promise resolves before timeout', async () => {
58
+ const testValue = 'test';
59
+ const promise = Promise.resolve(testValue);
60
+ const result = await promiseTimeout(promise, 100, new Error('Timeout'));
61
+ expect(result).toBe(testValue);
62
+ });
63
+ it('rejects when promise times out', async () => {
64
+ const promise = new Promise((resolve) => setTimeout(resolve, 200));
65
+ const exception = new Error('Timeout');
66
+ await expect(promiseTimeout(promise, 100, exception)).rejects.toThrow(exception);
67
+ });
68
+ it('rejects when original promise rejects', async () => {
69
+ const error = new Error('Original rejection');
70
+ const promise = Promise.reject(error);
71
+ await expect(promiseTimeout(promise, 100, new Error('Timeout'))).rejects.toThrow(error);
72
+ });
73
+ it('clears timeout after promise resolution', async () => {
74
+ vi.spyOn(global, 'clearTimeout');
75
+ const promise = Promise.resolve('test');
76
+ await promiseTimeout(promise, 100, new Error('Timeout'));
77
+ expect(clearTimeout).toHaveBeenCalled();
78
+ });
79
+ it('clears timeout after promise rejection', async () => {
80
+ vi.spyOn(global, 'clearTimeout');
81
+ const promise = Promise.reject(new Error('Original rejection'));
82
+ try {
83
+ await promiseTimeout(promise, 100, new Error('Timeout'));
84
+ }
85
+ catch {
86
+ // Ignore the error
87
+ }
88
+ expect(clearTimeout).toHaveBeenCalled();
89
+ });
90
+ });
91
+ describe('dateTimestamp', () => {
92
+ it('should get date timestamp in seconds', () => {
93
+ const date = new Date(2022, 1, 16, 17, 32, 11, 168);
94
+ const result = dateTimestamp(date);
95
+ const expected = Math.floor(date.getTime() / 1000);
96
+ expect(result).toEqual(expected);
97
+ });
16
98
  });
17
99
  }