@rainlanguage/ui-components 0.0.1-alpha.21 → 0.0.1-alpha.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__fixtures__/settings.yaml +125 -0
- package/dist/__mocks__/CodeMirrorRainlang.svelte +4 -0
- package/dist/__mocks__/CodeMirrorRainlang.svelte.d.ts +18 -0
- package/dist/__mocks__/MockComponent.svelte +4 -0
- package/dist/__mocks__/MockComponent.svelte.d.ts +3 -1
- package/dist/__mocks__/stores.d.ts +47 -33
- package/dist/__mocks__/stores.js +61 -38
- package/dist/components/ButtonLoading.svelte +1 -1
- package/dist/components/ButtonVaultLink.svelte +11 -11
- package/dist/components/ButtonVaultLink.svelte.d.ts +4 -3
- package/dist/components/CheckboxInactiveOrdersVault.svelte +20 -0
- package/dist/components/CheckboxInactiveOrdersVault.svelte.d.ts +19 -0
- package/dist/components/CheckboxMyItemsOnly.svelte +3 -2
- package/dist/components/CheckboxMyItemsOnly.svelte.d.ts +2 -3
- package/dist/components/CheckboxZeroBalanceVault.svelte.d.ts +2 -2
- package/dist/components/CodeMirrorDotrain.svelte +4 -0
- package/dist/components/CodeMirrorDotrain.svelte.d.ts +1 -0
- package/dist/components/CodeMirrorRainlang.svelte +3 -12
- package/dist/components/CodeMirrorRainlang.svelte.d.ts +2 -2
- package/dist/components/EditableSpan.svelte +3 -14
- package/dist/components/EditableSpan.svelte.d.ts +0 -1
- package/dist/components/Hash.svelte +3 -3
- package/dist/components/License.svelte +5 -4
- package/dist/components/ListViewOrderbookFilters.svelte +45 -23
- package/dist/components/ListViewOrderbookFilters.svelte.d.ts +27 -22
- package/dist/components/LocalDbStatusBadge.svelte +27 -0
- package/dist/components/LocalDbStatusBadge.svelte.d.ts +19 -0
- package/dist/components/LocalDbStatusCard.svelte +40 -0
- package/dist/components/LocalDbStatusCard.svelte.d.ts +20 -0
- package/dist/components/LocalDbStatusModal.svelte +103 -0
- package/dist/components/LocalDbStatusModal.svelte.d.ts +21 -0
- package/dist/components/OrderOrVaultHash.svelte +12 -12
- package/dist/components/OrderOrVaultHash.svelte.d.ts +4 -4
- package/dist/components/PageHeader.svelte +1 -1
- package/dist/components/TanstackAppTable.svelte +179 -28
- package/dist/components/TanstackAppTable.svelte.d.ts +14 -8
- package/dist/components/ToastDetail.svelte +42 -0
- package/dist/components/ToastDetail.svelte.d.ts +20 -0
- package/dist/components/Tooltip.svelte +8 -0
- package/dist/components/Tooltip.svelte.d.ts +21 -0
- package/dist/components/VaultBalanceChangeTypeFilter.svelte +23 -0
- package/dist/components/VaultBalanceChangeTypeFilter.svelte.d.ts +19 -0
- package/dist/components/VaultCard.svelte +18 -0
- package/dist/components/VaultCard.svelte.d.ts +19 -0
- package/dist/components/charts/LightweightChart.svelte +1 -1
- package/dist/components/charts/LightweightChart.svelte.d.ts +5 -5
- package/dist/components/charts/OrderTradesChart.svelte +300 -28
- package/dist/components/charts/OrderTradesChart.svelte.d.ts +4 -4
- package/dist/components/charts/TanstackLightweightChartLine.svelte +5 -9
- package/dist/components/charts/VaultBalanceChart.svelte +8 -26
- package/dist/components/charts/VaultBalanceChart.svelte.d.ts +1 -7
- package/dist/components/charts/transformAndSortData.d.ts +24 -0
- package/dist/components/charts/transformAndSortData.js +111 -0
- package/dist/components/checkbox/CheckboxActiveOrders.svelte +11 -0
- package/dist/components/checkbox/CheckboxActiveOrders.svelte.d.ts +19 -0
- package/dist/components/deployment/ButtonSelectOption.svelte +2 -0
- package/dist/components/deployment/ButtonSelectOption.svelte.d.ts +1 -0
- package/dist/components/deployment/ComposedRainlangModal.svelte +2 -1
- package/dist/components/deployment/ComposedRainlangModal.svelte.d.ts +1 -4
- package/dist/components/deployment/DeploymentSectionHeader.svelte +7 -4
- package/dist/components/deployment/DeploymentSteps.svelte +209 -216
- package/dist/components/deployment/DeploymentSteps.svelte.d.ts +6 -12
- package/dist/components/deployment/DeploymentTile.svelte +2 -2
- package/dist/components/deployment/DeploymentTile.svelte.d.ts +1 -1
- package/dist/components/deployment/DeploymentsSection.svelte +15 -22
- package/dist/components/deployment/DeploymentsSection.svelte.d.ts +3 -2
- package/dist/components/deployment/DepositInput.svelte +8 -10
- package/dist/components/deployment/DepositInput.svelte.d.ts +1 -2
- package/dist/components/deployment/DisclaimerModal.svelte +6 -7
- package/dist/components/deployment/FieldDefinitionInput.svelte +7 -11
- package/dist/components/deployment/FieldDefinitionInput.svelte.d.ts +1 -2
- package/dist/components/deployment/InvalidOrdersSection.svelte +17 -0
- package/dist/components/deployment/InvalidOrdersSection.svelte.d.ts +19 -0
- package/dist/components/deployment/{StrategyPage.svelte → OrderPage.svelte} +15 -24
- package/dist/components/deployment/OrderPage.svelte.d.ts +21 -0
- package/dist/components/deployment/SelectToken.svelte +125 -48
- package/dist/components/deployment/SelectToken.svelte.d.ts +4 -3
- package/dist/components/deployment/TokenBalance.svelte +19 -0
- package/dist/components/deployment/TokenBalance.svelte.d.ts +19 -0
- package/dist/components/deployment/TokenIOInput.svelte +25 -15
- package/dist/components/deployment/TokenIOInput.svelte.d.ts +3 -3
- package/dist/components/deployment/TokenSelectionModal.svelte +148 -0
- package/dist/components/deployment/TokenSelectionModal.svelte.d.ts +20 -0
- package/dist/components/deployment/{ValidStrategiesSection.svelte → ValidOrdersSection.svelte} +7 -7
- package/dist/components/deployment/ValidOrdersSection.svelte.d.ts +19 -0
- package/dist/components/deployment/VaultIdInformation.svelte +17 -0
- package/dist/components/deployment/VaultIdInformation.svelte.d.ts +21 -0
- package/dist/components/detail/OrderDetail.svelte +184 -80
- package/dist/components/detail/OrderDetail.svelte.d.ts +21 -15
- package/dist/components/detail/TanstackOrderQuote.svelte +92 -46
- package/dist/components/detail/TanstackOrderQuote.svelte.d.ts +14 -16
- package/dist/components/detail/VaultDetail.svelte +78 -77
- package/dist/components/detail/VaultDetail.svelte.d.ts +12 -18
- package/dist/components/dropdown/DropdownActiveNetworks.svelte +44 -0
- package/dist/components/dropdown/DropdownActiveNetworks.svelte.d.ts +19 -0
- package/dist/components/dropdown/DropdownCheckbox.svelte +4 -4
- package/dist/components/dropdown/DropdownOrderListAccounts.svelte +5 -2
- package/dist/components/dropdown/DropdownOrderListAccounts.svelte.d.ts +2 -3
- package/dist/components/dropdown/DropdownOrderbooksFilter.svelte +172 -0
- package/dist/components/dropdown/DropdownOrderbooksFilter.svelte.d.ts +25 -0
- package/dist/components/dropdown/DropdownTokensFilter.svelte +152 -0
- package/dist/components/dropdown/DropdownTokensFilter.svelte.d.ts +28 -0
- package/dist/components/icon/Refresh.svelte +2 -1
- package/dist/components/icon/Refresh.svelte.d.ts +1 -0
- package/dist/components/input/InputOrderHash.svelte +1 -1
- package/dist/components/input/InputOrderHash.svelte.d.ts +3 -3
- package/dist/components/input/InputRegistryUrl.svelte +36 -14
- package/dist/components/input/InputToken.svelte +2 -2
- package/dist/components/input/InputTokenAmount.svelte +16 -21
- package/dist/components/input/InputTokenAmount.svelte.d.ts +3 -3
- package/dist/components/tables/OrderAPY.svelte +6 -33
- package/dist/components/tables/OrderAPY.svelte.d.ts +1 -4
- package/dist/components/tables/OrderTradesListTable.svelte +84 -81
- package/dist/components/tables/OrderTradesListTable.svelte.d.ts +4 -4
- package/dist/components/tables/OrderVaultsVolTable.svelte +17 -22
- package/dist/components/tables/OrderVaultsVolTable.svelte.d.ts +2 -2
- package/dist/components/tables/OrdersListTable.svelte +200 -108
- package/dist/components/tables/OrdersListTable.svelte.d.ts +17 -21
- package/dist/components/tables/VaultBalanceChangesTable.svelte +83 -43
- package/dist/components/tables/VaultBalanceChangesTable.svelte.d.ts +13 -11
- package/dist/components/tables/VaultsListTable.svelte +268 -145
- package/dist/components/tables/VaultsListTable.svelte.d.ts +24 -32
- package/dist/components/transactions/FixedBottomTransaction.svelte +63 -0
- package/dist/components/transactions/FixedBottomTransaction.svelte.d.ts +16 -0
- package/dist/components/transactions/TransactionDetail.svelte +31 -0
- package/dist/components/transactions/TransactionDetail.svelte.d.ts +20 -0
- package/dist/components/transactions/TransactionList.svelte +17 -0
- package/dist/components/transactions/TransactionList.svelte.d.ts +16 -0
- package/dist/components/transactions/getStatusEmoji.d.ts +2 -0
- package/dist/components/transactions/getStatusEmoji.js +20 -0
- package/dist/components/wallet/WalletConnect.svelte +5 -4
- package/dist/components/wallet/WalletConnect.svelte.d.ts +0 -1
- package/dist/consts.d.ts +1 -0
- package/dist/consts.js +1 -0
- package/dist/errors/DeploymentStepsError.d.ts +8 -2
- package/dist/errors/DeploymentStepsError.js +7 -1
- package/dist/hooks/useGui.d.ts +1 -1
- package/dist/hooks/useGui.js +1 -1
- package/dist/hooks/useLocalDb.d.ts +3 -0
- package/dist/hooks/useLocalDb.js +10 -0
- package/dist/hooks/useRaindexClient.d.ts +3 -0
- package/dist/hooks/useRaindexClient.js +11 -0
- package/dist/index.d.ts +42 -19
- package/dist/index.js +41 -16
- package/dist/models/Transaction.d.ts +75 -0
- package/dist/models/Transaction.js +100 -0
- package/dist/providers/GuiProvider.svelte +1 -1
- package/dist/providers/GuiProvider.svelte.d.ts +1 -1
- package/dist/providers/LocalDbProvider.svelte +8 -0
- package/dist/providers/LocalDbProvider.svelte.d.ts +21 -0
- package/dist/providers/RaindexClientProvider.svelte +8 -0
- package/dist/providers/RaindexClientProvider.svelte.d.ts +21 -0
- package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte +8 -0
- package/dist/providers/dotrainRegistry/DotrainRegistryProvider.svelte.d.ts +24 -0
- package/dist/providers/dotrainRegistry/context.d.ts +9 -0
- package/dist/providers/dotrainRegistry/context.js +40 -0
- package/dist/providers/dotrainRegistry/useDotrainRegistry.d.ts +5 -0
- package/dist/providers/dotrainRegistry/useDotrainRegistry.js +35 -0
- package/dist/providers/registry/RegistryManager.d.ts +65 -0
- package/dist/providers/registry/RegistryManager.js +133 -0
- package/dist/providers/registry/RegistryProvider.svelte +6 -0
- package/dist/providers/registry/RegistryProvider.svelte.d.ts +21 -0
- package/dist/providers/registry/context.d.ts +10 -0
- package/dist/providers/registry/context.js +46 -0
- package/dist/providers/registry/useRegistry.d.ts +7 -0
- package/dist/providers/registry/useRegistry.js +29 -0
- package/dist/providers/toasts/ToastProvider.svelte +17 -0
- package/dist/providers/toasts/ToastProvider.svelte.d.ts +18 -0
- package/dist/providers/toasts/context.d.ts +14 -0
- package/dist/providers/toasts/context.js +22 -0
- package/dist/providers/toasts/useToasts.d.ts +16 -0
- package/dist/providers/toasts/useToasts.js +63 -0
- package/dist/providers/transactions/TransactionManager.d.ts +235 -0
- package/dist/providers/transactions/TransactionManager.js +509 -0
- package/dist/providers/transactions/TransactionProvider.svelte +11 -0
- package/dist/providers/transactions/TransactionProvider.svelte.d.ts +24 -0
- package/dist/providers/transactions/context.d.ts +19 -0
- package/dist/providers/transactions/context.js +28 -0
- package/dist/providers/transactions/useTransactions.d.ts +13 -0
- package/dist/providers/transactions/useTransactions.js +18 -0
- package/dist/providers/wallet/WalletProvider.svelte +7 -0
- package/dist/providers/wallet/WalletProvider.svelte.d.ts +21 -0
- package/dist/providers/wallet/context.d.ts +10 -0
- package/dist/providers/wallet/context.js +47 -0
- package/dist/providers/wallet/useAccount.d.ts +8 -0
- package/dist/providers/wallet/useAccount.js +148 -0
- package/dist/queries/keys.d.ts +1 -0
- package/dist/queries/keys.js +1 -0
- package/dist/queries/queryClient.d.ts +1 -1
- package/dist/queries/queryClient.js +11 -6
- package/dist/services/awaitTransactionIndexing.d.ts +107 -0
- package/dist/services/awaitTransactionIndexing.js +58 -0
- package/dist/services/getExplorerLink.d.ts +1 -1
- package/dist/services/getExplorerLink.js +2 -4
- package/dist/services/handleShareChoices.d.ts +2 -2
- package/dist/services/handleShareChoices.js +7 -2
- package/dist/services/historicalOrderCharts.d.ts +2 -2
- package/dist/services/historicalOrderCharts.js +267 -333
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.js +2 -1
- package/dist/services/loadRegistryUrl.d.ts +2 -0
- package/dist/services/loadRegistryUrl.js +22 -0
- package/dist/services/pairTradesChartData.d.ts +47 -0
- package/dist/services/pairTradesChartData.js +190 -0
- package/dist/services/registry.d.ts +5 -5
- package/dist/services/registry.js +8 -208
- package/dist/services/time.d.ts +12 -0
- package/dist/services/time.js +88 -6
- package/dist/storesGeneric/cachedWritableStore.d.ts +57 -0
- package/dist/storesGeneric/cachedWritableStore.js +93 -0
- package/dist/types/account.d.ts +3 -0
- package/dist/types/appStores.d.ts +9 -14
- package/dist/types/modal.d.ts +26 -14
- package/dist/types/{strategy.d.ts → order.d.ts} +3 -3
- package/dist/types/order.js +1 -0
- package/dist/types/toast.d.ts +11 -0
- package/dist/types/toast.js +1 -0
- package/dist/types/tokenBalance.d.ts +6 -0
- package/dist/types/tokenBalance.js +1 -0
- package/dist/types/transaction.d.ts +66 -21
- package/dist/types/transaction.js +31 -1
- package/dist/utils/configHelpers.d.ts +4 -0
- package/dist/utils/configHelpers.js +21 -0
- package/dist/utils/constructHashLink.d.ts +24 -0
- package/dist/utils/constructHashLink.js +115 -0
- package/dist/utils/getNetworkName.d.ts +1 -0
- package/dist/utils/getNetworkName.js +13 -0
- package/dist/utils/number.d.ts +0 -7
- package/dist/utils/number.js +0 -27
- package/dist/utils/tokens.d.ts +2 -0
- package/dist/utils/tokens.js +3 -0
- package/dist/utils/vaultBalanceChangeLabels.d.ts +4 -0
- package/dist/utils/vaultBalanceChangeLabels.js +18 -0
- package/package.json +39 -34
- package/dist/__fixtures__/orderDetail.d.ts +0 -99
- package/dist/__fixtures__/orderDetail.js +0 -204
- package/dist/__fixtures__/settings-12-11-24.json +0 -160
- package/dist/__mocks__/mockTransactionStore.d.ts +0 -22
- package/dist/__mocks__/mockTransactionStore.js +0 -56
- package/dist/__mocks__/settings.d.ts +0 -3
- package/dist/__mocks__/settings.js +0 -37
- package/dist/components/deployment/InvalidStrategiesSection.svelte +0 -19
- package/dist/components/deployment/InvalidStrategiesSection.svelte.d.ts +0 -19
- package/dist/components/deployment/StrategyPage.svelte.d.ts +0 -19
- package/dist/components/deployment/ValidStrategiesSection.svelte.d.ts +0 -19
- package/dist/components/deployment/getDeploymentTransactionArgs.d.ts +0 -17
- package/dist/components/deployment/getDeploymentTransactionArgs.js +0 -28
- package/dist/components/detail/DepositOrWithdrawButtons.svelte +0 -44
- package/dist/components/detail/DepositOrWithdrawButtons.svelte.d.ts +0 -26
- package/dist/components/dropdown/DropdownActiveSubgraphs.svelte +0 -38
- package/dist/components/dropdown/DropdownActiveSubgraphs.svelte.d.ts +0 -21
- package/dist/components/dropdown/DropdownOrderStatus.svelte +0 -31
- package/dist/components/dropdown/DropdownOrderStatus.svelte.d.ts +0 -19
- package/dist/stores/transactionStore.d.ts +0 -98
- package/dist/stores/transactionStore.js +0 -303
- package/dist/utils/time.d.ts +0 -12
- package/dist/utils/time.js +0 -27
- package/dist/utils/vault.d.ts +0 -2
- package/dist/utils/vault.js +0 -29
- /package/dist/types/{strategy.js → account.js} +0 -0
package/dist/services/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { fetchParseRegistry, fetchRegistryDotrains,
|
|
1
|
+
export { fetchParseRegistry, fetchRegistryDotrains, validateOrders } from './registry';
|
|
2
|
+
export { loadRegistryUrl } from './loadRegistryUrl';
|
|
2
3
|
export type { RegistryDotrain, RegistryFile } from './registry';
|
package/dist/services/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { fetchParseRegistry, fetchRegistryDotrains,
|
|
1
|
+
export { fetchParseRegistry, fetchRegistryDotrains, validateOrders } from './registry';
|
|
2
|
+
export { loadRegistryUrl } from './loadRegistryUrl';
|
|
@@ -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 {
|
|
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
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
31
|
+
export declare function validateOrders(registryDotrains: RegistryDotrain[]): Promise<OrderValidationResult>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DotrainOrderGui } from '@rainlanguage/orderbook
|
|
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
|
|
57
|
-
const
|
|
56
|
+
export async function validateOrders(registryDotrains) {
|
|
57
|
+
const ordersPromises = registryDotrains.map(async (registryDotrain) => {
|
|
58
58
|
try {
|
|
59
|
-
const result = await DotrainOrderGui.
|
|
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
|
|
82
|
-
const
|
|
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
|
|
85
|
+
const invalidOrders = ordersResults
|
|
86
86
|
.filter((result) => !result.valid)
|
|
87
87
|
.map((result) => result.data);
|
|
88
|
-
return {
|
|
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
|
}
|
package/dist/services/time.d.ts
CHANGED
|
@@ -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>;
|
package/dist/services/time.js
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
}
|